<|start_filename|>auth/app/src/main/java/com/google/firebase/quickstart/auth/java/MultiFactorUnenrollFragment.java<|end_filename|>
package com.google.firebase.quickstart.auth.java;

import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.navigation.fragment.NavHostFragment;

import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.MultiFactorInfo;
import com.google.firebase.auth.PhoneMultiFactorInfo;
import com.google.firebase.quickstart.auth.databinding.FragmentMultiFactorSignInBinding;

import java.util.ArrayList;
import java.util.List;

public class MultiFactorUnenrollFragment extends BaseFragment {

    private FragmentMultiFactorSignInBinding mBinding;

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        mBinding = FragmentMultiFactorSignInBinding.inflate(inflater, container, false);
        return mBinding.getRoot();
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        mBinding.smsCode.setVisibility(View.GONE);
        mBinding.finishMfaSignIn.setVisibility(View.GONE);

        List<Button> phoneFactorButtonList = new ArrayList<>();
        phoneFactorButtonList.add(mBinding.phoneFactor1);
        phoneFactorButtonList.add(mBinding.phoneFactor2);
        phoneFactorButtonList.add(mBinding.phoneFactor3);
        phoneFactorButtonList.add(mBinding.phoneFactor4);
        phoneFactorButtonList.add(mBinding.phoneFactor5);

        for (Button button : phoneFactorButtonList) {
            button.setVisibility(View.GONE);
        }

        List<MultiFactorInfo> multiFactorInfoList =
                FirebaseAuth.getInstance().getCurrentUser().getMultiFactor().getEnrolledFactors();

        for (int i = 0; i < multiFactorInfoList.size(); ++i) {
            PhoneMultiFactorInfo phoneMultiFactorInfo = (PhoneMultiFactorInfo) multiFactorInfoList.get(i);
            Button button = phoneFactorButtonList.get(i);
            button.setVisibility(View.VISIBLE);
            button.setText(phoneMultiFactorInfo.getPhoneNumber());
            button.setClickable(true);
            button.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    FirebaseAuth.getInstance()
                            .getCurrentUser()
                            .getMultiFactor()
                            .unenroll(phoneMultiFactorInfo)
                            .addOnCompleteListener(
                                    new OnCompleteListener<Void>() {
                                        @Override
                                        public void onComplete(@NonNull Task<Void> task) {
                                            if (task.isSuccessful()) {
                                                Toast.makeText(getContext(),
                                                        "Successfully unenrolled!", Toast.LENGTH_SHORT).show();
                                                NavHostFragment.findNavController(MultiFactorUnenrollFragment.this)
                                                        .popBackStack();
                                            } else {
                                                Toast.makeText(getContext(),
                                                        "Unable to unenroll second factor. " + task.getException(), Toast.LENGTH_SHORT).show();
                                            }
                                        }
                                    });
                }
            });
        }
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        mBinding = null;
    }
}


<|start_filename|>firestore/app/src/main/java/com/google/firebase/example/fireeats/kotlin/MainActivity.kt<|end_filename|>
package com.google.firebase.example.fireeats.kotlin

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.navigation.Navigation
import com.google.firebase.example.fireeats.R

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        setSupportActionBar(findViewById(R.id.toolbar))
        Navigation.findNavController(this, R.id.nav_host_fragment)
            .setGraph(R.navigation.nav_graph_kotlin)
    }
}

<|start_filename|>database/app/src/main/java/com/google/firebase/quickstart/database/kotlin/models/Post.kt<|end_filename|>
package com.google.firebase.quickstart.database.kotlin.models

import com.google.firebase.database.Exclude
import com.google.firebase.database.IgnoreExtraProperties
import java.util.HashMap

@IgnoreExtraProperties
data class Post(
    var uid: String? = "",
    var author: String? = "",
    var title: String? = "",
    var body: String? = "",
    var starCount: Int = 0,
    var stars: MutableMap<String, Boolean> = HashMap()
) {

    @Exclude
    fun toMap(): Map<String, Any?> {
        return mapOf(
                "uid" to uid,
                "author" to author,
                "title" to title,
                "body" to body,
                "starCount" to starCount,
                "stars" to stars
        )
    }
}


<|start_filename|>auth/app/src/main/java/com/google/firebase/quickstart/auth/java/MultiFactorFragment.java<|end_filename|>
/**
 * Copyright 2016 Google Inc. All Rights Reserved.
 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.google.firebase.quickstart.auth.java;

import android.app.AlertDialog;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.navigation.fragment.NavHostFragment;

import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.FirebaseUser;
import com.google.firebase.auth.MultiFactorInfo;
import com.google.firebase.auth.PhoneMultiFactorInfo;
import com.google.firebase.quickstart.auth.R;
import com.google.firebase.quickstart.auth.databinding.FragmentMultiFactorBinding;

import java.util.List;

public class MultiFactorFragment extends BaseFragment {

    public static final String RESULT_NEEDS_MFA_SIGN_IN = "RESULT_NEEDS_MFA";

    private static final String TAG = "MultiFactor";

    private FragmentMultiFactorBinding mBinding;

    private FirebaseAuth mAuth;

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        mBinding = FragmentMultiFactorBinding.inflate(inflater, container, false);
        return mBinding.getRoot();
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        setProgressBar(mBinding.progressBar);

        Bundle args = getArguments();
        if (args != null && args.getBoolean(RESULT_NEEDS_MFA_SIGN_IN)) {
            NavHostFragment.findNavController(this)
                    .navigate(R.id.action_mfa_to_mfasignin, args);
        }

        // Buttons
        mBinding.emailSignInButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                NavHostFragment.findNavController(MultiFactorFragment.this)
                        .navigate(R.id.action_mfa_to_emailpassword);
            }
        });
        mBinding.signOutButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                signOut();
            }
        });
        mBinding.verifyEmailButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                sendEmailVerification();
            }
        });
        mBinding.enrollMfa.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                NavHostFragment.findNavController(MultiFactorFragment.this)
                        .navigate(R.id.action_mfa_to_enroll);
            }
        });
        mBinding.unenrollMfa.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                NavHostFragment.findNavController(MultiFactorFragment.this)
                        .navigate(R.id.action_mfa_to_unenroll);
            }
        });
        mBinding.reloadButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                reload();
            }
        });

        // Initialize Firebase Auth
        mAuth = FirebaseAuth.getInstance();

        showDisclaimer();
    }

    @Override
    public void onStart() {
        super.onStart();
        // Check if user is signed in (non-null) and update UI accordingly.
        FirebaseUser currentUser = mAuth.getCurrentUser();
        updateUI(currentUser);
    }

    private void signOut() {
        mAuth.signOut();
        updateUI(null);
    }

    private void sendEmailVerification() {
        // Disable button
        mBinding.verifyEmailButton.setEnabled(false);

        // Send verification email
        final FirebaseUser user = mAuth.getCurrentUser();
        user.sendEmailVerification()
                .addOnCompleteListener(requireActivity(), new OnCompleteListener<Void>() {
                    @Override
                    public void onComplete(@NonNull Task<Void> task) {
                        // Re-enable button
                        mBinding.verifyEmailButton.setEnabled(true);

                        if (task.isSuccessful()) {
                            Toast.makeText(getContext(),
                                    "Verification email sent to " + user.getEmail(),
                                    Toast.LENGTH_SHORT).show();
                        } else {
                            Log.e(TAG, "sendEmailVerification", task.getException());
                            Toast.makeText(getContext(),
                                    "Failed to send verification email.",
                                    Toast.LENGTH_SHORT).show();
                        }
                    }
                });
    }

    private void reload() {
        mAuth.getCurrentUser().reload().addOnCompleteListener(new OnCompleteListener<Void>() {
            @Override
            public void onComplete(@NonNull Task<Void> task) {
                if (task.isSuccessful()) {
                    updateUI(mAuth.getCurrentUser());
                    Toast.makeText(getContext(),
                            "Reload successful!",
                            Toast.LENGTH_SHORT).show();
                } else {
                    Log.e(TAG, "reload", task.getException());
                    Toast.makeText(getContext(),
                            "Failed to reload user.",
                            Toast.LENGTH_SHORT).show();
                }
            }
        });
    }

    private void updateUI(FirebaseUser user) {
        hideProgressBar();
        if (user != null) {
            mBinding.status.setText(getString(R.string.emailpassword_status_fmt,
                    user.getEmail(), user.isEmailVerified()));
            mBinding.detail.setText(getString(R.string.firebase_status_fmt, user.getUid()));

            List<MultiFactorInfo> secondFactors = user.getMultiFactor().getEnrolledFactors();

            if (secondFactors.isEmpty()) {
                mBinding.unenrollMfa.setVisibility(View.GONE);
            } else {
                mBinding.unenrollMfa.setVisibility(View.VISIBLE);

                StringBuilder sb = new StringBuilder("Second Factors: ");
                String delimiter = ", ";
                for (MultiFactorInfo x : secondFactors) {
                    sb.append(((PhoneMultiFactorInfo) x).getPhoneNumber() + delimiter);
                }
                sb.setLength(sb.length() - delimiter.length());
                mBinding.mfaInfo.setText(sb.toString());
            }

            mBinding.emailSignInButton.setVisibility(View.GONE);
            mBinding.signedInButtons.setVisibility(View.VISIBLE);

            int reloadVisibility = secondFactors.isEmpty() ? View.VISIBLE : View.GONE;
            mBinding.reloadButton.setVisibility(reloadVisibility);

            if (user.isEmailVerified()) {
                mBinding.verifyEmailButton.setVisibility(View.GONE);
                mBinding.enrollMfa.setVisibility(View.VISIBLE);
            } else {
                mBinding.verifyEmailButton.setVisibility(View.VISIBLE);
                mBinding.enrollMfa.setVisibility(View.GONE);
            }
        } else {
            mBinding.status.setText(R.string.multi_factor_signed_out);
            mBinding.detail.setText(null);
            mBinding.mfaInfo.setText(null);

            mBinding.emailSignInButton.setVisibility(View.VISIBLE);
            mBinding.signedInButtons.setVisibility(View.GONE);
        }
    }

    private void showDisclaimer() {
        new AlertDialog.Builder(getContext())
                .setTitle("Warning")
                .setMessage("Multi-factor authentication with SMS is currently only available for " +
                        "Google Cloud Identity Platform projects. For more information see: " +
                        "https://cloud.google.com/identity-platform/docs/android/mfa")
                .setPositiveButton("OK", null)
                .show();
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        mBinding = null;
    }
}


<|start_filename|>admob/app/src/main/java/com/google/samples/quickstart/admobexample/java/FirstFragment.java<|end_filename|>
package com.google.samples.quickstart.admobexample.java;

import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import androidx.fragment.app.Fragment;
import androidx.navigation.fragment.NavHostFragment;

import com.google.android.gms.ads.AdRequest;
import com.google.android.gms.ads.AdView;
import com.google.android.gms.ads.FullScreenContentCallback;
import com.google.android.gms.ads.LoadAdError;
import com.google.android.gms.ads.MobileAds;
import com.google.android.gms.ads.interstitial.InterstitialAd;
import com.google.android.gms.ads.interstitial.InterstitialAdLoadCallback;
import com.google.samples.quickstart.admobexample.R;
import com.google.samples.quickstart.admobexample.databinding.FragmentFirstBinding;

class FirstFragment extends Fragment {

    private static final String TAG = "MainActivity";
    private static final String TEST_APP_ID = "ca-app-pub-3940256099942544~3347511713";

    private AdView mAdView;
    private InterstitialAd mInterstitialAd;
    private Button mLoadInterstitialButton;
    private FragmentFirstBinding binding;

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        binding = FragmentFirstBinding.inflate(inflater, container, false);
        return binding.getRoot();
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        checkIds();

        // Initialize the Google Mobile Ads SDK
        MobileAds.initialize(getContext());

        mAdView = binding.adView;

        requestNewInterstitial();

        mLoadInterstitialButton = binding.loadInterstitialButton;
        mLoadInterstitialButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (mInterstitialAd != null) {
                    mInterstitialAd.show(getActivity());
                } else {
                    beginSecondActivity();
                }
            }
        });

        // Disable button if an interstitial ad is not loaded yet.
        mLoadInterstitialButton.setEnabled(mInterstitialAd != null);
    }

    /**
     * Load a new interstitial ad asynchronously.
     */
    private void requestNewInterstitial() {
        AdRequest adRequest = new AdRequest.Builder().build();
        mAdView.loadAd(adRequest);

        // AdMob ad unit IDs are not currently stored inside the google-services.json file.
        // Developers using AdMob can store them as custom values in a string resource file or
        // simply use constants. Note that the ad units used here are configured to return only test
        // ads, and should not be used outside this sample.
        InterstitialAd.load(getContext(), getString(R.string.interstitial_ad_unit_id), adRequest, new InterstitialAdLoadCallback() {
            @Override
            public void onAdLoaded(@NonNull InterstitialAd interstitialAd) {
                super.onAdLoaded(interstitialAd);
                mInterstitialAd = interstitialAd;

                // Ad received, ready to display
                if (mLoadInterstitialButton != null) {
                    mLoadInterstitialButton.setEnabled(true);
                }

                mInterstitialAd.setFullScreenContentCallback(new FullScreenContentCallback() {
                    @Override
                    public void onAdDismissedFullScreenContent() {
                        super.onAdDismissedFullScreenContent();
                        requestNewInterstitial();
                        beginSecondActivity();
                    }
                });
            }

            @Override
            public void onAdFailedToLoad(@NonNull LoadAdError loadAdError) {
                super.onAdFailedToLoad(loadAdError);
                mInterstitialAd = null;
                Log.w(TAG, "onAdFailedToLoad:" + loadAdError.getMessage());
            }
        });
    }

    private void beginSecondActivity() {
        NavHostFragment.findNavController(this).navigate(R.id.action_FirstFragment_to_SecondFragment);
    }

    /** Called when leaving the activity */
    @Override
    public void onPause() {
        if (mAdView != null) {
            mAdView.pause();
        }
        super.onPause();
    }

    /** Called when returning to the activity */
    @Override
    public void onResume() {
        super.onResume();
        if (mAdView != null) {
            mAdView.resume();
        }
        if (mInterstitialAd == null) {
            requestNewInterstitial();
        }
    }

    /** Called before the activity is destroyed */
    @Override
    public void onDestroy() {
        if (mAdView != null) {
            mAdView.destroy();
        }
        super.onDestroy();
    }

    @VisibleForTesting
    public AdView getAdView() {
        return mAdView;
    }

    private void checkIds() {
        if (TEST_APP_ID.equals(getString(R.string.admob_app_id))) {
            Log.w(TAG, "Your admob_app_id is not configured correctly, please see the README");
        }
    }
}


<|start_filename|>database/app/src/main/java/com/google/firebase/quickstart/database/java/BaseFragment.java<|end_filename|>
package com.google.firebase.quickstart.database.java;

import android.view.View;
import android.widget.ProgressBar;

import androidx.fragment.app.Fragment;

import com.google.firebase.auth.FirebaseAuth;

public class BaseFragment extends Fragment {
    private ProgressBar mProgressBar;

    public void setProgressBar(int resId) {
        mProgressBar = getView().findViewById(resId);
    }

    public void showProgressBar() {
        if (mProgressBar != null) {
            mProgressBar.setVisibility(View.VISIBLE);
        }
    }

    public void hideProgressBar() {
        if (mProgressBar != null) {
            mProgressBar.setVisibility(View.INVISIBLE);
        }
    }

    public String getUid() {
        return FirebaseAuth.getInstance().getCurrentUser().getUid();
    }
}


<|start_filename|>auth/app/src/main/java/com/google/firebase/quickstart/auth/java/MainActivity.java<|end_filename|>
package com.google.firebase.quickstart.auth.java;

import android.os.Bundle;

import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.navigation.Navigation;

import com.google.firebase.quickstart.auth.R;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Navigation.findNavController(this, R.id.nav_host_fragment)
                .setGraph(R.navigation.nav_graph_java);
    }
}


<|start_filename|>crash/app/src/main/java/com/google/samples/quickstart/crash/kotlin/CustomKeySamples.kt<|end_filename|>
package com.google.samples.quickstart.crash.kotlin

import android.Manifest
import android.annotation.SuppressLint
import android.content.Context
import android.content.pm.PackageManager
import android.net.ConnectivityManager
import android.net.ConnectivityManager.NetworkCallback
import android.net.Network
import android.net.NetworkCapabilities
import android.os.Build
import android.telephony.TelephonyManager
import android.view.View
import androidx.core.content.ContextCompat
import com.google.android.gms.common.GoogleApiAvailability
import com.google.firebase.crashlytics.ktx.crashlytics
import com.google.firebase.crashlytics.ktx.setCustomKeys
import com.google.firebase.ktx.Firebase
import kotlinx.coroutines.internal.synchronized

/**
 * The following are samples of custom keys that may be useful to record via Crashlytics prior to a Crash.
 *
 * These utility methods are not meant to be comprehensive, but they are illustrative of the types of things you
 * could track using custom keys in Crashlytics.
 */
class CustomKeySamples(private val context: Context, private var callback: NetworkCallback? = null) {

    /**
     * Set a subset of custom keys simultaneously.
     */
    fun setSampleCustomKeys() {
        Firebase.crashlytics.setCustomKeys {
            key("Locale", locale)
            key("Screen Density", density)
            key("Google Play Services Availability", googlePlayServicesAvailability)
            key("Os Version", osVersion)
            key("Install Source", installSource)
            key("Preferred ABI", preferredAbi)
        }
    }

    /**
     * Update network state and add a hook to update network state going forward.
     *
     * Note: This code is executed above API level N.
     */
    fun updateAndTrackNetworkState() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
            connectivityManager
                    .getNetworkCapabilities(connectivityManager.activeNetwork)
                    ?.let { updateNetworkCapabilityCustomKeys(it) }

