Wie Sie auf die neue Gmail-API von meine Android-app?
Ich versuche Zugriff auf die neue Gmail-API (angekündigt 25.06.2014) von meinem Android app, um wieder alle e-mail-Nachrichten in einem bestimmten Benutzer-account. Ich entwickle die app in Eclipse mit dem ADT-plug-in.
Was ich bisher getan habe:
-
Registrierte ich die Anwendung in die Google Entwickler-Konsole
(link: console.developers.google.com/project). -
Implementierte ich die Google+ Sign-in button (link: developers.google.com/+/mobile/android/sign-in).
Die Google+ Sign-In-button wird der Benutzer authentifiziert und verwaltet die OAuth-2.0-Strömung, die vereinfacht die integration mit den Google-APIs. -
Ich einen zusätzlichen Anwendungsbereich "https://www.googleapis.com/auth/gmail.readonly' auf der Google+ - Autorisierung für den Zugriff auf die Gmail-API " angegeben
(Link: developers.google.com/gmail/api/v1/reference/users/threads/list).
In diesem Punkt habe ich eine initialisierte GoogleApiClient Objekt.
Den GoogleApiClient Objekt umschließt eine ServiceConnection (link: developer.android.com/reference/android/content/ServiceConnection.html) an den Google Play services. Die GoogleApiClient-Objekt wird verwendet, um die Kommunikation mit der Google+ API und wird funktional nach dem asynchronen Verbindung mit dem service, der anzeigt, dass:
- Google Play services auf dem Gerät ausgeführt wird und die app-Aktivität wurde erfolgreich gebunden die service-Verbindung,
- der Benutzer ausgewählt hat, ein Konto, das Sie verwenden möchten, mit der app und
- dem Konto des Nutzers erteilt hat, die Berechtigungen, die die app anfordert.
Wie gehe ich vor, von hier zu bekommen alle Meldungen mit diesem httprequest?
Ich habe versucht, den Zugriff auf die Gmail-API an dieser Stelle, aber ich erhalte Authentifizierung error 401: Anmeldung erforderlich, sogar dachte, dass der Google+ login war erfolgreich, und ich habe Sie erfolgreich zurückgegeben wird eine Liste von Benutzer-Kreisen.
BEARBEITEN: SecondActivity.java
import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import com.google.android.gms.auth.GoogleAuthException;
import com.google.android.gms.auth.GoogleAuthUtil;
import com.google.android.gms.auth.GooglePlayServicesAvailabilityException;
import com.google.android.gms.auth.UserRecoverableAuthException;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.common.SignInButton;
import com.google.android.gms.common.api.CommonStatusCodes;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.GoogleApiClient.ConnectionCallbacks;
import com.google.android.gms.common.api.GoogleApiClient.OnConnectionFailedListener;
import com.google.android.gms.common.api.ResultCallback;
import com.google.android.gms.common.api.Scope;
import com.google.android.gms.plus.People;
import com.google.android.gms.plus.People.LoadPeopleResult;
import com.google.android.gms.plus.Plus;
import com.google.android.gms.plus.model.people.Person;
import com.google.android.gms.plus.model.people.PersonBuffer;
import com.google.api.services.gmail.Gmail;
import com.google.api.services.gmail.Gmail.Users;
import com.google.api.services.gmail.Gmail.Users.Messages.GmailImport;
import com.google.api.services.gmail.GmailRequest;
import com.google.api.services.gmail.GmailRequestInitializer;
import com.google.api.services.gmail.GmailScopes;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.PendingIntent;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentSender.SendIntentException;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v7.app.ActionBarActivity;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import mk.ukim.feit.recognizer.application.PeopleAdapter;
import mk.ukim.feit.recognizer.interfaces.GetMessages;
import mk.ukim.feit.recognizer.tasks.GetMessagesTask;
import mk.ukim.feit.recognizer.util.MyClass;
import mk.ukim.feit.recognizer.util.exception.FaceClientException;
import mk.ukim.feit.recognizer.util.model.Face;
import mk.ukim.feit.recognizer.util.model.Guess;
import mk.ukim.feit.recognizer.util.model.Photo;
import mk.ukim.feit.recognizer.util.response.PhotoResponse;
import mk.ukim.feit.recognizer.util.response.PhotoResponseImpl;
import java.io.IOException;
import java.util.ArrayList;
public class SecondActivity extends FragmentActivity implements
GetMessages, ConnectionCallbacks, OnConnectionFailedListener,
ResultCallback<People.LoadPeopleResult>, View.OnClickListener {
private static final String TAG = "android-plus-quickstart";
private static final int STATE_DEFAULT = 0;
private static final int STATE_SIGN_IN = 1;
private static final int STATE_IN_PROGRESS = 2;
private static final int RC_SIGN_IN = 0;
private static final int MY_ACTIVITYS_AUTH_REQUEST_CODE=045;
private static final int DIALOG_PLAY_SERVICES_ERROR = 0;
private static final String SAVED_PROGRESS = "sign_in_progress";
private GoogleApiClient mGoogleApiClient;
String name;
private PendingIntent mSignInIntent;
private int mSignInError;
private SignInButton mSignInButton;
private Button mSignOutButton;
private Button mRevokeButton;
private TextView mStatus;
private ListView mCirclesListView;
private ArrayAdapter<String> mCirclesAdapter;
private ArrayList<String> mCirclesList;
public Scope gmail=new Scope("https://www.googleapis.com/auth/gmail.readonly");
String scope="https://www.googleapis.com/auth/gmail.readonly";
String email="[email protected]";
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
Intent intent = getIntent();
name="Team";
mSignInButton = (SignInButton) findViewById(R.id.sign_in_button);
mSignOutButton = (Button) findViewById(R.id.sign_out_button);
mRevokeButton = (Button) findViewById(R.id.revoke_access_button);
mStatus = (TextView) findViewById(R.id.sign_in_status);
mCirclesListView = (ListView) findViewById(R.id.circles_list);
mSignInButton.setOnClickListener(this);
mSignOutButton.setOnClickListener(this);
mRevokeButton.setOnClickListener(this);
mCirclesList = new ArrayList<String>();
mCirclesAdapter = new ArrayAdapter<String>(
this, R.layout.circle_member, mCirclesList);
mCirclesListView.setAdapter(mCirclesAdapter);
if (savedInstanceState != null) {
mSignInProgress = savedInstanceState
.getInt(SAVED_PROGRESS, STATE_DEFAULT);
}
mGoogleApiClient = buildGoogleApiClient();
}
private GoogleApiClient buildGoogleApiClient() {
return new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(Plus.API, Plus.PlusOptions.builder().build())
.addScope(Plus.SCOPE_PLUS_LOGIN)
.addScope(gmail)
.build();
}
@Override
protected void onStart() {
super.onStart();
mGoogleApiClient.connect();
getAndUseAuthTokenInAsyncTask();
}
@Override
protected void onStop() {
super.onStop();
if (mGoogleApiClient.isConnected()) {
mGoogleApiClient.disconnect();
}
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt(SAVED_PROGRESS, mSignInProgress);
}
@Override
public void onClick(View v) {
if (!mGoogleApiClient.isConnecting()) {
switch (v.getId()) {
case R.id.sign_in_button:
mStatus.setText(R.string.status_signing_in);
resolveSignInError();
break;
case R.id.sign_out_button:
Plus.AccountApi.clearDefaultAccount(mGoogleApiClient);
mGoogleApiClient.disconnect();
mGoogleApiClient.connect();
break;
case R.id.revoke_access_button:
Plus.AccountApi.clearDefaultAccount(mGoogleApiClient);
Plus.AccountApi.revokeAccessAndDisconnect(mGoogleApiClient);
mGoogleApiClient = buildGoogleApiClient();
mGoogleApiClient.connect();
break;
}
}
}
@Override
public void onConnected(Bundle connectionHint) {
Log.i(TAG, "onConnected");
getAndUseAuthTokenInAsyncTask();
mSignInButton.setEnabled(false);
mSignOutButton.setEnabled(true);
mRevokeButton.setEnabled(true);
//Retrieve some profile information. This is OK
Person currentUser = Plus.PeopleApi.getCurrentPerson(mGoogleApiClient);
String klient=mGoogleApiClient.toString();
mStatus.setText(String.format(
getResources().getString(R.string.signed_in_as),
currentUser.getDisplayName()));
Plus.PeopleApi.loadVisible(mGoogleApiClient, null)
.setResultCallback(this);
GetMessagesTask task = new GetMessagesTask(
SecondActivity.this, name, mGoogleApiClient);
task.setDelegate(SecondActivity.this);
task.execute();
//Indicate that the sign in process is complete.
mSignInProgress = STATE_DEFAULT;
}
@Override
public void onConnectionFailed(ConnectionResult result) {
//Refer to the javadoc for ConnectionResult to see what error codes might
//be returned in onConnectionFailed.
Log.i(TAG, "onConnectionFailed: ConnectionResult.getErrorCode() = "
+ result.getErrorCode());
if (mSignInProgress != STATE_IN_PROGRESS) {
mSignInIntent = result.getResolution();
mSignInError = result.getErrorCode();
if (mSignInProgress == STATE_SIGN_IN) {
//STATE_SIGN_IN indicates the user already clicked the sign in button
//so we should continue processing errors until the user is signed in
//or they click cancel.
resolveSignInError();
}
}
onSignedOut();
}
private void resolveSignInError() {
if (mSignInIntent != null) {
try {
mSignInProgress = STATE_IN_PROGRESS;
startIntentSenderForResult(mSignInIntent.getIntentSender(),
RC_SIGN_IN, null, 0, 0, 0);
} catch (SendIntentException e) {
Log.i(TAG, "Sign in intent could not be sent: "
+ e.getLocalizedMessage());
//The intent was canceled before it was sent. Attempt to connect to
//get an updated ConnectionResult.
mSignInProgress = STATE_SIGN_IN;
mGoogleApiClient.connect();
}
} else {
//Google Play services wasn't able to provide an intent for some
//error types, so we show the default Google Play services error
//dialog which may still start an intent if the
//user can resolve the issue.
showDialog(DIALOG_PLAY_SERVICES_ERROR);
}
}
@Override
public void onResult(LoadPeopleResult peopleData) {
if (peopleData.getStatus().getStatusCode() == CommonStatusCodes.SUCCESS) {
mCirclesList.clear();
PersonBuffer personBuffer = peopleData.getPersonBuffer();
try {
int count = personBuffer.getCount();
for (int i = 0; i < count; i++) {
mCirclesList.add(personBuffer.get(i).getDisplayName());
}
} finally {
personBuffer.close();
}
mCirclesAdapter.notifyDataSetChanged();
} else {
Log.e(TAG, "Error requesting visible circles: " + peopleData.getStatus());
}
}
private void onSignedOut() {
//Update the UI to reflect that the user is signed out.
mSignInButton.setEnabled(true);
mSignOutButton.setEnabled(false);
mRevokeButton.setEnabled(false);
mStatus.setText(R.string.status_signed_out);
mCirclesList.clear();
mCirclesAdapter.notifyDataSetChanged();
}
@Override
public void onConnectionSuspended(int cause) {
//The connection to Google Play services was lost for some reason.
//We call connect() to attempt to re-establish the connection or get a
//ConnectionResult that we can attempt to resolve.
mGoogleApiClient.connect();
}
@Override
protected Dialog onCreateDialog(int id) {
switch(id) {
case DIALOG_PLAY_SERVICES_ERROR:
if (GooglePlayServicesUtil.isUserRecoverableError(mSignInError)) {
return GooglePlayServicesUtil.getErrorDialog(
mSignInError,
this,
RC_SIGN_IN,
new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
Log.e(TAG, "Google Play services resolution cancelled");
mSignInProgress = STATE_DEFAULT;
mStatus.setText(R.string.status_signed_out);
}
});
} else {
return new AlertDialog.Builder(this)
.setMessage(R.string.play_services_error)
.setPositiveButton(R.string.close,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Log.e(TAG, "Google Play services error could not be "
+ "resolved: " + mSignInError);
mSignInProgress = STATE_DEFAULT;
mStatus.setText(R.string.status_signed_out);
}
}).create();
}
default:
return super.onCreateDialog(id);
}
}
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == MY_ACTIVITYS_AUTH_REQUEST_CODE) {
if (resultCode == RESULT_OK) {
getAndUseAuthTokenInAsyncTask();
}
}
}
public void getAndUseAuthTokenBlocking() throws UserRecoverableAuthException, IOException, GoogleAuthException {
final String token = GoogleAuthUtil.getToken(this, email, scope);
String fff="";
}
public void getAndUseAuthTokenInAsyncTask() {
AsyncTask<Void, Void, Void> task = new AsyncTask<Void,Void, Void>() {
@Override
protected Void doInBackground(Void... params) {
//TODO Auto-generated method stub
try {
getAndUseAuthTokenBlocking();
} catch (UserRecoverableAuthException e) {
//TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
//TODO Auto-generated catch block
e.printStackTrace();
} catch (GoogleAuthException e) {
//TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
};
task.execute((Void)null);
}
}
EDIT 2: LogCat
07-16 06:44:27.300: E/AndroidRuntime(11875): FATAL EXCEPTION: AsyncTask #2
07-16 06:44:27.300: E/AndroidRuntime(11875): java.lang.RuntimeException: An error occured while executing doInBackground()
07-16 06:44:27.300: E/AndroidRuntime(11875): at android.os.AsyncTask$3.done(AsyncTask.java:299)
07-16 06:44:27.300: E/AndroidRuntime(11875): at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:273)
07-16 06:44:27.300: E/AndroidRuntime(11875): at java.util.concurrent.FutureTask.setException(FutureTask.java:124)
07-16 06:44:27.300: E/AndroidRuntime(11875): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:307)
07-16 06:44:27.300: E/AndroidRuntime(11875): at java.util.concurrent.FutureTask.run(FutureTask.java:137)
07-16 06:44:27.300: E/AndroidRuntime(11875): at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
07-16 06:44:27.300: E/AndroidRuntime(11875): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
07-16 06:44:27.300: E/AndroidRuntime(11875): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
07-16 06:44:27.300: E/AndroidRuntime(11875): at java.lang.Thread.run(Thread.java:856)
07-16 06:44:27.300: E/AndroidRuntime(11875): Caused by: java.lang.NoClassDefFoundError: com.google.api.client.googleapis.auth.oauth2.GoogleCredential
07-16 06:44:27.300: E/AndroidRuntime(11875): at mk.ukim.feit.recognizer.GmailLinkGrabberService$getAuthToken.doInBackground(GmailLinkGrabberService.java:104)
07-16 06:44:27.300: E/AndroidRuntime(11875): at mk.ukim.feit.recognizer.GmailLinkGrabberService$getAuthToken.doInBackground(GmailLinkGrabberService.java:1)
07-16 06:44:27.300: E/AndroidRuntime(11875): at android.os.AsyncTask$2.call(AsyncTask.java:287)
07-16 06:44:27.300: E/AndroidRuntime(11875): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
07-16 06:44:27.300: E/AndroidRuntime(11875): ... 5 more
- Ich habe erfolgreich umgesetzt Gmail-API in meine android-app. Ich kann Ihnen helfen, zu Debuggen, wenn Sie uns Ihren code.
- Ich weiß nicht, wie Sie auf das gmail-Konto des angemeldeten Benutzers, nach der Rückkehr in die Google+ Kreise. Keine Hilfe? @gitter
- Ich will rufen
response=service.users().threads().list("me").setQ(query).setPageT
oken(pageToken).execute();
zum abrufen einer Liste mit allen passenden threads eine Abfrage im Posteingang des Benutzers. - Dieser code implementiert die gleiche: raw.githubusercontent.com/gitanshu/privly-android/gmail-rest/... Auch der Umfang sollte "oauth2:googleapis.com/auth/gmail.readonly"
- Ich habe versucht, die Umsetzung der code aus deinem link, aber kann nicht ankommen es zu wirken. In der neuen edit oben habe ich geschrieben das LogCat Fehler. Vielen Dank für deine Hilfe @gitter
- Dies ist die Codezeile, wo der Fehler Auftritt
GoogleCredential credential = new
GoogleCredential().setAccessToken(token);
@gitter - haben Sie kopiert alle erforderlichen jar-Dateien?
- Ich glaube, so habe ich die folgenden: android-support-v4.jar; apache-mime4j-0.6.jar; commons-lang-2.6.jar; face4j-core-1.6.3-SNAPSHOT.jar; google-api-client-1.18.0-rc.jar; google-api-client-android-1.18.0-rc.jar; google-api-client-jackson2-1.18.0-rc.jar; google-api-services-gmail-v1-rev3-1.18.0-rc.jar; google-http-client-android-1.18.0-rc.jar; google-http-client-jackson-1.18.0-rc.jar; google-http-client-jackson2-1.18.0-rc.jar; google-oauth-client-1.18.0-rc-sources.jar; google-oauth-client-1.18.0-rc.jar; httpclient-4.0.1.jar; httpmime-4.0.3.jar; jackson-core-2.1.3.jar; slf4j-android-1.6.1-RC1.jar
- Siehe meinen letzten Kommentar @gitter
- wären Sie bereit zu teilen Sie Ihre code, oder einige Erkenntnisse zumindest. Ich bin auch zu versuchen, die neue Gmail-API in Android, aber es ist überhaupt nicht einfach, da gibt es keine docs für Android-Umsetzung. Ich bin auch nur Wundern, wie Sie es dann geschafft.
- checkout dem 4. Kommentar auf diesen thread. Ich habe einen link von meinem code. Ich werde versuchen, das hinzufügen von mehr Dokumentation zu, wenn ich Zeit bekommen. Aber ich glaube, es ist einfach genug zu verstehen.
- Super!!! Würden Sie meinen, dass diese API bereit für den produktiven Einsatz auf Android noch. E. ich. wenn es scheint zu funktionieren gut genug für die Verwendung in veröffentlichten apps?
- Ja, es funktioniert sehr gut, ich habe noch nicht gefunden, keine Fehler...
- Ideal wäre es, wenn jemand könnte auf github eine voll funktionsfähige demo-app - mit jar-Dateien (oder noch besser - gradle Referenzen). Jemand etwas?
- Hi. Ich habe gitter Beispiel. Alles funktioniert Super außer das ich immer einen 403-Fehler, wenn Sie versuchen, um E-Mails. Hinzugefügt wurde die client-Id in der api-Konsole aber immer noch nicht gehen. Wer? Ach ja und verwendet den richtigen Bereich, sowie
- Haben Sie noch dieses problem? Vielleicht können Sie fügen Sie hier den code, wo du die Fehler? @TalMihr
- Ich bin der Anmeldung mit einem Google+login bu habe Probleme bei der Erstellung eines GoogleApiClient Objekt ich bin mit dem folgenden code:
Scope gmailreadonly = new Scope("oauth2:googleapis.com/auth/gmail.readonly"); mGoogleApiClient = new GoogleApiClient.Builder(this) .addConnectionCallbacks(this) .addOnConnectionFailedListener(this) .addApi(Plus.API) .addScope(Plus.SCOPE_PLUS_LOGIN) .addScope(gmailreadonly) .build();
- Es wurde eine neue Antwort, die hoffentlich klären einige dieser Kommentare sowie die OP ' s ursprüngliche Anfrage.
Du musst angemeldet sein, um einen Kommentar abzugeben.
(Feb 2017) Die Gmail-API (v1 gestartet Jun 2014) ist der beste Weg für die Integration von Gmail-Funktionalität in Ihre apps (und bevorzugt über POP/IMAP & SMTP). Um diese und die meisten anderen Google-APIs von Android, die Sie brauchen, um die Google APIs Client Library für Android (oder weitere Allgemeine Java, die Google APIs Client Library for Java).
Nun für einige arbeitsbeispiele: hier sind die Android quickstart & mehr Allgemeine Java-quickstart. Mit der Gmail API JavaDocs Referenz an Ihrer Seite ist keine schlechte Idee, entweder. OAuth2 ist nun die bevorzugte Methode zur Durchführung von auth, d.h. Sie müssen code, der so aussieht, plus die richtige Umfang:
Andere als dieses "setup", der OP hat die meisten alles, was benötigt wird, um etwas zu arbeiten:
ListThreadsResponse listResponse = mService.users().threads().list(user).execute();
-- quickstart verwendetlabels()
so können Sie nur ändern, umthreads()
Erfahren Sie mehr über die API, unten sind 3 videos, die erste Einführung in die API, wenn es gestartet. Wenn Sie nicht "allergisch" zu Python, ich habe das andere paar mit kurzen, aber mehr "real-world" - Beispiele über die Gmail-API (non-mobile aber):
Es ist nicht erwähnt als Teil des Titels, aber das 2. video oben verfügt über ein code-Beispiel, das die Zugriffe thread und Nachrichten mit der Gmail API.
Klasse ich benutze t Zugriff auf die gmail-api -
Um Diese Klasse zu verwenden -
Verwenden Sie diesen code:
Hoffe das hilft
Laut NoClassDefFoundError: com/google/api/client/util/Listen beim einrichten von oauth2 auf app engine,
Ihre
Fehler bedeutet, dass Sie eine Abhängigkeit fehlt in Ihrer Klasse Weg.
Aber auf der anderen Seite des Authentifizierungs-Fehler kann nur ein server-Fehler, da Ihr token ist alt und Sie brauchen nur, um Sie erneut eine neue. Sehen Sie, wenn diese hilft Ihnen bei allen. Es ist ein bisschen im Alter (geschrieben 2013), aber vielleicht einige der Kommentare, die helfen können.