GooglePlayServicesUtil vs GoogleApiAvailability

102

Estou tentando usar o Google Play Service em meu aplicativo Android. Como diz o documento do Google, precisamos verificar se a API do Google está disponível antes de usá-la. Eu procurei alguma maneira de verificar isso. Aqui está o que eu tenho:

private boolean checkPlayServices() {
int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
if (resultCode != ConnectionResult.SUCCESS) {
    if (GooglePlayServicesUtil.isUserRecoverableError(resultCode)) {
        GooglePlayServicesUtil.getErrorDialog(resultCode, this,
                PLAY_SERVICES_RESOLUTION_REQUEST).show();
    } else {
        Log.i(TAG, "This device is not supported.");
        finish();
    }
    return false;
}
return true;
}

Mas quando vou para a página GooglePlayServicesUtil do Google Api, https://developers.google.com/android/reference/com/google/android/gms/common/GooglePlayServicesUtil

Acho que todas as funções estão obsoletas . Por exemplo, o método

GooglePlayServicesUtil.isGooglePlayServicesAvailable (obsoleto)

E o Google recomenda usar:

GoogleApiAvailability.isGooglePlayServicesAvailable .

No entanto, quando tento usar GoogleApiAvailability.isGooglePlayServicesAvailable, recebo a mensagem de erro:

insira a descrição da imagem aqui

James
fonte
onde encontro GoogleApiAvailability? Eu não consigo encontrar.
mcmillab
@mcmillab +1. Eu atualizei de 8.1.0 para 8.4.0 e GooglePlayServicesUtilsumiu (o que parece uma má prática para uma atualização "menor"), mas não estou vendo GoogleApiAvailabilitypara usar como um substituto.
spaaarky21
Ao atualizar para o Firebase, verifique
Dawid Drozd

Respostas:

203

Eu encontrei a solução. No GoogleApiAvailability, todos os métodos são métodos públicos, enquanto em GooglePlayServicesUtiltodos os métodos são funções públicas estáticas.

Portanto, para usar GoogleApiAvailability, a maneira certa é:

private boolean checkPlayServices() {
    GoogleApiAvailability googleAPI = GoogleApiAvailability.getInstance();
    int result = googleAPI.isGooglePlayServicesAvailable(this);
    if(result != ConnectionResult.SUCCESS) {
        if(googleAPI.isUserResolvableError(result)) {
            googleAPI.getErrorDialog(this, result,
                    PLAY_SERVICES_RESOLUTION_REQUEST).show();
        }

        return false;
    }

    return true;
}
James
fonte
9
o que é: PLAY_SERVICES_RESOLUTION_REQUEST
Saman Sattari
12
private final static int PLAY_SERVICES_RESOLUTION_REQUEST = 9000;
Ferrrmolina
7
É um número inteiro arbitrário. Você pode compensar o valor.
Timmmm
4
Alguns preferem definir o valor para algo acima de 9.000.
matthias_b_nz
12
Todo o design da biblioteca do Google Play Services é uma bagunça. É tudo falho e difícil de acompanhar, além da falta de documentação.
mr5
64

A classe GooglePlayServicesUtil não deve mais ser usada!

Aqui está como a classe GoogleApiAvailability pode ser usado - quando, por exemplo, GCM (ou qualquer outro serviço do Google) é necessário:

public static final int REQUEST_GOOGLE_PLAY_SERVICES = 1972;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    if (savedInstanceState == null) {
        startRegistrationService();
    }
}

private void startRegistrationService() {
    GoogleApiAvailability api = GoogleApiAvailability.getInstance();
    int code = api.isGooglePlayServicesAvailable(this);
    if (code == ConnectionResult.SUCCESS) {
        onActivityResult(REQUEST_GOOGLE_PLAY_SERVICES, Activity.RESULT_OK, null);
    } else if (api.isUserResolvableError(code) &&
        api.showErrorDialogFragment(this, code, REQUEST_GOOGLE_PLAY_SERVICES)) {
        // wait for onActivityResult call (see below)
    } else {
        Toast.makeText(this, api.getErrorString(code), Toast.LENGTH_LONG).show();
    }
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    switch(requestCode) {
        case REQUEST_GOOGLE_PLAY_SERVICES:
            if (resultCode == Activity.RESULT_OK) {
                Intent i = new Intent(this, RegistrationService.class); 
                startService(i); // OK, init GCM
            }
            break;

        default:
            super.onActivityResult(requestCode, resultCode, data);
    }
}