            kotlin.synchronized(this) {
                if (callback == null) {
                    // Set up a callback to match our best-practices around custom keys being up-to-date
                    val newCallback: NetworkCallback = object : NetworkCallback() {
                        override fun onCapabilitiesChanged(network: Network, networkCapabilities: NetworkCapabilities) {
                            updateNetworkCapabilityCustomKeys(networkCapabilities)
                        }
                    }
                    callback = newCallback
                    connectivityManager.registerDefaultNetworkCallback(newCallback)
                }
            }
        }
    }

    /**
     * Remove the handler for the network state.
     *
     * Note: This code is executed above API level N.
     */
    fun stopTrackingNetworkState() {
        val connectivityManager = context
                .getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
        val oldCallback = callback
        kotlin.synchronized(this) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && oldCallback != null) {
                connectivityManager.unregisterNetworkCallback(oldCallback)
                callback = null
            }
        }
    }

    private fun updateNetworkCapabilityCustomKeys(networkCapabilities: NetworkCapabilities) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            Firebase.crashlytics.setCustomKeys {
                key("Network Bandwidth", networkCapabilities.linkDownstreamBandwidthKbps)
                key("Network Upstream", networkCapabilities.linkUpstreamBandwidthKbps)
                key("Network Metered", networkCapabilities
                        .hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED))
                // This key is long and not as easy to filter by.
                key("Network Capabilities", networkCapabilities.toString())
            }
        }
    }

    /**
     * @see {@link com.google.samples.quickstart.crash.java.CustomKeySamples.updateAndTrackNetworkState}, which does not require READ_PHONE_STATE
     * and returns more useful information about bandwidth, metering, and capabilities.
     *
     * Supressed deprecation warning because that code path is only used below API Level N.
     *
     * Supressed Lint warning because READ_PHONE_STATE is a high priority permission and
     * we don't want to enforce needing it for this code example.
     */
    @Suppress("DEPRECATION")
    @Deprecated("Prefer updateAndTrackNetworkState, which does not require READ_PHONE_STATE")
    @SuppressLint("MissingPermission")
    fun addPhoneStateRequiredNetworkKeys() {
        val telephonyManager = context
                .getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
        if (ContextCompat.checkSelfPermission(context, Manifest.permission.READ_PHONE_STATE)
                != PackageManager.PERMISSION_GRANTED) {
            return
        }

        val networkType: Int = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            telephonyManager.dataNetworkType
        } else {
            telephonyManager.networkType
        }

        Firebase.crashlytics.setCustomKeys {
            key("Network Type", networkType)
            key("Sim Operator", telephonyManager.simOperator)
        }
    }

    /**
     * Retrieve the locale information for the app.
     *
     * Supressed deprecation warning because that code path is only used below API Level N.
     */
    @Suppress("DEPRECATION")
    val locale: String
        get() = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            context
                    .resources
                    .configuration
                    .locales[0].toString()
        } else {
            context
                    .resources
                    .configuration.locale.toString()
        }

    /**
     * Retrieve the screen density information for the app.
     */
    val density: Float
        get() = context
                .resources
                .displayMetrics.density

    /**
     * Retrieve the locale information for the app.
     */
    val googlePlayServicesAvailability: String
        get() = if (GoogleApiAvailability
                        .getInstance()
                        .isGooglePlayServicesAvailable(context) == 0) "Unavailable" else "Available"

    /**
     * Return the underlying kernel version of the Android device.
     */
    val osVersion: String
        get() = System.getProperty("os.version") ?: "Unknown"

    /**
     * Retrieve the preferred ABI of the device. Some devices can support
     * multiple ABIs and the first one returned in the preferred one.
     *
     * Supressed deprecation warning because that code path is only used below Lollipop.
     */
    @Suppress("DEPRECATION")
    val preferredAbi: String
        get() = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            Build.SUPPORTED_ABIS[0]
        } else Build.CPU_ABI

    /**
     * Retrieve the install source and return it as a string.
     *
     * Supressed deprecation warning because that code path is only used below API level R.
     */
    @Suppress("DEPRECATION")
    val installSource: String
        get() = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
            try {
                val info = context
                        .packageManager
                        .getInstallSourceInfo(context.packageName)

                // This returns all three of the install source, originating source, and initiating
                // source.
                "Originating: ${info.originatingPackageName ?: "None"}, " +
                        "Installing: ${info.installingPackageName ?: "None"}, " +
                        "Initiating: ${info.initiatingPackageName ?: "None"}"
            } catch (e: PackageManager.NameNotFoundException) {
                "Unknown"
            }
        } else {
            context.packageManager.getInstallerPackageName(context.packageName) ?: "None"
        }

    /**
     * Add a focus listener that updates a custom key when this view gains the focus.
     */
    fun focusListener(view: View, hasFocus: Boolean) {
        if (hasFocus) {
            Firebase.crashlytics.setCustomKey("view_focus", view.id)
        }
    }
}


<|start_filename|>firestore/app/src/main/java/com/google/firebase/example/fireeats/kotlin/MainFragment.kt<|end_filename|>
package com.google.firebase.example.fireeats.kotlin

import android.app.Activity
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.Menu
import android.view.MenuInflater
import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
import androidx.annotation.StringRes
import androidx.appcompat.app.AlertDialog
import androidx.core.text.HtmlCompat
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider
import androidx.navigation.fragment.findNavController
import androidx.recyclerview.widget.LinearLayoutManager
import com.firebase.ui.auth.AuthUI
import com.firebase.ui.auth.ErrorCodes
import com.firebase.ui.auth.FirebaseAuthUIActivityResultContract
import com.firebase.ui.auth.data.model.FirebaseAuthUIAuthenticationResult
import com.google.android.material.snackbar.Snackbar
import com.google.firebase.auth.ktx.auth
import com.google.firebase.example.fireeats.R
import com.google.firebase.example.fireeats.databinding.FragmentMainBinding
import com.google.firebase.example.fireeats.kotlin.adapter.RestaurantAdapter
import com.google.firebase.example.fireeats.kotlin.model.Restaurant
import com.google.firebase.example.fireeats.kotlin.util.RatingUtil
import com.google.firebase.example.fireeats.kotlin.util.RestaurantUtil
import com.google.firebase.example.fireeats.kotlin.viewmodel.MainActivityViewModel
import com.google.firebase.firestore.DocumentSnapshot
import com.google.firebase.firestore.FirebaseFirestore
import com.google.firebase.firestore.FirebaseFirestoreException
import com.google.firebase.firestore.Query
import com.google.firebase.firestore.ktx.firestore
import com.google.firebase.ktx.Firebase

class MainFragment : Fragment(),
        FilterDialogFragment.FilterListener,
        RestaurantAdapter.OnRestaurantSelectedListener {

    lateinit var firestore: FirebaseFirestore
    lateinit var query: Query

    private lateinit var binding: FragmentMainBinding
    private lateinit var filterDialog: FilterDialogFragment
    lateinit var adapter: RestaurantAdapter

    private lateinit var viewModel: MainActivityViewModel

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        setHasOptionsMenu(true)
        binding = FragmentMainBinding.inflate(inflater, container, false);
        return binding.root;
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        // View model
        viewModel = ViewModelProvider(this).get(MainActivityViewModel::class.java)

        // Enable Firestore logging
        FirebaseFirestore.setLoggingEnabled(true)

        // Firestore
        firestore = Firebase.firestore

        // Get ${LIMIT} restaurants
        query = firestore.collection("restaurants")
                .orderBy("avgRating", Query.Direction.DESCENDING)
                .limit(LIMIT.toLong())

        // RecyclerView
        adapter = object : RestaurantAdapter(query, this@MainFragment) {
            override fun onDataChanged() {
                // Show/hide content if the query returns empty.
                if (itemCount == 0) {
                    binding.recyclerRestaurants.visibility = View.GONE
                    binding.viewEmpty.visibility = View.VISIBLE
                } else {
                    binding.recyclerRestaurants.visibility = View.VISIBLE
                    binding.viewEmpty.visibility = View.GONE
                }
            }

            override fun onError(e: FirebaseFirestoreException) {
                // Show a snackbar on errors
                Snackbar.make(binding.root,
                        "Error: check logs for info.", Snackbar.LENGTH_LONG).show()
            }
        }

        binding.recyclerRestaurants.layoutManager = LinearLayoutManager(context)
        binding.recyclerRestaurants.adapter = adapter

        // Filter Dialog
        filterDialog = FilterDialogFragment()

        binding.filterBar.setOnClickListener { onFilterClicked() }
        binding.buttonClearFilter.setOnClickListener { onClearFilterClicked() }
    }

    public override fun onStart() {
        super.onStart()

        // Start sign in if necessary
        if (shouldStartSignIn()) {
            startSignIn()
            return
        }

        // Apply filters
        onFilter(viewModel.filters)

        // Start listening for Firestore updates
        adapter.startListening()
    }

    public override fun onStop() {
        super.onStop()
        adapter.stopListening()
    }

    override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
        inflater.inflate(R.menu.menu_main, menu)
        return super.onCreateOptionsMenu(menu, inflater)
    }

    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        when (item.itemId) {
            R.id.menu_add_items -> onAddItemsClicked()
            R.id.menu_sign_out -> {
                AuthUI.getInstance().signOut(requireContext())
                startSignIn()
            }
        }
        return super.onOptionsItemSelected(item)
    }

    private fun onSignInResult(result: FirebaseAuthUIAuthenticationResult) {
        val response = result.idpResponse
        viewModel.isSigningIn = false

        if (result.resultCode != Activity.RESULT_OK) {
            if (response == null) {
                // User pressed the back button.
                requireActivity().finish()
            } else if (response.error != null && response.error!!.errorCode == ErrorCodes.NO_NETWORK) {
                showSignInErrorDialog(R.string.message_no_network)
            } else {
                showSignInErrorDialog(R.string.message_unknown)
            }
        }
    }

    private fun onFilterClicked() {
        // Show the dialog containing filter options
        filterDialog.show(childFragmentManager, FilterDialogFragment.TAG)
    }

    private fun onClearFilterClicked() {
        filterDialog.resetFilters()

        onFilter(Filters.default)
    }

    override fun onRestaurantSelected(restaurant: DocumentSnapshot) {
        // Go to the details page for the selected restaurant
        val action = MainFragmentDirections
            .actionMainFragmentToRestaurantDetailFragment(restaurant.id)

        findNavController().navigate(action)
    }

    override fun onFilter(filters: Filters) {
        // Construct query basic query
        var query: Query = firestore.collection("restaurants")

        // Category (equality filter)
        if (filters.hasCategory()) {
            query = query.whereEqualTo(Restaurant.FIELD_CATEGORY, filters.category)
        }

        // City (equality filter)
        if (filters.hasCity()) {
            query = query.whereEqualTo(Restaurant.FIELD_CITY, filters.city)
        }

        // Price (equality filter)
        if (filters.hasPrice()) {
            query = query.whereEqualTo(Restaurant.FIELD_PRICE, filters.price)
        }

        // Sort by (orderBy with direction)
        if (filters.hasSortBy()) {
            query = query.orderBy(filters.sortBy.toString(), filters.sortDirection)
        }

        // Limit items
        query = query.limit(LIMIT.toLong())

        // Update the query
        adapter.setQuery(query)

        // Set header
        binding.textCurrentSearch.text = HtmlCompat.fromHtml(filters.getSearchDescription(requireContext()),
                HtmlCompat.FROM_HTML_MODE_LEGACY)
        binding.textCurrentSortBy.text = filters.getOrderDescription(requireContext())

        // Save filters
        viewModel.filters = filters
    }

    private fun shouldStartSignIn(): Boolean {
        return !viewModel.isSigningIn && Firebase.auth.currentUser == null
    }

    private fun startSignIn() {
        // Sign in with FirebaseUI
        val signInLauncher = requireActivity().registerForActivityResult(
            FirebaseAuthUIActivityResultContract()
        ) { result -> this.onSignInResult(result)}

        val intent = AuthUI.getInstance().createSignInIntentBuilder()
                .setAvailableProviders(listOf(AuthUI.IdpConfig.EmailBuilder().build()))
                .setIsSmartLockEnabled(false)
                .build()

        signInLauncher.launch(intent)
        viewModel.isSigningIn = true
    }

    private fun onAddItemsClicked() {
        // Add a bunch of random restaurants
        val batch = firestore.batch()
        for (i in 0..9) {
            val restRef = firestore.collection("restaurants").document()

            // Create random restaurant / ratings
            val randomRestaurant = RestaurantUtil.getRandom(requireContext())
            val randomRatings = RatingUtil.getRandomList(randomRestaurant.numRatings)
            randomRestaurant.avgRating = RatingUtil.getAverageRating(randomRatings)

            // Add restaurant
            batch.set(restRef, randomRestaurant)

            // Add ratings to subcollection
            for (rating in randomRatings) {
                batch.set(restRef.collection("ratings").document(), rating)
            }
        }

        batch.commit().addOnCompleteListener { task ->
            if (task.isSuccessful) {
                Log.d(TAG, "Write batch succeeded.")
            } else {
                Log.w(TAG, "write batch failed.", task.exception)
            }
        }
    }

    private fun showSignInErrorDialog(@StringRes message: Int) {
        val dialog = AlertDialog.Builder(requireContext())
                .setTitle(R.string.title_sign_in_error)
                .setMessage(message)
                .setCancelable(false)
                .setPositiveButton(R.string.option_retry) { _, _ -> startSignIn() }
                .setNegativeButton(R.string.option_exit) { _, _ -> requireActivity().finish() }.create()

        dialog.show()
    }

    companion object {

        private const val TAG = "MainActivity"

        private const val LIMIT = 50
    }
}


<|start_filename|>database/app/src/main/java/com/google/firebase/quickstart/database/java/SignInFragment.java<|end_filename|>
package com.google.firebase.quickstart.database.java;

import android.content.Intent;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.navigation.Navigation;
import androidx.navigation.fragment.NavHostFragment;

import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.auth.AuthResult;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.FirebaseUser;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.quickstart.database.R;
import com.google.firebase.quickstart.database.databinding.FragmentSignInBinding;
import com.google.firebase.quickstart.database.java.models.User;

public class SignInFragment extends BaseFragment implements View.OnClickListener {

    private static final String TAG = "SignInFragment";

    private DatabaseReference mDatabase;
    private FirebaseAuth mAuth;

    private FragmentSignInBinding binding;

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        binding = FragmentSignInBinding.inflate(inflater, container, false);
        return binding.getRoot();
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        mDatabase = FirebaseDatabase.getInstance().getReference();
        mAuth = FirebaseAuth.getInstance();

        // Views
        setProgressBar(R.id.progressBar);

        // Click listeners
        binding.buttonSignIn.setOnClickListener(this);
        binding.buttonSignUp.setOnClickListener(this);
    }

    @Override
    public void onStart() {
        super.onStart();

        // Check auth on Activity start
        if (mAuth.getCurrentUser() != null) {
            onAuthSuccess(mAuth.getCurrentUser());
        }
    }

    private void signIn() {
        Log.d(TAG, "signIn");
        if (!validateForm()) {
            return;
        }

        showProgressBar();
        String email = binding.fieldEmail.getText().toString();
        String password = binding.fieldPassword.getText().toString();

        mAuth.signInWithEmailAndPassword(email, password)
                .addOnCompleteListener(getActivity(), new OnCompleteListener<AuthResult>() {
                    @Override
                    public void onComplete(@NonNull Task<AuthResult> task) {
                        Log.d(TAG, "signIn:onComplete:" + task.isSuccessful());
                        hideProgressBar();

                        if (task.isSuccessful()) {
                            onAuthSuccess(task.getResult().getUser());
                        } else {
                            Toast.makeText(getContext(), "Sign In Failed",
                                    Toast.LENGTH_SHORT).show();
                        }
                    }
                });
    }

    private void signUp() {
        Log.d(TAG, "signUp");
        if (!validateForm()) {
            return;
        }

        showProgressBar();
        String email = binding.fieldEmail.getText().toString();
        String password = <PASSWORD>.getText().toString();

        mAuth.createUserWithEmailAndPassword(email, password)
                .addOnCompleteListener(getActivity(), new OnCompleteListener<AuthResult>() {
                    @Override
                    public void onComplete(@NonNull Task<AuthResult> task) {
                        Log.d(TAG, "createUser:onComplete:" + task.isSuccessful());
                        hideProgressBar();

                        if (task.isSuccessful()) {
                            onAuthSuccess(task.getResult().getUser());
                        } else {
                            Toast.makeText(getContext(), "Sign Up Failed",
                                    Toast.LENGTH_SHORT).show();
                        }
                    }
                });
    }

    private void onAuthSuccess(FirebaseUser user) {
        String username = usernameFromEmail(user.getEmail());

        // Write new user
        writeNewUser(user.getUid(), username, user.getEmail());

        // Go to MainFragment
        NavHostFragment.findNavController(this).navigate(R.id.action_SignInFragment_to_MainFragment);
    }

    private String usernameFromEmail(String email) {
        if (email.contains("@")) {
            return email.split("@")[0];
        } else {
            return email;
        }
    }

    private boolean validateForm() {
        boolean result = true;
        if (TextUtils.isEmpty(binding.fieldEmail.getText().toString())) {
            binding.fieldEmail.setError("Required");
            result = false;
        } else {
            binding.fieldEmail.setError(null);
        }

        if (TextUtils.isEmpty(binding.fieldPassword.getText().toString())) {
            binding.fieldPassword.setError("Required");
            result = false;
        } else {
            binding.fieldPassword.setError(null);
        }

        return result;
    }

    private void writeNewUser(String userId, String name, String email) {
        User user = new User(name, email);

        mDatabase.child("users").child(userId).setValue(user);
    }

    public void onClick(View v) {
        int i = v.getId();
        if (i == R.id.buttonSignIn) {
            signIn();
        } else if (i == R.id.buttonSignUp) {
            signUp();
        }
    }
}


<|start_filename|>auth/app/src/main/java/com/google/firebase/quickstart/auth/java/PasswordlessActivity.java<|end_filename|>
package com.google.firebase.quickstart.auth.java;

import android.content.Intent;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.android.material.snackbar.Snackbar;
import com.google.firebase.auth.ActionCodeSettings;
import com.google.firebase.auth.AuthResult;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.FirebaseAuthActionCodeException;
import com.google.firebase.auth.FirebaseAuthInvalidCredentialsException;
import com.google.firebase.auth.FirebaseUser;
import com.google.firebase.quickstart.auth.R;
import com.google.firebase.quickstart.auth.databinding.ActivityPasswordlessBinding;

/**
 * Demonstrate Firebase Authentication without a password, using a link sent to an
 * email address.
 */
public class PasswordlessActivity extends BaseActivity implements View.OnClickListener {

    private static final String TAG = "PasswordlessSignIn";
    private static final String KEY_PENDING_EMAIL = "key_pending_email";

    private FirebaseAuth mAuth;

    private ActivityPasswordlessBinding mBinding;

    private String mPendingEmail;
    private String mEmailLink;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mBinding = ActivityPasswordlessBinding.inflate(getLayoutInflater());
        setContentView(mBinding.getRoot());
        setProgressBar(mBinding.progressBar);

        // Initialize Firebase Auth
        mAuth = FirebaseAuth.getInstance();

        mBinding.passwordlessSendEmailButton.setOnClickListener(this);
        mBinding.passwordlessSignInButton.setOnClickListener(this);
        mBinding.signOutButton.setOnClickListener(this);

        // Restore the "pending" email address
        if (savedInstanceState != null) {
            mPendingEmail = savedInstanceState.getString(KEY_PENDING_EMAIL, null);
            mBinding.fieldEmail.setText(mPendingEmail);
        }

