GooglePlayServicesUtil vs GoogleApiAvailability

103

Próbuję skorzystać z usługi Google Play w mojej aplikacji na Androida. Jak mówi dokument Google, przed użyciem musimy sprawdzić, czy Google API jest dostępne. Szukałem jakiegoś sposobu, żeby to sprawdzić. Oto co mam:

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;
}

Ale kiedy przechodzę do strony Google Api GooglePlayServicesUtil, https://developers.google.com/android/reference/com/google/android/gms/common/GooglePlayServicesUtil

Uważam, że wszystkie funkcje są przestarzałe . Na przykład metoda

GooglePlayServicesUtil.isGooglePlayServicesAvailable (wycofane)

A Google zaleca użycie:

GoogleApiAvailability.isGooglePlayServicesAvailable .

Jednak podczas próby skorzystania z GoogleApiAvailability.isGooglePlayServicesAvailable pojawia się komunikat o błędzie:

wprowadź opis obrazu tutaj

James
źródło
gdzie mogę znaleźć GoogleApiAvailability? Nie mogę tego znaleźć.
mcmillab
@mcmillab +1. Zaktualizowałem wersję 8.1.0 do 8.4.0 i GooglePlayServicesUtilzniknęła (co wydaje się złą praktyką w przypadku „drobnej” aktualizacji), ale nie GoogleApiAvailabilityzamierzam używać go jako zamiennika.
spaaarky21
Podczas aktualizacji do Firebase sprawdź
Dawid Drozd

Odpowiedzi:

204

Znalazłem rozwiązanie. W GoogleApiAvailabilitymetodzie wszystkie metody są metodami publicznymi, podczas gdy we GooglePlayServicesUtilwszystkich metodach są to statyczne funkcje publiczne.

Aby skorzystać z GoogleApiAvailability, należy:

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
źródło
9
co to jest: PLAY_SERVICES_RESOLUTION_REQUEST
Saman Sattari
12
private final static int PLAY_SERVICES_RESOLUTION_REQUEST = 9000;
Fmolina
7
To dowolna liczba całkowita. Możesz nadrobić wartość.
Timmmm
4
Niektórzy wolą ustawić wartość powyżej 9000.
matthias_b_nz
12
Cały projekt biblioteki usług Google Play to cały bałagan. To wszystko jest wadliwe i trudne do śledzenia, a także brak dokumentacji.
mr5
64

Nie należy już używać klasy GooglePlayServicesUtil !

Oto jak można zamiast tego użyć klasy GoogleApiAvailability - gdy np. Potrzebny jest GCM (lub dowolna inna usługa Google):

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

AKTUALIZACJA:

REQUEST_GOOGLE_PLAY_SERVICESjest stałą całkowitą o dowolnej nazwie i wartości, do których można się odwołać w onActivityResult()metodzie.

Również wywołanie this.onActivityResult()powyższego kodu jest w porządku (dzwonisz również super.onActivityResult()w innym miejscu).

Alexander Farber
źródło
2
Czy możesz wskazać źródło, które twierdzi, że „Klasa GooglePlayServicesUtil nie powinna być już używana!”. Interfejs API usług Google Play jest tak zagmatwany.
Lachezar
8
Wszystkie metody w GooglePlayServicesUtil oznaczone jako przestarzałe oraz zalecenie w górnej części javadoc, aby pobierać GOOGLE_PLAY_SERVICES_PACKAGEstałą z klasy GoogleApiAvailability, to sposób Google na poinformowanie Cię: nie używaj GooglePlayServicesUtiljuż tej klasy.
Alexander Farber,
3
Co się stanie, jeśli urządzenie ma starszą wersję usług Google Play, w której GoogleApiAvailabilityklasa nie istnieje? Jeśli odwołujemy się do klasy statycznie, nawet wewnątrz wyrażenia warunkowego, czy nie spowoduje to awarii aplikacji?
Kevin Krumwiede
6
@Kevin Krumwiede, GoogleApiAvailabilityjest częścią biblioteki klienta. Więc jego kod jest wkompilowany w aplikację => Nie martw się o to.
WindRider,
9
Nie powinieneś wywoływać onActivityResult (). Jest przeznaczony do wywołania z zewnątrz, gdy inna czynność zwraca wynik.
Yar
10

Zamiast tego będziesz musiał użyć GoogleApiAvailability :

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

thisreprezentuje context.

Gaurav
źródło
9

Sprawdź, czy urządzenie ma pakiet APK usług Google Play. Jeśli tak się nie stanie, wyświetl okno dialogowe, które umożliwia użytkownikom pobranie APK ze sklepu Google Play lub włączenie go w ustawieniach systemowych urządzenia.

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.
źródło
0

Dodałem to jako zabawę w klasie BaseActivity do wykorzystania we wszystkich miejscach

    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
}

użyj tego w ten sposób

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

        }
    )

Lub możesz go dostosować, jak chcesz.

Mahmoud Mabrok
źródło