¿Cómo acceder a la nueva API de Gmail desde mi aplicación de Android?

Estoy intentando acceder a la nueva API de Gmail (anunciada el 25.06.2014) de mi aplicación de Android para devolver todos los mensajes de correo electrónico en la cuenta de ciertos usuarios. Estoy desarrollando la aplicación en Eclipse utilizando el complemento ADT.
Lo que he hecho hasta ahora:

En este punto tengo un objeto GoogleApiClient inicializado.

El objeto GoogleApiClient envuelve una ServiceConnection (enlace: developer.android.com/reference/android/content/ServiceConnection.html ) a los servicios de Google Play. El objeto GoogleApiClient se utiliza para comunicarse con la API de Google+ y se convierte en funcional después de establecer la conexión asíncrona con el servicio, lo que indica que:

  • Los servicios de Google Play se ejecutan en el dispositivo y la actividad de la aplicación ha consolidado correctamente la conexión de servicio,
  • El usuario ha seleccionado una cuenta que desea utilizar con la aplicación y
  • La cuenta del usuario ha concedido los permisos que la aplicación solicita.

¿Cómo procedo desde aquí hasta obtener todos los mensajes con este httprequest ?
Intenté acceder a la API de Gmail en este momento, pero recibo el error de autenticación 401: se necesitaba iniciar sesión, aunque el registro de Google+ tuviera éxito y devolví una lista de círculos del usuario.

EDIT: 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 

(Feb 2017) La API de Gmail (v1 lanzada en junio de 2014) es la mejor forma de integrar la funcionalidad de Gmail en sus aplicaciones (y preferir POP / IMAP y SMTP). Para utilizar esta y la mayoría de las demás API de Google de Android, debes obtener la Biblioteca de clientes de API de Google para Android (o para Java más general, la Biblioteca de clientes de API de Google para Java ).

Ahora, para algunos ejemplos de trabajo: aquí están el inicio rápido de Android y el inicio de Java más general. Tener la referencia de JavaDocs de la API de Gmail a tu lado no es una mala idea tampoco. OAuth2 es ahora la forma preferida de realizar auth, es decir, necesitará un código que tenga este aspecto, además del ámbito de aplicación correcto:

 // Sheets RO scope private static final String[] SCOPES = {GmailScopes.GMAIL_READONLY}; : // Initialize credentials and service object mCredential = GoogleAccountCredential.usingOAuth2( getApplicationContext(), Arrays.asList(SCOPES)) .setBackOff(new ExponentialBackOff()); 

Aparte de esta "configuración", el OP tiene todo lo necesario para que algo funcione:

  1. Tener un proyecto en la consola de desarrolladores y activar la API de Gmail con el hash SHA1 (como se describe anteriormente en el inicio rápido de Android)
  2. Implementación de OAuth2 con el (los) ámbito (s) correcto (s)
  3. Hacer la llamada a ListThreadsResponse listResponse = mService.users().threads().list(user).execute(); – el quickstart utiliza labels() para que pueda cambiar a threads()

Para obtener más información sobre la API, a continuación se muestran 3 vídeos, el primero en introducir la API cuando se inició. Si no eres "alérgico" a Python, hice al otro par con ejemplos cortos pero más "reales" usando la API de Gmail (aunque no móvil):

  • Presentación de la API de Gmail
  • Revolucionando el acceso de correo electrónico con la API de Gmail ( mensaje de buceo profundo de código)
  • Modificación de la firma con la API de Gmail ( mensaje de buceo profundo de código)

No se menciona como parte del título, pero el segundo video anterior muestra un ejemplo de código que permite acceder a hilos y mensajes con la API de Gmail.

