Firebase Android Snippets

repository·master·Indexed 21 days ago

https://github.com/firebase/snippets-android

A collection of reference source code and implementation patterns used in the official Firebase Android documentation. Includes examples for Firebase App Check (custom providers and token retrieval) and Firebase Authentication (anonymous sign-in, custom tokens, Facebook login, OAuth providers, and Google Sign-In via Credential Manager).

Tokens
9.1K
Snippets
31
Records
32
Agent score
73%

What's inside firebase-snippets-android

  1. Sign out from Firebase and Credential Manager

    master

    To perform a complete sign-out, you must clear the session in both Firebase Authentication and the Android Credential Manager to prevent the user from being automatically signed back in via cached credentials.

    1. Call auth.signOut() to invalidate the Firebase session.
    2. Call credentialManager.clearCredentialState(ClearCredentialStateRequest()) to clear the local credential state.
    private fun signOut() {
        // Firebase sign out
        auth.signOut()
    
        // Clear current user credential state from all credential providers
        lifecycleScope.launch {
            try {
                val clearRequest = ClearCredentialStateRequest()
                credentialManager.clearCredentialState(clearRequest)
                updateUI(null)
            } catch (e: ClearCredentialException) {
                Log.e(TAG, "Couldn't clear user credentials: ${e.localizedMessage}")
            }
        }
    }
  2. Implement distributed counters in Firestore

    master

    To avoid contention when many clients update the same document simultaneously, use a distributed counter pattern. This involves creating a root counter document that holds the number of shards, and a subcollection of shards where each shard document holds a portion of the total count.

    1. Data Structure:

      • Root document: counters/${ID} containing numShards.
      • Shard documents: counters/${ID}/shards/${NUM} containing count.
    2. Operations:

      • Create: Initialize the root document and all shard documents with an initial count of 0.
      • Increment: Randomly select one shard from the subcollection and use FieldValue.increment(1) to update its count. This distributes the write load across multiple documents.
      • Get Count: Retrieve all shard documents in the subcollection and sum their count values locally.
    // Example usage pattern for distributed counters
    val db = FirebaseFirestore.getInstance()
    val counterRef = db.collection("counters").document("my_counter")
    val solution = SolutionCounters(db)
    
    // 1. Create the counter with 5 shards
    solution.createCounter(counterRef, 5)
        .addOnSuccessListener { /* Counter initialized */ }
    
    // 2. Increment the counter
    solution.incrementCounter(counterRef, 5)
    
    // 3. Get the total count
    solution.getCount(counterRef)
        .addOnSuccessListener { totalCount -> println("Total count: $totalCount") }
  3. Install a custom AppCheck provider factory

    master

    To use your custom provider, call installAppCheckProviderFactory() on the Firebase.appCheck instance during your application's initialization phase. This must be done before any other Firebase services attempt to use App Check.

    Firebase.initialize(context)
    Firebase.appCheck.installAppCheckProviderFactory(
        YourCustomAppCheckProviderFactory(),
    )
  4. Authenticate with Google using Firebase Auth and Credential Manager

    master

    To implement Google Sign-In in an Android app using Firebase, you combine the Android CredentialManager API with Firebase Authentication. The process involves three main steps:

    1. Configure a Google ID Option: Use GetGoogleIdOption.Builder to specify your server's client ID (not the Android client ID) and decide whether to filter by authorized accounts.
    2. Retrieve the Credential: Use CredentialManager.getCredential() to launch the system UI and retrieve a CustomCredential containing a Google ID token.
    3. Sign in to Firebase: Convert the retrieved credential into a GoogleAuthProvider credential using the ID token, then call auth.signInWithCredential(credential).

    Note: When signing out, you should call both auth.signOut() and credentialManager.clearCredentialState(ClearCredentialStateRequest()) to ensure the user is fully logged out from both Firebase and the system credential provider.

    // 1. Create the Google ID option
    val googleIdOption = GetGoogleIdOption.Builder()
        .setServerClientId(getString(R.string.default_web_client_id))
        .setFilterByAuthorizedAccounts(true)
        .build()
    
    // 2. Create the request
    val request = GetCredentialRequest.Builder()
        .addCredentialOption(googleIdOption)
        .build()
    
    // 3. Launch Credential Manager and handle result
    lifecycleScope.launch {
        try {
            val result = credentialManager.getCredential(baseContext, request)
            val credential = result.credential
            
            if (credential is CustomCredential && credential.type == TYPE_GOOGLE_ID_TOKEN_CREDENTIAL) {
                val googleIdTokenCredential = GoogleIdTokenCredential.createFrom(credential.data)
                val idToken = googleIdTokenCredential.idToken
                
                // 4. Sign in to Firebase
                val firebaseCredential = GoogleAuthProvider.getCredential(idToken, null)
                auth.signInWithCredential(firebaseCredential)
                    .addOnCompleteListener { task -> 
                        /* Handle success/failure */ 
                    }
            }
        } catch (e: GetCredentialException) {
            // Handle error
        }
    }
  5. Retrieve a limited-use App Check token

    master

    For specific use cases where you want to provide a token that is intended for a single use or a very short duration, use the limitedUseAppCheckToken property. This is useful for scenarios where you want to minimize the impact if a token is intercepted.

    Firebase.appCheck.limitedUseAppCheckToken.addOnSuccessListener {
        // Use the limited-use token here
    }
  6. Sign in with a custom token using FirebaseAuth

    master

    To authenticate a user using a custom token (minted by your backend server), use the signInWithCustomToken(token) method on a FirebaseAuth instance. This method returns a Task that you can monitor using addOnCompleteListener to handle successful authentication or failures.

    For detailed architectural guidance on how to mint these tokens, refer to the official documentation: https://firebase.google.com/docs/auth/android/custom-auth

    // Assuming 'auth' is an initialized FirebaseAuth instance and 'customToken' is your minted string
    customToken?.let {
        auth.signInWithCustomToken(it)
            .addOnCompleteListener(this) { task ->
                if (task.isSuccessful) {
                    // Sign in success
                    val user = auth.currentUser
                    updateUI(user)
                } else {
                    // Sign in failure
                    Log.w(TAG, "signInWithCustomToken:failure", task.exception)
                    Toast.makeText(baseContext, "Authentication failed.", Toast.LENGTH_SHORT).show()
                    updateUI(null)
                }
            }
    }
  7. Verify custom backend requests with App Check tokens

    master

    To protect your own backend services using Firebase App Check, you must retrieve an App Check token from the Firebase SDK and include it in your API requests. The standard way to do this is by adding the token to a custom HTTP header, typically named X-Firebase-AppCheck.

    1. Use Firebase.appCheck.getAppCheckToken(false) to retrieve the current token.
    2. Extract the token string using .token.
    3. Pass this string into your network client (e.g., Retrofit) via an HTTP header.
    // 1. Define your service with the App Check header
    interface YourExampleBackendService {
        @GET("yourExampleEndpoint")
        fun exampleData(
            @Header("X-Firebase-AppCheck") appCheckToken: String,
        ): Call<List<String>>
    }
    
    // 2. Retrieve the token and make the call
    Firebase.appCheck.getAppCheckToken(false).addOnSuccessListener {\<appCheckToken ->
        val token = appCheckToken.token
        val apiCall = yourExampleBackendService.exampleData(token)
        // ... execute call
    }
  8. Authenticate with Facebook using Firebase Auth

    master

    To authenticate a user with Facebook in an Android app using Firebase, you must first obtain a Facebook AccessToken using the Facebook SDK, then convert that token into a Firebase credential using FacebookAuthProvider.getCredential(). Finally, pass that credential to FirebaseAuth.signInWithCredential().

    Workflow

    1. Initialize Firebase Auth: Get an instance of FirebaseAuth via Firebase.auth.
    2. Handle Facebook Login: Use the Facebook SDK's LoginButton and CallbackManager to handle the login flow and retrieve an AccessToken.
    3. Convert to Firebase Credential: Use FacebookAuthProvider.getCredential(token.token) to create a credential from the Facebook token.
    4. Sign In: Call auth.signInWithCredential(credential) to complete the Firebase authentication process.
    // 1. Get the Facebook AccessToken from the Facebook SDK callback
    // 2. Create the Firebase credential
    val credential = FacebookAuthProvider.getCredential(token.token)
    
    // 3. Sign in to Firebase
    auth.signInWithCredential(credential)
        .addOnCompleteListener(this) { task ->
            if (task.isSuccessful) {
                val user = auth.currentUser
                // Sign in success
            } else {
                // Sign in failure
            }
        }
  9. Initialize FirebaseAuth and check current user status

    master

    To use Firebase Authentication in an Android Activity, initialize the FirebaseAuth instance using Firebase.auth. You can then check if a user is already signed in by accessing the currentUser property of the FirebaseAuth instance, typically within the onStart() lifecycle method.

    // Initialization
    auth = Firebase.auth
    
    // Checking current user status
    override fun onStart() {
        super.onStart()
        val currentUser = auth.currentUser
        updateUI(currentUser)
    }
  10. Call the 'recursiveDelete' Cloud Function to delete Firestore data

    master

    To perform a server-side recursive delete of a Firestore path, use the getHttpsCallable method from the Firebase Functions SDK to invoke the recursiveDelete function. Pass a HashMap containing the key "path" with the target Firestore path as its value. The operation is asynchronous and provides addOnSuccessListener and addOnFailureListener for handling the result.

    val deleteFn = Firebase.functions.getHttpsCallable("recursiveDelete")
    deleteFn.call(hashMapOf("path" to path))
        .addOnSuccessListener {
            // Delete Success
        }
        .addOnFailureListener {
            // Delete Failed
        }