IMPORTANT: Per accedir als fitxer de subversion: http://acacha.org/svn (sense password). Poc a poc s'aniran migrant els enllaços. Encara però funciona el subversion de la farga però no se sap fins quan... (usuari: prova i la paraula de pas 123456)

Authenticating Users in Mobile Apps: https://developers.google.com/accounts/docs/MobileApps
https://github.com/acacha/androidskeleton

Formulari propi Login

Pe a qüestions de disseny vegeu Login screen i per a Model consulteu:

http://www.androidhive.info/2012/01/android-login-and-registration-with-php-mysql-and-sqlite/

On s'utilitza una arquitectura Client/Servidor o una aplicació client Android es connecta a un servidor LAMP (PHP) i s'itercanvien missatges utilitzant JSON

Recursos:

Configuracions generals

Signatura d'aplicacions

Desenvolupament

Al configurar les APIs us demanaran el fingerprint del vostre certificat de desenvolupament. Es pot consultar amb:

$ keytool -list -v -keystore ~/.android/debug.keystore -alias androiddebugkey -storepass android -keypass android
Alias name: androiddebugkey
Creation date: 02/10/2013
Entry type: PrivateKeyEntry
Certificate chain length: 1
Certificate[1]:
Owner: CN=Android Debug, O=Android, C=US
Issuer: CN=Android Debug, O=Android, C=US
Serial number: d142a00
Valid from: Wed Oct 02 19:40:35 CEST 2013 until: Fri Sep 25 19:40:35 CEST 2043
Certificate fingerprints: 
	 MD5:  0D:DE:4A:46:4E:8E:6E:53:75:85:30:05:88:23:81:91
	 SHA1: 29:55:09:5C:E2:F7:3E:D5:3A:7C:B8:49:05:73:B3:D3:8D:25:DB:CB
	 SHA256: 0C:8D:A1:C4:E9:E1:0F:09:13:B8:D3:C7:32:C8:DB:B3:7B:B5:15:FA:74:EF:40:F8:89:90:C4:A3:F6:80:AA:54
	 Signature algorithm name: SHA256withRSA
	 Version: 3
...

IMPORTANT: El fitxer ~/.android/debug.keystore guarda tota les claus/certificats de desenvolupament d'android. El fitxer es genera sol el primer com que es construex una aplicació (build)

Aplicacions Google Play/Google Store

Quan volgueu aconseguir el hash d'una aplicació que vulgueu publicar al Google Play cal utilitzar la release key:

$ keytool -list -v -keystore ~/AndroidReleaseKeyStore/AndroidReleaseKeyStore.jks -alias androidreleasekey -storepass android -keypass android

NOTA: Canvieu ~/AndroidReleaseKeyStore/AndroidReleaseKeyStore.jks i androidreleasekey pel valors que us pertoquin. Per crear la relaease key podeu utilitzaar el wizard de Eclipse per exportar la aplicació a apk

Facebook

keytool -exportcert -alias YOUR_RELEASE_KEY_ALIAS -keystore YOUR_RELEASE_KEY_PATH | openssl sha1 -binary | openssl base64

Per exemple:

$ keytool -exportcert -alias sergiturbadenas_release_key  -keystore ~/Dropbox/Android/ReleaseKey/android_release_key.jks | openssl sha1 -binary | openssl base64
...
GoOUyauCtINDt2ko459C5q+XCvs=

Facebook

Primer de tot cal tenir la informació del fingerprint del vostre certificat de depuració tal i com s'indica a l'apartat anterior #Signatura d'aplicacions.

Després cal crear una app a:

https://developers.facebook.com/apps

Permisos de facebook. Login Button

S'estableixen al Login Button. Un exemple:

authButton.setFragment(this);
authButton.setReadPermissions(Arrays.asList("user_location", "user_birthday", "user_likes"));
Logout i revocar permisos
if (revoke == true) {
 Log.d(TAG, "LOGOUT and also revoke!...");
 Log.d(TAG, "First revoke...");
 new Request(
   session,
    "/me/permissions",
    null,
    HttpMethod.DELETE,
    new Request.Callback() {
        public void onCompleted(Response response) {
        /* handle the result */
      	Log.d(TAG, "Revoked. Response:" + response);
		        	
    }
  }
 ).executeAsync();
 session.closeAndClearTokenInformation();
} else {
   Log.d(TAG, "Only LOGOUT (no revoke)...");					
session.closeAndClearTokenInformation();
}

Troubleshooting. Resol·lució de problemes

This app has no Android key hashes configured. Configure you app key hashes at... =

S'ha creat la app a la web de facebook però no hem afegit el hash o no s'ha guardat correctament. Obriu la app a facebook i aneu a l'apartat settings, un exemple URL:

https://developers.facebook.com/apps/953279441368135/settings/

Comproveu aquí el hash és correcte:

$ keytool -exportcert -alias androiddebugkey -keystore ~/.android/debug.keystore | openssl sha1 -binary | openssl base64
Introduzca la contraseña del almacén de claves:  

*****************  WARNING WARNING WARNING  *****************
* La integridad de la información almacenada en el almacén de claves  *
* NO se ha comprobado.  Para comprobar dicha integridad, *
* debe proporcionar la contraseña del almacén de claves.                  *
*****************  WARNING WARNING WARNING  *****************

VZ4AcVh9zmj45PNg6ZCdnR4vMBs=

NOTA: Oco si és una release key cal posar el que pertoca

com.facebook.LoginActivity is not declared as activity in AndroidManifest.xml =

Clar no? Cal afegir:

<activity android:name="com.facebook.LoginActivity"
                 android:theme="@android:style/Theme.Translucent.NoTitleBar"
                 android:label="@string/app_name" />

Al fitxer AndroidManifest.xml igual que cal definir el app_id:

<meta-data android:name="com.facebook.sdk.ApplicationId" android:value="@string/app_id"/>

i els permisos d'accés a Internet:

 <uses-permission android:name="android.permission.INTERNET"/>

Exemples pas a pas

Scrumptious. Exemple pas a pas amb tutorial inclòs al Facebook SDK:

NOTA: Aplicació que utilitza Fragments però no ActionBar o Drawer Activity

Està al SDK. El podeu trobar al github:

https://github.com/facebook/facebook-android-sdk/tree/master/samples/Scrumptious

La documentació es troba a:

https://developers.facebook.com/docs/android/scrumptious?locale=ca_ES

Per fer Logins:

https://developers.facebook.com/docs/android/scrumptious/authenticate?locale=ca_ES

OBSOLET. Exemples amb funcions obsoletes a la API Facebook actual:

Podeu consultar:

http://www.androidhive.info/2012/03/android-facebook-connect-tutorial/

per veure el pas a pas que seguir per crear l'aplicació.

Finalment es necessari baixar la llibreria facebook-android-sdk:

https://github.com/facebook/facebook-android-sdk

Llibreria necessària per crear una aplicació amb un facebook social login.

També podeu consultar:

http://www.androidhive.info/2012/03/android-facebook-connect-tutorial/

Per veure el pas a pas

Recursos/Documentació:

Google Plus

Documentació oficial i explicacions prèvies

Vegeu la gràfica de:

http://www.riskcompletefailure.com/2013/03/common-problems-with-google-sign-in-on.html

Per conèixer el flux asincròn d'un signin amb Google Plus.

La documentació oficial es troba a la pàgina:

IMPORTANT: Com es comenta a http://stackoverflow.com/questions/22498336/why-does-google-login-accomplish-login-with-an-error el Login es realitza resolent un error (precisament l'error de no poder logar-se. Això és així per que el procediment és:)

1) Declarar i preparar l'objecte GoogleApiClient al mètode oncreate de l'activitat:

mGoogleApiClient = new GoogleApiClient.Builder(this)
 .addConnectionCallbacks(this)
 .addOnConnectionFailedListener(this).addApi(Plus.API)
 .addScope(Plus.SCOPE_PLUS_LOGIN).build();

2) Connectar a Google Play Services al mètode onStart de l'activitat i mirar si l'aplicació ja està autoritzada i l'usuari seleccionat:

mGoogleApiClient.connect();

Si l'usuari ja està connectat a Google (amb una Google Account) i ja a preautoritzat l'aplicació es fa el login automàticament. Sinó la connexió (realitzada al OnStart) falla i s'executa el mètode onConnectionFailed:


NOTA: Observeu que a la creació de l'objecte mGoogleApiClient realitzada al mètode onCreate en afegit un Listener addOnConnectionFailedListener que apunta a la mateixa activitat. Per això la activitat ha d'implementar la classe GoogleApiClient.OnConnectionFailedListener i implementar el mètode onConnectionFailed

public class SignInActivity extends Activity implements OnClickListener,
       GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener 

3) Un cop ha fallat la connexió, si es vol fer login cal resoldre l'error de connexió. Per aquest raó els on click al botó Login solen executar una funció del tipus resolveSignInError on es troba el codi per superar els múltiples possibles errors:

Resolve Sign Errors Examples