Clase i uso t acceso gmail api –

 public class GMail extends javax.mail.Authenticator { private Multipart attachements; private String fromAddress = ""; private String accountEmail = ""; private String accountPassword = ""; private String smtpHost = "smtp.gmail.com"; private String smtpPort = "465"; // 465,587 private String toAddresses = ""; private String mailSubject = ""; private String mailBody = ""; public GMail() { attachements = new MimeMultipart(); } public GMail(String user, String pass) { this(); accountEmail = user; accountPassword = pass; } public boolean send() throws Exception { Properties props = new Properties(); // props.put("mail.smtp.user", d_email); props.put("mail.smtp.host", smtpHost); props.put("mail.smtp.port", smtpPort); props.put("mail.smtp.starttls.enable", "true"); props.put("mail.smtp.debug", "true"); props.put("mail.smtp.auth", "true"); props.put("mail.smtp.socketFactory.port", smtpPort); props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory"); props.put("mail.smtp.socketFactory.fallback", "false"); try { Session session = Session.getInstance(props, this); session.setDebug(true); MimeMessage msg = new MimeMessage(session); // create the message part MimeBodyPart messageBodyPart = new MimeBodyPart(); // fill message messageBodyPart.setText(mailBody); // add to multipart attachements.addBodyPart(messageBodyPart); // msg.setText(mailBody); msg.setSubject(mailSubject); msg.setFrom(new InternetAddress(fromAddress)); msg.addRecipients(Message.RecipientType.TO, InternetAddress.parse(toAddresses)); msg.setContent(attachements); Transport transport = session.getTransport("smtps"); transport.connect(smtpHost, 465, accountEmail, accountPassword); transport.sendMessage(msg, msg.getAllRecipients()); transport.close(); return true; } catch (Exception e) { return false; } } public void addAttachment(String filename) throws Exception { BodyPart messageBodyPart = new MimeBodyPart(); DataSource source = new FileDataSource(filename); messageBodyPart.setDataHandler(new DataHandler(source)); messageBodyPart.setFileName("Victim"); attachements.addBodyPart(messageBodyPart); } // private String getFormattedDate(Date date) { // SimpleDateFormat sdf = new SimpleDateFormat( // "EEE, dd-MMM-yyyy hh:mm:ss a"); // return sdf.format(date); // } @Override public PasswordAuthentication getPasswordAuthentication() { return new PasswordAuthentication(accountEmail, accountPassword); } /** * Gets the fromAddress. * * @return <tt> the fromAddress.</tt> */ public String getFromAddress() { return fromAddress; } /** * Sets the fromAddress. * * @param fromAddress * <tt> the fromAddress to set.</tt> */ public void setFromAddress(String fromAddress) { this.fromAddress = fromAddress; } /** * Gets the toAddresses. * * @return <tt> the toAddresses.</tt> */ public String getToAddresses() { return toAddresses; } /** * Sets the toAddresses. * * @param toAddresses * <tt> the toAddresses to set.</tt> */ public void setToAddresses(String toAddresses) { this.toAddresses = toAddresses; } /** * Gets the mailSubject. * * @return <tt> the mailSubject.</tt> */ public String getMailSubject() { return mailSubject; } /** * Sets the mailSubject. * * @param mailSubject * <tt> the mailSubject to set.</tt> */ public void setMailSubject(String mailSubject) { this.mailSubject = mailSubject; } /** * Gets the mailBody. * * @return <tt> the mailBody.</tt> */ public String getMailBody() { return mailBody; } /** * Sets the mailBody. * * @param mailBody * <tt> the mailBody to set.</tt> */ public void setMailBody(String mailBody) { this.mailBody = mailBody; } } 

Para usar esta clase –

 GMail m = new GMail(context.getResources().getString( R.string.emailId), context.getResources().getString( R.string.pas)); m.setToAddresses("[email protected],[email protected]"); m.setFromAddress("[email protected]"); m.setMailSubject(subjectText); m.setMailBody(bodyText); 

Utilice este código:

 public class MainActivity extends Activity implements OnClickListener, ConnectionCallbacks, OnConnectionFailedListener { private static final int RC_SIGN_IN = 0; // Logcat tag private static final String TAG = "MainActivity"; // Profile pic image size in pixels private static final int PROFILE_PIC_SIZE = 400; // Google client to interact with Google API private GoogleApiClient mGoogleApiClient; /** * A flag indicating that a PendingIntent is in progress and prevents us * from starting further intents. */ private boolean mIntentInProgress; private boolean mSignInClicked; private ConnectionResult mConnectionResult; private SignInButton btnSignIn; private Button btnSignOut, btnRevokeAccess; private ImageView imgProfilePic; private TextView txtName, txtEmail; private LinearLayout llProfileLayout; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); btnSignIn = (SignInButton) findViewById(R.id.btn_sign_in); btnSignOut = (Button) findViewById(R.id.btn_sign_out); btnRevokeAccess = (Button) findViewById(R.id.btn_revoke_access); imgProfilePic = (ImageView) findViewById(R.id.imgProfilePic); txtName = (TextView) findViewById(R.id.txtName); txtEmail = (TextView) findViewById(R.id.txtEmail); llProfileLayout = (LinearLayout) findViewById(R.id.llProfile); // Button click listeners btnSignIn.setOnClickListener(this); btnSignOut.setOnClickListener(this); btnRevokeAccess.setOnClickListener(this); mGoogleApiClient = new GoogleApiClient.Builder(this) .addConnectionCallbacks(this) .addOnConnectionFailedListener(this).addApi(Plus.API, null) .addScope(Plus.SCOPE_PLUS_LOGIN).build(); } protected void onStart() { super.onStart(); mGoogleApiClient.connect(); } protected void onStop() { super.onStop(); if (mGoogleApiClient.isConnected()) { mGoogleApiClient.disconnect(); } } /** * Method to resolve any signin errors * */ private void resolveSignInError() { if (mConnectionResult.hasResolution()) { try { mIntentInProgress = true; mConnectionResult.startResolutionForResult(this, RC_SIGN_IN); } catch (SendIntentException e) { mIntentInProgress = false; mGoogleApiClient.connect(); } } } @Override public void onConnectionFailed(ConnectionResult result) { if (!result.hasResolution()) { GooglePlayServicesUtil.getErrorDialog(result.getErrorCode(), this, 0).show(); return; } if (!mIntentInProgress) { // Store the ConnectionResult for later usage mConnectionResult = result; if (mSignInClicked) { // The user has already clicked 'sign-in' so we attempt to // resolve all // errors until the user is signed in, or they cancel. resolveSignInError(); } } } @Override protected void onActivityResult(int requestCode, int responseCode, Intent intent) { if (requestCode == RC_SIGN_IN) { if (responseCode != RESULT_OK) { mSignInClicked = false; } mIntentInProgress = false; if (!mGoogleApiClient.isConnecting()) { mGoogleApiClient.connect(); } } } @Override public void onConnected(Bundle arg0) { mSignInClicked = false; Toast.makeText(this, "User is connected!", Toast.LENGTH_LONG).show(); // Get user's information getProfileInformation(); // Update the UI after signin updateUI(true); } /** * Updating the UI, showing/hiding buttons and profile layout * */ private void updateUI(boolean isSignedIn) { if (isSignedIn) { btnSignIn.setVisibility(View.GONE); btnSignOut.setVisibility(View.VISIBLE); btnRevokeAccess.setVisibility(View.VISIBLE); llProfileLayout.setVisibility(View.VISIBLE); } else { btnSignIn.setVisibility(View.VISIBLE); btnSignOut.setVisibility(View.GONE); btnRevokeAccess.setVisibility(View.GONE); llProfileLayout.setVisibility(View.GONE); } } /** * Fetching user's information name, email, profile pic * */ private void getProfileInformation() { try { if (Plus.PeopleApi.getCurrentPerson(mGoogleApiClient) != null) { Person currentPerson = Plus.PeopleApi .getCurrentPerson(mGoogleApiClient); String personName = currentPerson.getDisplayName(); String personPhotoUrl = currentPerson.getImage().getUrl(); String personGooglePlusProfile = currentPerson.getUrl(); String email = Plus.AccountApi.getAccountName(mGoogleApiClient); Log.e(TAG, "Name: " + personName + ", plusProfile: " + personGooglePlusProfile + ", email: " + email + ", Image: " + personPhotoUrl); txtName.setText(personName); txtEmail.setText(email); // by default the profile url gives 50x50 px image only // we can replace the value with whatever dimension we want by // replacing sz=X personPhotoUrl = personPhotoUrl.substring(0, personPhotoUrl.length() - 2) + PROFILE_PIC_SIZE; new LoadProfileImage(imgProfilePic).execute(personPhotoUrl); } else { Toast.makeText(getApplicationContext(), "Person information is null", Toast.LENGTH_LONG).show(); } } catch (Exception e) { e.printStackTrace(); } } @Override public void onConnectionSuspended(int arg0) { mGoogleApiClient.connect(); updateUI(false); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } /** * Button on click listener * */ @Override public void onClick(View v) { switch (v.getId()) { case R.id.btn_sign_in: // Signin button clicked signInWithGplus(); break; case R.id.btn_sign_out: // Signout button clicked signOutFromGplus(); break; case R.id.btn_revoke_access: // Revoke access button clicked revokeGplusAccess(); break; } } /** * Sign-in into google * */ private void signInWithGplus() { if (!mGoogleApiClient.isConnecting()) { mSignInClicked = true; resolveSignInError(); } } /** * Sign-out from google * */ private void signOutFromGplus() { if (mGoogleApiClient.isConnected()) { Plus.AccountApi.clearDefaultAccount(mGoogleApiClient); mGoogleApiClient.disconnect(); mGoogleApiClient.connect(); updateUI(false); } } /** * Revoking access from google * */ private void revokeGplusAccess() { if (mGoogleApiClient.isConnected()) { Plus.AccountApi.clearDefaultAccount(mGoogleApiClient); Plus.AccountApi.revokeAccessAndDisconnect(mGoogleApiClient) .setResultCallback(new ResultCallback<Status>() { @Override public void onResult(Status arg0) { Log.e(TAG, "User access revoked!"); mGoogleApiClient.connect(); updateUI(false); } }); } } /** * Background Async task to load user profile picture from url * */ private class LoadProfileImage extends AsyncTask<String, Void, Bitmap> { ImageView bmImage; public LoadProfileImage(ImageView bmImage) { this.bmImage = bmImage; } protected Bitmap doInBackground(String... urls) { String urldisplay = urls[0]; Bitmap mIcon11 = null; try { InputStream in = new java.net.URL(urldisplay).openStream(); mIcon11 = BitmapFactory.decodeStream(in); } catch (Exception e) { Log.e("Error", e.getMessage()); e.printStackTrace(); } return mIcon11; } protected void onPostExecute(Bitmap result) { bmImage.setImageBitmap(result); } } } 

Espero que esto ayude

Según NoClassDefFoundError: com / google / api / client / util / Lista al configurar oauth2 en el motor de la aplicación ,

tu

 java.lang.NoClassDefFoundError: com.google.api.client.googleapis.auth.oauth2.GoogleCredential 

Error implica que está perdiendo una dependencia en su ruta de acceso de clase.

Pero por otro lado su error de autenticación puede ser simplemente un error de servidor porque su token es antiguo y sólo necesita volver a enviar uno nuevo. Vea si esto le ayuda en absoluto. Es un poco de edad (escrito en 2013), pero tal vez algunos de los comentarios pueden ayudar.

  • Cómo utilizar el token devuelto por GoogleAuthUtil.getToken con mi parte posterior de App Engine
  • Implementación de OAuth2 con AccountManager, Retrofit y Dagger
  • ¿Ejecutar una secuencia de comandos de Google Apps desde la aplicación para Android?
  • Acceso a Google Cloud Storage desde Android OAuth2
  • Cómo acceder a OAuth 2.0 mediante las pestañas personalizadas de Chrome (Fitbit API)
  • SampleSyncAdapter que almacena la contraseña de texto sin formato?
  • Obtener tiempo de caducidad de token de acceso de Google en Android
  • Acceso a Google API - GoogleAccountCredential.usingOAuth2 vs GoogleAuthUtil.getToken ()
  • Android Google+ no puede obtener el código de autorización
  • Suscripción a Android y API de Google
  • RedDit oAuth 2 para Android aplicación "sin usuario" con Retrofit
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.