دسترسی به APIهای Google با GoogleApiClient (منسوخ شده)

می‌توانید از شی GoogleApiClient ("Google API Client") برای دسترسی به APIهای Google ارائه شده در کتابخانه خدمات Google Play (مانند Google Sign-In، Games و Drive) استفاده کنید. Google API Client یک نقطه ورودی مشترک به خدمات Google Play ارائه می دهد و اتصال شبکه بین دستگاه کاربر و هر سرویس Google را مدیریت می کند.

با این حال، رابط کاربری جدیدتر GoogleApi و پیاده‌سازی‌های آن آسان‌تر برای استفاده هستند و راه ارجح برای دسترسی به API‌های خدمات Play هستند. دسترسی به APIهای Google را ببینید.

این راهنما نشان می دهد که چگونه می توانید:

  • اتصال خود به خدمات Google Play را به صورت خودکار مدیریت کنید.
  • تماس‌های API همزمان و ناهمزمان را با هر یک از سرویس‌های Google Play انجام دهید.
  • در موارد نادری که این امر ضروری است، اتصال خود به خدمات Google Play را به صورت دستی مدیریت کنید. برای کسب اطلاعات بیشتر، به اتصالات مدیریت شده دستی مراجعه کنید.
شکل 1: تصویری که نشان می‌دهد چگونه Google API Client یک رابط برای اتصال و برقراری تماس با هر یک از سرویس‌های موجود Google Play مانند Google Play Games و Google Drive فراهم می‌کند.

برای شروع، ابتدا باید کتابخانه خدمات Google Play (نسخه 15 یا بالاتر) را برای Android SDK خود نصب کنید. اگر قبلاً این کار را انجام نداده‌اید، دستورالعمل‌های موجود در «راه‌اندازی Google Play Services SDK» را دنبال کنید.

یک اتصال مدیریت شده خودکار را شروع کنید

پس از اینکه پروژه شما به کتابخانه خدمات Google Play مرتبط شد، یک نمونه از GoogleApiClient با استفاده از APIهای GoogleApiClient.Builder در روش onCreate() فعالیت خود ایجاد کنید. کلاس GoogleApiClient.Builder روش هایی را ارائه می دهد که به شما امکان می دهد API های Google را که می خواهید استفاده کنید و دامنه های OAuth 2.0 مورد نظر خود را مشخص کنید. در اینجا یک نمونه کد است که یک نمونه GoogleApiClient ایجاد می کند که با سرویس Google Drive متصل می شود:

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

می‌توانید با افزودن فراخوان‌های اضافی به addApi() و addScope() چند API و چندین دامنه به یک GoogleApiClient اضافه کنید.

مهم: اگر Wearable API را به همراه سایر APIها به GoogleApiClient اضافه می‌کنید، ممکن است در دستگاه‌هایی که برنامه Wear OS را نصب نکرده‌اند، با خطاهای اتصال کلاینت مواجه شوید. برای جلوگیری از خطاهای اتصال، متد addApiIfAvailable() را فراخوانی کنید و از Wearable API عبور دهید تا به مشتری شما اجازه دهید تا API گم شده را به خوبی مدیریت کند. برای اطلاعات بیشتر، به دسترسی به Wearable API مراجعه کنید.

برای شروع یک اتصال مدیریت شده به طور خودکار، باید یک پیاده سازی برای رابط OnConnectionFailedListener تعیین کنید تا خطاهای اتصال غیرقابل حل را دریافت کنید. هنگامی که نمونه GoogleApiClient مدیریت خودکار شما تلاش می‌کند به APIهای Google متصل شود، به‌طور خودکار رابط کاربری را نمایش می‌دهد تا هرگونه نقص اتصال قابل حل را برطرف کند (مثلاً اگر خدمات Google Play نیاز به به‌روزرسانی داشته باشد). اگر خطایی رخ دهد که قابل حل نباشد، یک تماس با onConnectionFailed() دریافت خواهید کرد.

