GoogleApiClient ile Google API'lerine erişme (kullanımdan kaldırıldı)

Google Play Hizmetleri kitaplığında sağlanan Google API'lerine (Google ile Oturum Açma, Oyunlar ve Drive gibi) erişmek için GoogleApiClient ("Google API İstemcisi") nesnesini kullanabilirsiniz. Google API İstemcisi, Google Play hizmetleri için ortak bir giriş noktası sağlar ve kullanıcının cihazı ile her bir Google hizmeti arasındaki ağ bağlantısını yönetir.

Ancak kullanımı daha kolay olan yeni GoogleApi arayüzünün ve uygulamalarının kullanımı daha kolaydır ve Play Hizmetleri API'lerine erişmenin tercih edilen yollarıdır. Google API'lerine erişme konusuna bakın.

Bu kılavuzda, aşağıdakileri nasıl yapabileceğiniz gösterilmektedir:

  • Google Play Hizmetleri bağlantınızı otomatik olarak yönetin.
  • Google Play hizmetlerinin herhangi birine eşzamanlı ve eşzamansız API çağrıları gerçekleştirme.
  • Bunun gerekli olduğu nadir durumlarda, Google Play hizmetleriyle bağlantınızı manuel olarak yönetin. Daha fazla bilgi edinmek için Manuel olarak yönetilen bağlantılar başlıklı makaleyi inceleyin.
Şekil 1: Google API İstemcisi'nin, Google Play Games ve Google Drive gibi mevcut Google Play Hizmetleri'nden herhangi birine bağlanmak ve çağrı yapmak için nasıl bir arayüz sağladığını gösteren çizim.

Başlamak için önce Android SDK'nız için Google Play Hizmetleri kitaplığını (düzeltme 15 veya sonraki sürümler) yüklemeniz gerekir. Henüz yapmadıysanız Google Play Hizmetleri SDK'sını Ayarlama bölümündeki talimatları uygulayın.

Otomatik olarak yönetilen bir bağlantı başlatma

Projeniz Google Play Hizmetleri kitaplığına bağlandıktan sonra etkinliğinizin onCreate() yöntemindeki GoogleApiClient.Builder API'lerini kullanarak GoogleApiClient örneği oluşturun. GoogleApiClient.Builder sınıfı, kullanmak istediğiniz Google API'lerini ve istediğiniz OAuth 2.0 kapsamlarını belirtmenize olanak tanıyan yöntemler sunar. Google Drive hizmetine bağlanan bir GoogleApiClient örneği oluşturan kod örneğini burada bulabilirsiniz:

GoogleApiClient mGoogleApiClient = new GoogleApiClient.Builder(this)
    .enableAutoManage(this /* FragmentActivity */,
                      this /* OnConnectionFailedListener */)
    .addApi(Drive.API)
    .addScope(Drive.SCOPE_FILE)
    .build();

addApi() ve addScope() öğelerine ek çağrılar ekleyerek aynı GoogleApiClient öğesine birden çok API ve birden çok kapsam ekleyebilirsiniz.

Önemli: Wearable API'yi diğer API'lerle birlikte bir GoogleApiClient hesabına ekliyorsanız Wear OS uygulamasının yüklü olmadığı cihazlarda istemci bağlantısı hatalarıyla karşılaşabilirsiniz. Bağlantı hatalarını önlemek için addApiIfAvailable() yöntemini çağırın ve istemcinizin eksik API'yi sorunsuz şekilde işlemesine izin vermek için Wearable API'yi iletin. Daha fazla bilgi için Giyilebilir Cihaz API'sine erişme konusuna bakın.

Otomatik olarak yönetilen bir bağlantıyı başlatmak amacıyla çözülemeyen bağlantı hatalarını almak için OnConnectionFailedListener arayüzü için bir uygulama belirtmeniz gerekir. Otomatik olarak yönetilen GoogleApiClient örneğiniz Google API'lerine bağlanmaya çalıştığında, çözülebilir bağlantı hatalarını düzeltmek için (ör. Google Play hizmetlerinin güncellenmesi gerekiyorsa) otomatik olarak kullanıcı arayüzü gösterilir. Çözülemeyen bir hata oluşursa onConnectionFailed() numarasına bir çağrı alırsınız.

