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

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

Ancak daha yeni GoogleApi arayüzü ve uygulamalarının kullanımı daha kolaydır ve Play Hizmetleri API'lerine erişmek için tercih edilen yöntemdir. Google API'lerine erişme başlıklı makaleyi inceleyin.

Bu kılavuzda aşağıdakileri nasıl yapacağınız açıklanmaktadır:

  • Google Play Hizmetleri'ne bağlantınızı otomatik olarak yönetin.
  • Google Play Hizmetleri'nden herhangi birine senkron ve asenkron API çağrıları gerçekleştirme
  • Bunun gerekli olduğu nadir durumlarda Google Play Hizmetleri'ne olan bağlantınızı manuel olarak yönetin. Daha fazla bilgi 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 hizmetlerinden herhangi birine bağlanmak ve bu hizmetlere çağrı göndermek için nasıl bir arayüz sağladığını gösteren bir resim.

Başlamak için önce Android SDK'nız için Google Play Hizmetleri kitaplığını (15 veya daha yeni bir düzeltme sürümü) yüklemeniz gerekir. Henüz yapmadıysanız Google Play Hizmetleri SDK'sını ayarlama başlıklı makaledeki 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() metodunda 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 sağlar. Aşağıda, Google Drive hizmetine bağlanan bir GoogleApiClient örneği oluşturan bir kod örneği verilmiştir:

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 alanına birden fazla API ve birden fazla kapsam ekleyebilirsiniz.

Önemli: Wearable API'yi diğer API'lerle birlikte bir GoogleApiClient'e ekleyecekseniz 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 bir şekilde işlemesine izin vermek üzere Wearable API'yi iletin. Daha fazla bilgi için Wearable API'ye erişim başlıklı makaleyi inceleyin.