همچنین اگر برنامه شما نیاز دارد بداند که اتصال مدیریت شده به طور خودکار چه زمانی برقرار شده یا به حالت تعلیق درآمده است، می‌توانید یک پیاده‌سازی اختیاری برای رابط ConnectionCallbacks تعیین کنید. به عنوان مثال، اگر برنامه شما برای نوشتن داده‌ها در Google API تماس می‌گیرد، آن‌ها باید تنها پس از فراخوانی متد onConnected() فراخوانی شوند.

در اینجا یک نمونه فعالیت است که واسط های پاسخ به تماس را پیاده سازی کرده و آنها را به Google API Client اضافه می کند:

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 شما به طور خودکار پس از فراخوانی فعالیت شما onStart() متصل می شود و پس از تماس onStop() قطع می شود. برنامه شما می‌تواند بلافاصله پس از ساخت GoogleApiClient ، بدون منتظر ماندن برای تکمیل اتصال، درخواست‌های خواندن را برای APIهای Google ارسال کند.

با Google Services ارتباط برقرار کنید

پس از اتصال، مشتری شما می‌تواند با استفاده از APIهای مخصوص سرویسی که برنامه شما برای آنها مجاز است، تماس‌های خواندن و نوشتن برقرار کند، همانطور که توسط APIها و محدوده‌هایی که به نمونه GoogleApiClient خود اضافه کرده‌اید مشخص شده‌اند.

توجه: قبل از برقراری تماس با سرویس‌های خاص Google، ممکن است لازم باشد ابتدا برنامه خود را در کنسول برنامه‌نویس Google ثبت کنید. برای دستورالعمل‌ها، به راهنمای شروع مناسب برای API که استفاده می‌کنید، مانند Google Drive یا Google Sign-In مراجعه کنید.

هنگامی که درخواست خواندن یا نوشتن را با استفاده از GoogleApiClient انجام می دهید، سرویس گیرنده API یک شی PendingResult را برمی گرداند که نشان دهنده درخواست است. این بلافاصله قبل از تحویل درخواست به سرویس Google که برنامه شما با آن تماس می‌گیرد، اتفاق می‌افتد.

به عنوان مثال، در اینجا یک درخواست برای خواندن یک فایل از Google Drive است که یک شی PendingResult ارائه می دهد:

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

پس از اینکه برنامه شما دارای یک شی PendingResult شد، برنامه شما می‌تواند تعیین کند که آیا درخواست به عنوان تماس ناهمزمان یا همزمان انجام می‌شود.

نکته: برنامه شما می‌تواند درخواست‌های خواندن را در حالی که به خدمات Google Play متصل نیست، در نوبت قرار دهد. برای مثال، برنامه شما می‌تواند روش‌هایی را برای خواندن یک فایل از Google Drive فراخوانی کند، صرفنظر از اینکه نمونه GoogleApiClient شما هنوز متصل است یا خیر. پس از برقراری ارتباط، درخواست‌های خواندن در صف اجرا می‌شوند. اگر برنامه شما با سرویس‌های Google Play با روش‌های نوشتن تماس بگیرد در حالی که Google API Client متصل نیست، درخواست‌های نوشتن خطا ایجاد می‌کنند.

استفاده از تماس های ناهمزمان

برای ناهمزمان کردن درخواست، setResultCallback() در PendingResult فراخوانی کنید و یک پیاده سازی از رابط ResultCallback ارائه دهید. به عنوان مثال، این درخواست به صورت ناهمزمان اجرا شده است:

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

هنگامی که برنامه شما یک شی Result در پاسخ به تماس onResult() دریافت می کند، به عنوان نمونه ای از زیر کلاس مناسب که توسط API مورد استفاده شما مشخص شده است، مانند DriveApi.MetadataBufferResult ، تحویل داده می شود.

استفاده از تماس های همزمان

اگر می‌خواهید کد شما با یک ترتیب کاملاً تعریف شده اجرا شود، شاید به این دلیل که نتیجه یک فراخوانی به عنوان آرگومان دیگری مورد نیاز است، می‌توانید با فراخوانی await() در PendingResult درخواست خود را همزمان کنید. این موضوع رشته را مسدود می کند و پس از تکمیل درخواست، شی Result را برمی گرداند. این شی به عنوان نمونه ای از زیر کلاس مناسب که توسط API مورد استفاده شما مشخص شده است، برای مثال DriveApi.MetadataBufferResult تحویل داده می شود.