        // Check if the Intent that started the Activity contains an email sign-in link.
        checkIntent(getIntent());
    }

    @Override
    protected void onStart() {
        super.onStart();
        updateUI(mAuth.getCurrentUser());
    }

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        checkIntent(intent);
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putString(KEY_PENDING_EMAIL, mPendingEmail);
    }

    /**
     * Check to see if the Intent has an email link, and if so set up the UI accordingly.
     * This can be called from either onCreate or onNewIntent, depending on how the Activity
     * was launched.
     */
    private void checkIntent(@Nullable Intent intent) {
        if (intentHasEmailLink(intent)) {
            mEmailLink = intent.getData().toString();

            mBinding.status.setText(R.string.status_link_found);
            mBinding.passwordlessSendEmailButton.setEnabled(false);
            mBinding.passwordlessSignInButton.setEnabled(true);
        } else {
            mBinding.status.setText(R.string.status_email_not_sent);
            mBinding.passwordlessSendEmailButton.setEnabled(true);
            mBinding.passwordlessSignInButton.setEnabled(false);
        }
    }

    /**
     * Determine if the given Intent contains an email sign-in link.
     */
    private boolean intentHasEmailLink(@Nullable Intent intent) {
        if (intent != null && intent.getData() != null) {
            String intentData = intent.getData().toString();
            if (mAuth.isSignInWithEmailLink(intentData)) {
                return true;
            }
        }

        return false;
    }

    /**
     * Send an email sign-in link to the specified email.
     */
    private void sendSignInLink(String email) {
        ActionCodeSettings settings = ActionCodeSettings.newBuilder()
                .setAndroidPackageName(
                        getPackageName(),
                        false, /* install if not available? */
                        null   /* minimum app version */)
                .setHandleCodeInApp(true)
                .setUrl("https://auth.example.com/emailSignInLink")
                .build();

        hideKeyboard(mBinding.fieldEmail);
        showProgressBar();

        mAuth.sendSignInLinkToEmail(email, settings)
                .addOnCompleteListener(new OnCompleteListener<Void>() {
                    @Override
                    public void onComplete(@NonNull Task<Void> task) {
                        hideProgressBar();

                        if (task.isSuccessful()) {
                            Log.d(TAG, "Link sent");
                            showSnackbar("Sign-in link sent!");

                            mPendingEmail = email;
                            mBinding.status.setText(R.string.status_email_sent);
                        } else {
                            Exception e = task.getException();
                            Log.w(TAG, "Could not send link", e);
                            showSnackbar("Failed to send link.");

                            if (e instanceof FirebaseAuthInvalidCredentialsException) {
                                mBinding.fieldEmail.setError("Invalid email address.");
                            }
                        }
                    }
                });
    }

    /**
     * Sign in using an email address and a link, the link is passed to the Activity
     * from the dynamic link contained in the email.
     */
    private void signInWithEmailLink(String email, String link) {
        Log.d(TAG, "signInWithLink:" + link);

        hideKeyboard(mBinding.fieldEmail);
        showProgressBar();

        mAuth.signInWithEmailLink(email, link)
                .addOnCompleteListener(new OnCompleteListener<AuthResult>() {
                    @Override
                    public void onComplete(@NonNull Task<AuthResult> task) {
                        hideProgressBar();
                        mPendingEmail = null;

                        if (task.isSuccessful()) {
                            Log.d(TAG, "signInWithEmailLink:success");

                            mBinding.fieldEmail.setText(null);
                            updateUI(task.getResult().getUser());
                        } else {
                            Log.w(TAG, "signInWithEmailLink:failure", task.getException());
                            updateUI(null);

                            if (task.getException() instanceof FirebaseAuthActionCodeException) {
                                showSnackbar("Invalid or expired sign-in link.");
                            }
                        }
                    }
                });
    }

    private void onSendLinkClicked() {
        String email = mBinding.fieldEmail.getText().toString();
        if (TextUtils.isEmpty(email)) {
            mBinding.fieldEmail.setError("Email must not be empty.");
            return;
        }

        sendSignInLink(email);
    }

    private void onSignInClicked() {
        String email = mBinding.fieldEmail.getText().toString();
        if (TextUtils.isEmpty(email)) {
            mBinding.fieldEmail.setError("Email must not be empty.");
            return;
        }

        signInWithEmailLink(email, mEmailLink);
    }

    private void onSignOutClicked() {
        mAuth.signOut();

        updateUI(null);
        mBinding.status.setText(R.string.status_email_not_sent);
    }

    private void updateUI(@Nullable FirebaseUser user) {
        if (user != null) {
            mBinding.status.setText(getString(R.string.passwordless_status_fmt,
                    user.getEmail(), user.isEmailVerified()));

            mBinding.fieldEmail.setVisibility(View.GONE);
            mBinding.passwordlessButtons.setVisibility(View.GONE);
            mBinding.signOutButton.setVisibility(View.VISIBLE);
        } else {
            mBinding.fieldEmail.setVisibility(View.VISIBLE);
            mBinding.passwordlessButtons.setVisibility(View.VISIBLE);
            mBinding.signOutButton.setVisibility(View.GONE);
        }
    }

    private void showSnackbar(String message) {
        Snackbar.make(findViewById(android.R.id.content), message, Snackbar.LENGTH_SHORT).show();
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.passwordlessSendEmailButton:
                onSendLinkClicked();
                break;
            case R.id.passwordlessSignInButton:
                onSignInClicked();
                break;
            case R.id.signOutButton:
                onSignOutClicked();
                break;
        }
    }
}


<|start_filename|>auth/app/src/main/java/com/google/firebase/quickstart/auth/kotlin/MultiFactorUnenrollFragment.kt<|end_filename|>
package com.google.firebase.quickstart.auth.kotlin

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.navigation.fragment.findNavController
import com.google.firebase.auth.FirebaseAuth
import com.google.firebase.auth.PhoneMultiFactorInfo
import com.google.firebase.auth.ktx.auth
import com.google.firebase.ktx.Firebase
import com.google.firebase.quickstart.auth.databinding.FragmentMultiFactorSignInBinding

class MultiFactorUnenrollFragment : BaseFragment() {

    private var _binding: FragmentMultiFactorSignInBinding? = null
    private val binding: FragmentMultiFactorSignInBinding
        get() = _binding!!

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        _binding = FragmentMultiFactorSignInBinding.inflate(inflater, container, false)
        return binding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        binding.smsCode.visibility = View.GONE
        binding.finishMfaSignIn.visibility = View.GONE

        // Users are currently limited to having 5 second factors
        val phoneFactorButtonList = listOf(
                binding.phoneFactor1, binding.phoneFactor2, binding.phoneFactor3,
                binding.phoneFactor4, binding.phoneFactor5)
        for (button in phoneFactorButtonList) {
            button.visibility = View.GONE
        }

        val multiFactorInfoList = FirebaseAuth.getInstance().currentUser!!.multiFactor.enrolledFactors
        for (i in multiFactorInfoList.indices) {
            val phoneMultiFactorInfo = multiFactorInfoList[i] as PhoneMultiFactorInfo
            val button = phoneFactorButtonList[i]
            button.visibility = View.VISIBLE
            button.text = phoneMultiFactorInfo.phoneNumber
            button.isClickable = true
            button.setOnClickListener {
                Firebase.auth
                        .currentUser!!
                        .multiFactor
                        .unenroll(phoneMultiFactorInfo)
                        .addOnCompleteListener { task ->
                            if (task.isSuccessful) {
                                Toast.makeText(context,
                                        "Successfully unenrolled!", Toast.LENGTH_SHORT).show()
                                findNavController().popBackStack()
                            } else {
                                Toast.makeText(context,
                                        "Unable to unenroll second factor. ${task.exception}",
                                        Toast.LENGTH_SHORT)
                                        .show()
                            }
                        }
            }
        }
    }

    override fun onDestroyView() {
        super.onDestroyView()
        _binding = null
    }
}


<|start_filename|>auth/app/src/main/java/com/google/firebase/quickstart/auth/java/MultiFactorSignInFragment.java<|end_filename|>
package com.google.firebase.quickstart.auth.java;

import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.navigation.fragment.NavHostFragment;

import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.firebase.FirebaseException;
import com.google.firebase.auth.AuthResult;
import com.google.firebase.auth.MultiFactorInfo;
import com.google.firebase.auth.MultiFactorResolver;
import com.google.firebase.auth.PhoneAuthCredential;
import com.google.firebase.auth.PhoneAuthOptions;
import com.google.firebase.auth.PhoneAuthProvider;
import com.google.firebase.auth.PhoneMultiFactorGenerator;
import com.google.firebase.auth.PhoneMultiFactorInfo;
import com.google.firebase.quickstart.auth.databinding.FragmentMultiFactorSignInBinding;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

import static android.text.TextUtils.isEmpty;

/**
 * Fragment that handles MFA sign-in
 */
public class MultiFactorSignInFragment extends BaseFragment {

    private static final String KEY_VERIFICATION_ID = "key_verification_id";
    public static final String EXTRA_MFA_RESOLVER = "EXTRA_MFA_RESOLVER";

    private FragmentMultiFactorSignInBinding mBinding;

    private MultiFactorResolver mMultiFactorResolver;
    private PhoneAuthCredential mPhoneAuthCredential;
    private String mVerificationId;

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        mBinding = FragmentMultiFactorSignInBinding.inflate(inflater, container, false);
        return mBinding.getRoot();
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        if (savedInstanceState != null) {
            onViewStateRestored(savedInstanceState);
        }

        List<Button> phoneFactorButtonList = new ArrayList<>();
        phoneFactorButtonList.add(mBinding.phoneFactor1);
        phoneFactorButtonList.add(mBinding.phoneFactor2);
        phoneFactorButtonList.add(mBinding.phoneFactor3);
        phoneFactorButtonList.add(mBinding.phoneFactor4);
        phoneFactorButtonList.add(mBinding.phoneFactor5);

        for (Button button : phoneFactorButtonList) {
            button.setVisibility(View.GONE);
        }

        mBinding.finishMfaSignIn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                onClickFinishSignIn();
            }
        });

        mMultiFactorResolver = getResolverFromArguments(requireArguments());
        List<MultiFactorInfo> multiFactorInfoList = mMultiFactorResolver.getHints();

        for (int i = 0; i < multiFactorInfoList.size(); ++i) {
            PhoneMultiFactorInfo phoneMultiFactorInfo = (PhoneMultiFactorInfo) multiFactorInfoList.get(i);
            Button button = phoneFactorButtonList.get(i);
            button.setVisibility(View.VISIBLE);
            button.setText(phoneMultiFactorInfo.getPhoneNumber());
            button.setClickable(true);
            button.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    PhoneAuthProvider.verifyPhoneNumber(
                            PhoneAuthOptions.newBuilder()
                                    .setActivity(requireActivity())
                                    .setMultiFactorSession(mMultiFactorResolver.getSession())
                                    .setMultiFactorHint(phoneMultiFactorInfo)
                                    .setCallbacks(generateCallbacks())
                                    // A timeout of 0 disables SMS-auto-retrieval.
                                    .setTimeout(0L, TimeUnit.SECONDS)
                                    .build());
                }
            });
        }
    }

    @Override
    public void onSaveInstanceState(Bundle bundle) {
        super.onSaveInstanceState(bundle);
        bundle.putString(KEY_VERIFICATION_ID, mVerificationId);
    }

    @Override
    public void onViewStateRestored(@Nullable Bundle savedInstanceState) {
        super.onViewStateRestored(savedInstanceState);
        mVerificationId = savedInstanceState.getString(KEY_VERIFICATION_ID);
    }

    private View.OnClickListener generateFactorOnClickListener(PhoneMultiFactorInfo phoneMultiFactorInfo) {
        return new View.OnClickListener() {
            @Override
            public void onClick(View v) {

            }
        };
    }

    private PhoneAuthProvider.OnVerificationStateChangedCallbacks generateCallbacks() {
        return new PhoneAuthProvider.OnVerificationStateChangedCallbacks() {
            @Override
            public void onVerificationCompleted(@NonNull PhoneAuthCredential phoneAuthCredential) {
                MultiFactorSignInFragment.this.mPhoneAuthCredential = phoneAuthCredential;
                mBinding.finishMfaSignIn.performClick();
                Toast.makeText(getContext(), "Verification complete!", Toast.LENGTH_SHORT)
                        .show();
            }

            @Override
            public void onCodeSent(@NonNull String verificationId, @NonNull PhoneAuthProvider.ForceResendingToken token) {
                MultiFactorSignInFragment.this.mVerificationId = verificationId;
                mBinding.finishMfaSignIn.setClickable(true);
            }

            @Override
            public void onVerificationFailed(@NonNull FirebaseException e) {
                Toast.makeText(getContext(), "Error: " + e.getMessage(), Toast.LENGTH_SHORT)
                        .show();
            }
        };
    }

    private MultiFactorResolver getResolverFromArguments(Bundle arguments) {
        return arguments.getParcelable(EXTRA_MFA_RESOLVER);
    }

    private void onClickFinishSignIn() {
        if (mPhoneAuthCredential == null) {
            if (isEmpty(mBinding.smsCode.getText().toString())) {
                Toast.makeText(getContext(), "You need to enter an SMS code.", Toast.LENGTH_SHORT)
                        .show();
                return;
            }
            mPhoneAuthCredential =
                    PhoneAuthProvider.getCredential(
                            mVerificationId, mBinding.smsCode.getText().toString());
        }
        mMultiFactorResolver
                .resolveSignIn(PhoneMultiFactorGenerator.getAssertion(mPhoneAuthCredential))
                .addOnSuccessListener(
                        new OnSuccessListener<AuthResult>() {
                            @Override
                            public void onSuccess(AuthResult authResult) {
                                NavHostFragment.findNavController(MultiFactorSignInFragment.this)
                                        .popBackStack();
                            }
                        })
                .addOnFailureListener(
                        new OnFailureListener() {
                            @Override
                            public void onFailure(@NonNull Exception e) {
                                Toast.makeText(getContext(), "Error: " + e.getMessage(), Toast.LENGTH_SHORT)
                                        .show();
                            }
                        });
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        mBinding = null;
    }
}


<|start_filename|>admob/app/src/main/java/com/google/samples/quickstart/admobexample/kotlin/SecondFragment.kt<|end_filename|>
package com.google.samples.quickstart.admobexample.kotlin

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import com.google.samples.quickstart.admobexample.R

class SecondFragment : Fragment() {

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        return inflater.inflate(R.layout.fragment_second, container, false)
    }

}

<|start_filename|>database/app/src/main/java/com/google/firebase/quickstart/database/java/viewholder/CommentViewHolder.java<|end_filename|>
package com.google.firebase.quickstart.database.java.viewholder;

import android.view.View;
import android.widget.TextView;

import androidx.recyclerview.widget.RecyclerView;

import com.google.firebase.quickstart.database.R;

public class CommentViewHolder extends RecyclerView.ViewHolder {
    public TextView authorView;
    public TextView bodyView;

    public CommentViewHolder(View itemView) {
        super(itemView);
        authorView = itemView.findViewById(R.id.commentAuthor);
        bodyView = itemView.findViewById(R.id.commentBody);
    }
}


<|start_filename|>internal/lint/src/test/java/com/firebase/lint/InvalidImportDetectorTest.kt<|end_filename|>
package com.firebase.lint

import com.android.tools.lint.checks.infrastructure.LintDetectorTest.java
import com.android.tools.lint.checks.infrastructure.TestLintTask.lint
import com.firebase.lint.InvalidImportDetector.Companion.SHORT_MESSAGE
import org.junit.Test

class InvalidImportDetectorTest {

    private val javaPackage = java("""
      package com.google.firebase.java;

      public final class Hello {
        public static final class drawable {
        }
      }""").indented()

    @Test
    fun normalRImport() {
        lint()
                .allowMissingSdk()
                .files(javaPackage, java("""
          package com.google.firebase.java;

          import com.google.firebase.java.Hello;

          class Example {
          }""").indented())
                .issues(ISSUE_INVALID_IMPORT)
                .run()
                .expectClean()
    }

    @Test
    fun wrongImport() {
        lint()
                .allowMissingSdk()
                .files(javaPackage, java("""
          package com.google.firebase.kotlin;

          import com.google.firebase.java.Hello;

          class Example {
          }""").indented())
                .issues(ISSUE_INVALID_IMPORT)
                .run()
                .expect("""
          |src/com/google/firebase/kotlin/Example.java:3: Error: $SHORT_MESSAGE [SuspiciousImport]
          |import com.google.firebase.java.Hello;
          |       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          |1 errors, 0 warnings""".trimMargin())
    }
}