Otomatik olarak yönetilen bir bağlantı başlatmak için çö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ı (ör. Google Play Hizmetleri'nin güncellenmesi gerekiyorsa) düzeltmeye çalışmak için kullanıcı arayüzünü otomatik olarak gösterir. Çözülemeyen bir hata oluşursa onConnectionFailed() numaralı telefondan aranı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ı yapıyorsa bu çağrılar yalnızca onConnected() yöntemi çağrıldıktan sonra başlatılmalıdır.

Geri çağırma arayüzlerini uygulayan ve bunları Google API istemcisinin içine ekleyen örnek bir etkinlik aşağıda verilmiştir:

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()'i aradıktan sonra otomatik olarak bağlanır ve onStop()'ı aradıktan sonra bağlantıyı keser. 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 Hizmetleri ile iletişim kurma

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

Not: Belirli Google hizmetlerine çağrı göndermeden önce uygulamanızı Google Developers Console'a kaydetmeniz gerekebilir. Talimatlar için kullandığınız API'ye (ör. Google Drive veya Google ile Oturum Açma) ait uygun başlangıç kılavuzuna 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 ulaşmadan hemen önce gerçekleşir.

Örneğin, Google Drive'dan bir dosyayı okuma isteği aşağıdaki gibidir ve PendingResult nesnesi sağlar:

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

Uygulamanızda bir PendingResult nesnesi oluşturulduktan sonra, istemin asenkron çağrı olarak mı yoksa senkron çağrı olarak mı işleneceğini belirtebilirsiniz.

İpucu: Uygulamanız, Google Play Hizmetleri'ne bağlı değilken okuma isteklerini sıraya ekleyebilir. Örneğin, uygulamanız GoogleApiClient örneğinizin henüz bağlı olup olmadığına bakılmaksızın Google Drive'dan dosya okuma yöntemlerini çağırabilir. Bağlantı kurulduktan sonra, sıraya alınmış okuma istekleri yürütülür. Google API istemciniz bağlı değilken uygulamanız 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() işlevini çağırın ve ResultCallback arayüzünün bir uygulamasını sağlayın. Örneğin, asenkron olarak yürütülen istek aşağıda verilmiştir:

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ğırma işlevinde bir Result nesnesi aldığında bu nesne, kullandığınız API tarafından belirtilen uygun alt sınıfın bir örneği olarak (ör. DriveApi.MetadataBufferResult) gönderilir.

Eşzamanlı çağrıları kullanma

Kodunuzun kesinlikle tanımlanmış bir sırada yürütülmesini istiyorsanız (ör. bir çağrının sonucunun başka bir çağrının bağımsız değişkeni olarak kullanılması gerektiği için) PendingResult üzerinde await() çağrısı yaparak isteğinizi eşzamanlı hale getirebilirsiniz. Bu işlem, 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 (ör. DriveApi.MetadataBufferResult) yayınlanır.

await() çağrısı, sonuç gelene kadar iş parçacığını engellediğinden uygulamanız hiçbir zaman kullanıcı arayüzü iş parçacığında Google API'lerine senkronize istek göndermemelidir. Uygulamanız, AsyncTask nesnesi kullanarak yeni bir mesaj dizisi oluşturabilir ve senkronize isteği yapmak için bu mesaj dizisini kullanabilir.

Aşağıdaki örnekte, Google Drive'a senkron çağrı olarak dosya isteği gönderme işlemi gösterilmektedir:

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

private class GetFileTask extends AsyncTask<String, Void, Void> {
    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, el ve giyilebilir cihazlarda çalışan uygulamalar için bir iletişim kanalı sağlar. API, sistemin gönderip senkronize edebileceği bir veri nesnesi grubundan ve uygulamalarınızı bir veri katmanı kullanarak önemli etkinlikler hakkında bilgilendiren dinleyicilerden oluşur. Wearable API, Android 4.3 (API düzeyi 18) veya sonraki sürümleri çalıştıran cihazlarda, giyilebilir cihaz bağlıyken ve cihaza Wear OS tamamlayıcı uygulaması yüklendiğinde kullanılabilir.

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

Uygulamanız diğer Google API'lerini değil, Wearable API'yi kullanıyorsa addApi() yöntemini çağırarak bu API'yi ekleyebilirsiniz. Aşağıdaki örnekte, Wearable API'nin 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 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ığı 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 kullanılabilir olup olmadığını kontrol etmek için addApiIfAvailable() yöntemini çağırın ve Wearable 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ılabilir olduğundan emin olun:

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

API Bağlantı Hatalarını Yoksayma

addApi() çağrısı yaparsanı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şlevi tetiklenir.

addApiIfAvailable() kullanarak API bağlantısı hatasının yoksayılmasını sağlayabilirsiniz. addApiIfAvailable() ile eklenen bir API, kurtarılamaz bir hata nedeniyle (ör. Wear için API_UNAVAILABLE) bağlanamazsa bu API, GoogleApiClient'inizden kaldırılır ve istemci diğer API'lere bağlanmaya devam eder. Ancak herhangi bir API bağlantısı, kurtarılabilir bir hatayla (OAuth kullanıcı rızası çözümleme amacı gibi) başarısız olursa istemci bağlantısı işlemi de başarısız olur. Otomatik olarak yönetilen bir bağlantı kullanıldığında GoogleApiClient mümkün olduğunda bu tür hataları çözmeye çalışır. Manuel olarak yönetilen bir bağlantı kullanıldığında, çözüm amacı içeren bir ConnectionResult, onConnectionFailed() geri çağırma işlevine gönderilir. API bağlantısı hataları yalnızca hatanın çözümü yoksa ve API addApiIfAvailable() ile eklendiyse yoksayılır. Manuel bağlantı hatası yönetimini nasıl uygulayacağınızı öğrenmek için Bağlantı hatalarını yönetme başlıklı makaleyi inceleyin.

addApiIfAvailable() ile eklenen API'ler bağlı GoogleApiClient örneğinde her zaman mevcut olmayabileceğinden, hasConnectedApi() kullanarak 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ı olduğunda belirli bir API'nin neden bağlanamadığını öğrenmek için getConnectionResult() çağrısını yapı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 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 önce API bağlantısı başarısız olursa istenmeyebilir. addScope() ile eklenen kapsamlar ise her zaman istenir.

Manuel olarak yönetilen bağlantılar

Bu kılavuzun büyük bir kısmı, otomatik olarak çözülen hatalarla otomatik olarak yönetilen bir bağlantı başlatmak için enableAutoManage yönteminin nasıl kullanılacağını gösterir. Neredeyse her durumda, Android uygulamanızdan Google API'lerine bağlanmanın en iyi ve en kolay yolu budur. Ancak uygulamanızda Google API'lerine manuel olarak yönetilen bir bağlantı kullanmak isteyeceğiniz bazı durumlar vardır:

  • Bir etkinlik dışında Google API'lerine erişmek veya API bağlantısının kontrolünü elinde tutmak için
  • Bağlantı hatası işleme ve çözümünü özelleştirme

Bu bölümde bu ve diğer ileri düzey kullanım alanlarına örnekler verilmiştir.

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

GoogleApiClient ile manuel olarak yönetilen bir bağlantı başlatmak için geri çağırma arayüzleri ConnectionCallbacks ve OnConnectionFailedListener 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 asenkron connect() yöntemine yanıt olarak geri çağırma alır.

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

Bir bağlantıyı manuel olarak yönetirken connect() ve disconnect() yöntemlerini uygulamanızın yaşam döngüsünün doğru noktalarında çağırmanız gerekir. Bir etkinlik bağlamında en iyi uygulama, etkinliğinizin onStart() yönteminde connect() ve etkinliğinizin onStop() yönteminde disconnect() çağrısıdır. Otomatik olarak yönetilen bir bağlantı kullanıldığında 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ı denemenizin başarısız olma olasılığı yüksektir ve uygulamanız, kullanıcı hesabı belirtilmediği için SIGN_IN_REQUIRED hatasıyla onConnectionFailed() çağrısı alır.

Bağlantı hatalarını ele alma

Uygulamanız onConnectionFailed() geri arama işlevini çağrıldığında, sağlanan ConnectionResult nesnesinde hasResolution() işlevini çağırmanız gerekir. Doğru döndürülürse uygulamanız, ConnectionResult nesnesinde startResolutionForResult() çağırarak kullanıcıdan hatayı çözmek için 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ı olan bağlama uygun bir etkinlik (ör. kullanıcının hesap seçmesine yardımcı olan bir etkinlik) başlatır.

hasResolution() yanlış döndürürse uygulamanız, hata kodunu bu yönteme ileterek GoogleApiAvailability.getErrorDialog() yöntemini çağırmalıdır. Bu işlem, Google Play hizmetleri tarafından sağlanan ve hataya uygun bir Dialog döndürür. İletişim kutusu, hatayı açıklayan bir mesajın yanı sıra hatayı çözebilecek bir etkinliği başlatma işlemi de sağlayabilir (ör. kullanıcının Google Play Hizmetleri'nin daha yeni bir sürümünü yüklemesi gerektiğinde).

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

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ğırma çağrısını alır. Ardından uygulamanız connect()'u 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 doğru/yanlış değerini fark etmişsinizdir. Bu sayede, kullanıcı hatayı çözerken aynı hatanın tekrar tekrar çözülmeye çalışılmasını önlemek için uygulama durumu izlenir. Ö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 neden olur. connect() yöntemi de tekrar çağrılır. Bu, startResolutionForResult() işlevinin tekrar çağrılmasına neden olur. Bu çağrı, mevcut hesap seçici iletişim kutusunun önüne başka bir hesap seçici iletişim kutusu oluşturur.

Bu boole değeri, yalnızca etkinlik örnekleri arasında kalıcıysa amaçlanan amacını yerine getirir. Sonraki bölümde, cihazda gerçekleşen diğer kullanıcı işlemlerine veya etkinliklere rağmen uygulamanızın hata işleme durumunu nasıl koruyacağınız açıklanmaktadır.

Hataları çözerken durumu koruma

Bir hatayı çözmeyle ilgili önceki bir deneme devam ederken onConnectionFailed() kodunun yürütülmesini önlemek için uygulamanızın bir hatayı çözmeye çalışıp çalışmadığını izleyen bir boole değişkeni tutmanız gerekir.

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

Etkinliğin yeniden başlatılması sırasında (ör. kullanıcı ekranı döndürdüğünde) boole değerini takip etmek için onSaveInstanceState() kullanarak boole değerini 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.