在 Android 上使用 Tasks API

警告:本文档已废弃。 如需了解如何使用 OAuth 2.0 授权 Android 应用,请参阅 Android Play 服务授权文档

本文档介绍了如何在 Android 设备上将 Tasks API 与 OAuth 2.0 搭配使用。其中介绍了用于获取用户 Google Tasks 访问权限的授权机制,以及如何在 Android 应用中创建可供使用的 Tasks API 服务对象。

为了让您的 Android 应用能够使用 Tasks API,您需要执行以下几个步骤:

  1. 选择用户的 Google 账号
  2. AccountManager 获取 Task API 的 OAuth 2.0 访问令牌
  3. 确定您的项目并设置 Tasks Service 对象
  4. 调用 Tasks API

导入 Google 的客户端库

本文档中的示例使用 Java 版 Google API 客户端库。您需要将以下 jar 添加到 Android 应用中,为此,请将下列 jar 放置在 Android 应用根目录下的 /assets 文件夹中。此外,随着本文档的过时,请查看是否有新版本。

导入 Google API 客户端库 jar 及其 Android 扩展程序(均包含在 google-api-java-client-1.4.1-beta.zip 中):

  • google-api-client-1.4.1-beta.jar
  • google-api-client-extensions-android2-1.4.1-beta.jar
  • google-api-client-googleapis-1.4.1-beta.jar
  • google-api-client-googleapis-extensions-android2-1.4.1-beta.jar

导入 Tasks 专用 jar:

导入依赖项(全部属于 google-api-java-client-1.4.1-beta.zip):

  • commons-codec-1.3.jar
  • gson-1.6.jar
  • guava-r09.jar
  • httpclient-4.0.3.jar
  • httpcore-4.0.1.jar
  • jackson-core-asl-1.6.7.jar
  • jsr305-1.3.9.jar

Android 中的 Google 账号

从 Android 2.0 开始,AccountManager 会管理您在环境中注册的账号,即 设置 > 账号和同步下列出的账号。具体而言,它会处理授权流程,并可以生成使用 API 访问数据所需的授权令牌。

在您的 Android 环境中注册的账号
在您的 Android 环境中注册的账号

为了能够使用 AccountManager 获取账号并请求授权令牌,您需要在 Android 应用清单中添加以下权限:

<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.USE_CREDENTIALS" />

您可以使用 AccountManager 获取您要访问 Tasks 的 Google 账号。AccountManager 不仅可以管理 Google 账号,还可以管理其他供应商的账号。因此,您需要使用以下代码专门请求 Google 账号:

AccountManager accountManager = AccountManager.get(activity);
Account[] accounts = accountManager.getAccountsByType("com.google");

或者,适用于 Java 的 Google API 客户端库附带一个仅处理 Google 账号的 GoogleAccountManager

GoogleAccountManager googleAccountManager = new GoogleAccountManager(activity);
Account[] accounts = googleAccountManager.getAccounts();

如果 Android 设备上有多个 Google 账号,您应通过如下所示的对话框提示用户选择要使用的账号:

选择账号对话框
选择账号对话框

您可以在 activity 的 onCreateDialog 方法中使用以下 switch/case 代码构建此类对话框:

@Override
protected Dialog onCreateDialog(int id) {
  switch (id) {
    case DIALOG_ACCOUNTS:
      AlertDialog.Builder builder = new AlertDialog.Builder(this);
      builder.setTitle("Select a Google account");
      final Account[] accounts = accountManager.getAccountsByType("com.google");
      final int size = accounts.length;
      String[] names = new String[[]size];
      for (int i = 0; i < size; i++) {
        names[[]i] = accounts[[]i].name;
      }
      builder.setItems(names, new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog, int which) {
          // Stuff to do when the account is selected by the user
          gotAccount(accounts[[]which]);
        }
      });
      return builder.create();
  }
  return null;
}

调用 showDialog(DIALOG_ACCOUNTS) 会显示账号选择器对话框。

Android 上的 Google API 授权流程

现在,用户已选择一个账号,我们可以请求 AccountManager 为 Task API 签发 OAuth 2.0 访问令牌。具体方法是调用 AccountManager.getAuthToken() 方法。在 AccountManager.getAuthToken() 调用期间,AccountManager 将负责与 Google API 授权端点联系。当 AccountManager 检索到授权令牌后,它将运行您在方法调用中定义的 AccountManagerCallback

manager.getAuthToken(account, AUTH_TOKEN_TYPE, null, activity, new AccountManagerCallback<Bundle>() {
    public void run(AccountManagerFuture<Bundle> future) {
      try {
        // If the user has authorized your application to use the tasks API
        // a token is available.
        String token = future.getResult().getString(AccountManager.KEY_AUTHTOKEN);
        // Now you can use the Tasks API...
        useTasksAPI(token);
      } catch (OperationCanceledException e) {
        // TODO: The user has denied you access to the API, you should handle that
      } catch (Exception e) {
        handleException(e);
      }
    }
  }, null);

