In questa lezione verranno illustrati i passi per aggiungere una schermata di autenticazione che sfrutti il protocollo OAuth e il social login tramite Google, a partire da un progetto appena creato su Android Studio.
Prerequisiti
Come primo passo, carichiamo all’interno del progetto il file di configurazione scaricato durante la registrazione dell’applicazione alla Google Developer Console.
Il file google-services.json deve essere posizionato all’interno della cartella app allo stesso livello della cartella src.
Al suo interno sarà possibile trovare diverse informazioni, quali:
- informazioni sul progetto;
- informazioni sul client, come l’ID dell’applicazione, il package name e le informazioni di OAuth per il processo di autorizzazione e autenticazione.
Aggiunto il file di configurazione, è finalmente possibile integrare il login tramite Google.
Modifica del Gradle
Per integrare la liberia è necessario scaricarla tramite Maven aggiungendo nel buildscript del progetto il seguente codice:
repositories {
mavenCentral()
}
Successivamente, nel build.gradle dell’applicazione va dichiarata la dipendenza dalla libreria Google Play Services, come segue.
dependencies {
…
compile 'com.google.android.gms:play-services-auth:9.8.0'
}
A differenza di altre librerie, la Google Play Services permette di ereditare permessi impiegati per vari servizi, come l’accesso alla rete, richiesto invece per Facebook.
Modifica del layout
Apriamo il layout activity_login.xml presente in src/main/res/layout e aggiungiamo all’interno del ConstraintLayout
, che funge da contenitore, il bottone di default di Google per il login.
<com.google.android.gms.common.SignInButton
android:id="@+id/google_login_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
android:visibility="visible"
tools:visibility="gone"/>
Come si può intuire, oltre a porre il bottone al centro della schermata, sono state aggiunte due ulteriori proprietà per gestirne la visibilità prima e dopo l’autenticazione. All’avvio dell’applicazione, l’utente vedrà il bottone di login, che scomparirà ad autenticazione avvenuta e lascerà spazio al bottone di disconnessione dell’account e di logout.
Per fare questo, è necessario aggiungere un altro ConstraintLayout
che contenga al suo interno i due bottoni affiancati tra loro. Si riporta di seguito il codice necessario.
<android.support.constraint.ConstraintLayout
android:id="@+id/sign_out_and_disconnect"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
android:visibility="gone"
tools:visibility="visible">
<Button
android:id="@+id/google_logout_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintRight_toLeftOf="@+id/disconnect_button"
android:text="@string/sign_out"/>
<Button
android:id="@+id/disconnect_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="10dp"
app:layout_constraintLeft_toRightOf="@+id/google_logout_button"
android:text="@string/disconnect" />
</android.support.constraint.ConstraintLayout>
Ovviamente, il bottone di default per l’autenticazione può essere rimpiazzato da un altro bottone custom creato attraverso il classico Widget
.
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/custom_sign_in" />
Ciononostante, è importante rispettare le direttive fornite da Google per lo stile del bottone, reperibili al seguente link.
Modifica della LoginActivity
Spostiamoci adesso all’interno della LoginActivity
al fine di gestire l’autenticazione tramite Google.
Nel metodo onCreate()
aggiungiamo identifichiamo i tre bottoni inseriti all’interno dell’interfaccia grafica e impostiamo il metodo setOnClickListener()
che permetterà di invocare il metodo corretto in base al pulsante premuto dall’utente.
private GoogleApiClient mGoogleApiClient;
...
@Override
protected void onCreate(Bundle savedInstanceState) {
...
findViewById(R.id.google_login_button).setOnClickListener(this);
findViewById(R.id.google_logout_button).setOnClickListener(this);
findViewById(R.id.disconnect_button).setOnClickListener(this);
...
}
Successivamente, sempre all’interno del metodo, istanziamo un nuovo oggetto GoogleSignInOptions
con il parametro di default DEFAULT_SIGN_IN
che permette di ottenere le informazioni di base dell’utente e passiamo questo oggetto al metodo addAPI()
per la creazione di un nuovo oggetto GoogleApiClient
che permetterà di accedere.
GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestEmail()
.build();
mGoogleApiClient = new GoogleApiClient.Builder(this)
.enableAutoManage(this, this)
.addApi(Auth.GOOGLE_SIGN_IN_API, gso)
.build();
Ora che abbiamo tutto l’occorrente per la creazione della LoginActivity
, è necessario gestire il comportamento dei bottoni di login, logout e di revoca dell’autorizzazione e quando devono essere visualizzati dall’utente. Si riporta di seguito l'implementazione di questi metodi a cui si aggiunge l'implementazione del metodo handleSignInResult
che verrà richiamato nel metodo onActivityResult
per gestire il coportamento dell'applicazione in base al risultato del processo di autenticazinoe.
private void handleSignInResult(GoogleSignInResult result) {
if (result.isSuccess()) {
GoogleSignInAccount acct = result.getSignInAccount();
updateUI(true);
} else {
updateUI(false);
}
}
private void signIn() {
Log.d("signIn", "start");
Intent signInIntent = Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient);
startActivityForResult(signInIntent, RC_SIGN_IN);
Log.d("signIn", "finish");
}
Dove il metodo updateUI()
è il seguente:
private void updateUI(boolean signedIn) {
if (signedIn) {
findViewById(R.id.google_login_button).setVisibility(View.GONE);
findViewById(R.id.sign_out_and_disconnect).setVisibility(View.VISIBLE);
} else {
findViewById(R.id.google_login_button).setVisibility(View.VISIBLE);
findViewById(R.id.sign_out_and_disconnect).setVisibility(View.GONE);
}
}
Se l’autenticazione è avvenuta con successo allora il bottone di login non verrà più visualizzato dall’utente lasciando il suo spazio al contenitore contenente i bottoni di logout e di disconnessione dal servizio. Contrariamente, nel caso in cui l’utente voglia uscire dall’applicazione il container verrà nascosto per mostrare nuovamente all’utente il bottone di login.
A questo punto aggiungiamo i metodi per il logout e per la disconnessione come segue.
private void signOut() {
Auth.GoogleSignInApi.signOut(mGoogleApiClient).setResultCallback(
new ResultCallback<Status>() {
@Override
public void onResult(Status status) {
updateUI(false);
}
});
}
private void revokeAccess() {
Auth.GoogleSignInApi.revokeAccess(mGoogleApiClient).setResultCallback(
new ResultCallback<Status>() {
@Override
public void onResult(Status status) {
// INSERIRE IL CODICE PER RIMUOVERE I DATI DELL’UTENTE SALVATI IN BASE ALLA LOGICA DELLA PROPRIA APP
updateUI(false);
}
});
}
Entrambi i metodi implementano quelli dell’interfaccia Auth.GoogleSignInApi
, signOut()
e revokeAccess()
, definendo al loro interno il metodo updateUI()
per aggiornare la grafica.
Una volta aggiunti questi metodi, non resta che impostarli ai relativi bottoni attraverso metodo onClick
di onClickListener()
, come segue:
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.google_login_button:
signIn();
break;
case R.id.google_logout_button:
signOut();
break;
case R.id.disconnect_button:
revokeAccess();
break;
}
}
Infine aggiungiamo il metodo onActivityResult()
per gestire il comportamento dell’applicazione nella gestione del risultato ed in presenza di errori di connessione. Si riporta di seguito il relativo codice.
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == RC_SIGN_IN) {
GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data);
handleSignInResult(result);
}
}
Risultato finale
Eseguiamo l'applicazione sul dispositivo mobile o sull’emulatore.
All’avvio dell'applicazione, viene mostrata la LoginActivity
contenente il bottone di default precedentemente aggiunto all’interfaccia.
Cliccando sul bottone, verrà richiesto all'utente di autenticarsi con il proprio account Google e di accettare i termini del servizio.
Una volta autenticato, l’utente viene rimandato nuovamente alla LoginActivity
ma, al posto del bottone di autenticazione, appariranno i bottoni di logout e di disconnessione dell’account, come in figura.
Cliccando sul bottone di sign out, l’utente verrà disconnesso dall’applicazione e quando si autenticherà nuovamente non verranno richiesti i dati di accesso, ma verrà mostrata una schermata di selezione dell’account con la possibilità di aggiungerne uno nuovo.
Il codice sorgente di questa lezione è reperibile su Github.