Uygulamanızın otomatik olarak yönetilen bağlantının ne zaman kurulduğunu veya askıya alındığını bilmesi gerekiyorsa ConnectionCallbacks arayüzü için isteğe bağlı bir uygulama da belirtebilirsiniz. Örneğin, uygulamanız Google API'lerine veri yazmak için çağrılar yapıyorsa bu çağrılar yalnızca onConnected() yöntemi çağrıldıktan sonra çağrılmalıdır.

Burada, geri çağırma arayüzlerini uygulayan ve bunları Google API İstemcisi'ne ekleyen bir örnek etkinlik gösterilmektedir:

import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.GoogleApiClient.OnConnectionFailedListener;
import gms.drive.*;
import android.support.v4.app.FragmentActivity;

public class MyActivity extends FragmentActivity
        implements OnConnectionFailedListener {
    private GoogleApiClient mGoogleApiClient;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // Create a GoogleApiClient instance
        mGoogleApiClient = new GoogleApiClient.Builder(this)
                .enableAutoManage(this /* FragmentActivity */,
                                  this /* OnConnectionFailedListener */)
                .addApi(Drive.API)
                .addScope(Drive.SCOPE_FILE)
                .build();

        // ...
    }

    @Override
    public void onConnectionFailed(ConnectionResult result) {
        // An unresolvable error has occurred and a connection to Google APIs
        // could not be established. Display an error message, or handle
        // the failure silently

        // ...
    }
}

Etkinliğiniz onStart() çağrısından sonra GoogleApiClient örneğiniz otomatik olarak bağlanır ve onStop() çağrısından sonra bağlantısı kesilir. Uygulamanız, GoogleApiClient oluşturulduktan sonra bağlantının tamamlanmasını beklemeden Google API'lerine hemen okuma isteği göndermeye başlayabilir.

Google hizmetleriyle iletişim kurun

İstemciniz bağlandıktan sonra GoogleApiClient örneğinize eklediğiniz API'ler ve kapsamlarda belirtilen şekilde uygulamanızın yetkilendirildiği hizmete özgü API'leri kullanarak okuma ve yazma çağrıları yapabilir.

Not: Belirli Google hizmetlerine çağrı yapmadan önce, uygulamanızı Google Developers Console'a kaydetmeniz gerekebilir. Talimatlar için kullandığınız API'ye yönelik uygun başlangıç kılavuzuna (ör. Google Drive veya Google ile Oturum Açma) bakın.

GoogleApiClient kullanarak bir okuma veya yazma isteği gerçekleştirdiğinizde API istemcisi, isteği temsil eden bir PendingResult nesnesi döndürür. Bu işlem, istek uygulamanızın çağrı yaptığı Google hizmetine teslim edilmeden hemen önce gerçekleşir.

Örneğin, Google Drive'dan PendingResult nesnesi sağlayan bir dosyayı okuma isteğini burada görebilirsiniz:

Query query = new Query.Builder()
        .addFilter(Filters.eq(SearchableField.TITLE, filename));
PendingResult<DriveApi.MetadataBufferResult> result = Drive.DriveApi.query(mGoogleApiClient, query);

Uygulamanız bir PendingResult nesnesine sahip olduğunda, uygulamanız isteğin eşzamansız çağrı mı yoksa eşzamanlı çağrı olarak mı işleneceğini belirtebilir.

İpucu: Uygulamanız, Google Play Hizmetleri'ne bağlı değilken okuma isteklerini sıraya alabilir. Örneğin, uygulamanız, GoogleApiClient örneğinizin henüz bağlı olup olmamasından bağımsız olarak Google Drive'dan dosya okumak için yöntemler çağırabilir. Bağlantı kurulduktan sonra sıraya alınan okuma istekleri yürütülür. Uygulamanız, Google API İstemciniz bağlı değilken Google Play Hizmetleri yazma yöntemlerini çağırırsa yazma istekleri hata oluşturur.

Eşzamansız çağrıları kullanma

İsteği eşzamansız hale getirmek için PendingResult üzerinden setResultCallback() yöntemini çağırın ve ResultCallback arayüzünün uygulanmasını sağlayın. Örneğin, eşzamansız olarak yürütülen istek şöyledir:

private void loadFile(String filename) {
    // Create a query for a specific filename in Drive.
    Query query = new Query.Builder()
            .addFilter(Filters.eq(SearchableField.TITLE, filename))
            .build();
    // Invoke the query asynchronously with a callback method
    Drive.DriveApi.query(mGoogleApiClient, query)
            .setResultCallback(new ResultCallback<DriveApi.MetadataBufferResult>() {
        @Override
        public void onResult(DriveApi.MetadataBufferResult result) {
            // Success! Handle the query result.
            // ...
        }
    });
}