<|start_filename|>auth/app/src/main/java/com/google/firebase/quickstart/auth/java/AnonymousAuthFragment.java<|end_filename|>
/**
 * Copyright 2021 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.google.firebase.quickstart.auth.java;

import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.auth.AuthCredential;
import com.google.firebase.auth.AuthResult;
import com.google.firebase.auth.EmailAuthProvider;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.FirebaseUser;
import com.google.firebase.quickstart.auth.R;
import com.google.firebase.quickstart.auth.databinding.FragmentAnonymousAuthBinding;

public class AnonymousAuthFragment extends BaseFragment {
    private static final String TAG = "AnonymousAuth";

    private FirebaseAuth mAuth;

    private FragmentAnonymousAuthBinding mBinding;

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
                             @Nullable Bundle savedInstanceState) {
        mBinding = FragmentAnonymousAuthBinding.inflate(inflater, container, false);
        return mBinding.getRoot();
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        // Initialize Firebase Auth
        mAuth = FirebaseAuth.getInstance();

        // Fields
        setProgressBar(mBinding.progressBar);

        // Click listeners
        mBinding.buttonAnonymousSignIn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                signInAnonymously();
            }
        });
        mBinding.buttonAnonymousSignOut.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                signOut();
            }
        });
        mBinding.buttonLinkAccount.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                linkAccount();
            }
        });
    }

    @Override
    public void onStart() {
        super.onStart();
        // Check if user is signed in (non-null) and update UI accordingly.
        FirebaseUser currentUser = mAuth.getCurrentUser();
        updateUI(currentUser);
    }

    private void signInAnonymously() {
        showProgressBar();
        mAuth.signInAnonymously()
                .addOnCompleteListener(requireActivity(), new OnCompleteListener<AuthResult>() {
                    @Override
                    public void onComplete(@NonNull Task<AuthResult> task) {
                        if (task.isSuccessful()) {
                            // Sign in success, update UI with the signed-in user's information
                            Log.d(TAG, "signInAnonymously:success");
                            FirebaseUser user = mAuth.getCurrentUser();
                            updateUI(user);
                        } else {
                            // If sign in fails, display a message to the user.
                            Log.w(TAG, "signInAnonymously:failure", task.getException());
                            Toast.makeText(getContext(), "Authentication failed.",
                                    Toast.LENGTH_SHORT).show();
                            updateUI(null);
                        }

                        hideProgressBar();
                    }
                });
    }

    private void signOut() {
        mAuth.signOut();
        updateUI(null);
    }

    private void linkAccount() {
        // Make sure form is valid
        if (!validateLinkForm()) {
            return;
        }

        // Get email and password from form
        String email = mBinding.fieldEmail.getText().toString();
        String password = mBinding.fieldPassword.getText().toString();

        // Create EmailAuthCredential with email and password
        AuthCredential credential = EmailAuthProvider.getCredential(email, password);

        // Link the anonymous user to the email credential
        showProgressBar();

        mAuth.getCurrentUser().linkWithCredential(credential)
                .addOnCompleteListener(requireActivity(), new OnCompleteListener<AuthResult>() {
                    @Override
                    public void onComplete(@NonNull Task<AuthResult> task) {
                        if (task.isSuccessful()) {
                            Log.d(TAG, "linkWithCredential:success");
                            FirebaseUser user = task.getResult().getUser();
                            updateUI(user);
                        } else {
                            Log.w(TAG, "linkWithCredential:failure", task.getException());
                            Toast.makeText(getContext(), "Authentication failed.",
                                    Toast.LENGTH_SHORT).show();
                            updateUI(null);
                        }

                        hideProgressBar();
                    }
                });
    }

    private boolean validateLinkForm() {
        boolean valid = true;

        String email = mBinding.fieldEmail.getText().toString();
        if (TextUtils.isEmpty(email)) {
            mBinding.fieldEmail.setError("Required.");
            valid = false;
        } else {
            mBinding.fieldEmail.setError(null);
        }

        String password = mBinding.fieldPassword.getText().toString();
        if (TextUtils.isEmpty(password)) {
            mBinding.fieldPassword.setError("Required.");
            valid = false;
        } else {
            mBinding.fieldPassword.setError(null);
        }

        return valid;
    }

    private void updateUI(FirebaseUser user) {
        hideProgressBar();

        TextView idView = mBinding.anonymousStatusId;
        TextView emailView = mBinding.anonymousStatusEmail;
        boolean isSignedIn = (user != null);

        // Status text
        if (isSignedIn) {
            idView.setText(getString(R.string.id_fmt, user.getUid()));
            emailView.setText(getString(R.string.email_fmt, user.getEmail()));
        } else {
            idView.setText(R.string.signed_out);
            emailView.setText(null);
        }

        // Button visibility
        mBinding.buttonAnonymousSignIn.setEnabled(!isSignedIn);
        mBinding.buttonAnonymousSignOut.setEnabled(isSignedIn);
        mBinding.buttonLinkAccount.setEnabled(isSignedIn);
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        mBinding = null;
    }
}


<|start_filename|>database/app/src/main/java/com/google/firebase/quickstart/database/kotlin/BaseFragment.kt<|end_filename|>
package com.google.firebase.quickstart.database.kotlin

import android.view.View
import android.widget.ProgressBar
import androidx.fragment.app.Fragment
import com.google.firebase.auth.ktx.auth
import com.google.firebase.ktx.Firebase

open class BaseFragment : Fragment() {
    private var progressBar: ProgressBar? = null

    val uid: String
        get() = Firebase.auth.currentUser!!.uid

    fun setProgressBar(resId: Int) {
        progressBar = view?.findViewById(resId)
    }

    fun showProgressBar() {
        progressBar?.visibility = View.VISIBLE
    }

    fun hideProgressBar() {
        progressBar?.visibility = View.INVISIBLE
    }
}

<|start_filename|>firestore/app/src/main/java/com/google/firebase/example/fireeats/java/FilterDialogFragment.java<|end_filename|>
package com.google.firebase.example.fireeats.java;

import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Spinner;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.DialogFragment;

import com.google.firebase.example.fireeats.R;
import com.google.firebase.example.fireeats.databinding.DialogFiltersBinding;
import com.google.firebase.example.fireeats.java.model.Restaurant;
import com.google.firebase.firestore.Query;

/**
 * Dialog Fragment containing filter form.
 */
public class FilterDialogFragment extends DialogFragment implements View.OnClickListener {

    public static final String TAG = "FilterDialog";

    interface FilterListener {

        void onFilter(Filters filters);

    }

    private DialogFiltersBinding mBinding;
    private FilterListener mFilterListener;

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater,
                             @Nullable ViewGroup container,
                             @Nullable Bundle savedInstanceState) {
        mBinding = DialogFiltersBinding.inflate(inflater, container, false);
        
        mBinding.buttonSearch.setOnClickListener(this);
        mBinding.buttonCancel.setOnClickListener(this);

        return mBinding.getRoot();
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        mBinding = null;
    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);

        if (getParentFragment() instanceof FilterListener) {
            mFilterListener = (FilterListener) getParentFragment();
        }
    }

    @Override
    public void onResume() {
        super.onResume();
        getDialog().getWindow().setLayout(
                ViewGroup.LayoutParams.MATCH_PARENT,
                ViewGroup.LayoutParams.WRAP_CONTENT);
    }

    public void onSearchClicked() {
        if (mFilterListener != null) {
            mFilterListener.onFilter(getFilters());
        }

        dismiss();
    }

    public void onCancelClicked() {
        dismiss();
    }

    @Nullable
    private String getSelectedCategory() {
        String selected = (String) mBinding.spinnerCategory.getSelectedItem();
        if (getString(R.string.value_any_category).equals(selected)) {
            return null;
        } else {
            return selected;
        }
    }

    @Nullable
    private String getSelectedCity() {
        String selected = (String) mBinding.spinnerCity.getSelectedItem();
        if (getString(R.string.value_any_city).equals(selected)) {
            return null;
        } else {
            return selected;
        }
    }

    private int getSelectedPrice() {
        String selected = (String) mBinding.spinnerPrice.getSelectedItem();
        if (selected.equals(getString(R.string.price_1))) {
            return 1;
        } else if (selected.equals(getString(R.string.price_2))) {
            return 2;
        } else if (selected.equals(getString(R.string.price_3))) {
            return 3;
        } else {
            return -1;
        }
    }

    @Nullable
    private String getSelectedSortBy() {
        String selected = (String) mBinding.spinnerSort.getSelectedItem();
        if (getString(R.string.sort_by_rating).equals(selected)) {
            return Restaurant.FIELD_AVG_RATING;
        } if (getString(R.string.sort_by_price).equals(selected)) {
            return Restaurant.FIELD_PRICE;
        } if (getString(R.string.sort_by_popularity).equals(selected)) {
            return Restaurant.FIELD_POPULARITY;
        }

        return null;
    }

    @Nullable
    private Query.Direction getSortDirection() {
        String selected = (String) mBinding.spinnerSort.getSelectedItem();
        if (getString(R.string.sort_by_rating).equals(selected)) {
            return Query.Direction.DESCENDING;
        } if (getString(R.string.sort_by_price).equals(selected)) {
            return Query.Direction.ASCENDING;
        } if (getString(R.string.sort_by_popularity).equals(selected)) {
            return Query.Direction.DESCENDING;
        }

        return null;
    }

    public void resetFilters() {
        if (mBinding != null) {
            mBinding.spinnerCategory.setSelection(0);
            mBinding.spinnerCity.setSelection(0);
            mBinding.spinnerPrice.setSelection(0);
            mBinding.spinnerSort.setSelection(0);
        }
    }

    public Filters getFilters() {
        Filters filters = new Filters();

        if (mBinding != null) {
            filters.setCategory(getSelectedCategory());
            filters.setCity(getSelectedCity());
            filters.setPrice(getSelectedPrice());
            filters.setSortBy(getSelectedSortBy());
            filters.setSortDirection(getSortDirection());
        }

        return filters;
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.buttonSearch:
                onSearchClicked();
                break;
            case R.id.buttonCancel:
                onCancelClicked();
                break;
        }
    }
}


<|start_filename|>firestore/app/src/main/java/com/google/firebase/example/fireeats/java/MainActivity.java<|end_filename|>
package com.google.firebase.example.fireeats.java;

import android.os.Bundle;

import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.navigation.Navigation;

import com.google.firebase.example.fireeats.R;

public class  MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        setSupportActionBar(this.<Toolbar>findViewById(R.id.toolbar));

        Navigation.findNavController(this, R.id.nav_host_fragment)
                .setGraph(R.navigation.nav_graph_java);
    }
}


<|start_filename|>auth/app/src/main/java/com/google/firebase/quickstart/auth/kotlin/CustomAuthFragment.kt<|end_filename|>
package com.google.firebase.quickstart.auth.kotlin

import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.fragment.app.Fragment
import com.google.firebase.auth.FirebaseAuth
import com.google.firebase.auth.FirebaseUser
import com.google.firebase.auth.ktx.auth
import com.google.firebase.ktx.Firebase
import com.google.firebase.quickstart.auth.R
import com.google.firebase.quickstart.auth.databinding.FragmentCustomBinding

/**
 * Demonstrate Firebase Authentication using a custom minted token. For more information, see:
 * https://firebase.google.com/docs/auth/android/custom-auth
 */
class CustomAuthFragment : Fragment() {

    private lateinit var auth: FirebaseAuth

    private var _binding: FragmentCustomBinding? = null
    private val binding: FragmentCustomBinding
        get() = _binding!!

    private var customToken: String? = null
    private lateinit var tokenReceiver: TokenBroadcastReceiver

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        _binding = FragmentCustomBinding.inflate(inflater, container, false)
        return binding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        // Button click listeners
        binding.buttonSignIn.setOnClickListener { startSignIn() }

        // Create token receiver (for demo purposes only)
        tokenReceiver = object : TokenBroadcastReceiver() {
            override fun onNewToken(token: String?) {
                Log.d(TAG, "onNewToken:$token")
                setCustomToken(token.toString())
            }
        }

        // Initialize Firebase Auth
        auth = Firebase.auth
    }

    override fun onStart() {
        super.onStart()
        // Check if user is signed in (non-null) and update UI accordingly.
        val currentUser = auth.currentUser
        updateUI(currentUser)
    }

    override fun onResume() {
        super.onResume()
        requireActivity().registerReceiver(tokenReceiver, TokenBroadcastReceiver.filter)
    }

    override fun onPause() {
        super.onPause()
        requireActivity().unregisterReceiver(tokenReceiver)
    }

    private fun startSignIn() {
        // Initiate sign in with custom token
        customToken?.let {
            auth.signInWithCustomToken(it)
                    .addOnCompleteListener(requireActivity()) { task ->
                        if (task.isSuccessful) {
                            // Sign in success, update UI with the signed-in user's information
                            Log.d(TAG, "signInWithCustomToken:success")
                            val user = auth.currentUser
                            updateUI(user)
                        } else {
                            // If sign in fails, display a message to the user.
                            Log.w(TAG, "signInWithCustomToken:failure", task.exception)
                            Toast.makeText(context, "Authentication failed.",
                                    Toast.LENGTH_SHORT).show()
                            updateUI(null)
                        }
                    }
        }
    }

    private fun updateUI(user: FirebaseUser?) {
        if (user != null) {
            binding.textSignInStatus.text = getString(R.string.custom_auth_signin_status_user, user.uid)
        } else {
            binding.textSignInStatus.text = getString(R.string.custom_auth_signin_status_failed)
        }
    }

    private fun setCustomToken(token: String) {
        customToken = token

        val status = "Token:$customToken"

        // Enable/disable sign-in button and show the token
        binding.buttonSignIn.isEnabled = true
        binding.textTokenStatus.text = status
    }

    override fun onDestroyView() {
        super.onDestroyView()
        _binding = null
    }

    companion object {
        private const val TAG = "CustomAuthFragment"
    }
}


<|start_filename|>auth/app/src/main/java/com/google/firebase/quickstart/auth/kotlin/AnonymousAuthFragment.kt<|end_filename|>
package com.google.firebase.quickstart.auth.kotlin

import android.os.Bundle
import android.text.TextUtils
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import com.google.firebase.auth.EmailAuthProvider
import com.google.firebase.auth.FirebaseAuth
import com.google.firebase.auth.FirebaseUser
import com.google.firebase.auth.ktx.auth
import com.google.firebase.ktx.Firebase
import com.google.firebase.quickstart.auth.R
import com.google.firebase.quickstart.auth.databinding.FragmentAnonymousAuthBinding

class AnonymousAuthFragment : BaseFragment() {
    private var _binding: FragmentAnonymousAuthBinding? = null
    private val binding: FragmentAnonymousAuthBinding
        get() = _binding!!

    private lateinit var auth: FirebaseAuth

    override fun onCreateView(
            inflater: LayoutInflater,
            container: ViewGroup?,
            savedInstanceState: Bundle?
    ): View {
        _binding = FragmentAnonymousAuthBinding.inflate(inflater, container, false)
        return binding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        setProgressBar(binding.progressBar)

        // Initialize Firebase Auth
        auth = Firebase.auth

        // Click listeners
        binding.buttonAnonymousSignIn.setOnClickListener {
            signInAnonymously()
        }
        binding.buttonAnonymousSignOut.setOnClickListener {
            signOut()
        }
        binding.buttonLinkAccount.setOnClickListener {
            linkAccount()
        }
    }

    override fun onStart() {
        super.onStart()
        // Check if user is signed in (non-null) and update UI accordingly.
        val currentUser = auth.currentUser
        updateUI(currentUser)
    }

    private fun signInAnonymously() {
        showProgressBar()
        auth.signInAnonymously()
                .addOnCompleteListener(requireActivity()) { task ->
                    if (task.isSuccessful) {
                        // Sign in success, update UI with the signed-in user's information
                        Log.d(TAG, "signInAnonymously:success")
                        val user = auth.currentUser
                        updateUI(user)
                    } else {
                        // If sign in fails, display a message to the user.
                        Log.w(TAG, "signInAnonymously:failure", task.exception)
                        Toast.makeText(context, "Authentication failed.",
                                Toast.LENGTH_SHORT).show()
                        updateUI(null)
                    }

                    hideProgressBar()
                }
    }

    private fun signOut() {
        auth.signOut()
        updateUI(null)
    }

    private fun linkAccount() {
        // Make sure form is valid
        if (!validateLinkForm()) {
            return
        }

        // Get email and password from the form
        val email = binding.fieldEmail.text.toString()
        val password = binding.fieldPassword.text.toString()

        // Create EmailAuthCredential with email and password
        val credential = EmailAuthProvider.getCredential(email, password)

        // Link the anonymous user to the email credential
        showProgressBar()

        auth.currentUser!!.linkWithCredential(credential)
                .addOnCompleteListener(requireActivity()) { task ->
                    if (task.isSuccessful) {
                        Log.d(TAG, "linkWithCredential:success")
                        val user = task.result?.user
                        updateUI(user)
                    } else {
                        Log.w(TAG, "linkWithCredential:failure", task.exception)
                        Toast.makeText(context, "Authentication failed.",
                                Toast.LENGTH_SHORT).show()
                        updateUI(null)
                    }

                    hideProgressBar()
                }
    }

    private fun validateLinkForm(): Boolean {
        var valid = true

        val email = binding.fieldEmail.text.toString()
        if (TextUtils.isEmpty(email)) {
            binding.fieldEmail.error = "Required."
            valid = false
        } else {
            binding.fieldEmail.error = null
        }

        val password = binding.fieldPassword.text.toString()
        if (TextUtils.isEmpty(password)) {
            binding.fieldPassword.error = "Required."
            valid = false
        } else {
            binding.fieldPassword.error = null
        }

        return valid
    }

    private fun updateUI(user: FirebaseUser?) {
        hideProgressBar()
        val isSignedIn = user != null

        // Status text
        if (isSignedIn) {
            binding.anonymousStatusId.text = getString(R.string.id_fmt, user!!.uid)
            binding.anonymousStatusEmail.text = getString(R.string.email_fmt, user.email)
        } else {
            binding.anonymousStatusId.setText(R.string.signed_out)
            binding.anonymousStatusEmail.text = null
        }

        // Button visibility
        binding.buttonAnonymousSignIn.isEnabled = !isSignedIn
        binding.buttonAnonymousSignOut.isEnabled = isSignedIn
        binding.buttonLinkAccount.isEnabled = isSignedIn
    }

    override fun onDestroyView() {
        super.onDestroyView()
        _binding = null
    }

    companion object {
        private const val TAG = "AnonymousAuth"
    }
}

<|start_filename|>auth/app/src/main/java/com/google/firebase/quickstart/auth/java/ChooserFragment.java<|end_filename|>
/**
 * Copyright 2021 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.google.firebase.quickstart.auth.java;

import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.navigation.fragment.NavHostFragment;

import com.google.firebase.quickstart.auth.R;
import com.google.firebase.quickstart.auth.databinding.FragmentChooserBinding;

/**
 * Simple list-based Fragment to redirect to one of the other Activities. This Fragment does not
 * contain any useful code related to Firebase Authentication. You may want to start with
 * one of the following Files:
 *     {@link GoogleSignInFragment}
 *     {@link FacebookLoginFragment}}
 *     {@link EmailPasswordFragment}
 *     {@link PasswordlessActivity}
 *     {@link PhoneAuthFragment}
 *     {@link AnonymousAuthFragment}
 *     {@link CustomAuthFragment}
 *     {@link GenericIdpFragment}
 *     {@link MultiFactorFragment}
 */
public class ChooserFragment extends Fragment {

    private static final int[] NAV_ACTIONS = new int[]{
            R.id.action_google,
            R.id.action_facebook,
            R.id.action_emailpassword,
            R.id.action_passwordless,
            R.id.action_phoneauth,
            R.id.action_anonymousauth,
            R.id.action_firebaseui,
            R.id.action_customauth,
            R.id.action_genericidp,
            R.id.action_mfa,
    };

    private static final String [] CLASS_NAMES = new String[] {
            "GoogleSignInFragment",
            "FacebookLoginFragment",
            "EmailPasswordFragment",
            "PasswordlessActivity",
            "PhoneAuthFragment",
            "AnonymousAuthFragment",
            "FirebaseUIFragment",
            "CustomAuthFragment",
            "GenericIdpFragment",
            "MultiFactorFragment",
    };

    private static final int[] DESCRIPTION_IDS = new int[] {
            R.string.desc_google_sign_in,
            R.string.desc_facebook_login,
            R.string.desc_emailpassword,
            R.string.desc_passwordless,
            R.string.desc_phone_auth,
            R.string.desc_anonymous_auth,
            R.string.desc_firebase_ui,
            R.string.desc_custom_auth,
            R.string.desc_generic_idp,
            R.string.desc_multi_factor,
    };

