'Firebase Authentication failing on android emulators due to missing Play Store

I've been tryin to get Firebase Authentication working, but I keep getting the following errors in Logcat when I try to login.

These seems to indicate that the Play Store needs to be installed for Authentication to work? Is there a way to do that on an emulator?

I'm using the "API 30 x86 with Google APIs" system image to test with and am getting this error every time.

Testing with a physical device seems to work as expected. But I've been unable to find a work-around for the emulators thus far.

Logcat

2022-03-08 09:38:37.265 3784-3784/<package-name> W/GooglePlayServicesUtil: <package-name> requires the Google Play Store, but it is missing.
2022-03-08 09:38:37.270 3784-3810/<package-name> W/GooglePlayServicesUtil: <package-name> requires the Google Play Store, but it is missing.
2022-03-08 09:38:37.270 3784-3810/<package-name> W/GoogleApiManager: The service for com.google.android.gms.internal.auth-api.zbo is not available: ConnectionResult{statusCode=SERVICE_INVALID, resolution=null, message=null}
2022-03-08 09:38:37.363 3784-3784/<package-name> E/LoginActivity: sign-in failed
    com.firebase.ui.auth.FirebaseUiException: Exception serialization error, forced wrapping. Original: com.firebase.ui.auth.FirebaseUiException: Play Services update cancelled, original cause: com.google.android.gms.common.api.ApiException: 9: Error connecting to Google Play services
        at com.firebase.ui.auth.KickoffActivity$2.onFailure(KickoffActivity.java:77)
        at com.google.android.gms.tasks.zzk.run(com.google.android.gms:play-services-tasks@@18.0.1:1)
        at android.os.Handler.handleCallback(Handler.java:938)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:223)
        at android.app.ActivityThread.main(ActivityThread.java:7656)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)

LoginActivity

public class LoginActivity extends AppCompatActivity {
    private static final String LOG_TAG = LoginActivity.class.getSimpleName();
    private Button loginButton;
    private ActivityResultLauncher<Intent> signInLauncher;

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

        // Register a callback for when the sign in process is complete
        signInLauncher =
            registerForActivityResult(
                new FirebaseAuthUIActivityResultContract(),
                (result) -> onSignInResult(result)
            );

        // Register click listener
        loginButton = findViewById(R.id.loginButton);
        loginButton.setOnClickListener((view) -> {

            // Choose authentication providers
            List<AuthUI.IdpConfig> providers = new ArrayList<>();
            providers.add(new AuthUI.IdpConfig.EmailBuilder().build());
            providers.add(new AuthUI.IdpConfig.GoogleBuilder().build());

            // Create sign-in intent
            Intent signInIntent =
                AuthUI.getInstance()
                    .createSignInIntentBuilder()
                    .setAvailableProviders(providers)
                    .build();

            // Launch sign-in activity
            signInLauncher.launch(signInIntent);
        });
    }

    private void onSignInResult(FirebaseAuthUIAuthenticationResult result) {
        if (result.getResultCode() == RESULT_OK) {
            FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
            Log.i(LOG_TAG, "sign-in successful: " + user.getUid());
        } else {
            IdpResponse response = result.getIdpResponse();
            if (response != null) {
                FirebaseUiException error = response.getError();
                Log.e(LOG_TAG, "sign-in failed", error);
            } else {
                Log.e(LOG_TAG, "sign-in failed: no response");
            }
        }
    }
}

Documentation

This code is based on Easily add sign-in to your Android app with FirebaseUI



Solution 1:[1]

Contrary to what I expected, it seems that the Play Store images are only available for some devices.

Mix of virtual devices, with and without the play store in AVD manager

I typically use the "Nexus S" phone and "Nexus 7" tablet for testing, as they have low resolutions and are less resource-intensive. However Google does not seem to support installing the Play Store on either of those images. ?

To create an emulator with the Play Store pre-installed:

  1. Open the Android Virtual Device (AVD) Manager in Android Studio.
  2. Click on "Create Virtual Device..." Create Virtual Device button in AVD Manager
  3. Select one of the small number Pixel Phones that support the Play Store. Supported Pixel Phones
  4. Now you will be able to download and use the images with (Play Store) for testing. Download Play Store Images
  5. Happy hunting!

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Paul Smith