Uygulamanız onResult() geri çağırmasında bir Result nesnesi aldığında, bu nesne, kullandığınız API tarafından belirtilen uygun alt sınıfın (ör. DriveApi.MetadataBufferResult) bir örneği olarak yayınlanır.

Eşzamanlı aramaları kullanma

Kodunuzun kesin olarak tanımlanmış bir sırada yürütülmesini istiyorsanız (bir çağrının sonucu bir başkasının bağımsız değişkeni olarak gerekiyor olabilir) PendingResult üzerinde await() yöntemini çağırarak isteğinizi eşzamanlı hale getirebilirsiniz. Bu, iş parçacığını engeller ve istek tamamlandığında Result nesnesini döndürür. Bu nesne, kullandığınız API tarafından belirtilen uygun alt sınıfın örneği olarak yayınlanır (örneğin, DriveApi.MetadataBufferResult).

await() çağrısı, sonuç gelene kadar iş parçacığını engellediğinden, uygulamanız kullanıcı arayüzü iş parçacığında Google API'lerine hiçbir zaman eşzamanlı istek yapmamalıdır. Uygulamanız bir AsyncTask nesnesi kullanarak yeni bir ileti dizisi oluşturabilir ve eşzamanlı istekte bulunmak için bu ileti dizisini kullanabilir.

Aşağıdaki örnekte, Google Drive'a eşzamanlı çağrı olarak nasıl dosya isteğinde bulunulacağı gösterilmektedir:

private void loadFile(String filename) {
    new GetFileTask().execute(filename);
}

private class GetFileTask extends AsyncTask {
    protected void doInBackground(String filename) {
        Query query = new Query.Builder()
                .addFilter(Filters.eq(SearchableField.TITLE, filename))
                .build();
        // Invoke the query synchronously
        DriveApi.MetadataBufferResult result =
                Drive.DriveApi.query(mGoogleApiClient, query).await();

        // Continue doing other stuff synchronously
        // ...
    }
}

Wearable API'ye erişme

Wearable API, avuç içi cihazlarda ve giyilebilir cihazlarda çalışan uygulamalar için bir iletişim kanalı sağlar. API, sistemin gönderip senkronize edebileceği bir dizi veri nesnesinden ve bir veri katmanı kullanarak uygulamalarınıza önemli etkinlikler hakkında bilgi veren dinleyicilerden oluşur. Wearable API, Android 4.3 (API düzeyi 18) veya sonraki sürümleri çalıştıran cihazlarda bir giyilebilir cihaz bağlıyken ve cihazda Wear OS tamamlayıcı uygulaması yüklü olduğunda kullanılabilir.

Wearable API'yi tek başına kullanma

Uygulamanız Wearable API'yi kullanıyor ancak diğer Google API'lerini kullanmıyorsa bu API'yi addApi() yöntemini çağırarak ekleyebilirsiniz. Aşağıdaki örnekte Wearable API'yi GoogleApiClient örneğinize nasıl ekleyeceğiniz gösterilmektedir:

GoogleApiClient mGoogleApiClient = new GoogleApiClient.Builder(this)
    .enableAutoManage(this /* FragmentActivity */,
                      this /* OnConnectionFailedListener */)
    .addApi(Wearable.API)
    .build();

Wearable API'nin kullanılamadığı durumlarda, Wearable API'yi içeren bağlantı istekleri API_UNAVAILABLE hata koduyla başarısız olur.

Aşağıdaki örnekte, Wearable API'nin kullanılabilir olup olmadığının nasıl belirleneceği gösterilmektedir:

// Connection failed listener method for a client that only
// requests access to the Wearable API
@Override
public void onConnectionFailed(ConnectionResult result) {
    if (result.getErrorCode() == ConnectionResult.API_UNAVAILABLE) {
        // The Wearable API is unavailable
    }
    // ...
}

Wearable API'yi diğer Google API'leriyle kullanma

Uygulamanız diğer Google API'lerine ek olarak Wearable API'yi kullanıyorsa addApiIfAvailable() yöntemini çağırın ve kullanılabilir olup olmadığını kontrol etmek için Wearable API'yi iletin. Uygulamanızın API'nin kullanılamadığı durumları sorunsuz şekilde ele almasına yardımcı olmak için bu kontrolü kullanabilirsiniz.

