GooglePlayServicesUtil.getErrorDialog имеет значение null

Я использую ACRA (arca.ch) для создания автоматических отчетов об ошибках.

Я только что выпустил новую версию своего приложения с использованием Google Maps Android API v2. Я получаю сообщение об ошибке от пользователей EEEPad и Transformer Pad при попытке отобразить диалоговое окно, возвращенное GooglePlayServicesUtil.getErrorDialog. Кто-нибудь знает, почему это может произойти?

Вот соответствующий код и Logcat, как сообщает acra:

При вызове этой строки:

int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
if(resultCode != ConnectionResult.SUCCESS)
{
        //The dialog that comes back is null (probably due to the logcat message)
        Dialog dialog = GooglePlayServicesUtil.getErrorDialog(resultCode, this, 69);
        //So when I call the next line, the app crashes with a NullPointerException
        dialog.show();
}
...

Логкат:

12-18 04:21:04.531 W/GooglePlayServicesUtil( 3977): Google Play Store signature invalid.
12-18 04:21:04.551 E/GooglePlayServicesUtil( 3977): Google Play services is invalid. Cannot recover.

Заранее благодарим за любую помощь, которую вы можете предоставить.

Обновить

Google еще не решил проблему, и я обновлю этот вопрос, как только что-нибудь услышу (см. ответ CommonsWare для ссылки на отчет об ошибке Google). В то же время, если вы столкнулись с этой проблемой и не хотите, чтобы ваше приложение зависло, вот что я сейчас делаю:

public void checkGooglePlayServicesAvailability()
{
    int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
    if(resultCode != ConnectionResult.SUCCESS)
    {
        Dialog dialog = GooglePlayServicesUtil.getErrorDialog(resultCode, this, 69);
        if(dialog != null)
        {
            dialog.show();                
        }
        else
        {
            showOkDialogWithText(this, "Something went wrong. Please make sure that you have the Play Store installed and that you are connected to the internet. Contact developer with details if this persists.");
        }
    }

    Log.d("GooglePlayServicesUtil Check", "Result is: " + resultCode);
}

public static void showOkDialogWithText(Context context, String messageText)
{
    Builder builder = new AlertDialog.Builder(context);
    builder.setMessage(messageText);
    builder.setCancelable(true);
    builder.setPositiveButton("OK", null);
    AlertDialog dialog = builder.create();
    dialog.show();
}

person DiscDev    schedule 18.12.2012    source источник
comment
Привет, DiscDev! Когда я пытаюсь использовать showOkDialogWithText(), выдается ошибка, говорящая о том, что невозможно создать обработчик внутри потока, который не вызвал looper.prepare(), почему он пытается работать в рабочем потоке, а не в потоке пользовательского интерфейса?   -  person Satish Sojitra    schedule 28.02.2017


Ответы (4)


Google предлагает (также в docs), вызывая getErrorDialog(), если код результата SERVICE_MISSING, SERVICE_VERSION_UPDATE_REQUIRED или SERVICE_DISABLED. Таким образом, возможно, последний возможный код состояния (SERVICE_INVALID) вызывает проблемы.

Я использую следующий код, и пока он работает нормально (тестирование в эмуляторе, платформа 2.3.3):

int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(activity.getApplicationContext());
if (resultCode == ConnectionResult.SUCCESS) {
    activity.selectMap();
} else if (resultCode == ConnectionResult.SERVICE_MISSING ||
           resultCode == ConnectionResult.SERVICE_VERSION_UPDATE_REQUIRED ||
           resultCode == ConnectionResult.SERVICE_DISABLED) {
    Dialog dialog = GooglePlayServicesUtil.getErrorDialog(resultCode, activity, 1);
    dialog.show();
}
person Nevermore    schedule 04.01.2013
comment
Я только что проверил getErrorDialog с ConnectionResult.SERVICE_INVALID и получил null на своем Nexus S. Так что я полагаю, что этот ответ правильный. - person Alexander Mironov; 09.01.2013
comment
Итак, вы все вместе игнорируете SERVICE_INVALID? Разве это не должно быть обработано также? - person CompEng88; 28.03.2014
comment
Следует использовать GoogleApiAvailability, а не GooglePlayServicesUtil. - person IgorGanapolsky; 20.12.2016

Похоже, вам нужно проверить с помощью isUserRecoverableError, прежде чем пытаться отобразить диалог.

  int status = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
  if (status != ConnectionResult.SUCCESS) {
    if (GooglePlayServicesUtil.isUserRecoverableError(status)) {
      GooglePlayServicesUtil.getErrorDialog(status, this, 
      REQUEST_CODE_RECOVER_PLAY_SERVICES).show();
    } else {
      Toast.makeText(this, "This device is not supported.", 
          Toast.LENGTH_LONG).show();
      finish();
    }
  }
person Rahim    schedule 04.08.2013
comment
+1 - GooglePlayServicesUtil.isUserRecoverableError(status) более элегантен, чем перечисление всех возможных состояний. - person Ondrej Svejdar; 17.02.2014
comment
+1 - я использую это сейчас, но после прочтения этого вопроса я думаю, что я также проверю на нулевое значение, так как его легко добавить. - person eselk; 25.06.2015

На основе кода Рахима я добавляю возможность запретить пользователю закрывать диалоговое окно Службы Google Play (нажав кнопку «Назад») и продолжать использовать приложение без установленных Служб Google Play:

private void checkGooglePlayServicesAvailable() {
    int status = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
    if (status != ConnectionResult.SUCCESS) {
        if (GooglePlayServicesUtil.isUserRecoverableError(status)) {
            Dialog dialog = GooglePlayServicesUtil.getErrorDialog(status, this, 0);
            dialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
                @Override
                public void onCancel(DialogInterface dialogInterface) {
                    MainActivity.this.finish();
                }
            });
            dialog.show();
        } else {
            Toast.makeText(this, "This device is not supported.", Toast.LENGTH_LONG).show();
            finish();
        }
    }
}
person Daniele B    schedule 26.03.2014

Обновление ответа @Nevermore, поскольку методы GooglePlayServicesUtil устарели в пользу GoogleApiAvailability:

GoogleApiAvailability googleApiAvailability = GoogleApiAvailability.getInstance();
int resultCode = googleApiAvailability.isGooglePlayServicesAvailable(activity.getApplicationContext());
if (resultCode == ConnectionResult.SUCCESS) {
    activity.selectMap();
} else if (resultCode == ConnectionResult.SERVICE_MISSING ||
           resultCode == ConnectionResult.SERVICE_VERSION_UPDATE_REQUIRED ||
           resultCode == ConnectionResult.SERVICE_DISABLED) {
    Dialog dialog = googleApiAvailability.getErrorDialog(activity, resultCode, 1);
    dialog.show();
}

Обратите внимание, что порядок первых двух параметров в getErrorDialog() был изменен в реализации GoogleApiAvailability.

person DaveAlden    schedule 11.10.2016