Вы можете использовать объект GoogleApiClient
(«Google API Client») для доступа к API Google, предоставляемым в библиотеке сервисов Google Play (таких как Google Sign-In, Games и Drive). Клиент Google API предоставляет общую точку входа в сервисы Google Play и управляет сетевым соединением между устройством пользователя и каждым сервисом Google.
Однако новый интерфейс GoogleApi
и его реализации проще в использовании и являются предпочтительным способом доступа к API сервисов Play. См. Доступ к API Google .
В этом руководстве показано, как вы можете:
- Автоматически управляйте подключением к сервисам Google Play.
- Выполняйте синхронные и асинхронные вызовы API к любым сервисам Google Play.
- Управляйте подключением к сервисам Google Play вручную в тех редких случаях, когда это необходимо. Чтобы узнать больше, см. раздел Управляемые вручную подключения .

Чтобы начать, вам необходимо сначала установить библиотеку служб 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();
Вы можете добавить несколько API и несколько областей действия к одному и тому же GoogleApiClient
, добавив дополнительные вызовы к addApi()
и addScope()
.
Важно: Если вы добавляете API Wearable
вместе с другими API в GoogleApiClient
, вы можете столкнуться с ошибками подключения клиента на устройствах, на которых не установлено приложение Wear OS. Чтобы избежать ошибок подключения, вызовите метод addApiIfAvailable()
и передайте API Wearable
, чтобы позволить вашему клиенту изящно обработать отсутствующий API. Для получения дополнительной информации см. Доступ к API Wearable .
Чтобы начать автоматически управляемое соединение, необходимо указать реализацию для интерфейса OnConnectionFailedListener
для получения неразрешимых ошибок соединения. Когда ваш автоматически управляемый экземпляр GoogleApiClient
пытается подключиться к API Google, он автоматически отображает пользовательский интерфейс для попытки исправить любые разрешимые ошибки соединения (например, если необходимо обновить службы Google Play). Если возникает ошибка, которую невозможно устранить, вы получите вызов onConnectionFailed()
.
Вы также можете указать необязательную реализацию для интерфейса ConnectionCallbacks
, если вашему приложению необходимо знать, когда автоматически управляемое соединение установлено или приостановлено. Например, если ваше приложение делает вызовы для записи данных в API Google, они должны вызываться только после вызова метода onConnected()
.
Вот пример действия, реализующего интерфейсы обратного вызова и добавляющего их в клиент Google API:
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()
. Ваше приложение может немедленно начать делать запросы на чтение к API Google после создания GoogleApiClient
, не дожидаясь завершения подключения.
Связь с Google Services
После подключения ваш клиент может выполнять вызовы чтения и записи, используя API-интерфейсы конкретной службы, для которых ваше приложение авторизовано, как указано в API-интерфейсах и областях, добавленных вами в экземпляр GoogleApiClient
.
Примечание: Перед вызовом определенных служб Google вам может потребоваться зарегистрировать свое приложение в консоли разработчика Google. Инструкции см. в соответствующем руководстве по началу работы для используемого вами API, например Google Drive или Google Sign-In .
Когда вы выполняете запрос на чтение или запись с помощью GoogleApiClient
, клиент API возвращает объект PendingResult
, представляющий запрос. Это происходит немедленно, до того, как запрос будет доставлен в службу Google, которую вызывает ваше приложение.
Например, вот запрос на чтение файла с Google Диска, который предоставляет объект 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 не подключен.
Использование асинхронных вызовов
Чтобы сделать запрос асинхронным, вызовите 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 в потоке пользовательского интерфейса. Ваше приложение может создать новый поток с помощью объекта AsyncTask
и использовать этот поток для выполнения синхронного запроса.
В следующем примере показано, как выполнить запрос файла на Google Диск в виде синхронного вызова:
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 // ... } }
Доступ к API носимых устройств
Wearable API предоставляет канал связи для приложений, работающих на портативных и носимых устройствах. API состоит из набора объектов данных, которые система может отправлять и синхронизировать, и прослушивателей, которые уведомляют ваши приложения о важных событиях с помощью уровня данных. Wearable API доступен на устройствах под управлением Android 4.3 (уровень API 18) или выше, когда подключено носимое устройство и на устройстве установлено сопутствующее приложение Wear OS .
Использование API носимых устройств автономно
Если ваше приложение использует API Wearable , но не другие API Google, вы можете добавить этот API, вызвав метод addApi()
. В следующем примере показано, как добавить API Wearable к вашему экземпляру GoogleApiClient
:
GoogleApiClient mGoogleApiClient = new GoogleApiClient.Builder(this) .enableAutoManage(this /* FragmentActivity */, this /* OnConnectionFailedListener */) .addApi(Wearable.API) .build();
В ситуациях, когда API носимых устройств недоступен, запросы на подключение, включающие API носимых устройств, завершаются ошибкой API_UNAVAILABLE
.
В следующем примере показано, как определить, доступен ли 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 } // ... }
Использование API носимых устройств с другими API Google
Если ваше приложение использует API Wearable в дополнение к другим API Google, вызовите метод addApiIfAvailable()
и передайте API Wearable, чтобы проверить, доступен ли он. Вы можете использовать эту проверку, чтобы помочь вашему приложению изящно обрабатывать случаи, когда API недоступен.
В следующем примере показано, как получить доступ к API носимых устройств вместе с 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
может успешно подключиться к Google Drive без подключения к Wearable API , если он недоступен. После подключения экземпляра GoogleApiClient
убедитесь, что Wearable API доступен, прежде чем выполнять вызовы API:
boolean wearAvailable = mGoogleApiClient.hasConnectedApi(Wearable.API);
Игнорирование сбоев подключения API
Если вы вызываете addApi()
и GoogleApiClient
не может успешно подключиться к этому API, вся операция подключения для этого клиента завершается неудачей и активируется обратный вызов onConnectionFailed()
.
Вы можете зарегистрировать ошибку подключения API, которую нужно игнорировать, с помощью addApiIfAvailable()
. Если API, добавленный с помощью addApiIfAvailable()
, не может подключиться из-за неустранимой ошибки (например, API_UNAVAILABLE
для Wear), этот API удаляется из вашего GoogleApiClient
, и клиент продолжает подключаться к другим API. Однако, если какое-либо подключение API завершается неудачей с устранимой ошибкой (например, намерением разрешения согласия OAuth), операция подключения клиента завершается неудачей. При использовании автоматически управляемого соединения GoogleApiClient
попытается разрешить такие ошибки, когда это возможно. При использовании вручную управляемого соединения ConnectionResult
, содержащий намерение разрешения, доставляется в обратный вызов onConnectionFailed()
. Ошибки подключения API игнорируются только в том случае, если для ошибки нет разрешения, а API был добавлен с помощью addApiIfAvailable()
. Чтобы узнать, как реализовать ручную обработку сбоев подключения, см. Обработка сбоев подключения .
Поскольку API, добавленные с помощью addApiIfAvailable()
не всегда могут присутствовать в подключенном экземпляре GoogleApiClient
, вам следует защитить вызовы этих API, добавив проверку с помощью hasConnectedApi()
. Чтобы выяснить, почему определенному API не удалось подключиться, когда вся операция подключения для клиента прошла успешно, вызовите getConnectionResult()
и получите код ошибки из объекта ConnectionResult
. Если ваш клиент вызывает API, когда он не подключен к клиенту, вызов завершается ошибкой с кодом состояния API_NOT_AVAILABLE
.
Если API, который вы добавляете через addApiIfAvailable()
требует одну или несколько областей, добавьте эти области в качестве параметров в вызове метода addApiIfAvailable()
, а не с помощью метода addScope()
. Области, добавленные с использованием этого подхода, могут не быть запрошены, если соединение API не удалось установить до получения согласия OAuth, тогда как области, добавленные с помощью addScope()
, всегда запрашиваются.
Подключения, управляемые вручную
Большая часть этого руководства показывает, как использовать метод enableAutoManage
для инициирования автоматически управляемого соединения с автоматически разрешаемыми ошибками. Почти во всех случаях это лучший и самый простой способ подключения к API Google из вашего приложения Android. Однако есть некоторые ситуации, когда вам может понадобиться использовать вручную управляемое соединение с API Google в вашем приложении:
- Для доступа к API Google вне действия или сохранения контроля над соединением API
- Для настройки обработки и устранения ошибок подключения
В этом разделе приведены примеры этих и других расширенных вариантов использования.
Запустить вручную управляемое соединение
Чтобы инициировать вручную управляемое подключение к GoogleApiClient
, необходимо указать реализацию для интерфейсов обратного вызова ConnectionCallbacks
и OnConnectionFailedListener
. Эти интерфейсы получают обратные вызовы в ответ на асинхронный метод connect()
, когда подключение к службам Google Play успешно, неудачно или приостановлено.
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 Диск или Google Play Игры, есть большая вероятность, что ваша первая попытка подключения окажется неудачной, и ваше приложение получит вызов onConnectionFailed()
с ошибкой SIGN_IN_REQUIRED
поскольку не была указана учетная запись пользователя.
Обработка сбоев соединения
Когда ваше приложение получает вызов обратного вызова onConnectionFailed()
, вы должны вызвать hasResolution()
для предоставленного объекта ConnectionResult
. Если он возвращает true, ваше приложение может запросить у пользователя немедленное действие для устранения ошибки, вызвав startResolutionForResult()
для объекта ConnectionResult
. Метод startResolutionForResult()
ведет себя так же, как startActivityForResult()
в этой ситуации, и запускает действие, соответствующее контексту, которое помогает пользователю устранить ошибку (например, действие, которое помогает пользователю выбрать учетную запись).
Если hasResolution()
возвращает false, ваше приложение должно вызвать GoogleApiAvailability.getErrorDialog()
, передав код ошибки этому методу. Это возвращает Dialog
, предоставленный службами Google Play, который соответствует ошибке. Диалог может просто предоставить сообщение, объясняющее ошибку, или он также может предоставить действие для запуска действия, которое может устранить ошибку (например, когда пользователю необходимо установить более новую версию служб Google Play).
Например, ваш метод обратного вызова 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()
во время предыдущей попытки устранения ошибки, необходимо сохранить логическое значение, отслеживающее, пытается ли ваше приложение устранить ошибку.
Как показано в примере кода выше, ваше приложение должно устанавливать логическое значение true
каждый раз, когда оно вызывает startResolutionForResult()
или отображает диалоговое окно из GoogleApiAvailability.getErrorDialog()
. Затем, когда ваше приложение получает RESULT_OK
в обратном вызове onActivityResult()
, установите логическое значение 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.