Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

Google Login su Android con Firebase

Come utilizzare Firebase per implementare l'autenticazione tramite Google (social login) all'interno di un'app mobile per Android.
Come utilizzare Firebase per implementare l'autenticazione tramite Google (social login) all'interno di un'app mobile per Android.
Link copiato negli appunti

In questa lezione, vedremo come integrare il social login tramite Google utilizzando Firebase nella nostra applicazione. I passi da compiere sono molto simili a quelli illustrati nella lezione 7, a differenza dell'implementazione dei metodi di login e logout.

Modifica del build.gradle del modulo app

Apriamo il build.gradle del Module:app e nelle dipendenze dell'applicazione aggiungiamo quella mancante per Google:

dependencies {
	. . .
	//Google Play Services
	compile 'com.google.android.gms:play-services-auth:11.8.0'
}

Sincronizziamo il gradle cliccando su Sync Now, che comparirà in alto a destra dopo aver aggiunto la dipendenza.

Modifica delle risorse e dell'AndroidManifest

Apriamo l'AndroidManifest.xml per aggiungere all'interno del tag application i meta-data relativi alla versione della libreria Play Services con cui viene compilata l'applicazione:

<meta-data
android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version" />

Modifica del layout

Passiamo adesso alla modifica del layout per aggiungere il bottone che permetterà all'utente di effettuare il login. Per farlo, apriamo il file activity_login.xml che si trova in src/main/res/layout, e inseriamo all'interno del ConstaintLayout il codice seguente:

<com.google.android.gms.common.SignInButton
	android:id="@+id/bt_log_in"
	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" />

In questo modo abbiamo aggiunto il SignInButton fornito da Google, posizionandolo al centro del parent.

Modifica della LoginActivity

Inseriti gli elementi basilari per la schermata di login, è necessario configurarne la logica per eseguire il processo di autorizzazione e autenticazione.

All'interno dell'Activity dovremo compiere diverse operazioni che si riassumono nei seguenti passi:

  • implementare l'interfaccia OnClickListener;
  • inizializzare l'autenticazione tramite Firebase e Google implementando il metodo onActivityResult;
  • implementare i metodi di login e logout;
  • gestire l'access token tramite Firebase;
  • aggiornare l'interfaccia in base all'esito dell'autenticazione;

Iniziamo con l'instanziare il bottone di login che utilizzeremo nella nostra Activity.

public class LoginActivity extends AppCompatActivity implements View.OnClickListener {
	private SignInButton mLoginButton;
	. . .
	@Override
	protected void onCreate(Bundle savedInstanceState) {
	. . .
		mLoginButton = findViewById(R.id.bt_log_in);
		mLoginButton.setOnClickListener(this);
		mLoginButton.setSize(SignInButton.SIZE_WIDE);
		findViewById(R.id.bt_log_out).setOnClickListener(this);
	. . .
	}
	. . .
	public void signInt() { /*@TODO*/ }
	//modificato rispetto la lezione 15
	@Override
	public void onClick(View v) {
		int i = v.getId();
		if (i == R.id.bt_log_in) {
			signIn();
		} else if (i == R.id.bt_log_out) {
			signOut();
		}
	}
}

Nel codice proposto, è stata impostata la dimensione del bottone di login di Google a SIZE_WIDE, al fine di avere un bottone sufficientemente grande. Inoltre, i metodi di signIn e signOut verranno invocati quando l'utente cliccherà sul bottone di logout.

Focalizziamoci ora sull'inizializzazione del processo di login. All'interno del metodo OnCreate, istanziamo la FirebaseAuth, le GoogleSignInOptions e il GoogleSignInClient, che sfruttando le opzioni definite gestirà il processo di login/logout. Per farlo definiamo le variabili:

private FirebaseAuth mFirebaseAuth;
private GoogleSignInClient mGoogleSignInClient;

e nel metodo onCreate:

protected void onCreate(Bundle savedInstanceState) {
	. . .
	mFirebaseAuth = FirebaseAuth.getInstance();
			GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
			.requestIdToken(getString(R.string.default_web_client_id))
			.requestEmail()
			.build();
	mGoogleSignInClient = GoogleSignIn.getClient(this, gso);
 }

In questo modo abbiamo:

  • ottenuto un'istanza di FirebaseAuth;
  • definito le opzioni per il login tramite Google:
    • impostando il tipo di login (DEFAULT_SIGN_IN);
    • specificando che è richiesto un token ID per gli utenti autenticati definendo l'ID client del server che verificherà l'integrità del token;
    • specificando che è richiesta l'email per l'autenticazione;
  • creato una nuova istanza del GoogleSignInClient per il login.

Per completare l'integrazione del login, aggiungiamo la definizione dei metodi signIn e signOut che avvieranno rispettivamente l'Intent di login e il processo di logout da Firebase e da Google, come mostrato di seguito:

private static final int RC_SIGN_IN = 9001;
. . .
private void signIn() {
	Intent signInIntent = mGoogleSignInClient.getSignInIntent();
	startActivityForResult(signInIntent, RC_SIGN_IN);
}
private void signOut() {
	mFirebaseAuth.signOut();
	mGoogleSignInClient.signOut().addOnCompleteListener(this,
			new OnCompleteListener<Void>() {
				@Override
				public void onComplete(@NonNull Task<Void> task) {
					updateUI(null);
				}
			});
}

La variabile RC_SIGN_IN è il request code per il login di Google e serve come identificativo per il metodo onActivityResult che eseguirà il flusso di operazioni previsto per quel requestCode.