از آنجایی که فراخوانی await() تا رسیدن به نتیجه، رشته را مسدود می‌کند، برنامه شما هرگز نباید درخواست‌های همزمان به APIهای Google در رشته UI ارسال کند. برنامه شما می تواند با استفاده از یک شی AsyncTask یک رشته جدید ایجاد کند و از آن رشته برای ایجاد درخواست همزمان استفاده کند.

مثال زیر نحوه درخواست فایل به Google Drive را به صورت تماس همزمان نشان می دهد:

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 دسترسی پیدا کنید

Wearable API یک کانال ارتباطی برای برنامه‌هایی که روی دستگاه‌های دستی و پوشیدنی اجرا می‌شوند، فراهم می‌کند. API شامل مجموعه‌ای از اشیاء داده‌ای است که سیستم می‌تواند ارسال و همگام‌سازی کند، و شنوندگانی که برنامه‌های شما را از رویدادهای مهم با استفاده از یک لایه داده مطلع می‌کنند. Wearable API در دستگاه‌های دارای Android نسخه 4.3 (سطح API 18) یا بالاتر، زمانی که دستگاه پوشیدنی متصل است و برنامه همراه Wear OS روی دستگاه نصب شده است، در دسترس است.

استفاده از Wearable API به تنهایی

اگر برنامه شما از Wearable API استفاده می کند اما از سایر API های Google استفاده نمی کند، می توانید با فراخوانی متد addApi() این API را اضافه کنید. مثال زیر نحوه اضافه کردن Wearable API را به نمونه GoogleApiClient خود نشان می دهد:

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

در شرایطی که Wearable API در دسترس نیست، درخواست‌های اتصال که شامل Wearable API هستند با کد خطای API_UNAVAILABLE ناموفق می‌شوند.

مثال زیر نشان می دهد که چگونه می توان تشخیص داد که آیا Wearable API موجود است یا خیر:

// 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 با سایر APIهای Google

اگر برنامه شما از Wearable API علاوه بر سایر API های Google استفاده می کند، متد addApiIfAvailable() را فراخوانی کنید و برای بررسی در دسترس بودن آن Wearable API را ارسال کنید. می‌توانید از این بررسی برای کمک به برنامه‌تان برای رسیدگی به مواردی که API در دسترس نیست، استفاده کنید.

مثال زیر نحوه دسترسی به Wearable API همراه با Drive API را نشان می دهد:

// 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();

در مثال بالا، GoogleApiClient می‌تواند بدون اتصال به Wearable API با موفقیت به Google Drive متصل شود، اگر در دسترس نباشد. پس از اتصال نمونه GoogleApiClient خود، قبل از برقراری تماس‌های API مطمئن شوید که Wearable API در دسترس است:

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

نادیده گرفتن خطاهای اتصال API

اگر با addApi() تماس بگیرید و GoogleApiClient نتواند با موفقیت به آن API متصل شود، کل عملیات اتصال برای آن کلاینت با شکست مواجه می‌شود و پاسخ تماس onConnectionFailed() را راه‌اندازی می‌کند.

با استفاده از addApiIfAvailable() می توانید یک شکست اتصال API را ثبت کنید تا نادیده گرفته شود. اگر یک API اضافه شده با addApiIfAvailable() به دلیل خطای غیرقابل بازیابی (مانند API_UNAVAILABLE برای Wear) متصل نشود، آن API از GoogleApiClient شما حذف می‌شود و کلاینت به اتصال به APIهای دیگر ادامه می‌دهد. با این حال، اگر هر یک از اتصال API با یک خطای قابل بازیابی (مانند هدف قطعنامه رضایت OAuth) با شکست مواجه شود، عملیات اتصال کلاینت با شکست مواجه می شود. هنگام استفاده از یک اتصال مدیریت شده به طور خودکار GoogleApiClient تلاش می کند تا در صورت امکان چنین خطاهایی را برطرف کند. هنگام استفاده از یک اتصال مدیریت شده دستی، یک ConnectionResult حاوی یک هدف رزولوشن به پاسخ تماس onConnectionFailed() تحویل داده می شود. خرابی‌های اتصال API تنها در صورتی نادیده گرفته می‌شوند که هیچ قطعنامه‌ای برای خرابی وجود نداشته باشد و API با addApiIfAvailable() اضافه شده باشد. برای آشنایی با نحوه اجرای مدیریت شکست اتصال دستی، به رسیدگی به خرابی های اتصال مراجعه کنید.

