Acceda al cliente de google plus desde múltiples actividades

Estoy desarrollando una aplicación en la que he integrado google plus. Hasta ahora está funcionando bien, puedo recuperar el perfil del usuario.

Pero ahora quiero hacer lo siguiente:

1) Tengo dos actividad signInActivity y shareActivity .

2) Si el usuario ya está signInActivity con signInActivity , no debería solicitar el shareActivity de shareActivity en shareActivity y debe compartir el contenido directamente.

3) Si el usuario no ha iniciado sesión en signInActivity y trata de compartir datos mediante shareActivity , la aplicación debe shareActivity el usuario y luego solo compartir los datos. En este caso, si el usuario regresa a la actividad de signInActivity , la aplicación debe mostrar que “ya se ha registrado”.

En resumen, quiero que el inicio de sesión del usuario sea central dentro de la aplicación, de modo que si está firmado, debe estar accesible desde cualquier actividad.

He oído sobre el token de acceso, pero no sé cómo usarlo y el documento dice que caduca en una hora que no es lo que quiero.

¿Cómo puedo hacer el inicio de sesión de google plus? ¿Es posible? o necesito autenticar al usuario en cada actividad?

Administrar una instancia separada de GoogleApiClient en cada actividad no provocará que se solicite al usuario que inicie sesión varias veces.

El inicio de sesión de Google+ (es decir, GoogleApiClient) proporciona una interfaz para las cuentas de Google en el dispositivo y el servicio central de servicios de Google Play; no tiene estado por instancia de GoogleApiClient. Por lo tanto, una vez que se autentica una cuenta de dispositivo para su aplicación, las nuevas instancias de GoogleApiClient accederán al mismo estado. GoogleApiClient está diseñado específicamente para ser una forma liviana de acceder al estado central administrado por los servicios de Google Play.

¡Estás de suerte con los tokens de acceso! Los servicios de Google Play se encargan de gestionar todos los tokens. Entonces, aunque los tokens de acceso solo duran una hora, como dices, si tratas de utilizar PlusClient para acceder a una API de Google y tu token de acceso ha expirado, los servicios de Google Play solicitarán de forma transparente un nuevo token de acceso y completarán la llamada.

Eche un vistazo a la primera parte de esta charla de E / S de Google para más detalles:

http://www.youtube.com/watch?v=_KBHf1EODuk

0. TL; DR

Para el codificador impaciente, se puede encontrar una versión funcional de la siguiente implementación en GitHub . Esta es la misma respuesta escrita en otra publicación de Stack Overflow .

Después de volver a escribir el código de actividad de inicio de sesión varias veces en muchas aplicaciones diferentes, la solución fácil (y no tan elegante) fue crear el cliente de API de Google como un objeto de clase de aplicación. Pero, dado que el estado de la conexión afecta el flujo UX, nunca estuve contento con este enfoque.

Reduciendo nuestro problema solo al concepto de conexión , podemos considerar que:

  1. Oculta el cliente API de Google.
  2. Tiene estados finitos.
  3. Es un (más bien) único.
  4. El estado actual afecta el comportamiento de la aplicación.

1. Patrón de Proxy

Dado que Connection encapsula GoogleApiClient , implementará ConnectionCallbacks y OnConnectionFailedListener :

 @Override public void onConnected(Bundle hint) { changeState(State.OPENED); } @Override public void onConnectionSuspended(int cause) { changeState(State.CLOSED); connect(); } @Override public void onConnectionFailed(ConnectionResult result) { if (currentState.equals(State.CLOSED) && result.hasResolution()) { changeState(State.CREATED); connectionResult = result; } else { connect(); } } 