Aşağıdaki örnekte, Drive API ile birlikte Wearable API'ye nasıl erişileceği gösterilmektedir:

// Create a GoogleApiClient instance
mGoogleApiClient = new GoogleApiClient.Builder(this)
        .enableAutoManage(this /* FragmentActivity */,
                          this /* OnConnectionFailedListener */)
        .addApi(Drive.API)
        .addApiIfAvailable(Wearable.API)
        .addScope(Drive.SCOPE_FILE)
        .build();

Yukarıdaki örnekte GoogleApiClient, mevcut değilse Wearable API'ye bağlanmadan Google Drive'a başarılı bir şekilde bağlanabilir. GoogleApiClient örneğinizi bağladıktan sonra, API çağrıları yapmadan önce Wearable API'nin kullanılabilir olduğundan emin olun:

boolean wearAvailable = mGoogleApiClient.hasConnectedApi(Wearable.API);

API Bağlantı Hataları Yoksayılıyor

addApi() yöntemini çağırırsanız ve GoogleApiClient bu API'ye başarılı bir şekilde bağlanamazsa söz konusu istemcinin bağlantı işleminin tamamı başarısız olur ve onConnectionFailed() geri çağırma işlemini tetikler.

addApiIfAvailable() kullanarak yok sayılacak bir API bağlantı hatası kaydedebilirsiniz. addApiIfAvailable() ile eklenen bir API, kurtarılamayan bir hata nedeniyle (Wear için API_UNAVAILABLE gibi) bağlanamazsa söz konusu API, GoogleApiClient uygulamanızdan çıkarılır ve istemci, diğer API'lere bağlanmaya devam eder. Ancak API bağlantıları kurtarılabilir bir hatayla (ör. OAuth izin çözümleme amacı) başarısız olursa istemci bağlantı işlemi başarısız olur. Otomatik olarak yönetilen bir bağlantı kullanılırken GoogleApiClient, mümkün olduğunda bu tür hataları düzeltmeye çalışır. Manuel olarak yönetilen bir bağlantı kullanılırken onConnectionFailed() geri çağırmaya çözüm amacı içeren bir ConnectionResult iletilir. API bağlantı hataları yalnızca hatanın çözümü yoksa ve API addApiIfAvailable() ile eklenmişse yoksayılır. Bağlantı hatalarını manuel olarak işlemenin nasıl yapılacağını öğrenmek için Bağlantı hatalarını işleme bölümüne bakın.

addApiIfAvailable() ile eklenen API'ler bağlı GoogleApiClient örneğinde her zaman mevcut olmayabileceğinden bu API'lere yapılan çağrıları hasConnectedApi() ile bir denetim ekleyerek korumanız gerekir. İstemci için tüm bağlantı işlemi başarıyla tamamlandığında belirli bir API'nin neden bağlanamadığını öğrenmek isterseniz getConnectionResult() yöntemini çağırın ve ConnectionResult nesnesinden hata kodunu alın. İstemciniz, istemciye bağlı değilken bir API'yi çağırırsa çağrı, API_NOT_AVAILABLE durum koduyla başarısız olur.

addApiIfAvailable() aracılığıyla eklediğiniz API bir veya daha fazla kapsam gerektiriyorsa addScope() yöntemini kullanmak yerine bu kapsamları addApiIfAvailable() yöntem çağrınıza parametre olarak ekleyin. API bağlantısı OAuth izni alınmadan başarısız olursa bu yaklaşım kullanılarak eklenen kapsamlar istenmeyebilir. Ancak addScope() ile eklenen kapsamlar her zaman istenir.

Manuel olarak yönetilen bağlantılar

Bu kılavuzun büyük bölümünde, otomatik olarak yönetilen hatalar içeren ve otomatik olarak yönetilen bir bağlantı başlatmak için enableAutoManage yönteminin nasıl kullanılacağı gösterilmektedir. Neredeyse her durumda bu, Android uygulamanızdan Google API'lerine bağlanmanın en iyi ve en kolay yoludur. Ancak bazı durumlarda uygulamanızdaki Google API'lerine manuel olarak yönetilen bağlantı kullanmak isteyebilirsiniz:

  • Google API'lerine bir etkinlik dışında erişmek veya API bağlantısının kontrolünü elinizde tutmak için
  • Bağlantı hatası işlemeyi ve çözümlemeyi özelleştirmek için

Bu bölümde, bunlara ve diğer gelişmiş kullanım alanlarına örnekler verilmiştir.

