J'utilise ACRA ( arca.ch ) pour générer des rapports d'erreur automatiques.
Je viens de publier une nouvelle version de mon application à l'aide de l'API v2 de Google Maps Android. Je reçois une erreur signalée par les utilisateurs d'EEEPad et de Transformer Pad lorsque je tente d'afficher la boîte de dialogue renvoyée par GooglePlayServicesUtil.getErrorDialog. Est-ce que quelqu'un sait pourquoi cela pourrait arriver?
Voici le code pertinent et Logcat tels que rapportés par acra:
En appelant cette ligne:
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.
Merci d'avance pour toute aide que vous pouvez fournir.
Mettre à jour
Le problème n'a pas encore été résolu par Google et je mettrai à jour cette question dès que j'aurai entendu quoi que ce soit (voir la réponse de CommonsWare pour le lien du rapport Google Bug). En attendant, si vous rencontrez ce problème et que vous ne voulez pas que votre application se bloque, voici ce que je fais pour le moment:
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();
}
Google suggère (également dans docs ) d’appeler getErrorDialog()
si le code de résultat est SERVICE_MISSING
, SERVICE_VERSION_UPDATE_REQUIRED
ou SERVICE_DISABLED
. Donc, il se peut que le dernier code d’état possible (SERVICE_INVALID
) soit la cause du problème.
J'utilise le code suivant et jusqu'à présent, il semble fonctionner correctement (test sur émulateur, plate-forme 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();
}
On dirait que vous devez vérifier avec isUserRecoverableError
avant d'essayer d'afficher la boîte de dialogue.
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();
}
}
En fonction du code de Rahim, j'ajoute la possibilité d'empêcher l'utilisateur de fermer la boîte de dialogue Services Google Play (en appuyant sur le bouton Précédent) et de continuer à utiliser l'application sans les services 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();
}
}
}
Mise à jour de la réponse par @Nevermore , puisque les méthodes GooglePlayServicesUtil
sont déconseillées au profit de 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();
}
Notez que l'ordre des deux premiers paramètres dans getErrorDialog()
a été inversé dans l'implémentation GoogleApiAvailability
.