Las actividades pueden comunicarse con la clase Connection a través de los métodos connect , disconnect y revoke , pero sus comportamientos se deciden por el estado actual. La máquina de estados requiere los siguientes métodos:

 protected void onSignIn() { if (!googleApiClient.isConnected() && !googleApiClient.isConnecting()) { googleApiClient.connect(); } } protected void onSignOut() { if (googleApiClient.isConnected()) { Plus.AccountApi.clearDefaultAccount(googleApiClient); googleApiClient.disconnect(); googleApiClient.connect(); changeState(State.CLOSED); } } protected void onSignUp() { Activity activity = activityWeakReference.get(); try { changeState(State.OPENING); connectionResult.startResolutionForResult(activity, REQUEST_CODE); } catch (IntentSender.SendIntentException e) { changeState(State.CREATED); googleApiClient.connect(); } } protected void onRevoke() { Plus.AccountApi.clearDefaultAccount(googleApiClient); Plus.AccountApi.revokeAccessAndDisconnect(googleApiClient); googleApiClient = googleApiClientBuilder.build(); googleApiClient.connect(); changeState(State.CLOSED); } 

2. Patrón de estado

Este es un patrón de comportamiento que permite a un objeto alterar su comportamiento cuando cambia su estado interno. El libro GoF Design Patterns describe cómo se puede representar una conexión TCP mediante este patrón (que también es nuestro caso).

Un estado de una máquina de estados debería ser un singleton , y lo más fácil de hacerlo en Java era crear Enum named State siguiente manera:

 public enum State { CREATED { @Override void connect(Connection connection) { connection.onSignUp(); } @Override void disconnect(Connection connection) { connection.onSignOut(); } }, OPENING {}, OPENED { @Override void disconnect(Connection connection) { connection.onSignOut(); } @Override void revoke(Connection connection) { connection.onRevoke(); } }, CLOSED { @Override void connect(Connection connection) { connection.onSignIn(); } }; void connect(Connection connection) {} void disconnect(Connection connection) {} void revoke(Connection connection) {} 

La clase de Connection contiene el contexto, es decir, el estado actual, que define cómo se comportarán los métodos de connect , disconnect y revoke :

 public void connect() { currentState.connect(this); } public void disconnect() { currentState.disconnect(this); } public void revoke() { currentState.revoke(this); } private void changeState(State state) { currentState = state; setChanged(); notifyObservers(state); } 

3. Patrón Singleton

Como no es necesario recrear esta clase repetidamente, lo proporcionamos como singleton:

 public static Connection getInstance(Activity activity) { if (null == sConnection) { sConnection = new Connection(activity); } return sConnection; } public void onActivityResult(int result) { if (result == Activity.RESULT_OK) { changeState(State.CREATED); } else { changeState(State.CLOSED); } onSignIn(); } private Connection(Activity activity) { activityWeakReference = new WeakReference<>(activity); googleApiClientBuilder = new GoogleApiClient .Builder(activity) .addConnectionCallbacks(this) .addOnConnectionFailedListener(this) .addApi(Plus.API, Plus.PlusOptions.builder().build()) .addScope(new Scope("email")); googleApiClient = googleApiClientBuilder.build(); currentState = State.CLOSED; } 

4. Patrón observable

La clase Connection amplía Java Observable , por lo que una o más actividades pueden observar los cambios de estado:

 @Override protected void onCreate(Bundle bundle) { connection = Connection.getInstance(this); connection.addObserver(this); } @Override protected void onStart() { connection.connect(); } @Override protected void onDestroy() { connection.deleteObserver(this); connection.disconnect(); } @Override protected void onActivityResult(int request, int result, Intent data) { if (Connection.REQUEST_CODE == request) { connection.onActivityResult(result); } } @Override public void update(Observable observable, Object data) { if (observable != connection) { return; } // Your presentation logic goes here... } 

Para cualquiera que lea esta pregunta, también puede verificar esta respuesta por Ian Barber y también la siguiente, respondida por Lee, que explica tres maneras amplias de trabajar con el inicio de sesión de Google plus y múltiples actividades que en realidad encontré muy útiles.