Manuel olarak yönetilen bir bağlantı başlatma

GoogleApiClient ile manuel olarak yönetilen bağlantı başlatmak üzere geri çağırma arayüzleri ConnectionCallbacks ve OnConnectionFailedListener için bir uygulama belirtmeniz gerekir. Bu arayüzler, Google Play hizmetleri bağlantısı başarılı olduğunda, başarısız olduğunda veya askıya alındığında eşzamansız connect() yöntemine yanıt olarak geri çağırmalar alır.

    mGoogleApiClient = new GoogleApiClient.Builder(this)
            .addApi(Drive.API)
            .addScope(Drive.SCOPE_FILE)
            .addConnectionCallbacks(this)
            .addOnConnectionFailedListener(this)
            .build()

Bağlantıyı manuel olarak yönetirken connect() ve disconnect() yöntemlerini uygulamanızın yaşam döngüsünde doğru noktalarda çağırmanız gerekir. Bir etkinlik bağlamında en iyi uygulama, etkinliğinizin onStart() yönteminde connect(), etkinliğinizin onStop() yönteminde disconnect() çağrısı yapmaktır. Otomatik olarak yönetilen bir bağlantı kullanılırken connect() ve disconnect() yöntemleri otomatik olarak çağrılır.

Google Drive veya Google Play Games gibi kimlik doğrulama gerektiren API'lere bağlanmak için GoogleApiClient kullanıyorsanız ilk bağlantı denemeniz başarısız olabilir ve kullanıcı hesabı belirtilmediğinden uygulamanız SIGN_IN_REQUIRED hatasıyla onConnectionFailed() numaralı telefonu arar.

Bağlantı hatalarını işleme

Uygulamanız onConnectionFailed() geri çağırmaya bir çağrı aldığında sağlanan ConnectionResult nesnesinde hasResolution() öğesini çağırmanız gerekir. Doğru döndürülürse uygulamanız, kullanıcıdan ConnectionResult nesnesinde startResolutionForResult() yöntemini çağırarak hatayı çözmek için hemen işlem yapmasını isteyebilir. Bu durumda startResolutionForResult() yöntemi, startActivityForResult() ile aynı şekilde davranır ve bağlama uygun bir etkinlik başlatır. Bu etkinlik, kullanıcının hatayı çözmesine yardımcı olur (ör. kullanıcının hesap seçmesine yardımcı olan bir etkinlik).

hasResolution() false döndürürse uygulamanız GoogleApiAvailability.getErrorDialog() yöntemini çağırarak hata kodunu bu yönteme iletir. Bu, Google Play hizmetleri tarafından sağlanan, hataya uygun bir Dialog döndürür. İletişim kutusu sadece hatayı açıklayan bir mesaj sağlayabilir veya hatayı çözebilecek bir etkinlik başlatmak üzere bir işlem de sağlayabilir (örneğin, kullanıcının Google Play hizmetlerinin daha yeni bir sürümünü yüklemesi gerekir).

Örneğin, onConnectionFailed() geri çağırma yönteminiz artık şu şekilde görünmelidir:

public class MyActivity extends Activity
        implements ConnectionCallbacks, OnConnectionFailedListener {

    // Request code to use when launching the resolution activity
    private static final int REQUEST_RESOLVE_ERROR = 1001;
    // Unique tag for the error dialog fragment
    private static final String DIALOG_ERROR = "dialog_error";
    // Bool to track whether the app is already resolving an error
    private boolean mResolvingError = false;

    // ...

    @Override
    public void onConnectionFailed(ConnectionResult result) {
        if (mResolvingError) {
            // Already attempting to resolve an error.
            return;
        } else if (result.hasResolution()) {
            try {
                mResolvingError = true;
                result.startResolutionForResult(this, REQUEST_RESOLVE_ERROR);
            } catch (SendIntentException e) {
                // There was an error with the resolution intent. Try again.
                mGoogleApiClient.connect();
            }
        } else {
            // Show dialog using GoogleApiAvailability.getErrorDialog()
            showErrorDialog(result.getErrorCode());
            mResolvingError = true;
        }
    }

    // The rest of this code is all about building the error dialog

    /* Creates a dialog for an error message */
    private void showErrorDialog(int errorCode) {
        // Create a fragment for the error dialog
        ErrorDialogFragment dialogFragment = new ErrorDialogFragment();
        // Pass the error that should be displayed
        Bundle args = new Bundle();
        args.putInt(DIALOG_ERROR, errorCode);
        dialogFragment.setArguments(args);
        dialogFragment.show(getSupportFragmentManager(), "errordialog");
    }

    /* Called from ErrorDialogFragment when the dialog is dismissed. */
    public void onDialogDismissed() {
        mResolvingError = false;
    }

    /* A fragment to display an error dialog */
    public static class ErrorDialogFragment extends DialogFragment {
        public ErrorDialogFragment() { }

        @Override
        public Dialog onCreateDialog(Bundle savedInstanceState) {
            // Get the error code and retrieve the appropriate dialog
            int errorCode = this.getArguments().getInt(DIALOG_ERROR);
            return GoogleApiAvailability.getInstance().getErrorDialog(
                    this.getActivity(), errorCode, REQUEST_RESOLVE_ERROR);
        }

        @Override
        public void onDismiss(DialogInterface dialog) {
            ((MyActivity) getActivity()).onDialogDismissed();
        }
    }
}

