35

Używam ACRA (arca.ch) do generowania raportów o błędach.GooglePlayServicesUtil.getErrorDialog ma wartość null

Właśnie wydałem nową wersję mojej aplikacji za pomocą Google Maps Android API v2. Dostaję błąd zgłoszony przez użytkowników EEEPad i Transformer Pad podczas próby wyświetlenia okna zwróconego przez GooglePlayServicesUtil.getErrorDialog. Czy ktoś wie, dlaczego tak się stało?

Oto odpowiedni kod i Logcat jak donosi Acra:

Podczas rozmowy tej linii:

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(); 
} 
... 

Logcat:

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. 

Dzięki z góry za wszelką pomoc można dostarczyć .

Aktualizacja

Problem nie został rozwiązany przez google i jeszcze będę aktualizować tę kwestię raz słyszę coś (patrz odpowiedź CommonsWare za Bug linku raport Google). W tym czasie, jeśli natkniesz się tego problemu i nie chcą swoją aplikację do katastrofy, oto co robię na razie:

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(); 
} 
+0

Witaj, DiscDev, Kiedy próbuję użyć showOkDialogWithText(), pojawia się błąd mówiący, że "nie można utworzyć programu obsługi wewnątrz wątku, który nie nazwał looper.prepare()", dlaczego próbuje uruchomić wątek roboczy zamiast wątku interfejsu użytkownika? –

Odpowiedz

37

Google suggests (również w docs) wywołanie getErrorDialog() jeśli wynik kod to SERVICE_MISSING, SERVICE_VERSION_UPDATE_REQUIRED lub SERVICE_DISABLED. Możliwe, że ostatni możliwy kod stanu (SERVICE_INVALID) jest przyczyną problemów.

Używam poniższy kod i jak dotąd wydaje się działać OK (testowanie w emulatorze, platformę 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(); 
} 
+0

Właśnie przetestowałem 'getErrorDialog' z' ConnectionResult.SERVICE_INVALID' i otrzymałem 'null' na moim Nexusie S. Więc przypuszczam, że ta odpowiedź jest poprawna. –

+1

Więc ignorujesz SERVICE_INVALID razem? Czy nie powinno to być również obsługiwane? – ComputerEngineer88

+0

Należy użyć ** GoogleApiAvailable **, a nie ** GooglePlayServicesUtil **. –

22

Wygląda na to trzeba sprawdzić z isUserRecoverableError przed próbą, aby wyświetlić dialog.

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(); 
    } 
    } 
+3

+1 - GooglePlayServicesUtil.isUserRecoverableError (status) jest bardziej elegancki niż wyliczanie wszystkich możliwych stanów. –

+0

+1 - Używam tego teraz, ale po przeczytaniu tego pytania, myślę, że sprawdzę również wartość zerową, ponieważ łatwo ją dodać. – eselk

8

podstawie kodu Rahim za dodaję zdolność zapobiegania użytkownikowi oddalenie Google Play dialogowe Usługi (przez naciśnięcie przycisku Wstecz) i kontynuować korzystanie z aplikacji bez usług Google Play zainstalowane:

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(); 
     } 
    } 
} 
+0

+1 dzięki za udostępnienie tego bardziej kompletnego rozwiązania. –

+0

Dobry dodatkowy dodatek. –

0

aktualizację odpowiedź @Nevermore, ponieważ GooglePlayServicesUtil metody zastąpiona 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(); 
} 

Uwaga: kolejność pierwszych dwóch parametrów w getErrorDialog() została zmieniona w implementacji GoogleApiAvailability.