Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Styling dialog presented via GoogleApiAvailability.showErrorDialogFragment independently of Activity

Background

I have an Activity with the following theme applied:

<style name="BlueTheme" parent="Theme.AppCompat.Light.NoActionBar">
    <item name="colorPrimary">@color/light_blue</item>
    <item name="colorPrimaryDark">@color/dark_blue</item>
    <item name="colorAccent">@color/mid_blue</item>
    <item name="android:textColor">@color/white</item>
    <item name="android:windowBackground">@color/light_blue</item>
    <item name="dialogTheme">@style/BaseDialog</item>
    <item name="alertDialogTheme">@style/BaseDialog</item>
    ...
</style>

where the dialog theme is defined as follows:

<style name="BaseDialog" parent="Theme.AppCompat.Dialog.Alert">
    <item name="colorAccent">@color/light_blue</item>
    <item name="android:textColor">@color/black</item>
    <item name="android:textColorPrimary">@color/gray</item>
    <item name="android:background">@color/white</item>
</style>

The majority of the content of this screen is presented as white text on an all-blue background.

This Activity attempts to update the device security provider by invoking ProviderInstaller.installIfNeededAsync(this, this);. If this fails, I show a dialog using the following code:

@Override
public void onProviderInstallFailed(final int errorCode, final Intent recoveryIntent) {
    final GoogleApiAvailability googleApiAvailability = GoogleApiAvailability.getInstance();

    if (googleApiAvailability.isUserResolvableError(errorCode)) {
        googleApiAvailability.showErrorDialogFragment(
                this,
                errorCode,
                ERROR_RESOLUTION_REQUEST_CODE);
    }
}

Here's what that dialog looks like for one example failure:

enter image description here

This is a problem. The dialog title is white, so is not visible against the dialog background. Note that support alert dialogs displayed manually on other screens are correctly colored according to the BaseDialog style.

Research So Far

The Dialog presented by calling googleApiAvailability.showErrorDialogFragment is constructed using an instance of android.app.AlertDialog.Builder rather than android.support.v7.app.AlertDialog.Builder. Given this, my belief is that the colors of the platform dialog are being populated as follows:

  • title from BlueTheme.android:textcolor
  • message from BlueTheme.android:primaryTextColor
  • button from BlueTheme.colorAccent

and are not populated using values from BlueTheme.dialogTheme or BlueTheme.alertDialogTheme.

I've been considering the following options for working around this issue:

  1. Manually show a support alert dialog. Cons of this approach: no way to retrieve the custom per-error-code title/message that the built-in dialog would use (as far as I can tell);
  2. Set android:textColor, android:textColorPrimary and colorAccent in BlueTheme to the values needed to obtain a correctly-colored dialog, then override these colors per-widget in XML layout files. Cons of this approach: ugly, lots of overriding needed;

Neither seem great. I also briefly investigated using a ContextThemeWrapper (no go, the showErrorDialogFragment method requires an Activity instance) and looked for a way to request that the Google Play Services dialog be constructed using a support AlertDialog builder (didn't find one).

Question

Am I missing a more obvious approach to styling this dialog?

like image 460
stkent Avatar asked Sep 11 '25 12:09

stkent


1 Answers

    GoogleApiAvailability googleAPI = GoogleApiAvailability.getInstance();
    int googlePlayServicesAvailableError = googleAPI.isGooglePlayServicesAvailable(this);
    Intent errorResolutionIntent = googleAPI.getErrorResolutionIntent(this, googlePlayServicesAvailableError, null);

    AlertDialog.Builder builder = new AlertDialog.Builder(this, R.style.DialogTheme);
    builder.setTitle("Title");
    builder.setMessage(ConnectionErrorMessages.getErrorMessage(this, googlePlayServicesAvailableError));
    builder.setPositiveButton(ConnectionErrorMessages.getErrorDialogButtonMessage(this, googlePlayServicesAvailableError), new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int which) {
            startActivityForResult(errorResolutionIntent, REQUEST_GOOGLE_PLAY_SERVICES);
        }
    });
    builder.setCancelable(false);

    if (!isFinishing()) {
        builder.show();
    } 
like image 141
Mladen Rakonjac Avatar answered Sep 14 '25 02:09

Mladen Rakonjac