Kullanıcı startResolutionForResult() tarafından sağlanan iletişim kutusunu tamamladıktan veya GoogleApiAvailability.getErrorDialog() tarafından sağlanan mesajı kapattıktan sonra etkinliğiniz RESULT_OK sonuç kodunu içeren onActivityResult() geri çağırmasını alır. Bu işlemin ardından uygulamanız connect()'i tekrar arayabilir. Örneğin:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == REQUEST_RESOLVE_ERROR) {
        mResolvingError = false;
        if (resultCode == RESULT_OK) {
            // Make sure the app is not already connected or attempting to connect
            if (!mGoogleApiClient.isConnecting() &&
                    !mGoogleApiClient.isConnected()) {
                mGoogleApiClient.connect();
            }
        }
    }
}

Yukarıdaki kodda mResolvingError boole'sini fark etmiş olabilirsiniz. Bu sayede, aynı hatayı tekrar tekrar çözmek için teşebbüslerden kaçınmak amacıyla uygulama durumunu kullanıcı hatayı çözerken izler. Örneğin, kullanıcının SIGN_IN_REQUIRED hatasını çözmesine yardımcı olmak için hesap seçici iletişim kutusu gösterilirken kullanıcı ekranı döndürebilir. Bu, etkinliğinizi yeniden oluşturur ve onStart() yönteminizin tekrar çağrılmasına, ardından connect() yönteminin tekrar çağrılmasına neden olur. Bu işlem, yeni bir startResolutionForResult() çağrısıyla sonuçlanır. Bu da mevcut iletişim kutusunun önünde başka bir hesap seçici iletişim kutusu oluşturur.

Bu boole, yalnızca etkinlik örneklerinde devam ederse amaçlanan amacına hizmet eder. Sonraki bölümde, cihazda gerçekleşen diğer kullanıcı işlemlerine veya etkinliklerine rağmen uygulamanızın hata işleme durumunu nasıl sürdüreceğiniz açıklanmaktadır.

Bir hatayı çözerken durumu koruma

Önceki bir hata düzeltme girişimi devam ederken kodu onConnectionFailed()'te çalıştırmaktan kaçınmak için uygulamanızın bir hatayı çözmeye çalışıp çalışmadığını izleyen bir boole eklemeniz gerekir.

Yukarıdaki kod örneğinde gösterildiği gibi, uygulamanız startResolutionForResult() işlevini her çağırdığında veya GoogleApiAvailability.getErrorDialog() iletişim kutusunu görüntülediğinde true değerine bir boole ayarlamalıdır. Ardından, uygulamanız onActivityResult() geri çağırmasında RESULT_OK değerini aldığında boole'yi false olarak ayarlayın.

Boole işlemini etkinlik yeniden başlatmalarında (ör. kullanıcının ekranı döndürdüğünde) takip etmek için boole'yi, onSaveInstanceState() kullanarak etkinliğin kayıtlı örnek verilerine kaydedin:

private static final String STATE_RESOLVING_ERROR = "resolving_error";

@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    outState.putBoolean(STATE_RESOLVING_ERROR, mResolvingError);
}

Ardından onCreate() sırasında kaydedilen durumu kurtarın:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // ...
    mResolvingError = savedInstanceState != null
            && savedInstanceState.getBoolean(STATE_RESOLVING_ERROR, false);
}

Artık uygulamanızı güvenli bir şekilde çalıştırmaya ve Google Play Hizmetleri'ne manuel olarak bağlanmaya hazırsınız.