از آنجا که APIهای اضافه شده با addApiIfAvailable() ممکن است همیشه در نمونه GoogleApiClient متصل وجود نداشته باشند، باید با افزودن یک چک با استفاده از hasConnectedApi() از تماس‌های این APIها محافظت کنید. برای اینکه بفهمید چرا یک API خاص در زمانی که کل عملیات اتصال برای کلاینت موفقیت آمیز بود، متصل نشد، getConnectionResult() را فراخوانی کنید و کد خطا را از شی ConnectionResult دریافت کنید. اگر سرویس گیرنده شما با یک API تماس بگیرد زمانی که به مشتری متصل نیست، تماس با کد وضعیت API_NOT_AVAILABLE انجام نمی شود.

اگر API که از طریق addApiIfAvailable() اضافه می کنید به یک یا چند محدوده نیاز دارد، به جای استفاده از متد addScope() ، آن دامنه ها را به عنوان پارامتر در فراخوانی متد addApiIfAvailable() () خود اضافه کنید. اگر اتصال API قبل از دریافت رضایت OAuth از کار بیفتد، ممکن است دامنه‌های اضافه‌شده با این رویکرد درخواست نشود، در حالی که دامنه‌هایی که با addScope() اضافه می‌شوند همیشه درخواست می‌شوند.

اتصالات مدیریت شده به صورت دستی

اکثر این راهنما به شما نشان می دهد که چگونه از روش enableAutoManage برای شروع یک اتصال مدیریت شده خودکار با خطاهای حل شده خودکار استفاده کنید. تقریباً در همه موارد، این بهترین و ساده‌ترین راه برای اتصال به Google API از برنامه Android شما است. با این حال، شرایطی وجود دارد که می‌خواهید از یک اتصال مدیریت شده دستی به Google API در برنامه خود استفاده کنید:

  • برای دسترسی به APIهای Google خارج از یک فعالیت یا حفظ کنترل اتصال API
  • برای سفارشی کردن رسیدگی و حل خطای اتصال

این بخش نمونه هایی از این موارد و سایر موارد استفاده پیشرفته را ارائه می دهد.

یک اتصال مدیریت شده دستی را شروع کنید

برای راه‌اندازی یک اتصال مدیریت‌شده دستی به GoogleApiClient ، باید یک پیاده‌سازی برای رابط‌های پاسخ به تماس، ConnectionCallbacks و OnConnectionFailedListener مشخص کنید. هنگامی که اتصال به سرویس‌های Google Play موفقیت آمیز، شکست یا تعلیق می‌شود، این واسط‌ها در پاسخ به روش ناهمزمان connect() تماس دریافت می‌کنند.

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

هنگام مدیریت یک اتصال به صورت دستی، باید متدهای connect() و disconnect() را در نقاط مناسب در چرخه عمر برنامه خود فراخوانی کنید. در زمینه فعالیت، بهترین روش فراخوانی connect() در متد onStart() اکتیویتی و disconnect() در متد onStop() اکتیویتی است. متدهای connect() و disconnect() به طور خودکار هنگام استفاده از یک اتصال مدیریت شده خودکار فراخوانی می شوند.

اگر از GoogleApiClient برای اتصال به APIهایی که نیاز به احراز هویت دارند، مانند Google Drive یا Google Play Games، استفاده می‌کنید، احتمال زیادی وجود دارد که اولین تلاش شما برای اتصال ناموفق باشد و برنامه شما با خطای SIGN_IN_REQUIRED تماسی با onConnectionFailed() دریافت کند، زیرا حساب کاربری مشخص نشده بود.

رفع خرابی های اتصال