ATUALIZAR:

REQUEST_GOOGLE_PLAY_SERVICESé uma constante inteira com nome e valor arbitrários, que pode ser referenciada no onActivityResult()método.

Além disso, ligar this.onActivityResult()no código acima está correto (você também liga super.onActivityResult()no outro lugar).

Alexander Farber
fonte
2
Você pode apontar para a fonte que afirma que "A classe GooglePlayServicesUtil não deve ser usada mais!". A API do Google Play Services é tão confusa.
Lachezar
8
Todos os métodos em GooglePlayServicesUtil marcados como obsoletos mais a recomendação no topo do javadoc para obter a GOOGLE_PLAY_SERVICES_PACKAGEconstante da classe GoogleApiAvailability é a maneira do Google de dizer a você: não use mais a GooglePlayServicesUtilclasse.
Alexander Farber
3
E se o dispositivo tiver uma versão mais antiga do Google Play Services na qual a GoogleApiAvailabilityclasse não existe? Se fizermos referência à classe estaticamente, mesmo dentro de uma expressão condicional, o aplicativo não travará?
Kevin Krumwiede de
6
@Kevin Krumwiede, GoogleApiAvailabilityfaz parte da biblioteca do cliente. Portanto, seu código é compilado no aplicativo => Não se preocupe com isso.
WindRider
9
Você não deve chamar onActivityResult (). Ele deve ser chamado de fora, quando outra atividade retornar um resultado.
Yar
10

Em vez disso, você terá que usar GoogleApiAvailability :

GoogleApiAvailability googleApiAvailability = GoogleApiAvailability.getInstance(); 
int errorCode = googleApiAvailability.isGooglePlayServicesAvailable(this);

thisrepresenta o context.

Gaurav
fonte
9

Verifique o dispositivo para certificar-se de que possui o APK do Google Play Services. Caso contrário, exiba uma caixa de diálogo que permite aos usuários baixar o APK da Google Play Store ou habilitá-lo nas configurações de sistema do dispositivo.

public static boolean checkPlayServices(Activity activity) {
    final int PLAY_SERVICES_RESOLUTION_REQUEST = 9000;
    GoogleApiAvailability apiAvailability = GoogleApiAvailability.getInstance();
    int resultCode = apiAvailability.isGooglePlayServicesAvailable(activity);
    if (resultCode != ConnectionResult.SUCCESS) {
        if (apiAvailability.isUserResolvableError(resultCode)) {
            apiAvailability.getErrorDialog(activity, resultCode, PLAY_SERVICES_RESOLUTION_REQUEST)
                    .show();
        } else {
            Logger.logE(TAG, "This device is not supported.");
        }
        return false;
    }
    return true;
}
Anoop M
fonte
0

Eu adicionei isso como divertido na classe BaseActivity para ser usado em todos os lugares

    fun checkGooglePlayServices(okAction : ()-> Unit , errorAction: (msg:String, isResolved:Boolean)-> Unit){
    val apiAvailability = GoogleApiAvailability.getInstance()
    val resultCode = apiAvailability.isGooglePlayServicesAvailable(this)
    if (resultCode != ConnectionResult.SUCCESS) {
        if (apiAvailability.isUserResolvableError(resultCode)) {
            apiAvailability.getErrorDialog(
                this,
                resultCode,
                PLAY_SERVICES_RESOLUTION_REQUEST
            ).show()
             // dialoe when click on ok should let user go to install/update play serices


            errorAction("dialog is shown" , true)

        } else {
          "checkGooglePlayServices  This device is not supported.".log(mTag)
            errorAction("This device is not supported",false)
        }
    }else{
        okAction()
    }
}

companion object {
    const val PLAY_SERVICES_RESOLUTION_REQUEST = 1425
}

use assim

    (activity as? BaseActivity)?.checkGooglePlayServices({
        // ok so start map
        initializeMap()
    },
        { msg, isResolved ->
            if (!isResolved)
                context?.show(msg)

        }
    )

Ou você pode personalizá-lo como quiser.

Mahmoud Mabrok
fonte