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

Google Play Hizmetleri kitaplığında (Google ile Oturum Açma, Oyunlar ve Drive gibi) sağlanan Google API'lerine 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.

Bununla birlikte, yeni GoogleApi arayüzü ve uygulamaları daha kolay kullanılabilir ve Play Hizmetleri API'lerine erişmenin tercih edilen yoludur. Google API'lerine erişme konusuna bakın.

Bu kılavuzda, aşağıdaki işlemleri nasıl yapacağınız gösterilmektedir:

  • Google Play Hizmetleri bağlantınızı otomatik olarak yönetin.
  • Google Play hizmetlerinden 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 istemcisinin, Google Play Games ve Google Drive gibi mevcut Google Play hizmetlerine bağlanmak ve bunlara çağrı yapmak için nasıl bir arayüz sağladığını gösteren resim.

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ı kurma 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önteminde 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 bir kod örneğini aşağıda bulabilirsiniz:

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

addApi() ve addScope()'a ek çağrılar ekleyerek aynı GoogleApiClient'a birden fazla API ve kapsam ekleyebilirsiniz.

Önemli: Wearable API'yi diğer API'lerle birlikte bir GoogleApiClient hizmetine eklerseniz Wear OS uygulaması yüklü olmayan cihazlarda istemci bağlantısı hatalarıyla karşılaşabilirsiniz. Bağlantı hatalarından kaçınmak için addApiIfAvailable() yöntemini çağırın ve Wearable API'yi ileterek istemcinizin eksik API'yi sorunsuz bir şekilde ele alabilmesini sağlayın. Daha fazla bilgi için Giyilebilir cihaz API'sine erişme başlıklı makaleyi inceleyin.

Otomatik olarak yönetilen bir bağlantı başlatmak istiyorsanız çözülemeyen bağlantı hataları almak üzere 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üzeltmeye çalışmak için otomatik olarak kullanıcı arayüzünü gösterir (örneğin, Google Play hizmetlerinin güncellenmesi gerekiyorsa). Çözümlenemeyen bir hata oluşursa onConnectionFailed() numaralı telefona çağrı yapılır.

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 yazmaya yönelik çağrılar yapıyorsa bunların yalnızca onConnected() yöntemi çağrıldıktan sonra çağrılması gerekir.

Geri çağırma arayüzlerini uygulayan ve bunları Google API İstemcisi'ne ekleyen örnek bir etkinliği burada görebilirsiniz:

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

        // ...
    }
}

GoogleApiClient örneğiniz, etkinliğiniz onStart() çağrısından sonra 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 okuma isteği göndermeye hemen başlayabilir.

Google hizmetleriyle iletişim kurma

Bağlantı kurulduktan sonra istemciniz, GoogleApiClient örneğinize eklediğiniz API'ler ve kapsamlar tarafından belirtildiği üzere, uygulamanızın yetkilendirildiği hizmete özgü API'leri kullanarak okuma ve yazma çağrıları yapabilir.

Not: Belirli Google hizmetlerini aramadan önce uygulamanızı Google Developer Console'a kaydetmeniz gerekebilir. Talimatlar için, kullandığınız API'ye ilişkin 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ğırdığı Google hizmetine teslim edilmeden hemen önce gerçekleşir.

Örneğin, Google Drive'dan PendingResult nesnesi sağlayan bir dosyanın okunması isteğini aşağıda 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 isteğin eşzamansız çağrı olarak 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, GoogleApiClient örneğinizin bağlı olup olmadığından bağımsız olarak uygulamanız, Google Drive'dan dosya okumak için yöntemler çağırabilir. Bağlantı kurulduktan sonra sıraya alınmış 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 üzerinde setResultCallback() yöntemini çağırın ve ResultCallback arayüzünün uygulamasını sağlayın. Örneğin, eşzamansız olarak yürütülen istek şu şekildedir:

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, 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ı çağrıları kullanma

Kodunuzun kesin olarak tanımlanmış bir sırada yürütülmesini istiyorsanız (örneğin, bir çağrının sonucunun başka bir çağrının sonucu olarak başka bir çağrının bağımsız değişkeni olarak gerekmesinden), PendingResult üzerinde await() yöntemini çağırarak isteğinizi eşzamanlı hale getirebilirsiniz. Bu komut ileti dizisini 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 bir örneği olarak yayınlanır (ör. DriveApi.MetadataBufferResult).

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

Aşağıdaki örnekte, eşzamanlı çağrı olarak Google Drive'a nasıl dosya isteği gönderileceği 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

Giyilebilir API, elde kullanılan ve giyilebilir cihazlarda çalışan uygulamalar için bir iletişim kanalı sağlar. API, sistemin gönderip senkronize edebileceği bir veri nesnesi kümesinden ve bir veri katmanı kullanarak uygulamalarınızı önemli olaylarla ilgili bilgilendiren dinleyicilerden oluşur. Giyilebilir API, Android 4.3 (API düzeyi 18) veya sonraki sürümleri çalıştıran cihazlarda giyilebilir bir cihaz bağlıyken ve Wear OS tamamlayıcı uygulaması cihazda yüklü olduğunda kullanılabilir.

Giyilebilir API'yi bağımsız olarak kullanma