Cal tenir en compte que cal resoldre múltiples (possibles) problemes per fer la connexió, els més habituals:

  • Si no hi ha connexió a Internet aconseguir una connexió (recordeu que la app necessita persmisos d'accés a Internet)
  • Si hi ha més d'un compte de Google, escollir un compte. Recordeu que l'aplicació necessita GET_ACCOUNTS permission.
  • L'usuari ha d'autoritzar com a mínim un primer cop a l'aplicació
  • Altres?

El mètode onConnected (onConnected callback) és l'esdeveniment que s'executa si el Login és correcte ja sigui per un click al botó signin o per que l'usuari i la app ja estaven pre-autoritzats!.

NOTA: Observeu que a la creació de l'objecte mGoogleApiClient realitzada al mètode onCreate en afegit un Listener addConnectionCallbacks que apunta a la mateixa activitat. Per això la activitat ha d'implementar la classe GoogleApiClient.ConnectionCallbacks i implementar el mètode onConnected

public class SignInActivity extends Activity implements OnClickListener,
       GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener 

Per aquesta raó no hi ha cap mètode anomenat login! De fet el login es realitza remotament als servidors de Google no en el propi dispositiu i per aquest raó el fluxe ha de ser asíncron.

Exemples pas a pas

Cal primer tenir instal·lat Google Play Services. Podeu veure un pas a pas a:

http://www.sgoliver.net/blog/?p=4116

i a:

http://www.androidhive.info/2014/02/android-login-with-google-plus-account-1/

I també cal tenir preparat el fingerprint del nostre certificat de desenvolupador. Consulteu:

Autenticació_Android#Signatura_d.27aplicacions

I afegir l'API i crear una nova app a la Google Api Console:

https://code.google.com/apis/console/b/0/

També podeu veure un pas a pas a:

http://www.androidhive.info/2014/02/android-login-with-google-plus-account-1/

onConnectionFailed

Capçalera del mètode:

public void onConnectionFailed(ConnectionResult result) 

Opcional però aconsellable és primer fer un Log:

Log.i(TAG, "onConnectionFailed: ConnectionResult.getErrorCode() = " + result.getErrorCode());

L'objecte result conté el resultat de l'error de connexió. El primer que se sol fer és comprovar si l'error NO és solucionable i aleshores mostrar una finestra d'error i sortir de la funció:

if (!result.hasResolution()) {
 GooglePlayServicesUtil.getErrorDialog(result.getErrorCode(), this, 0).show();
 return;
}

L'objecte local a la funció result s'ha de guardar com a propietat de la activitat per tal de poder-lo utilitzar en altres funcions:

mConnectionResult = result;

on mConnectionResult és una propietat privada:

private ConnectionResult mConnectionResult;

Normalment es fa quelcom similar a:

if (result.getErrorCode() == ConnectionResult.API_UNAVAILABLE) {
	          // An API requested for GoogleApiClient is not available. The device's current
	          // configuration might not be supported with the requested API or a required component
	          // may not be installed, such as the Android Wear application. You may need to use a
	          // second GoogleApiClient to manage the application's optional APIs.
	    } else 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();
			}
		}

Es poden tractar de forma especifica els errors possibles (consulteu [1]):

1) API NO DISPONIBLE:

if (result.getErrorCode() == ConnectionResult.API_UNAVAILABLE) {
         // An API requested for GoogleApiClient is not available. The device's current
         // configuration might not be supported with the requested API or a required component
         // may not be installed, such as the Android Wear application. You may need to use a
         // second GoogleApiClient to manage the application's optional APIs.
     }

Altres exemples:

  • INTERNAL_ERROR: Si no es configura bé la Google API console (per exemple no sha notificat el paquet i el fingerprint de la clau de desenvolupador) sol saltar aquest error i l'aplicació es tanca bruscament. Podem comprovar l'error i tracta l'error.
  • NETWORK_ERROR o TIMEOUT:
  • SIGN_IN_REQUIRED
  • Consulteu la llista completa a [2]


Recursos:


Troubleshooting. Resol·lució de problemes

Múltiples Activitats

Activar la depuració:

$ adb shell
$ setprop log.tag.GooglePlusPlatform VERBOSE
$ logcat | grep GLS

Invalid key

$ logcat | grep GLS                                          
W/GLSActivity( 1595): gms.StatusHelper Status from wire: INVALID_KEY status: null
I/GLSUser ( 1595): [GLSUser]  extracting token using key:Auth
W/GLSActivity( 1595): gms.StatusHelper Status from wire: INVALID_KEY status: null
I/GLSUser ( 1595): GLS error: INVALID_KEY acacha@gmail.com oauth2:https://www.googleapis.com/auth/plus.login
I/GLSUser ( 1595): [GLSUser]  extracting token using key:Auth
W/GLSUser ( 1595): [GLSUser] [GLSUser]  Permission for com.google.android.gms to access oauth2:https://www.googleapis.com/auth/userlocation.reporting will be managed locally.
W/GLSActivity( 1595): gms.StatusHelper Status from wire: INVALID_KEY status: null
I/GLSUser ( 1595): [GLSUser]  extracting token using key:Auth
W/GLSActivity( 1595): gms.StatusHelper Status from wire: INVALID_KEY status: null
I/GLSUser ( 1595): GLS error: INVALID_KEY acacha@gmail.com oauth2:https://www.googleapis.com/auth/plus.login