Implementiamo, quindi, il metodo onActivityResult che inoltra al metodo firebaseAuthWithGoogle l'account ottenuto durante il processo di login avviato tramite l'Intent.

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
	super.onActivityResult(requestCode, resultCode, data);
	if (requestCode == RC_SIGN_IN) {
		Task<GoogleSignInAccount> task = GoogleSignIn.getSignedInAccountFromIntent(data);
		try {
			GoogleSignInAccount account = task.getResult(ApiException.class);
			firebaseAuthWithGoogle(account);
		} catch (ApiException e) {
			updateUI(null);
		}
	}
}

Implementiamo ora i metodi firebaseAuthWithGoogle e updateUI per gestire il GoogleSignInAccount ottenuto tramite Google durante il processo di login e per aggiornare l'interfaccia utente in base all'esito del login.

Il firebaseAuthWithGoogle va implementato come segue.

private void firebaseAuthWithGoogle(GoogleSignInAccount account) {
	showProgressDialog();
	AuthCredential credential = GoogleAuthProvider.getCredential(account.getIdToken(), null);
	mFirebaseAuth.signInWithCredential(credential)
			.addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
				@Override
				public void onComplete(@NonNull Task<AuthResult> task) {
					if (task.isSuccessful()) {
						FirebaseUser user = mFirebaseAuth.getCurrentUser();
						updateUI(user);
					} else {
						Toast.makeText(LoginActivity.this, "Authentication failed.",
								Toast.LENGTH_SHORT).show();
						updateUI(null);
					}
					hideProgressDialog();
				}
			});
}

All'interno del metodo, si è:

  • richiamato il metodo per mostrare la ProgressDialog;
  • ottenuto le credenziali attraverso il metodo statico getCredential dell'oggetto GoogleAuthProvider che prende in input l'id del token (ottenuto durante l'autenticazione e che deve essere verificato dal server) e restituisce un oggetto AuthCredential;
  • tentato l'accesso a Google tramite il metodo signInWithCredential passando in input le credenziali appena recuperate restituendo un oggetto Task<AuthResult>;
  • aggiunto un listener al Task che viene richiamato quando quest'ultimo sarà terminato;
  • richiamato il metodo per nascondere la ProgressDialog.

In particolare, quando il Task sarà terminato, in caso di successo verranno recuperate le informazioni dell'utente e aggiornata l'interfaccia tramite il metodo updateUI.

Implementiamo, ora, il metodo updateUI che verificherà se l'oggetto FirebaseUser è stato inizializzato aggiornando l'interfaccia. In caso di successo, verrà nascosto il bottone di login rendendo visibile e popolando il LinearLayout definito in precedenza. Contrariamente, verrà mostrato solo il bottone di login. Si riporta per completezza l'implementazione del metodo:

private void updateUI(FirebaseUser user) {
	if (user != null) {
		mLoginButton.setVisibility(View.GONE);
		mUserInfoLayout.setVisibility(View.VISIBLE);
		mUserNameTV.setText(user.getDisplayName());
		String imageUrl = user.getPhotoUrl().toString();
		imageUrl = imageUrl.replace("/s96-c/","/s200-c/");
		String userId = "";
		for(UserInfo profile : user.getProviderData()){
			if(FacebookAuthProvider.PROVIDER_ID.equals(profile.getProviderId())) {
				userId = profile.getUid();
			}
		}
		Picasso.with(this)
				.load(imageUrl)
				.placeholder(R.drawable.placeholder)
				.into(mUserImageIV);
	} else {
		mLoginButton.setVisibility(View.VISIBLE);
		mUserInfoLayout.setVisibility(View.GONE);
	}
}

In particolare, per popolare il layout con le informazioni dell'utente è possibile utilizzare l'oggetto FirebaseUser da cui estrarre i dati dell'utente.

L'URL dell'immagine di profilo può essere ottenuta tramite il metodo getPhotoUrl().toString() dell'oggetto, ma questa soluzione limita la dimensione dell'immagine a quella più piccola offerta dalle API di Google. Questa limitazione è facilmente superabile effettuando una sostituzione all'interno dell'URL in formato stringa. In particolare, impostando la dimensione a s200-c otterremo un'immagine di profilo quadrata dalle dimensioni di 200x200 pixel.

Infine, la responsabilità di caricare l'immagine verrà assegnata alla libreria Picasso che prende in input l'URL da caricare e il contenitore in cui inserirla.

Risultato finale

Eseguiamo l'applicazione sul dispositivo mobile o sull'emulatore.

All'avvio dell'applicazione, viene mostrata la schermata iniziale contenente il bottone di default precedentemente aggiunto all'interfaccia e qui di seguito riportato.

Figura 87. Schermata autenticazione (click per ingrandire)

Schermata autenticazione

Cliccando sul bottone verrà richiesto all'utente di autenticarsi con il proprio account Google, chiedendo allo stesso l'autorizzazione per l'accesso ai dati personali da parte dell'applicazione.

Figura 88. Schermata di a) autenticazione di Google, b) autorizzazione per l'accesso ai dati (click per ingrandire)

Schermata di a) autenticazione di Google, b) autorizzazione per l'accesso ai dati

Una volta loggati, verremo nuovamente reindirizzati alla schermata della LoginActivity ma, al posto del bottone di login, verranno mostrate le informazioni dell'utente e il bottone di logout.

Figura 89. LoginActivity con le informazioni dell'utente e il bottone di logout (click per ingrandire)

LoginActivity con le informazioni dell'utente e il bottone di logout

Cliccando sul bottone di logout verrà effettuato il logout da Google e l'applicazione mostrerà nuovamente il bottone di login.

Ti consigliamo anche