正如您可能已经知道的那样,Android AccountManager 对 OAuth 2.0 提供实验性支持。设置 AUTH_TOKEN_TYPE 时,只需在要访问的 API 的范围前面添加 oauth2: 前缀即可。因此,对于 Tasks API,您可以使用:

String AUTH_TOKEN_TYPE = "oauth2:https://www.googleapis.com/auth/tasks";

使用上述值作为 AUTH_TOKEN_TYPE 时会出现以下问题:字符串 oauth2:https://www.googleapis.com/auth/tasks 会在授权对话框中显示为您要访问的 Google 产品的名称。为解决此问题,Tasks API 提供了特殊的(可读取的)AUTH_TOKEN_TYPE 别名。它们等同于使用 OAuth 2.0 范围。例如,您可以使用:

String AUTH_TOKEN_TYPE = "Manage your tasks";

您还可以使用 AUTH_TOKEN_TYPE 别名 View your tasks,该别名相当于 Tasks API 的只读范围:oauth2:https://www.googleapis.com/auth/tasks.readonly

AccountManager.getAuthToken() 调用期间,AccountManager 会检查您的应用是否已获授权访问 Tasks API。如果您的应用尚未获得授权,AccountManager 会启动一个 Activity,以向用户显示授权对话框,以便用户允许拒绝您的应用在其账号中使用 Tasks API。

授权对话框
授权对话框

如果用户拒绝您的应用访问 Tasks API,系统会在 future.getResult() 调用期间抛出 OperationCanceledException。您应妥善处理此问题,例如要求用户重新选择账号,或显示一条消息并附上重新授予访问权限的按钮。

标识您的应用并设置 Tasks API 服务对象

现在,您的应用已获得访问 Tasks API 的授权,并且已获得访问令牌,但您还需要一个 API 密钥,您需要在 Google API 控制台中从项目中获取该密钥,因为它是发出 Tasks API 调用的强制性要求。具体步骤如下:

  1. 创建项目或使用现有项目
  2. 将 Tasks API 开关切换到 ON(开启),为您的项目启用 Tasks API
  3. API 密钥位于 API 访问 > 简单 API 访问 > API 密钥

从 API 控制台获取 API 密钥
从 API 控制台获取 API 密钥

API 密钥是必需的,因为它用于标识您的应用,因此允许 API 扣减配额并使用为您的项目定义的配额规则。您需要在 Tasks service 对象上指定 API 密钥

useTasksAPI(String accessToken) {
  // Setting up the Tasks API Service
  HttpTransport transport = AndroidHttp.newCompatibleTransport();
  AccessProtectedResource accessProtectedResource = new GoogleAccessProtectedResource(accessToken);
  Tasks service = new Tasks(transport, accessProtectedResource, new JacksonFactory());
  service.accessKey = INSERT_YOUR_API_KEY;
  service.setApplicationName("Google-TasksSample/1.0");

  // TODO: now use the service to query the Tasks API
}

accessToken 仅在一定时间内有效,因此当其过期时,您必须获取新的令牌。您可以通过以下 2 种方式处理此问题:

  • 每次通过 API 发出请求时,都向 AccountManager 请求 accessToken。由于 AccountManager 会缓存令牌,因此此解决方案是可接受的。
  • 请继续使用 accessToken,直到收到 403 错误为止,然后向 AccountManager 请求新的令牌。

通过 API 操控任务

至此,您应该已经完成了 Tasks API service 对象的完整设置,您可以根据 Tasks API 开发者指南使用该对象查询 API,例如:

// Getting all the Task lists
List taskLists = service.tasklists.list().execute().items;

// Getting the list of tasks in the default task list
List tasks = service.tasks.list("@default").execute().items;

// Add a task to the default task list
Task task = new Task();
task.title = "New Task";
task.notes = "Please complete me";
task.due = "2010-10-15T12:00:00.000Z";
Task result = service.tasks.insert("@default", task).execute();

请务必向 Android 应用清单中添加访问互联网的权限,否则对 Tasks API 端点的上述请求将会失败:

<uses-permission android:name="android.permission.INTERNET" />

示例应用

我们最近在 Java 版 Google API 客户端库示例代码库中添加了一个新示例,以帮助您开始在 Android 上使用 Tasks API 和 OAuth 2.0。此示例是一个简单但完全可用的 Android 应用,它会请求使用 Tasks API 的授权,并在 ListView 中显示默认任务列表的任务。

在 ListView 的默认任务列表中显示任务
在 ListView 的默认任务列表中显示任务

请按照以下说明运行示例,并随时在 Google Tasks API 论坛中发布您的反馈或问题。