    private FragmentChooserBinding mBinding;

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        mBinding = FragmentChooserBinding.inflate(inflater, container, false);
        return mBinding.getRoot();
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        MyArrayAdapter adapter = new MyArrayAdapter(requireContext(), android.R.layout.simple_list_item_2);
        adapter.setDescriptionIds(DESCRIPTION_IDS);

        mBinding.listView.setAdapter(adapter);
        mBinding.listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                int destination = NAV_ACTIONS[position];
                NavHostFragment.findNavController(ChooserFragment.this)
                        .navigate(destination);
            }
        });
    }

    public static class MyArrayAdapter extends ArrayAdapter<String> {

        private Context mContext;
        private int[] mDescriptionIds;

        public MyArrayAdapter(Context context, int resource) {
            super(context, resource, CLASS_NAMES);

            mContext = context;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            View view = convertView;

            if (convertView == null) {
                LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                view = inflater.inflate(android.R.layout.simple_list_item_2, null);
            }

            ((TextView) view.findViewById(android.R.id.text1)).setText(CLASS_NAMES[position]);
            ((TextView) view.findViewById(android.R.id.text2)).setText(mDescriptionIds[position]);

            return view;
        }

        public void setDescriptionIds(int[] descriptionIds) {
            mDescriptionIds = descriptionIds;
        }
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        mBinding = null;
    }
}


<|start_filename|>database/app/src/main/java/com/google/firebase/quickstart/database/kotlin/MainFragment.kt<|end_filename|>
package com.google.firebase.quickstart.database.kotlin

import android.os.Bundle
import android.view.LayoutInflater
import android.view.Menu
import android.view.MenuInflater
import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.navigation.fragment.findNavController
import androidx.viewpager2.adapter.FragmentStateAdapter
import com.google.android.material.tabs.TabLayoutMediator
import com.google.firebase.auth.ktx.auth
import com.google.firebase.ktx.Firebase
import com.google.firebase.quickstart.database.R
import com.google.firebase.quickstart.database.databinding.FragmentMainBinding
import com.google.firebase.quickstart.database.kotlin.listfragments.MyPostsFragment
import com.google.firebase.quickstart.database.kotlin.listfragments.MyTopPostsFragment
import com.google.firebase.quickstart.database.kotlin.listfragments.RecentPostsFragment

class MainFragment : Fragment() {
    private var _binding: FragmentMainBinding? = null
    private val binding get() = _binding!!

    private lateinit var pagerAdapter: FragmentStateAdapter

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        _binding = FragmentMainBinding.inflate(inflater, container, false)
        return binding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        setHasOptionsMenu(true)

        // Create the adapter that will return a fragment for each section
        pagerAdapter = object : FragmentStateAdapter(parentFragmentManager, viewLifecycleOwner.lifecycle) {
            private val fragments = arrayOf<Fragment>(
                    RecentPostsFragment(),
                    MyPostsFragment(),
                    MyTopPostsFragment())

            override fun createFragment(position: Int) = fragments[position]

            override fun getItemCount() = fragments.size
        }

        // Set up the ViewPager with the sections adapter.
        with(binding) {
            container.adapter = pagerAdapter
            TabLayoutMediator(tabs, container) { tab, position ->
                tab.text = when(position) {
                    0 -> getString(R.string.heading_recent)
                    1 -> getString(R.string.heading_my_posts)
                    else -> getString(R.string.heading_my_top_posts)
                }
            }.attach()
        }
    }

    override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
        inflater.inflate(R.menu.menu_main, menu)
    }

    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        return if (item.itemId == R.id.action_logout) {
            Firebase.auth.signOut()
            findNavController().navigate(R.id.action_MainFragment_to_SignInFragment)
            true
        } else {
            super.onOptionsItemSelected(item)
        }
    }

    override fun onDestroy() {
        super.onDestroy()
        _binding = null
    }
}

<|start_filename|>crash/app/src/main/java/com/google/samples/quickstart/crash/java/CustomKeySamples.java<|end_filename|>
package com.google.samples.quickstart.crash.java;

import android.Manifest;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.pm.InstallSourceInfo;
import android.content.pm.PackageManager;
import android.net.ConnectivityManager;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.os.Build;
import android.telephony.TelephonyManager;
import android.view.View;

import androidx.core.content.ContextCompat;

import com.google.android.gms.common.GoogleApiAvailability;
import com.google.firebase.crashlytics.CustomKeysAndValues;
import com.google.firebase.crashlytics.FirebaseCrashlytics;

import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;

/**
 * The following are samples of custom keys that may be useful to record via Crashlytics prior to a Crash.
 * <p>
 * These utility methods are not meant to be comprehensive, but they are illustrative of the types of things you
 * could track using custom keys in Crashlytics.
 */
public class CustomKeySamples {


    private final Context context;

    // Lazily instantiated when a listener is set up.
    private ConnectivityManager.NetworkCallback callback = null;

    public CustomKeySamples(Context context) {
        this.context = context;
    }

    /**
     * Set a subset of custom keys simultaneously.
     */
    public void setSampleCustomKeys() {
        FirebaseCrashlytics.getInstance().setCustomKeys(new CustomKeysAndValues.Builder()
                .putString("Locale", getLocale())
                .putFloat("Screen Density", getDensity())
                .putString("Google Play Services Availability", getGooglePlayServicesAvailability())
                .putString("Os Version", getOsVersion())
                .putString("Install Source", getInstallSource())
                .putString("Preferred ABI", getPreferredAbi()).build());
    }

    /**
     * Update network state and add a hook to update network state going forward.
     *
     * Note: This code is executed above API level N.
     */
    public void updateAndTrackNetworkState() {
        ConnectivityManager connectivityManager = (ConnectivityManager) context
                .getSystemService(Context.CONNECTIVITY_SERVICE);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            NetworkCapabilities networkCapabilities = connectivityManager
                    .getNetworkCapabilities(connectivityManager.getActiveNetwork());
            if (networkCapabilities != null) {
                updateNetworkCapabilityCustomKeys(networkCapabilities);
            }
            synchronized(this) {
                if (callback == null) {
                    // Set up a callback to match our best-practices around custom keys being up-to-date
                    callback = new ConnectivityManager.NetworkCallback() {
                        @Override
                        public void onCapabilitiesChanged(Network network, NetworkCapabilities networkCapabilities) {
                            updateNetworkCapabilityCustomKeys(networkCapabilities);
                        }
                    };
                    connectivityManager.registerDefaultNetworkCallback(callback);
                }
            }
        }
    }

    /**
     * Remove the handler for the network state.
     *
     * Note: This code is executed above API level N.
     */
    public void stopTrackingNetworkState() {
        ConnectivityManager connectivityManager = (ConnectivityManager) context
                .getSystemService(Context.CONNECTIVITY_SERVICE);
        synchronized(this) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && callback != null) {
                connectivityManager.unregisterNetworkCallback(callback);
                callback = null;
            }
        }
    }

    private void updateNetworkCapabilityCustomKeys(NetworkCapabilities networkCapabilities) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            FirebaseCrashlytics.getInstance().setCustomKeys(new CustomKeysAndValues.Builder()
                    .putInt("Network Bandwidth", networkCapabilities.getLinkDownstreamBandwidthKbps())
                    .putInt("Network Upstream", networkCapabilities.getLinkUpstreamBandwidthKbps())
                    .putBoolean("Network Metered", networkCapabilities.hasCapability(NET_CAPABILITY_NOT_METERED))
                    // This key is long and not as easy to filter by.
                    .putString("Network Capabilities", networkCapabilities.toString()).build());
        }
    }

    /**
     * @see {@link com.google.samples.quickstart.crash.java.CustomKeySamples#updateAndTrackNetworkState},
     * which does not require READ_PHONE_STATE
     * and returns more useful information about bandwidth, metering, and capabilities.
     *
     * Supressed deprecation warning because that code path is only used below API Level N.
     */
    @Deprecated
    @SuppressLint("MissingPermission")
    public void addPhoneStateRequiredNetworkKeys() {
        TelephonyManager telephonyManager = ((TelephonyManager) context
                .getSystemService(Context.TELEPHONY_SERVICE));

        if (ContextCompat.checkSelfPermission(context, Manifest.permission.READ_PHONE_STATE) !=
                PackageManager.PERMISSION_GRANTED) {
            return;
        }

        int networkType;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            networkType = telephonyManager.getDataNetworkType();
        } else {
            networkType = telephonyManager.getNetworkType();
        }
        String simOperatorId = telephonyManager.getSimOperator();
        FirebaseCrashlytics.getInstance().setCustomKey("Network Type", networkType);
        FirebaseCrashlytics.getInstance().setCustomKey("Sim Operator", simOperatorId);
    }

    /**
     * Retrieve the locale information for the app.
     *
     * Supressed deprecation warning because that code path is only used below API Level N.
     */
    @SuppressWarnings("deprecation")
    public String getLocale() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            return context
                    .getResources()
                    .getConfiguration()
                    .getLocales().get(0).toString();
        }

        return context
                .getResources()
                .getConfiguration().locale.toString();
    }

    /**
     * Retrieve the screen density information for the app.
     */
    public float getDensity() {
        return context
                .getResources()
                .getDisplayMetrics()
                .density;
    }

    /**
     * Retrieve the locale information for the app.
     */
    public String getGooglePlayServicesAvailability() {
        return GoogleApiAvailability
                .getInstance()
                .isGooglePlayServicesAvailable(context) == 0 ? "Unavailable" : "Available";
    }

    /**
     * Return the underlying kernel version of the Android device.
     */
    public String getOsVersion() {
        String osVersion = System.getProperty("os.version");
        return osVersion != null ? osVersion : "Unknown";
    }

    /**
     * Retrieve the preferred ABI of the device. Some devices can support
     * multiple ABIs and the first one returned in the preferred one.
     *
     * Supressed deprecation warning because that code path is only used below Lollipop.
     */
    @SuppressWarnings("deprecation")
    public String getPreferredAbi() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            return Build.SUPPORTED_ABIS[0];
        }

        return Build.CPU_ABI;
    }

    /**
     * Retrieve the install source and return it as a string.
     *
     * Supressed deprecation warning because that code path is only used below API level R.
     */
    public String getInstallSource() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
            try {
                InstallSourceInfo info = context
                        .getPackageManager()
                        .getInstallSourceInfo(context.getPackageName());

                String originating = info.getOriginatingPackageName() == null ? "None" :
                        info.getOriginatingPackageName();
                String installing = info.getInstallingPackageName() == null ? "None" : info.getInstallingPackageName();
                String initiating = info.getInitiatingPackageName() == null ? "None" : info.getInitiatingPackageName();

                // This returns all three of the install source, originating source, and initiating
                // source.
                return "Originating: " + originating +
                        ", Installing: " + installing +
                        ", Initiating: " + initiating;
            } catch (PackageManager.NameNotFoundException e) {
                return "Unknown";
            }
        }

        String installerPackageName = context
                .getPackageManager()
                .getInstallerPackageName(context.getPackageName());

        return installerPackageName == null ? "None" : installerPackageName;
    }

    /**
     * Add a focus listener that updates a custom key when this view gains the focus.
     **/
    public void focusListener(View view, boolean hasFocus) {
        if (hasFocus) {
            FirebaseCrashlytics.getInstance().setCustomKey("view_focus", view.getId());
        }
    }
}


<|start_filename|>database/app/src/main/java/com/google/firebase/quickstart/database/kotlin/MainActivity.kt<|end_filename|>
package com.google.firebase.quickstart.database.kotlin

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.isGone
import androidx.core.view.isVisible
import androidx.navigation.findNavController
import com.google.firebase.quickstart.database.R
import com.google.firebase.quickstart.database.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity() {

    private lateinit var binding: ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
        val toolbar = binding.toolbar
        setSupportActionBar(toolbar)

        val fab = binding.fab
        val navController = findNavController(R.id.nav_host_fragment)
        navController.setGraph(R.navigation.nav_graph_kotlin)
        navController.addOnDestinationChangedListener { _, destination, _ ->
            if (destination.id == R.id.MainFragment) {
                fab.isVisible = true
                fab.setOnClickListener {
                    navController.navigate(R.id.action_MainFragment_to_NewPostFragment)
                }
            } else {
                fab.isGone = true
            }
        }
    }
}

<|start_filename|>auth/app/src/main/java/com/google/firebase/quickstart/auth/java/MultiFactorEnrollFragment.java<|end_filename|>
package com.google.firebase.quickstart.auth.java;

import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.navigation.fragment.NavHostFragment;

import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.FirebaseException;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.MultiFactorSession;
import com.google.firebase.auth.PhoneAuthCredential;
import com.google.firebase.auth.PhoneAuthOptions;
import com.google.firebase.auth.PhoneAuthProvider;
import com.google.firebase.auth.PhoneAuthProvider.OnVerificationStateChangedCallbacks;
import com.google.firebase.auth.PhoneMultiFactorGenerator;
import com.google.firebase.quickstart.auth.databinding.FragmentPhoneAuthBinding;

import java.util.concurrent.TimeUnit;

/**
 * Fragment that allows the user to enroll second factors.
 */
public class MultiFactorEnrollFragment extends BaseFragment {

    private static final String TAG = "MfaEnrollFragment";

    private FragmentPhoneAuthBinding mBinding;

    private String mCodeVerificationId;

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        mBinding = FragmentPhoneAuthBinding.inflate(inflater, container, false);
        return mBinding.getRoot();
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        mBinding.titleText.setText("SMS as a Second Factor");
        mBinding.status.setVisibility(View.GONE);
        mBinding.detail.setVisibility(View.GONE);
        mBinding.buttonStartVerification.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                onClickVerifyPhoneNumber();
            }
        });
        mBinding.buttonVerifyPhone.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                onClickSignInWithPhoneNumber();
            }
        });
    }

    private void onClickVerifyPhoneNumber() {
        String phoneNumber = mBinding.fieldPhoneNumber.getText().toString();

        OnVerificationStateChangedCallbacks callbacks =
                new OnVerificationStateChangedCallbacks() {
                    @Override
                    public void onVerificationCompleted(PhoneAuthCredential credential) {
                        // Instant-validation has been disabled (see requireSmsValidation below).
                        // Auto-retrieval has also been disabled (timeout is set to 0).
                        // This should never be triggered.
                        throw new RuntimeException(
                                "onVerificationCompleted() triggered with instant-validation and auto-retrieval disabled.");
                    }

                    @Override
                    public void onCodeSent(
                            final String verificationId, PhoneAuthProvider.ForceResendingToken token) {
                        Log.d(TAG, "onCodeSent:" + verificationId);
                        Toast.makeText( getContext(), "SMS code has been sent", Toast.LENGTH_SHORT)
                                .show();

                        mCodeVerificationId = verificationId;
                    }

                    @Override
                    public void onVerificationFailed(FirebaseException e) {
                        Log.w(TAG, "onVerificationFailed ", e);
                        Toast.makeText(getContext(), "Verification failed: " + e.getMessage(), Toast.LENGTH_SHORT)
                                .show();
                    }
                };

        FirebaseAuth.getInstance()
                .getCurrentUser()
                .getMultiFactor()
                .getSession()
                .addOnCompleteListener(
                        new OnCompleteListener<MultiFactorSession>() {
                            @Override
                            public void onComplete(@NonNull Task<MultiFactorSession> task) {
                                if (task.isSuccessful()) {
                                    PhoneAuthOptions phoneAuthOptions =
                                            PhoneAuthOptions.newBuilder()
                                                    .setPhoneNumber(phoneNumber)
                                                    // A timeout of 0 disables SMS-auto-retrieval.
                                                    .setTimeout(0L, TimeUnit.SECONDS)
                                                    .setMultiFactorSession(task.getResult())
                                                    .setCallbacks(callbacks)
                                                    // Disable instant-validation.
                                                    .requireSmsValidation(true)
                                                    .build();

                                    PhoneAuthProvider.verifyPhoneNumber(phoneAuthOptions);
                                } else {
                                    Toast.makeText(getContext(),
                                            "Failed to get session: " + task.getException(), Toast.LENGTH_SHORT)
                                            .show();
                                }
                            }
                        });
    }

    private void onClickSignInWithPhoneNumber() {
        String smsCode = mBinding.fieldVerificationCode.getText().toString();
        if (TextUtils.isEmpty(smsCode)) {
            return;
        }
        PhoneAuthCredential credential = PhoneAuthProvider.getCredential(mCodeVerificationId, smsCode);
        enrollWithPhoneAuthCredential(credential);
    }

    private void enrollWithPhoneAuthCredential(PhoneAuthCredential credential) {
        FirebaseAuth.getInstance()
                .getCurrentUser()
                .getMultiFactor()
                .enroll(PhoneMultiFactorGenerator.getAssertion(credential), /* displayName= */ null)
                .addOnSuccessListener(new OnSuccessListener<Void>() {
                    @Override
                    public void onSuccess(Void aVoid) {
                        Toast.makeText(getContext(), "MFA enrollment was successful",
                                Toast.LENGTH_LONG)
                                .show();

                        NavHostFragment.findNavController(MultiFactorEnrollFragment.this)
                                .popBackStack();
                    }
                })
                .addOnFailureListener(new OnFailureListener() {
                    @Override
                    public void onFailure(@NonNull Exception e) {
                        Log.d(TAG, "MFA failure", e);
                        Toast.makeText(getContext(),
                                "MFA enrollment was unsuccessful. " + e,
                                Toast.LENGTH_LONG)
                                .show();
                    }
                });
    }
}


<|start_filename|>auth/app/src/main/java/com/google/firebase/quickstart/auth/kotlin/ChooserFragment.kt<|end_filename|>
package com.google.firebase.quickstart.auth.kotlin

import android.content.Context
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ArrayAdapter
import android.widget.TextView
import androidx.fragment.app.Fragment
import androidx.navigation.fragment.findNavController
import com.google.firebase.quickstart.auth.R
import com.google.firebase.quickstart.auth.databinding.FragmentChooserBinding

/**
 * Simple list-based Fragment to redirect to one of the other Fragments. This Fragment does not
 * contain any useful code related to Firebase Authentication. You may want to start with
 * one of the following Files:
 *     {@link GoogleSignInFragment}
 *     {@link FacebookLoginFragment}
 *     {@link EmailPasswordFragment}
 *     {@link PasswordlessActivity}
 *     {@link PhoneAuthFragment}
 *     {@link AnonymousAuthFragment}
 *     {@link CustomAuthFragment}
 *     {@link GenericIdpFragment}
 *     {@link MultiFactorFragment}
 */
class ChooserFragment : Fragment() {

    private var _binding: FragmentChooserBinding? = null
    private val binding: FragmentChooserBinding
        get() = _binding!!