هنگامی که برنامه شما تماسی با پاسخ تماس onConnectionFailed() دریافت می کند، باید hasResolution() در شی ConnectionResult ارائه شده فراخوانی کنید. اگر مقدار true را برگرداند، برنامه شما می تواند از کاربر درخواست کند تا با فراخوانی startResolutionForResult() در شی ConnectionResult ، اقدامی فوری برای رفع خطا انجام دهد. متد startResolutionForResult() در این شرایط مانند startActivityForResult() عمل می‌کند و یک اکتیویتی مناسب با زمینه راه‌اندازی می‌کند که به کاربر کمک می‌کند تا خطا را برطرف کند (مانند فعالیتی که به کاربر در انتخاب حساب کمک می‌کند).

اگر hasResolution() false برگرداند، برنامه شما باید GoogleApiAvailability.getErrorDialog() را فراخوانی کند و کد خطا را به این روش ارسال کند. این یک Dialog ارائه شده توسط سرویس‌های Google Play را برمی‌گرداند که متناسب با خطا است. این گفتگو ممکن است به سادگی پیامی را ارائه دهد که خطا را توضیح می دهد، یا همچنین ممکن است اقدامی برای راه اندازی فعالیتی ارائه دهد که می تواند خطا را برطرف کند (مانند زمانی که کاربر نیاز به نصب نسخه جدیدتری از خدمات Google Play دارد).

برای مثال، متد callback onConnectionFailed() شما اکنون باید به شکل زیر باشد:

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

پس از اینکه کاربر گفتگوی ارائه شده توسط startResolutionForResult() را تکمیل کرد یا پیام ارائه شده توسط GoogleApiAvailability.getErrorDialog() را رد کرد، فعالیت شما پاسخ تماس onActivityResult() را با کد نتیجه RESULT_OK دریافت می کند. سپس برنامه شما می تواند دوباره connect() فراخوانی کند. مثلا:

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

در کد بالا، احتمالا متوجه بولی، mResolvingError شده اید. این حالت برنامه را در حالی که کاربر در حال رفع خطا است پیگیری می کند تا از تلاش های مکرر برای رفع همان خطا جلوگیری کند. به عنوان مثال، در حالی که گفتگوی انتخابگر حساب برای کمک به کاربر برای رفع خطای SIGN_IN_REQUIRED نمایش داده می شود، کاربر ممکن است صفحه را بچرخاند. این اکتیویتی شما را دوباره ایجاد می‌کند و باعث می‌شود متد onStart() دوباره فراخوانی شود، که سپس دوباره connect() را فراخوانی می‌کند. این منجر به فراخوانی دیگری برای startResolutionForResult() می شود که یک گفتگوی انتخابگر حساب دیگر در مقابل یکی از موجود ایجاد می کند.

این بولی تنها در صورتی به هدف مورد نظر خود عمل می کند که در تمام نمونه های فعالیت ادامه داشته باشد. بخش بعدی توضیح می‌دهد که چگونه می‌توانید وضعیت رسیدگی به خطای برنامه خود را با وجود سایر اقدامات یا رویدادهایی که در دستگاه رخ می‌دهد، حفظ کنید.

حفظ حالت در حین رفع خطا

برای جلوگیری از اجرای کد در onConnectionFailed() در حالی که تلاش قبلی برای حل یک خطا در حال انجام است، باید یک Boolean نگه دارید که ردیابی کند آیا برنامه شما قبلاً در حال تلاش برای رفع خطا است یا خیر.

همانطور که در مثال کد بالا نشان داده شده است، برنامه شما باید هر بار که startResolutionForResult() را فراخوانی می‌کند یا کادر گفتگوی GoogleApiAvailability.getErrorDialog() نمایش می‌دهد، یک Boolean را روی true تنظیم کند. سپس، هنگامی که برنامه شما RESULT_OK در پاسخ به تماس onActivityResult() دریافت کرد، boolean را روی false تنظیم کنید.

برای پیگیری بولی در طول راه اندازی مجدد فعالیت (مانند زمانی که کاربر صفحه را می چرخاند)، با استفاده از onSaveInstanceState() بولی را در داده های نمونه ذخیره شده فعالیت ذخیره کنید:

private static final String STATE_RESOLVING_ERROR = "resolving_error";

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

سپس حالت ذخیره شده را در طول onCreate() بازیابی کنید:

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

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

اکنون آماده اجرای ایمن برنامه خود و اتصال دستی به خدمات Google Play هستید.