Solució:

Donar d'alta correctament el paquet i el fingerprint de la clau de depuració a Google API Console. Vegeu requeriments!


Recursos:

Twitter

Cal anar a:

https://dev.twitter.com/apps/new

i crear una nova app per aconseguir la consumer key i consumer secret

IMPORTANT: Give some dummy url in the callback url field to make the app as browser app. (If you leave it as blank it will act as Desktop app which won’t work in mobile device)

Podeu veure el pas a pas a:

http://www.androidhive.info/2012/09/android-twitter-oauth-connect-tutorial/

Finalment és necessita la llibreria twitter4j

Podeu trobar aplicacions d'exemple a:

OAuth i callback URL

L'exemple de Twitter utilitzar OAuth i una callback URL. Com s'implementa una callback URL si l'aplicació no és una aplicació web i no té cap URL? Doncs tenir en compte el següent:

  1. Al definir la callback URL a la web https://dev.twitter.com/ podeu posar la URL que vulgueu ja que no la utilitzarem
  2. La aplicació ha d'indicar la callback URL que volem utilitzar
  3. Utilitzant el fitxer de Manifest registrarem al SO Android amb un intent-filter una Activitat de la nostra app que podrà ser cridada quan una aplicació del sistema demani una URL en un cert format que definirem naltros mateixos.

Vegem un exemple de fitxer Manifest:

<activity android:name="com.iesebre.dam2.pa201415.sergi.androidTwitterConnect.MainActivity"
          android:label="@string/title_activity_main" >
           <intent-filter>
               <action android:name="android.intent.action.MAIN" />

               <category android:name="android.intent.category.LAUNCHER" />
           </intent-filter>
           <intent-filter>
               <action android:name="android.intent.action.VIEW" />
               <category android:name="android.intent.category.DEFAULT" />
               <category android:name="android.intent.category.BROWSABLE" />
               <data android:scheme="oauth" android:host="com.iesebre.dam2.pa201415.sergi.androidTwitterConnect"/>
           </intent-filter>
</activity>

Estem definint que Android obrirà la nostra aplicació (i concretament la activitat com.iesebre.dam2.pa201415.sergi.androidTwitterConnect.MainActivity) quan es vulgui obrir qualsevol URL amb el format:

oauth://com.iesebre.dam2.pa201415.sergi.androidTwitterConnect[:port][/path]

és a dir qualsevol URL que apunti al host com.iesebre.dam2.pa201415.sergi.androidTwitterConnect.

NOTA: No poseu al vostre exemple com.iesebre.dam2.pa201415.sergi.androidTwitterConnect i poseu un nom de host que sigui més complicat de repetir-se i que si pot ser només pugui estar relacionat a la vostra aplicació

Al mètode onCreate de la vostra activitat es comprova si es ve d'un intent amb aquesta URL:

Uri uri = getIntent().getData();
if (uri != null && uri.toString().startsWith(TWITTER_CALLBACK_URL)) {
...
} 

i es processa la URL per obtenir l'accés Token de Oauth i fer les tasques que pertoquin. Vegeu el codi d'exemple:

https://github.com/acacha/Android-Twitter-Connect

Recursos:

Android Hive

Facebook

Twitter

Recursos:

Google

Pas a pas:

https://developer.android.com/google/auth/api-client.html

Resol·lució de problemes:

Explicació del codi:

A partir de: https://developer.android.com/google/auth/api-client.html

Objecte GoogleApiClient (https://developer.android.com/reference/com/google/android/gms/common/api/GoogleApiClient.html).

 https://developer.android.com/google/auth/api-client.html

té un builder per fer la configuració:

mGoogleApiClient = new GoogleApiClient.Builder(this)

.addConnectionCallbacks(this) .addOnConnectionFailedListener(this).addApi(Plus.API) .addScope(Plus.SCOPE_PLUS_LOGIN).build();

NOTA: Google play Services dona accés a diverses APIs (sempre i quan les activeu a Google Api Console). Per exemple per a Google Drive:

 // Create a GoogleApiClient instance
       mGoogleApiClient = new GoogleApiClient.Builder(this)
               .addApi(Drive.API)
               .addScope(Drive.SCOPE_FILE)
               .addConnectionCallbacks(this)
               .addOnConnectionFailedListener(this)
               .build();



Recursos:

Exemples acacha

NOTA: basat en Android hive i altres...

Exemple amb els tres sistemes (Facebook, Google i Twitter) alhora

Vegeu : https://github.com/acacha/androidskeleton

Facebook

Google Plus

https://github.com/acacha/Google-Plus-Login-Android

Twitter

https://github.com/acacha/Android-Twitter-Connect

Llibreries

AndroidSocialNetwork

Socialauth

Socialauth

Vegeu també