    override fun onCreateView(
            inflater: LayoutInflater,
            container: ViewGroup?,
            savedInstanceState: Bundle?
    ): View {
        _binding = FragmentChooserBinding.inflate(inflater, container, false)
        return binding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        // Set up Adapter
        val adapter = MyArrayAdapter(requireContext(), android.R.layout.simple_list_item_2)
        adapter.setDescriptionIds(DESCRIPTION_IDS)

        binding.listView.adapter = adapter
        binding.listView.setOnItemClickListener { _, _, position, _ ->
            val actionId = NAV_ACTIONS[position]
            findNavController().navigate(actionId)
        }
    }

    class MyArrayAdapter(
        private val ctx: Context,
        resource: Int
    ) : ArrayAdapter<String>(ctx, resource, CLASS_NAMES) {
        private var descriptionIds: IntArray? = null

        override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
            var view = convertView

            if (convertView == null) {
                val inflater = ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
                view = inflater.inflate(android.R.layout.simple_list_item_2, null)
            }

            // Android internal resource hence can't use synthetic binding
            view?.findViewById<TextView>(android.R.id.text1)?.text = CLASS_NAMES[position]
            view?.findViewById<TextView>(android.R.id.text2)?.setText(descriptionIds!![position])

            return view!!
        }

        fun setDescriptionIds(descriptionIds: IntArray) {
            this.descriptionIds = descriptionIds
        }
    }

    override fun onDestroyView() {
        super.onDestroyView()
        _binding = null
    }

    companion object {
        private val NAV_ACTIONS = arrayOf(
                R.id.action_google,
                R.id.action_facebook,
                R.id.action_emailpassword,
                R.id.action_passwordless,
                R.id.action_phoneauth,
                R.id.action_anonymousauth,
                R.id.action_firebaseui,
                R.id.action_customauth,
                R.id.action_genericidp,
                R.id.action_mfa
        )
        private val CLASS_NAMES = arrayOf(
                "GoogleSignInFragment",
                "FacebookLoginFragment",
                "EmailPasswordFragment",
                "PasswordlessActivity",
                "PhoneAuthFragment",
                "AnonymousAuthFragment",
                "FirebaseUIFragment",
                "CustomAuthFragment",
                "GenericIdpFragment",
                "MultiFactorFragment"
        )
        private val DESCRIPTION_IDS = intArrayOf(
                R.string.desc_google_sign_in,
                R.string.desc_facebook_login,
                R.string.desc_emailpassword,
                R.string.desc_passwordless,
                R.string.desc_phone_auth,
                R.string.desc_anonymous_auth,
                R.string.desc_firebase_ui,
                R.string.desc_custom_auth,
                R.string.desc_generic_idp,
                R.string.desc_multi_factor
        )
    }
}


<|start_filename|>firestore/app/src/main/java/com/google/firebase/example/fireeats/java/RatingDialogFragment.java<|end_filename|>
package com.google.firebase.example.fireeats.java;

import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;

import androidx.annotation.Nullable;
import androidx.fragment.app.DialogFragment;

import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.example.fireeats.R;
import com.google.firebase.example.fireeats.databinding.DialogRatingBinding;
import com.google.firebase.example.fireeats.java.model.Rating;

import me.zhanghai.android.materialratingbar.MaterialRatingBar;

/**
 * Dialog Fragment containing rating form.
 */
public class RatingDialogFragment extends DialogFragment implements View.OnClickListener {

    public static final String TAG = "RatingDialog";

    private DialogRatingBinding mBinding;
    
    interface RatingListener {

        void onRating(Rating rating);

    }

    private RatingListener mRatingListener;

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater,
                             @Nullable ViewGroup container,
                             @Nullable Bundle savedInstanceState) {
        mBinding = DialogRatingBinding.inflate(inflater, container, false);

        mBinding.restaurantFormButton.setOnClickListener(this);
        mBinding.restaurantFormCancel.setOnClickListener(this);

        return mBinding.getRoot();
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        mBinding = null;
    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);

        if (getParentFragment() instanceof RatingListener) {
            mRatingListener = (RatingListener) getParentFragment();
        }
    }

    @Override
    public void onResume() {
        super.onResume();
        getDialog().getWindow().setLayout(
                ViewGroup.LayoutParams.MATCH_PARENT,
                ViewGroup.LayoutParams.WRAP_CONTENT);

    }

    private void onSubmitClicked(View view) {
        Rating rating = new Rating(
                FirebaseAuth.getInstance().getCurrentUser(),
                mBinding.restaurantFormRating.getRating(),
                mBinding.restaurantFormText.getText().toString());

        if (mRatingListener != null) {
            mRatingListener.onRating(rating);
        }

        dismiss();
    }

    private void onCancelClicked(View view) {
        dismiss();
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.restaurantFormButton:
                onSubmitClicked(v);
                break;
            case R.id.restaurantFormCancel:
                onCancelClicked(v);
                break;
        }
    }

}


<|start_filename|>admob/app/src/main/java/com/google/samples/quickstart/admobexample/kotlin/FirstFragment.kt<|end_filename|>
package com.google.samples.quickstart.admobexample.kotlin

import android.os.Bundle
import android.util.Log
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import androidx.navigation.fragment.findNavController
import com.google.android.gms.ads.AdRequest
import com.google.android.gms.ads.AdView
import com.google.android.gms.ads.FullScreenContentCallback
import com.google.android.gms.ads.LoadAdError
import com.google.android.gms.ads.MobileAds
import com.google.android.gms.ads.interstitial.InterstitialAd
import com.google.android.gms.ads.interstitial.InterstitialAdLoadCallback
import com.google.samples.quickstart.admobexample.R
import com.google.samples.quickstart.admobexample.databinding.FragmentFirstBinding

class FirstFragment : Fragment() {

    private var _binding: FragmentFirstBinding? = null
    private val binding get() = _binding!!
    private var interstitialAd: InterstitialAd? = null
    private lateinit var adView: AdView
    private lateinit var loadInterstitialButton: Button

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
                              savedInstanceState: Bundle?): View {
        _binding = FragmentFirstBinding.inflate(inflater, container, false)
        return binding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        adView = binding.adView
        loadInterstitialButton = binding.loadInterstitialButton

        checkIds()

        // Initialize the Google Mobile Ads SDK
        MobileAds.initialize(requireContext())

        requestNewInterstitial()

        loadInterstitialButton.setOnClickListener {
            if (interstitialAd != null) {
                interstitialAd?.show(requireActivity())
            } else {
                goToNextFragment()
            }
        }

        // Disable button if an interstitial ad is not loaded yet.
        loadInterstitialButton.isEnabled = interstitialAd != null
    }

    /**
     * Load a new interstitial ad asynchronously.
     */
    private fun requestNewInterstitial() {
        // AdMob ad unit IDs are not currently stored inside the google-services.json file.
        // Developers using AdMob can store them as custom values in a string resource file or
        // simply use constants. Note that the ad units used here are configured to return only test
        // ads, and should not be used outside this sample.
        val adRequest = AdRequest.Builder().build()

        adView.loadAd(adRequest)

        InterstitialAd.load(
                requireContext(),
                getString(R.string.interstitial_ad_unit_id),
                adRequest,
                object : InterstitialAdLoadCallback() {
                    override fun onAdLoaded(ad: InterstitialAd) {
                        super.onAdLoaded(ad)
                        interstitialAd = ad
                        // Ad received, ready to display
                        loadInterstitialButton.isEnabled = true

                        interstitialAd?.fullScreenContentCallback = object : FullScreenContentCallback() {
                            override fun onAdDismissedFullScreenContent() {
                                super.onAdDismissedFullScreenContent()
                                goToNextFragment()
                            }
                        }
                    }

                    override fun onAdFailedToLoad(error: LoadAdError) {
                        super.onAdFailedToLoad(error)
                        interstitialAd = null
                        Log.w(TAG, "onAdFailedToLoad:${error.message}")
                    }
                }
        )
    }

    private fun goToNextFragment() {
        findNavController().navigate(R.id.action_FirstFragment_to_SecondFragment)
    }

    /** Called when leaving the activity  */
    override fun onPause() {
        adView.pause()
        super.onPause()
    }

    /** Called when returning to the activity  */
    override fun onResume() {
        super.onResume()
        adView.resume()
        if (interstitialAd == null) {
            requestNewInterstitial()
        }
    }

    /** Called before the activity is destroyed  */
    override fun onDestroy() {
        adView.destroy()
        super.onDestroy()
    }

    private fun checkIds() {
        if (TEST_APP_ID == getString(R.string.admob_app_id)) {
            Log.w(TAG, "Your admob_app_id is not configured correctly, please see the README")
        }
    }

    companion object {
        private const val TAG = "FirstFragment"
        private const val TEST_APP_ID = "ca-app-pub-3940256099942544~3347511713"
    }

    override fun onDestroyView() {
        super.onDestroyView()
        _binding = null
    }
}

<|start_filename|>database/app/src/main/java/com/google/firebase/quickstart/database/java/MainActivity.java<|end_filename|>
/*
 * Copyright 2015 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.google.firebase.quickstart.database.java;

import android.os.Bundle;
import android.view.View;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.navigation.NavController;
import androidx.navigation.NavDestination;
import androidx.navigation.Navigation;

import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.firebase.quickstart.database.R;
import com.google.firebase.quickstart.database.databinding.ActivityMainBinding;

public class  MainActivity extends AppCompatActivity {

    private FloatingActionButton fab;
    private NavController navController;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ActivityMainBinding binding = ActivityMainBinding.inflate(getLayoutInflater());
        setContentView(binding.getRoot());
        setSupportActionBar(binding.toolbar);

        fab = binding.fab;

        navController = Navigation.findNavController(this, R.id.nav_host_fragment);
        navController.setGraph(R.navigation.nav_graph_java);
        navController.addOnDestinationChangedListener(new NavController.OnDestinationChangedListener() {
            @Override
            public void onDestinationChanged(@NonNull NavController controller, @NonNull NavDestination destination, @Nullable Bundle arguments) {
                if (destination.getId() == R.id.MainFragment) {
                    fab.setVisibility(View.VISIBLE);
                    fab.setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View view) {
                            navController.navigate(R.id.action_MainFragment_to_NewPostFragment);
                        }
                    });
                } else {
                    fab.setVisibility(View.GONE);
                }
            }
        });
    }
}


<|start_filename|>firestore/app/src/main/java/com/google/firebase/example/fireeats/java/RestaurantDetailFragment.java<|end_filename|>
package com.google.firebase.example.fireeats.java;

import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.InputMethodManager;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.LinearLayoutManager;

import com.bumptech.glide.Glide;
import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.android.gms.tasks.Task;
import com.google.android.material.snackbar.Snackbar;
import com.google.firebase.example.fireeats.R;
import com.google.firebase.example.fireeats.databinding.FragmentRestaurantDetailBinding;
import com.google.firebase.example.fireeats.java.adapter.RatingAdapter;
import com.google.firebase.example.fireeats.java.model.Rating;
import com.google.firebase.example.fireeats.java.model.Restaurant;
import com.google.firebase.example.fireeats.java.util.RestaurantUtil;
import com.google.firebase.firestore.DocumentReference;
import com.google.firebase.firestore.DocumentSnapshot;
import com.google.firebase.firestore.EventListener;
import com.google.firebase.firestore.FirebaseFirestore;
import com.google.firebase.firestore.FirebaseFirestoreException;
import com.google.firebase.firestore.ListenerRegistration;
import com.google.firebase.firestore.Query;
import com.google.firebase.firestore.Transaction;

public class RestaurantDetailFragment extends Fragment
        implements EventListener<DocumentSnapshot>, RatingDialogFragment.RatingListener, View.OnClickListener {

    private static final String TAG = "RestaurantDetail";

    private FragmentRestaurantDetailBinding mBinding;
    
    private RatingDialogFragment mRatingDialog;

    private FirebaseFirestore mFirestore;
    private DocumentReference mRestaurantRef;
    private ListenerRegistration mRestaurantRegistration;

    private RatingAdapter mRatingAdapter;

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        mBinding = FragmentRestaurantDetailBinding.inflate(inflater, container, false);
        return mBinding.getRoot();
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        mBinding.restaurantButtonBack.setOnClickListener(this);
        mBinding.fabShowRatingDialog.setOnClickListener(this);

        String restaurantId = RestaurantDetailFragmentArgs.fromBundle(getArguments()).getKeyRestaurantId();

        // Initialize Firestore
        mFirestore = FirebaseFirestore.getInstance();

        // Get reference to the restaurant
        mRestaurantRef = mFirestore.collection("restaurants").document(restaurantId);

        // Get ratings
        Query ratingsQuery = mRestaurantRef
                .collection("ratings")
                .orderBy("timestamp", Query.Direction.DESCENDING)
                .limit(50);

        // RecyclerView
        mRatingAdapter = new RatingAdapter(ratingsQuery) {
            @Override
            protected void onDataChanged() {
                if (getItemCount() == 0) {
                    mBinding.recyclerRatings.setVisibility(View.GONE);
                    mBinding.viewEmptyRatings.setVisibility(View.VISIBLE);
                } else {
                    mBinding.recyclerRatings.setVisibility(View.VISIBLE);
                    mBinding.viewEmptyRatings.setVisibility(View.GONE);
                }
            }
        };
        mBinding.recyclerRatings.setLayoutManager(new LinearLayoutManager(requireContext()));
        mBinding.recyclerRatings.setAdapter(mRatingAdapter);

        mRatingDialog = new RatingDialogFragment();
    }

    @Override
    public void onStart() {
        super.onStart();

        mRatingAdapter.startListening();
        mRestaurantRegistration = mRestaurantRef.addSnapshotListener(this);
    }

    @Override
    public void onStop() {
        super.onStop();

        mRatingAdapter.stopListening();

        if (mRestaurantRegistration != null) {
            mRestaurantRegistration.remove();
            mRestaurantRegistration = null;
        }
    }

    /**
     * Listener for the Restaurant document ({@link #mRestaurantRef}).
     */
    @Override
    public void onEvent(DocumentSnapshot snapshot, FirebaseFirestoreException e) {
        if (e != null) {
            Log.w(TAG, "restaurant:onEvent", e);
            return;
        }

        onRestaurantLoaded(snapshot.toObject(Restaurant.class));
    }

    private void onRestaurantLoaded(Restaurant restaurant) {
        mBinding.restaurantName.setText(restaurant.getName());
        mBinding.restaurantRating.setRating((float) restaurant.getAvgRating());
        mBinding.restaurantNumRatings.setText(getString(R.string.fmt_num_ratings, restaurant.getNumRatings()));
        mBinding.restaurantCity.setText(restaurant.getCity());
        mBinding.restaurantCategory.setText(restaurant.getCategory());
        mBinding.restaurantPrice.setText(RestaurantUtil.getPriceString(restaurant));

        // Background image
        Glide.with(mBinding.restaurantImage.getContext())
                .load(restaurant.getPhoto())
                .into(mBinding.restaurantImage);
    }

    public void onBackArrowClicked(View view) {
        requireActivity().onBackPressed();
    }

    public void onAddRatingClicked(View view) {
        mRatingDialog.show(getChildFragmentManager(), RatingDialogFragment.TAG);
    }

    @Override
    public void onRating(Rating rating) {
        // In a transaction, add the new rating and update the aggregate totals
        addRating(mRestaurantRef, rating)
                .addOnSuccessListener(requireActivity(), new OnSuccessListener<Void>() {
                    @Override
                    public void onSuccess(Void aVoid) {
                        Log.d(TAG, "Rating added");

                        // Hide keyboard and scroll to top
                        hideKeyboard();
                        mBinding.recyclerRatings.smoothScrollToPosition(0);
                    }
                })
                .addOnFailureListener(requireActivity(), new OnFailureListener() {
                    @Override
                    public void onFailure(@NonNull Exception e) {
                        Log.w(TAG, "Add rating failed", e);

                        // Show failure message and hide keyboard
                        hideKeyboard();
                        Snackbar.make(mBinding.getRoot(), "Failed to add rating",
                                Snackbar.LENGTH_SHORT).show();
                    }
                });
    }

    private Task<Void> addRating(final DocumentReference restaurantRef, final Rating rating) {
        // Create reference for new rating, for use inside the transaction
        final DocumentReference ratingRef = restaurantRef.collection("ratings").document();

        // In a transaction, add the new rating and update the aggregate totals
        return mFirestore.runTransaction(new Transaction.Function<Void>() {
            @Override
            public Void apply(Transaction transaction) throws FirebaseFirestoreException {
                Restaurant restaurant = transaction.get(restaurantRef).toObject(Restaurant.class);

                // Compute new number of ratings
                int newNumRatings = restaurant.getNumRatings() + 1;

                // Compute new average rating
                double oldRatingTotal = restaurant.getAvgRating() * restaurant.getNumRatings();
                double newAvgRating = (oldRatingTotal + rating.getRating()) / newNumRatings;

                // Set new restaurant info
                restaurant.setNumRatings(newNumRatings);
                restaurant.setAvgRating(newAvgRating);

                // Commit to Firestore
                transaction.set(restaurantRef, restaurant);
                transaction.set(ratingRef, rating);

                return null;
            }
        });
    }

    private void hideKeyboard() {
        View view = requireActivity().getCurrentFocus();
        if (view != null) {
            ((InputMethodManager) requireActivity().getSystemService(Context.INPUT_METHOD_SERVICE))
                    .hideSoftInputFromWindow(view.getWindowToken(), 0);
        }
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.restaurantButtonBack:
                onBackArrowClicked(v);
                break;
            case R.id.fabShowRatingDialog:
                onAddRatingClicked(v);
                break;
        }
    }

}


<|start_filename|>auth/app/src/main/java/com/google/firebase/quickstart/auth/kotlin/MainActivity.kt<|end_filename|>
package com.google.firebase.quickstart.auth.kotlin

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.navigation.findNavController
import com.google.firebase.quickstart.auth.R

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        findNavController(R.id.nav_host_fragment).setGraph(R.navigation.nav_graph_kotlin)
    }
}

<|start_filename|>database/app/src/main/java/com/google/firebase/quickstart/database/kotlin/NewPostFragment.kt<|end_filename|>
package com.google.firebase.quickstart.database.kotlin

import android.os.Bundle
import android.text.TextUtils
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.navigation.fragment.findNavController
import com.google.firebase.database.DataSnapshot
import com.google.firebase.database.DatabaseError
import com.google.firebase.database.DatabaseReference
import com.google.firebase.database.ValueEventListener
import com.google.firebase.database.ktx.database
import com.google.firebase.database.ktx.getValue
import com.google.firebase.ktx.Firebase
import com.google.firebase.quickstart.database.R
import com.google.firebase.quickstart.database.databinding.FragmentNewPostBinding
import com.google.firebase.quickstart.database.kotlin.models.Post
import com.google.firebase.quickstart.database.kotlin.models.User