Uygulamanız Wearable API'yi kullanıyor ancak diğer Google API'lerini kullanmıyorsa addApi() yöntemini çağırarak bu API'yi ekleyebilirsiniz. Aşağıdaki örnekte, Giyilebilir Cihaz API'sinin GoogleApiClient örneğinize nasıl ekleneceği 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 anlaşılacağı 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'lerinin yanı sıra Wearable API'yi de kullanıyorsa addApiIfAvailable() yöntemini çağırın ve kullanılabilir olup olmadığını kontrol etmek için Giyilebilir API'yi iletin. Uygulamanızın, API'nin kullanılamadığı durumları sorunsuz bir ş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, kullanılamıyorsa Wearable API'ye bağlanmadan Google Drive'a başarıyla bağlanabilir. GoogleApiClient örneğinizi bağladıktan sonra, API çağrıları yapmadan önce Wearable API'nin kullanılabildiğinden emin olun:

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

API Bağlantı Hatalarını Yoksayma

addApi() yöntemini çağırırsanız ve GoogleApiClient söz konusu API'ye başarıyla bağlanamazsa söz konusu istemci için bağlantı işleminin tamamı başarısız olur ve onConnectionFailed() geri çağırmasını tetikler.

Yoksayılacak bir API bağlantı hatasını addApiIfAvailable() kullanarak kaydedebilirsiniz. addApiIfAvailable() ile eklenen bir API düzeltilemeyen bir hata (ör. Wear için API_UNAVAILABLE) nedeniyle bağlanamazsa söz konusu API, GoogleApiClient bölümünden çıkarılır ve istemci, diğer API'lere bağlanmaya devam eder. Ancak herhangi bir API bağlantısı 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ı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ğırmasına çözüm amacı içeren bir ConnectionResult gönderilir. API bağlantı hataları yalnızca hata için bir çözüm yoksa ve API addApiIfAvailable() ile eklenmişse yoksayılır. Manuel bağlantı hatası işlemenin nasıl uygulanacağı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 bulunmayabileceğinden, hasConnectedApi() ile bir kontrol ekleyerek bu API'lere yapılan çağrıları korumanız gerekir. İstemci için bağlantı işleminin tamamı başarılıyken belirli bir API'nin neden bağlanamadığını öğrenmek için getConnectionResult() işlevini çağırın ve ConnectionResult nesnesinden hata kodunu alın. İstemciniz, istemciye bağlı olmadığında bir API çağırırsa çağrı, API_NOT_AVAILABLE durum koduyla başarısız olur.

addApiIfAvailable() üzerinden eklediğiniz API için bir veya daha fazla kapsam gerekiyorsa bu kapsamları addScope() yöntemini kullanmak yerine addApiIfAvailable() yöntem çağrınıza parametre olarak ekleyin. Bu yaklaşım kullanılarak eklenen kapsamlar, OAuth izni alınmadan API bağlantısı başarısız olursa istenemeyebilir. addScope() ile eklenen kapsamlar her zaman istenir.

Manuel olarak yönetilen bağlantılar

Bu kılavuzun büyük kısmında, otomatik olarak yönetilen hatalarla 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 kolay yoludur. Ancak, uygulamanızda Google API'leriyle manuel olarak yönetilen bir bağlantı kullanmak isteyebileceğiniz bazı durumlar vardır:

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

Bu bölümde bu 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 istiyorsanız ConnectionCallbacks ve OnConnectionFailedListener geri çağırma arayüzleri için bir uygulama belirtmeniz gerekir. Bu arayüzler, Google Play Hizmetleri ile bağlantı 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 uygulamanızın yaşam döngüsünün doğru noktalarında connect() ve disconnect() yöntemlerini çağırmanız gerekir. Bir etkinlik bağlamında en iyi uygulama, etkinliğinizin onStart() yönteminde connect() ile 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ını içeren bir onConnectionFailed() numarasına çağrı alabilir.

Bağlantı hatalarını işleme

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

hasResolution() "false" döndürürse uygulamanız GoogleApiAvailability.getErrorDialog() çağrısı yaparak hata kodunu bu yönteme iletir. Bu, Google Play hizmetleri tarafından sağlanan ve hataya uygun bir Dialog döndürür. İletişim kutusunda hatayı açıklayan bir mesaj gösterilebilir veya hatayı çözebilecek bir etkinliği başlatacak bir işlem de (ör. kullanıcının Google Play Hizmetleri'nin daha yeni bir sürümünü yüklemesi gerektiğinde) sunabilir.

Örneğin, onConnectionFailed() geri çağırma yönteminiz artık aşağıdaki gibi 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. Bunun ardından uygulamanız connect() numarasını 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 değerini fark etmişsinizdir. Bu sayede, kullanıcı hatayı çözümlerken aynı hatayı tekrar tekrar çözme girişiminde bulunmamak için uygulama durumu takip edilir. Ö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 işlem, etkinliğinizi yeniden oluşturur ve onStart() yönteminizin tekrar çağrılmasına, ardından da connect() yöntemini çağırır. Bu durumda startResolutionForResult() için başka bir çağrı yapılır. Bu çağrı, mevcut hesabın önünde başka bir hesap seçici iletişim kutusu oluşturur.

Bu boole, yalnızca etkinlik örneklerinde devam ederse 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 durumunun nasıl korunacağı açıklanmaktadır.

Bir hatayı çözümlerken durumu koruma

Bir hatayı düzeltmeye yönelik önceki bir girişim devam ederken onConnectionFailed()'te kodun çalıştırılmasını önlemek için uygulamanızın halihazırda bir hatayı düzeltmeye çalışıp çalışmadığını izleyen bir boole tutmanız gerekir.

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

Etkinlik yeniden başlatmalarında (ör. kullanıcı ekranı döndürdüğünde) boole değerini takip etmek için etkinliğin kayıtlı örnek verilerindeki boole değerini onSaveInstanceState() kullanarak 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);
}

Daha sonra, onCreate() sırasında kayıtlı 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.