通过 GoogleApiClient 访问 Google API(已弃用)

您可以使用 GoogleApiClient(“Google API 客户端”) 对象来访问 Google Play 服务库中提供的 Google API (例如 Google 登录、游戏和云端硬盘)。Google API 客户端提供了 Google Play 服务和管理网络的通用入口点 用户的设备与各项 Google 服务之间的连接。

不过,较新的 GoogleApi 接口及其实现更易于 和 是访问 Play 服务 API 的首选方式。 请参阅访问 Google API

本指南介绍了如何执行以下操作:

  • 自动管理与 Google Play 服务的关联。
  • 对任何 Google Play 服务执行同步和异步 API 调用。
  • 在极少数情况下,您需要手动管理与 Google Play 服务的连接 。如需了解详情,请参阅手动管理的连接
。 <ph type="x-smartling-placeholder">
</ph>
图 1:显示 Google API 客户端如何提供 用于连接和调用任何可用的 Google Play 服务(例如 Google Play 游戏和 Google 云端硬盘。

首先,您必须先安装 Google Play 服务库(修订版 15 或更高版本) 。如果您尚未按照上述说明操作,请按照 设置 Google Play 服务 SDK

启动自动管理的连接

在您的项目关联到 Google Play 服务库后,创建 GoogleApiClient,使用 GoogleApiClient.Builder API(位于您的 Activity 的 onCreate() 方法。通过 GoogleApiClient.Builder 类提供的方法可让您指定要使用的 Google API 和所需的 OAuth 2.0 范围。下面的代码示例创建了一个 与 Google 云端硬盘服务连接的 GoogleApiClient 实例:

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

您可以将多个 API 和多个范围添加到同一个 GoogleApiClient 方法是向 addApi() 附加其他调用 和addScope()

重要提示:如果您要将 Wearable API 与其他 API 一起添加到 GoogleApiClient, 未安装 Wear OS 应用。接收者 为避免连接错误,请调用 addApiIfAvailable() 方法并传入 Wearable API,以允许您的客户端妥善处理缺少的 API。如需了解详情,请参阅访问 Wearable API

如需启动自动管理的连接,您必须指定 OnConnectionFailedListener 的实现 接收无法解析的连接错误。当您自动管理 GoogleApiClient 实例尝试连接到 Google API,系统将自动 显示界面,以尝试修复任何可解决的连接故障(例如, Google Play 服务需要更新)。如果发生 问题解决后,我们会立即致电 onConnectionFailed()

如果您的应用需要知道ConnectionCallbacks 建立或暂停自动管理的连接。例如,如果 您的应用进行调用以向 Google API 写入数据,则应调用这些调用 仅在调用 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() 后断开连接。 您的应用可以立即开始 在构建 GoogleApiClient 后向 Google API 发出读取请求,而不 等待连接完成

与 Google 服务通信

连接后,您的客户端可以使用服务专属 API 进行读取和写入调用, 您添加到 GoogleApiClient 实例。

注意:在调用特定 Google 服务之前,您可能需要先注册您的 了解其应用。有关说明,请参阅 入门指南,例如 Google 云端硬盘Google 登录

当您使用 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 服务的情况下,将读取请求加入队列。对于 例如,无论您的 GoogleApiClient 实例是否已连接,应用都可以调用方法来读取 Google 云端硬盘中的文件。建立连接后,会执行已加入队列的读取请求。如果您的应用调用 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() 在结果到达之前阻塞线程,则您的应用绝不应在 界面线程。您的应用可以使用 AsyncTask 对象创建新线程,并使用该线程发出同步请求。

以下示例展示了如何以同步调用的形式向 Google 云端硬盘发送文件请求:

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 但未使用其他 Google API,您可以通过以下方法添加此 API: 调用 addApi() 方法。以下示例展示了如何将 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 与其他 Google API 搭配使用

如果您的应用除了使用其他 Google API 之外,还使用 Wearable API,请调用 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 可以成功连接到 Google 云端硬盘,而不连接到 Wearable API(如果不可用)。更新后 请连接你的GoogleApiClient 实例,在进行 API 调用之前确保 Wearable API 可用:

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

忽略 API 连接故障

如果您调用 addApi(),但 GoogleApiClient 无法执行以下操作: 成功连接到该 API,则该客户端的整个连接操作将失败,并且 触发 onConnectionFailed() 回调。

您可以使用 addApiIfAvailable()。如果通过 由于发生不可恢复的错误,addApiIfAvailable() 无法连接 (如 Wear 的 API_UNAVAILABLE), 该 API 将从您的 GoogleApiClient 丢弃,并且客户端继续 连接到其他 API。但是,如果任何 API 连接因可恢复的错误(如 OAuth 同意解析 intent),则客户端连接操作将失败。时间 如果使用的是自动管理的连接,GoogleApiClient 将尝试 以解决此类错误。使用手动管理的连接时 包含解析 intent 的 ConnectionResult 传递给 onConnectionFailed() 回调。API 仅当没有针对连接故障的解决方法时,系统才会忽略此故障 并且该 API 已添加到 与 addApiIfAvailable() 共享。 了解如何实现手动连接失败 请参阅处理连接故障

由于使用 addApiIfAvailable()可能并不总是出现在已连接的 GoogleApiClient 实例,则应通过添加检查代码来保护对这些 API 的调用 (使用 hasConnectedApi())。为了解 当客户端的整个连接操作成功时,特定 API 连接失败,请调用 getConnectionResult(),并从 ConnectionResult 对象。如果您的客户端在未调用某个 API 时调用该 API, 调用将失败,并显示 API_NOT_AVAILABLE 状态代码。

如果您通过 addApiIfAvailable() 添加的 API 需要一个或 请将这些范围作为参数添加到 addApiIfAvailable() 方法调用,而不是使用 addScope() 方法。如果 API 则连接失败后才能获得 OAuth 同意,而使用 始终请求 addScope()

手动管理的连接

本指南的大部分内容将介绍如何使用 enableAutoManage 方法启动 具有自动解决的错误的自动管理连接。即将在 在所有情况下,这是从您的 Android 应用。不过,在某些情况下,您需要使用 在您的应用中手动管理与 Google API 的连接:

  • 在活动之外访问 Google API 或保留对 API 的控制权 连接
  • 自定义连接错误的处理和解决方法

本部分提供了这些及其他高级用例的示例。

启动手动管理的连接

如需启动与 GoogleApiClient 的手动管理连接,您必须: 为回调接口指定实现 ConnectionCallbacksOnConnectionFailedListener。 这些接口会收到回调以响应异步 connect() 方法, 与 Google Play 服务的连接成功、失败或被暂停。

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

手动管理连接时,您需要调用 connect()disconnect() 在应用的生命周期的正确时间点添加方法。在活动中 上下文,最佳实践是在 activity 的 onStart() 中调用 connect() 方法,以及 activity 的 onStop() 方法中的 disconnect()connect()disconnect() 方法 在使用自动管理的连接时会自动调用。

如果您使用 GoogleApiClient 连接到需要 例如 Google 云端硬盘或 Google Play 游戏 您的第一次连接尝试将失败,并且您的应用将收到呼叫 发送至onConnectionFailed() 使用SIGN_IN_REQUIRED 错误,原因是未指定用户账号。

处理连接故障

当应用收到对 onConnectionFailed() 的调用时 回调,则应调用 hasResolution() 提供的ConnectionResult 对象。如果它返回 true,您的应用可以通过以下方式请求用户立即采取措施来解决错误: 正在呼叫startResolutionForResult() 针对 ConnectionResult 对象的操作。 startResolutionForResult() 方法 在这种情况下,行为与 startActivityForResult() 相同, 并启动一个适合上下文的 activity,以帮助用户解决错误(例如,帮助用户解决相关问题的 activity) 选择账号)。

如果状态为 hasResolution() 返回 false,您的应用应调用 GoogleApiAvailability.getErrorDialog()、 将错误代码传递给此方法。这将返回一个 Dialog(由 Google Play 提供) 对相应错误进行适当更改的服务。对话框可能只会提供一条消息 也可能提供一个操作来启动可以解决该错误的 activity (例如,当用户需要安装较新版本的 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() 提供的消息, 您的 activity 会收到 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 错误时,用户可以旋转屏幕。这会重新创建您的 Activity 并导致 onStart() 方法 然后再次调用 connect()。这个 会导致系统对 startResolutionForResult(), 系统会在现有账号选择器对话框前面再创建一个账号选择器对话框。

仅当跨 activity 实例持续存在此布尔值时,它才会有其预期用途。 下一部分将介绍如何维护应用的错误处理状态(即便有其他用户操作) 或事件中发生的事件

解决错误时保持状态

为避免在 Cloud Shell 中 onConnectionFailed() 而之前尝试解决某个错误时,您需要保留一个布尔值, 跟踪您的应用是否已尝试解决错误。

如上面的代码示例所示,应用每次调用时都应将布尔值设置为 true startResolutionForResult() 或者从 GoogleApiAvailability.getErrorDialog()。 然后,当您的应用收到 RESULT_OK(在 onActivityResult() 回调,请将布尔值设置为 false

如需在 activity 重启时(例如当用户旋转屏幕时)跟踪该布尔值, 使用以下代码在 activity 的已保存实例数据中保存布尔值: 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 服务了。