class NewPostFragment : BaseFragment() {
    private var _binding: FragmentNewPostBinding? = null
    private val binding get() = _binding!!

    private lateinit var database: DatabaseReference

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        _binding = FragmentNewPostBinding.inflate(inflater, container, false)
        return binding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        database = Firebase.database.reference

        binding.fabSubmitPost.setOnClickListener { submitPost() }
    }

    private fun submitPost() {
        val title = binding.fieldTitle.text.toString()
        val body = binding.fieldBody.text.toString()

        // Title is required
        if (TextUtils.isEmpty(title)) {
            binding.fieldTitle.error = REQUIRED
            return
        }

        // Body is required
        if (TextUtils.isEmpty(body)) {
            binding.fieldBody.error = REQUIRED
            return
        }

        // Disable button so there are no multi-posts
        setEditingEnabled(false)
        Toast.makeText(context, "Posting...", Toast.LENGTH_SHORT).show()

        val userId = uid
        database.child("users").child(userId).addListenerForSingleValueEvent(
                object : ValueEventListener {
                    override fun onDataChange(dataSnapshot: DataSnapshot) {
                        // Get user value
                        val user = dataSnapshot.getValue<User>()

                        if (user == null) {
                            // User is null, error out
                            Log.e(TAG, "User $userId is unexpectedly null")
                            Toast.makeText(context,
                                    "Error: could not fetch user.",
                                    Toast.LENGTH_SHORT).show()
                        } else {
                            // Write new post
                            writeNewPost(userId, user.username.toString(), title, body)
                        }

                        setEditingEnabled(true)
                        findNavController().navigate(R.id.action_NewPostFragment_to_MainFragment)
                    }

                    override fun onCancelled(databaseError: DatabaseError) {
                        Log.w(TAG, "getUser:onCancelled", databaseError.toException())
                        setEditingEnabled(true)
                    }
                })
    }

    private fun setEditingEnabled(enabled: Boolean) {
        with(binding) {
            fieldTitle.isEnabled = enabled
            fieldBody.isEnabled = enabled
            if (enabled) {
                fabSubmitPost.show()
            } else {
                fabSubmitPost.hide()
            }
        }
    }

    private fun writeNewPost(userId: String, username: String, title: String, body: String) {
        // Create new post at /user-posts/$userid/$postid and at
        // /posts/$postid simultaneously
        val key = database.child("posts").push().key
        if (key == null) {
            Log.w(TAG, "Couldn't get push key for posts")
            return
        }

        val post = Post(userId, username, title, body)
        val postValues = post.toMap()

        val childUpdates = hashMapOf<String, Any>(
                "/posts/$key" to postValues,
                "/user-posts/$userId/$key" to postValues
        )

        database.updateChildren(childUpdates)
    }

    override fun onDestroy() {
        super.onDestroy()
        _binding = null
    }

    companion object {
        private const val TAG = "NewPostFragment"
        private const val REQUIRED = "Required"
    }
}

<|start_filename|>auth/app/src/main/java/com/google/firebase/quickstart/auth/kotlin/EmailPasswordFragment.kt<|end_filename|>
package com.google.firebase.quickstart.auth.kotlin

import android.content.Intent
import android.os.Bundle
import android.text.TextUtils
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.core.os.bundleOf
import androidx.navigation.fragment.findNavController
import com.google.firebase.auth.FirebaseAuth
import com.google.firebase.auth.FirebaseAuthMultiFactorException
import com.google.firebase.auth.FirebaseUser
import com.google.firebase.auth.ktx.auth
import com.google.firebase.ktx.Firebase
import com.google.firebase.quickstart.auth.R
import com.google.firebase.quickstart.auth.databinding.FragmentEmailpasswordBinding

class EmailPasswordFragment : BaseFragment() {

    private lateinit var auth: FirebaseAuth

    private var _binding: FragmentEmailpasswordBinding? = null
    private val binding: FragmentEmailpasswordBinding
        get() = _binding!!

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        _binding = FragmentEmailpasswordBinding.inflate(inflater, container, false)
        return binding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        setProgressBar(binding.progressBar)

        // Buttons
        with (binding) {
            emailSignInButton.setOnClickListener {
                val email = binding.fieldEmail.text.toString()
                val password = binding.fieldPassword.text.toString()
                signIn(email, password)
            }
            emailCreateAccountButton.setOnClickListener {
                val email = binding.fieldEmail.text.toString()
                val password = binding.fieldPassword.text.toString()
                createAccount(email, password)
            }
            signOutButton.setOnClickListener { signOut() }
            verifyEmailButton.setOnClickListener { sendEmailVerification() }
            reloadButton.setOnClickListener { reload() }
        }

        // Initialize Firebase Auth
        auth = Firebase.auth
    }

    public override fun onStart() {
        super.onStart()
        // Check if user is signed in (non-null) and update UI accordingly.
        val currentUser = auth.currentUser
        if(currentUser != null){
            reload();
        }
    }

    private fun createAccount(email: String, password: String) {
        Log.d(TAG, "createAccount:$email")
        if (!validateForm()) {
            return
        }

        showProgressBar()

        auth.createUserWithEmailAndPassword(email, password)
                .addOnCompleteListener(requireActivity()) { task ->
                    if (task.isSuccessful) {
                        // Sign in success, update UI with the signed-in user's information
                        Log.d(TAG, "createUserWithEmail:success")
                        val user = auth.currentUser
                        updateUI(user)
                    } else {
                        // If sign in fails, display a message to the user.
                        Log.w(TAG, "createUserWithEmail:failure", task.exception)
                        Toast.makeText(context, "Authentication failed.",
                                Toast.LENGTH_SHORT).show()
                        updateUI(null)
                    }

                    hideProgressBar()
                }
    }

    private fun signIn(email: String, password: String) {
        Log.d(TAG, "signIn:$email")
        if (!validateForm()) {
            return
        }

        showProgressBar()

        auth.signInWithEmailAndPassword(email, password)
                .addOnCompleteListener(requireActivity()) { task ->
                    if (task.isSuccessful) {
                        // Sign in success, update UI with the signed-in user's information
                        Log.d(TAG, "signInWithEmail:success")
                        val user = auth.currentUser
                        updateUI(user)
                    } else {
                        // If sign in fails, display a message to the user.
                        Log.w(TAG, "signInWithEmail:failure", task.exception)
                        Toast.makeText(context, "Authentication failed.",
                                Toast.LENGTH_SHORT).show()
                        updateUI(null)
                        checkForMultiFactorFailure(task.exception!!)
                    }

                    if (!task.isSuccessful) {
                        binding.status.setText(R.string.auth_failed)
                    }
                    hideProgressBar()
                }
    }

    private fun signOut() {
        auth.signOut()
        updateUI(null)
    }

    private fun sendEmailVerification() {
        // Disable button
        binding.verifyEmailButton.isEnabled = false

        // Send verification email
        val user = auth.currentUser!!
        user.sendEmailVerification()
                .addOnCompleteListener(requireActivity()) { task ->
                    // Re-enable button
                    binding.verifyEmailButton.isEnabled = true

                    if (task.isSuccessful) {
                        Toast.makeText(context,
                                "Verification email sent to ${user.email} ",
                                Toast.LENGTH_SHORT).show()
                    } else {
                        Log.e(TAG, "sendEmailVerification", task.exception)
                        Toast.makeText(context,
                                "Failed to send verification email.",
                                Toast.LENGTH_SHORT).show()
                    }
                }
    }

    private fun reload() {
        auth.currentUser!!.reload().addOnCompleteListener { task ->
            if (task.isSuccessful) {
                updateUI(auth.currentUser)
                Toast.makeText(context, "Reload successful!", Toast.LENGTH_SHORT).show()
            } else {
                Log.e(TAG, "reload", task.exception)
                Toast.makeText(context, "Failed to reload user.", Toast.LENGTH_SHORT).show()
            }
        }
    }

    private fun validateForm(): Boolean {
        var valid = true

        val email = binding.fieldEmail.text.toString()
        if (TextUtils.isEmpty(email)) {
            binding.fieldEmail.error = "Required."
            valid = false
        } else {
            binding.fieldEmail.error = null
        }

        val password = binding.fieldPassword.text.toString()
        if (TextUtils.isEmpty(password)) {
            binding.fieldPassword.error = "Required."
            valid = false
        } else {
            binding.fieldPassword.error = null
        }

        return valid
    }

    private fun updateUI(user: FirebaseUser?) {
        hideProgressBar()
        if (user != null) {
            binding.status.text = getString(R.string.emailpassword_status_fmt,
                    user.email, user.isEmailVerified)
            binding.detail.text = getString(R.string.firebase_status_fmt, user.uid)

            binding.emailPasswordButtons.visibility = View.GONE
            binding.emailPasswordFields.visibility = View.GONE
            binding.signedInButtons.visibility = View.VISIBLE

            if (user.isEmailVerified) {
                binding.verifyEmailButton.visibility = View.GONE
            } else {
                binding.verifyEmailButton.visibility = View.VISIBLE
            }
        } else {
            binding.status.setText(R.string.signed_out)
            binding.detail.text = null

            binding.emailPasswordButtons.visibility = View.VISIBLE
            binding.emailPasswordFields.visibility = View.VISIBLE
            binding.signedInButtons.visibility = View.GONE
        }
    }

    private fun checkForMultiFactorFailure(e: Exception) {
        // Multi-factor authentication with SMS is currently only available for
        // Google Cloud Identity Platform projects. For more information:
        // https://cloud.google.com/identity-platform/docs/android/mfa
        if (e is FirebaseAuthMultiFactorException) {
            Log.w(TAG, "multiFactorFailure", e)
            val resolver = e.resolver
            val args = bundleOf(
                    MultiFactorSignInFragment.EXTRA_MFA_RESOLVER to resolver,
                    MultiFactorFragment.RESULT_NEEDS_MFA_SIGN_IN to true
            )
            findNavController().navigate(R.id.action_emailpassword_to_mfa, args)
        }
    }

    override fun onDestroyView() {
        super.onDestroyView()
        _binding = null
    }

    companion object {
        private const val TAG = "EmailPassword"
        private const val RC_MULTI_FACTOR = 9005
    }
}


<|start_filename|>auth/app/src/main/java/com/google/firebase/quickstart/auth/java/FirebaseUIFragment.java<|end_filename|>
package com.google.firebase.quickstart.auth.java;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;

import androidx.activity.result.ActivityResultLauncher;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;

import com.firebase.ui.auth.AuthUI;
import com.firebase.ui.auth.FirebaseAuthUIActivityResultContract;
import com.firebase.ui.auth.data.model.FirebaseAuthUIAuthenticationResult;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.FirebaseUser;
import com.google.firebase.quickstart.auth.BuildConfig;
import com.google.firebase.quickstart.auth.R;
import com.google.firebase.quickstart.auth.databinding.FragmentFirebaseUiBinding;

import java.util.Collections;

/**
 * Demonstrate authentication using the FirebaseUI-Android library. This fragment demonstrates
 * using FirebaseUI for basic email/password sign in.
 * <p>
 * For more information, visit https://github.com/firebase/firebaseui-android
 */
public class FirebaseUIFragment extends Fragment {

    private FirebaseAuth mAuth;

    private FragmentFirebaseUiBinding mBinding;

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        mBinding = FragmentFirebaseUiBinding.inflate(inflater, container, false);
        return mBinding.getRoot();
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        // Initialize Firebase Auth
        mAuth = FirebaseAuth.getInstance();

        mBinding.signInButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                startSignIn();
            }
        });

        mBinding.signOutButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                signOut();
            }
        });
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        mBinding = null;
    }

    @Override
    public void onStart() {
        super.onStart();
        updateUI(mAuth.getCurrentUser());
    }

    private void onSignInResult(FirebaseAuthUIAuthenticationResult result) {
        if (result.getResultCode() == Activity.RESULT_OK) {
            // Sign in succeeded
            updateUI(mAuth.getCurrentUser());
        } else {
            // Sign in failed
            Toast.makeText(getContext(), "Sign In Failed", Toast.LENGTH_SHORT).show();
            updateUI(null);
        }
    }

    private void startSignIn() {
        // Build FirebaseUI sign in intent. For documentation on this operation and all
        // possible customization see: https://github.com/firebase/firebaseui-android
        ActivityResultLauncher<Intent> signinLauncher = requireActivity()
                .registerForActivityResult(new FirebaseAuthUIActivityResultContract(),
                        this::onSignInResult
                );

        Intent intent = AuthUI.getInstance().createSignInIntentBuilder()
                .setIsSmartLockEnabled(!BuildConfig.DEBUG)
                .setAvailableProviders(Collections.singletonList(
                        new AuthUI.IdpConfig.EmailBuilder().build()))
                .setLogo(R.mipmap.ic_launcher)
                .build();

        signinLauncher.launch(intent);
    }

    private void updateUI(FirebaseUser user) {
        if (user != null) {
            // Signed in
            mBinding.status.setText(getString(R.string.firebaseui_status_fmt, user.getEmail()));
            mBinding.detail.setText(getString(R.string.id_fmt, user.getUid()));

            mBinding.signInButton.setVisibility(View.GONE);
            mBinding.signOutButton.setVisibility(View.VISIBLE);
        } else {
            // Signed out
            mBinding.status.setText(R.string.signed_out);
            mBinding.detail.setText(null);

            mBinding.signInButton.setVisibility(View.VISIBLE);
            mBinding.signOutButton.setVisibility(View.GONE);
        }
    }

    private void signOut() {
        AuthUI.getInstance().signOut(getContext());
        updateUI(null);
    }
}


<|start_filename|>auth/app/src/main/java/com/google/firebase/quickstart/auth/kotlin/MultiFactorFragment.kt<|end_filename|>
package com.google.firebase.quickstart.auth.kotlin

import android.app.AlertDialog
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.core.view.isGone
import androidx.navigation.fragment.findNavController
import com.google.firebase.auth.FirebaseAuth
import com.google.firebase.auth.FirebaseUser
import com.google.firebase.auth.PhoneMultiFactorInfo
import com.google.firebase.auth.ktx.auth
import com.google.firebase.ktx.Firebase
import com.google.firebase.quickstart.auth.R
import com.google.firebase.quickstart.auth.databinding.FragmentMultiFactorBinding

class MultiFactorFragment : BaseFragment() {
    private lateinit var auth: FirebaseAuth

    private var _binding: FragmentMultiFactorBinding? = null
    private val binding: FragmentMultiFactorBinding
        get() = _binding!!

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        _binding = FragmentMultiFactorBinding.inflate(inflater, container, false)
        return binding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        setProgressBar(binding.progressBar)

        arguments?.let { args ->
            if (args.getBoolean(RESULT_NEEDS_MFA_SIGN_IN)) {
                findNavController().navigate(R.id.action_mfa_to_mfasignin, args)
            }
        }

        // Buttons
        binding.emailSignInButton.setOnClickListener {
            findNavController().navigate(R.id.action_mfa_to_emailpassword)
        }
        binding.signOutButton.setOnClickListener { signOut() }
        binding.verifyEmailButton.setOnClickListener { sendEmailVerification() }
        binding.enrollMfa.setOnClickListener {
            findNavController().navigate(R.id.action_mfa_to_enroll)
        }
        binding.unenrollMfa.setOnClickListener {
            findNavController().navigate(R.id.action_mfa_to_unenroll)
        }
        binding.reloadButton.setOnClickListener { reload() }

        // Initialize Firebase Auth
        auth = Firebase.auth

        showDisclaimer()
    }

    public override fun onStart() {
        super.onStart()
        // Check if user is signed in (non-null) and update UI accordingly.
        val currentUser = auth.currentUser
        updateUI(currentUser)
    }

    private fun signOut() {
        auth.signOut()
        updateUI(null)
    }

    private fun sendEmailVerification() { // Disable button
        binding.verifyEmailButton.isEnabled = false
        // Send verification email
        val user = auth.currentUser!!
        user.sendEmailVerification()
                .addOnCompleteListener(requireActivity()) { task ->
                    // Re-enable button
                    binding.verifyEmailButton.isEnabled = true
                    if (task.isSuccessful) {
                        Toast.makeText(context,
                                "Verification email sent to " + user.email,
                                Toast.LENGTH_SHORT).show()
                    } else {
                        Log.e(TAG, "sendEmailVerification", task.exception)
                        Toast.makeText(context,
                                "Failed to send verification email.",
                                Toast.LENGTH_SHORT).show()
                    }
                }
    }

    private fun reload() {
        auth.currentUser!!.reload().addOnCompleteListener { task ->
            if (task.isSuccessful) {
                updateUI(auth.currentUser)
                Toast.makeText(context,
                        "Reload successful!",
                        Toast.LENGTH_SHORT).show()
            } else {
                Log.e(TAG, "reload", task.exception)
                Toast.makeText(context,
                        "Failed to reload user.",
                        Toast.LENGTH_SHORT).show()
            }
        }
    }

    private fun updateUI(user: FirebaseUser?) {
        hideProgressBar()
        if (user != null) {
            binding.status.text = getString(R.string.emailpassword_status_fmt,
                    user.email, user.isEmailVerified)
            binding.detail.text = getString(R.string.firebase_status_fmt, user.uid)
            val secondFactors = user.multiFactor.enrolledFactors
            if (secondFactors.isEmpty()) {
                binding.unenrollMfa.visibility = View.GONE
            } else {
                binding.unenrollMfa.visibility = View.VISIBLE
                val sb = StringBuilder("Second Factors: ")
                val delimiter = ", "
                for (x in secondFactors) {
                    sb.append((x as PhoneMultiFactorInfo).phoneNumber + delimiter)
                }
                sb.setLength(sb.length - delimiter.length)
                binding.mfaInfo.text = sb.toString()
            }
            binding.emailSignInButton.visibility = View.GONE
            binding.signedInButtons.visibility = View.VISIBLE
            val reloadVisibility = if (secondFactors.isEmpty()) View.VISIBLE else View.GONE
            binding.reloadButton.visibility = reloadVisibility
            binding.verifyEmailButton.isGone = user.isEmailVerified
            binding.enrollMfa.isGone = !user.isEmailVerified
        } else {
            binding.status.setText(R.string.multi_factor_signed_out)
            binding.detail.text = null
            binding.mfaInfo.text = null
            binding.emailSignInButton.visibility = View.VISIBLE
            binding.signedInButtons.visibility = View.GONE
        }
    }

    private fun showDisclaimer() {
        AlertDialog.Builder(requireContext())
                .setTitle("Warning")
                .setMessage("Multi-factor authentication with SMS is currently only available for " +
                        "Google Cloud Identity Platform projects. For more information see: " +
                        "https://cloud.google.com/identity-platform/docs/android/mfa")
                .setPositiveButton("OK", null)
                .show()
    }

    override fun onDestroyView() {
        super.onDestroyView()
        _binding = null
    }

    companion object {
        const val RESULT_NEEDS_MFA_SIGN_IN = "RESULT_NEEDS_MFA"
        private const val TAG = "MultiFactor"
    }
}


<|start_filename|>database/app/src/main/java/com/google/firebase/quickstart/database/kotlin/SignInFragment.kt<|end_filename|>
package com.google.firebase.quickstart.database.kotlin

import android.os.Bundle
import android.text.TextUtils
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.navigation.fragment.findNavController
import com.google.firebase.auth.FirebaseAuth
import com.google.firebase.auth.FirebaseUser
import com.google.firebase.auth.ktx.auth
import com.google.firebase.database.DatabaseReference
import com.google.firebase.database.ktx.database
import com.google.firebase.ktx.Firebase
import com.google.firebase.quickstart.database.R
import com.google.firebase.quickstart.database.databinding.FragmentSignInBinding
import com.google.firebase.quickstart.database.kotlin.models.User

class SignInFragment : BaseFragment() {
    private var _binding: FragmentSignInBinding? = null
    private val binding get() = _binding!!

    private lateinit var database: DatabaseReference
    private lateinit var auth: FirebaseAuth

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        _binding = FragmentSignInBinding.inflate(inflater, container, false)
        return binding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        database = Firebase.database.reference
        auth = Firebase.auth

        setProgressBar(R.id.progressBar)

        // Click listeners
        with(binding) {
            buttonSignIn.setOnClickListener { signIn() }
            buttonSignUp.setOnClickListener { signUp() }
        }
    }

    override fun onStart() {
        super.onStart()

        // Check auth on Fragment start
        auth.currentUser?.let {
            onAuthSuccess(it)
        }
    }

    private fun signIn() {
        Log.d(TAG, "signIn")
        if (!validateForm()) {
            return
        }

        showProgressBar()
        val email = binding.fieldEmail.text.toString()
        val password = binding.fieldPassword.text.toString()

        auth.signInWithEmailAndPassword(email, password)
                .addOnCompleteListener(requireActivity()) { task ->
                    Log.d(TAG, "signIn:onComplete:" + task.isSuccessful)
                    hideProgressBar()

                    if (task.isSuccessful) {
                        onAuthSuccess(task.result?.user!!)
                    } else {
                        Toast.makeText(context, "Sign In Failed",
                                Toast.LENGTH_SHORT).show()
                    }
                }
    }

    private fun signUp() {
        Log.d(TAG, "signUp")
        if (!validateForm()) {
            return
        }

        showProgressBar()
        val email = binding.fieldEmail.text.toString()
        val password = binding.fieldPassword.text.toString()

        auth.createUserWithEmailAndPassword(email, password)
                .addOnCompleteListener(requireActivity()) { task ->
                    Log.d(TAG, "createUser:onComplete:" + task.isSuccessful)
                    hideProgressBar()

                    if (task.isSuccessful) {
                        onAuthSuccess(task.result?.user!!)
                    } else {
                        Toast.makeText(context, "Sign Up Failed",
                                Toast.LENGTH_SHORT).show()
                    }
                }
    }

    private fun onAuthSuccess(user: FirebaseUser) {
        val username = usernameFromEmail(user.email!!)

        // Write new user
        writeNewUser(user.uid, username, user.email)

        // Go to MainFragment
        findNavController().navigate(R.id.action_SignInFragment_to_MainFragment)
    }

    private fun usernameFromEmail(email: String): String {
        return if (email.contains("@")) {
            email.split("@".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()[0]
        } else {
            email
        }
    }

    private fun validateForm(): Boolean {
        var result = true
        if (TextUtils.isEmpty(binding.fieldEmail.text.toString())) {
            binding.fieldEmail.error = "Required"
            result = false
        } else {
            binding.fieldEmail.error = null
        }

        if (TextUtils.isEmpty(binding.fieldPassword.text.toString())) {
            binding.fieldPassword.error = "Required"
            result = false
        } else {
            binding.fieldPassword.error = null
        }

        return result
    }

    private fun writeNewUser(userId: String, name: String, email: String?) {
        val user = User(name, email)
        database.child("users").child(userId).setValue(user)
    }

    override fun onDestroy() {
        super.onDestroy()
        _binding = null
    }

    companion object {
        private const val TAG = "SignInFragment"
    }
}

<|start_filename|>auth/app/src/main/java/com/google/firebase/quickstart/auth/kotlin/MultiFactorSignInFragment.kt<|end_filename|>
package com.google.firebase.quickstart.auth.kotlin

import android.os.Bundle
import android.text.TextUtils
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.navigation.fragment.findNavController
import com.google.firebase.FirebaseException
import com.google.firebase.auth.MultiFactorResolver
import com.google.firebase.auth.PhoneAuthCredential
import com.google.firebase.auth.PhoneAuthOptions
import com.google.firebase.auth.PhoneAuthProvider
import com.google.firebase.auth.PhoneMultiFactorGenerator
import com.google.firebase.auth.PhoneMultiFactorInfo
import com.google.firebase.quickstart.auth.databinding.FragmentMultiFactorSignInBinding
import java.util.concurrent.TimeUnit

/**
 * Fragment that handles MFA sign-in
 */
class MultiFactorSignInFragment : BaseFragment() {

    private var _binding: FragmentMultiFactorSignInBinding? = null
    private val binding: FragmentMultiFactorSignInBinding
        get() = _binding!!

    private lateinit var multiFactorResolver: MultiFactorResolver
    private var lastPhoneAuthCredential: PhoneAuthCredential? = null
    private var lastVerificationId: String? = null

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        return super.onCreateView(inflater, container, savedInstanceState)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        savedInstanceState?.let { onViewStateRestored(it) }

        // Users are currently limited to having 5 second factors
        val phoneFactorButtonList = listOf(
                binding.phoneFactor1, binding.phoneFactor2, binding.phoneFactor3,
                binding.phoneFactor4, binding.phoneFactor5)
        for (button in phoneFactorButtonList) {
            button.visibility = View.GONE
        }

        binding.finishMfaSignIn.setOnClickListener { onClickFinishSignIn() }
        multiFactorResolver = getResolverFromArguments(requireArguments())

        val multiFactorInfoList = multiFactorResolver.hints
        for (i in multiFactorInfoList.indices) {
            val phoneMultiFactorInfo = multiFactorInfoList[i] as PhoneMultiFactorInfo
            val button = phoneFactorButtonList[i]
            button.visibility = View.VISIBLE
            button.text = phoneMultiFactorInfo.phoneNumber
            button.isClickable = true
            button.setOnClickListener(generateFactorOnClickListener(phoneMultiFactorInfo))
        }
    }

    override fun onSaveInstanceState(bundle: Bundle) {
        super.onSaveInstanceState(bundle)
        bundle.putString(KEY_VERIFICATION_ID, lastVerificationId)
    }

    override fun onViewStateRestored(savedInstanceState: Bundle?) {
        super.onViewStateRestored(savedInstanceState)
        savedInstanceState?.let { savedState ->
            lastVerificationId = savedState.getString(KEY_VERIFICATION_ID)
        }
    }

    private fun generateFactorOnClickListener(phoneMultiFactorInfo: PhoneMultiFactorInfo): View.OnClickListener {
        return View.OnClickListener {
            PhoneAuthProvider.verifyPhoneNumber(
                    PhoneAuthOptions.newBuilder()
                            .setActivity(requireActivity())
                            .setMultiFactorSession(multiFactorResolver.session)
                            .setMultiFactorHint(phoneMultiFactorInfo)
                            .setCallbacks(generateCallbacks()) // A timeout of 0 disables SMS-auto-retrieval.
                            .setTimeout(0L, TimeUnit.SECONDS)
                            .build())
        }
    }

    private fun generateCallbacks(): PhoneAuthProvider.OnVerificationStateChangedCallbacks {
        return object : PhoneAuthProvider.OnVerificationStateChangedCallbacks() {
            override fun onVerificationCompleted(phoneAuthCredential: PhoneAuthCredential) {
                lastPhoneAuthCredential = phoneAuthCredential
                binding.finishMfaSignIn.performClick()
                Toast.makeText(context, "Verification complete!", Toast.LENGTH_SHORT)
                        .show()
            }

            override fun onCodeSent(verificationId: String, token: PhoneAuthProvider.ForceResendingToken) {
                lastVerificationId = verificationId
                binding.finishMfaSignIn.isClickable = true
            }

            override fun onVerificationFailed(e: FirebaseException) {
                Toast.makeText(context, "Error: ${e.message}", Toast.LENGTH_SHORT)
                        .show()
            }
        }
    }

    private fun getResolverFromArguments(arguments: Bundle): MultiFactorResolver {
        return arguments.getParcelable(EXTRA_MFA_RESOLVER)!!
    }

    private fun onClickFinishSignIn() {
        if (lastPhoneAuthCredential == null) {
            if (TextUtils.isEmpty(binding.smsCode.text.toString())) {
                Toast.makeText(context, "You need to enter an SMS code.", Toast.LENGTH_SHORT)
                        .show()
                return
            }
            lastPhoneAuthCredential = PhoneAuthProvider.getCredential(
                    lastVerificationId!!, binding.smsCode.text.toString())
        }
        multiFactorResolver
                .resolveSignIn(PhoneMultiFactorGenerator.getAssertion(lastPhoneAuthCredential!!))
                .addOnSuccessListener {
                    findNavController().popBackStack()
                }
                .addOnFailureListener { e ->
                    Toast.makeText(context, "Error: " + e.message, Toast.LENGTH_SHORT)
                            .show()
                }
    }

    override fun onDestroyView() {
        super.onDestroyView()
        _binding = null
    }

    companion object {
        private const val KEY_VERIFICATION_ID = "key_verification_id"
        const val EXTRA_MFA_RESOLVER = "EXTRA_MFA_RESOLVER"
    }
}

<|start_filename|>auth/app/src/main/java/com/google/firebase/quickstart/auth/java/GenericIdpFragment.java<|end_filename|>
/**
 * Copyright 2016 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.google.firebase.quickstart.auth.java;

import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.auth.AuthResult;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.FirebaseUser;
import com.google.firebase.auth.OAuthProvider;
import com.google.firebase.quickstart.auth.R;
import com.google.firebase.quickstart.auth.databinding.FragmentGenericIdpBinding;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Demonstrate Firebase Authentication using a Generic Identity Provider (IDP).
 */
@SuppressWarnings("Convert2Lambda")
public class GenericIdpFragment extends BaseFragment {

    private static final String TAG = "GenericIdp";

    private static final Map<String,String> PROVIDER_MAP = new HashMap<String, String>() {
        {
            put("Apple", "apple.com");
            put("Microsoft", "microsoft.com");
            put("Yahoo", "yahoo.com");
            put("Twitter", "twitter.com");
        }
    };

    private FragmentGenericIdpBinding mBinding;
    private ArrayAdapter<String> mSpinnerAdapter;

    private FirebaseAuth mAuth;

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        mBinding = FragmentGenericIdpBinding.inflate(inflater, container, false);
        return mBinding.getRoot();
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        // Initialize Firebase Auth
        mAuth = FirebaseAuth.getInstance();

        // Set up button click listeners
        mBinding.genericSignInButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                signIn();
            }
        });
        mBinding.signOutButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mAuth.signOut();
                updateUI(null);
            }
        });

        // Spinner
        List<String> providers = new ArrayList<>(PROVIDER_MAP.keySet());
        mSpinnerAdapter = new ArrayAdapter<>(requireContext(), R.layout.item_spinner_list, providers);
        mBinding.providerSpinner.setAdapter(mSpinnerAdapter);
        mBinding.providerSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                mBinding.genericSignInButton.setText(getString(R.string.generic_signin_fmt, mSpinnerAdapter.getItem(position)));
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {}
        });
        mBinding.providerSpinner.setSelection(0);
    }

    @Override
    public void onStart() {
        super.onStart();
        // Check if user is signed in (non-null) and update UI accordingly.
        FirebaseUser currentUser = mAuth.getCurrentUser();
        updateUI(currentUser);

        // Look for a pending auth result
        Task<AuthResult> pending = mAuth.getPendingAuthResult();
        if (pending != null) {
            pending.addOnSuccessListener(new OnSuccessListener<AuthResult>() {
                @Override
                public void onSuccess(AuthResult authResult) {
                    Log.d(TAG, "checkPending:onSuccess:" + authResult);
                    updateUI(authResult.getUser());
                }
            }).addOnFailureListener(new OnFailureListener() {
                @Override
                public void onFailure(@NonNull Exception e) {
                    Log.w(TAG, "checkPending:onFailure", e);
                }
            });
        } else {
            Log.d(TAG, "checkPending: null");
        }
    }

    private void signIn() {
        // Could add custom scopes here
        ArrayList<String> scopes = new ArrayList<>();

        // Examples of provider ID: apple.com (Apple), microsoft.com (Microsoft), yahoo.com (Yahoo)
        String providerId = getProviderId();

        mAuth.startActivityForSignInWithProvider(requireActivity(),
                OAuthProvider.newBuilder(providerId, mAuth)
                        .setScopes(scopes)
                        .build())
                .addOnSuccessListener(
                        new OnSuccessListener<AuthResult>() {
                            @Override
                            public void onSuccess(AuthResult authResult) {
                                Log.d(TAG, "activitySignIn:onSuccess:" + authResult.getUser());
                                updateUI(authResult.getUser());
                            }
                        })
                .addOnFailureListener(
                        new OnFailureListener() {
                            @Override
                            public void onFailure(@NonNull Exception e) {
                                Log.w(TAG, "activitySignIn:onFailure", e);
                                showToast(getString(R.string.error_sign_in_failed));
                            }
                        });
    }

    private String getProviderId() {
        String providerName = mSpinnerAdapter.getItem(mBinding.providerSpinner.getSelectedItemPosition());
        return PROVIDER_MAP.get(providerName);
    }

    private void updateUI(FirebaseUser user) {
        hideProgressBar();
        if (user != null) {
            mBinding.status.setText(getString(R.string.generic_status_fmt, user.getDisplayName(), user.getEmail()));
            mBinding.detail.setText(getString(R.string.firebase_status_fmt, user.getUid()));

            mBinding.spinnerLayout.setVisibility(View.GONE);
            mBinding.genericSignInButton.setVisibility(View.GONE);
            mBinding.signOutButton.setVisibility(View.VISIBLE);
        } else {
            mBinding.status.setText(R.string.signed_out);
            mBinding.detail.setText(null);

            mBinding.spinnerLayout.setVisibility(View.VISIBLE);
            mBinding.genericSignInButton.setVisibility(View.VISIBLE);
            mBinding.signOutButton.setVisibility(View.GONE);
        }
    }

    private void showToast(String message) {
        Toast.makeText(getContext(), message, Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        mBinding = null;
    }
}


<|start_filename|>auth/app/src/main/java/com/google/firebase/quickstart/auth/java/CustomAuthFragment.java<|end_filename|>
/**
 * Copyright Google Inc. All Rights Reserved.
 * <p/>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p/>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p/>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.google.firebase.quickstart.auth.java;

import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;

import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.auth.AuthResult;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.FirebaseUser;
import com.google.firebase.quickstart.auth.databinding.FragmentCustomBinding;

/**
 * Demonstrate Firebase Authentication using a custom minted token. For more information, see:
 * https://firebase.google.com/docs/auth/android/custom-auth
 */
public class CustomAuthFragment extends Fragment {

    private static final String TAG = "CustomAuthFragment";

    private FirebaseAuth mAuth;

    private FragmentCustomBinding mBinding;
    private String mCustomToken;
    private TokenBroadcastReceiver mTokenReceiver;

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        mBinding = FragmentCustomBinding.inflate(inflater, container, false);
        return mBinding.getRoot();
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        // Button click listeners
        mBinding.buttonSignIn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                startSignIn();
            }
        });

        // Create token receiver (for demo purposes only)
        mTokenReceiver = new TokenBroadcastReceiver() {
            @Override
            public void onNewToken(String token) {
                Log.d(TAG, "onNewToken:" + token);
                setCustomToken(token);
            }
        };

        // Initialize Firebase Auth
        mAuth = FirebaseAuth.getInstance();
    }

    @Override
    public void onStart() {
        super.onStart();
        // Check if user is signed in (non-null) and update UI accordingly.
        FirebaseUser currentUser = mAuth.getCurrentUser();
        updateUI(currentUser);
    }

    @Override
    public void onResume() {
        super.onResume();
        requireActivity().registerReceiver(mTokenReceiver, TokenBroadcastReceiver.getFilter());
    }


    @Override
    public void onPause() {
        super.onPause();
        requireActivity().unregisterReceiver(mTokenReceiver);
    }

    private void startSignIn() {
        // Initiate sign in with custom token
        mAuth.signInWithCustomToken(mCustomToken)
                .addOnCompleteListener(requireActivity(), new OnCompleteListener<AuthResult>() {
                    @Override
                    public void onComplete(@NonNull Task<AuthResult> task) {
                        if (task.isSuccessful()) {
                            // Sign in success, update UI with the signed-in user's information
                            Log.d(TAG, "signInWithCustomToken:success");
                            FirebaseUser user = mAuth.getCurrentUser();
                            updateUI(user);
                        } else {
                            // If sign in fails, display a message to the user.
                            Log.w(TAG, "signInWithCustomToken:failure", task.getException());
                            Toast.makeText(getContext(), "Authentication failed.",
                                    Toast.LENGTH_SHORT).show();
                            updateUI(null);
                        }
                    }
                });
    }

    private void updateUI(FirebaseUser user) {
        if (user != null) {
            mBinding.textSignInStatus.setText("User ID: " + user.getUid());
        } else {
            mBinding.textSignInStatus.setText("Error: sign in failed.");
        }
    }

    private void setCustomToken(String token) {
        mCustomToken = token;

        String status;
        if (mCustomToken != null) {
            status = "Token:" + mCustomToken;
        } else {
            status = "Token: null";
        }

        // Enable/disable sign-in button and show the token
        mBinding.buttonSignIn.setEnabled((mCustomToken != null));
        mBinding.textTokenStatus.setText(status);
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        mBinding = null;
    }
}


<|start_filename|>database/app/src/main/java/com/google/firebase/quickstart/database/kotlin/viewholder/CommentViewHolder.kt<|end_filename|>
package com.google.firebase.quickstart.database.kotlin.viewholder

import android.view.View
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.google.firebase.quickstart.database.R
import com.google.firebase.quickstart.database.kotlin.models.Comment

class CommentViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
    fun bind(comment: Comment) {
        itemView.findViewById<TextView>(R.id.commentAuthor).text = comment.author
        itemView.findViewById<TextView>(R.id.commentBody).text = comment.text
    }
}