从 Android 客户端调用后端 API

本页面介绍 Android 客户端如何调用使用 Cloud Endpoints Frameworks 为 App Engine 构建的后端 API。

生成客户端库

您的 Android 客户端需要从客户端使用的后端 API 生成的客户端库。如果您还没有客户端库,请参阅生成客户端库了解详情。本文档中的步骤说明了如何将客户端库添加到 Android 客户端项目。

设置项目

在以下说明中,您需使用 Android Studio。 如果您还没有这样做,则需要设置 Android Studio 以支持使用该框架的客户端。

配置项目

在 Android Studio 中,您的项目会将 build.gradle 文件用于依赖项和其他设置。默认情况下,Android Studio 会创建一个父项目级 build.gradle 文件,并在 Android 模块中创建一个 Android 应用专属的此文件。以下说明适用于 Android 模块中应用专属的 build.gradle

要配置 build.gradle,请执行以下操作:

  1. 双击 build.gradle 将其打开。

  2. 修改此文件,使其包含以下几行的内容:

    buildscript {
        repositories {
            mavenCentral()
        }
        dependencies {
            classpath 'com.android.tools.build:gradle:1.0.0'
        }
    }
    apply plugin: 'com.android.application'
    
    repositories {
        mavenCentral()
        mavenLocal()
    }
    
    android {
        compileSdkVersion 26
    
        defaultConfig {
            applicationId "com.mycompany.myapp"
            minSdkVersion 17
            targetSdkVersion 26
            versionCode 1
            versionName "1.0"
        }
        buildTypes {
            release {
                minifyEnabled false
                proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            }
        }
        packagingOptions {
            exclude 'META-INF/DEPENDENCIES'
        }
    }
    
    dependencies {
        implementation 'com.android.support:appcompat-v7:26.1.0'
        implementation 'com.android.support.constraint:constraint-layout:1.1.3'
        // BEGIN Google APIs
        // Play Services will validate the application prior to allowing OAuth2 access.
        implementation 'com.google.android.gms:play-services-auth:16.0.0'
        implementation 'com.google.android.gms:play-services-identity:16.0.0'
        // The following lines implement maven imports as defined at:
        // https://github.com/googleapis/google-api-java-client/wiki/Setup-Instructions
        // Add the Google API client library.
        implementation('com.google.api-client:google-api-client:1.28.0') {
            // Exclude artifacts that the Android SDK/Runtime provides.
            exclude(group: 'xpp3', module: 'xpp3')
            exclude(group: 'org.apache.httpcomponents', module: 'httpclient')
            exclude(group: 'junit', module: 'junit')
            exclude(group: 'com.google.android', module: 'android')
        }
        // Add the Android extensions for the Google API client library.
        // This will automatically include play services as long as you have download that library
        // from the Android SDK manager.
        // Add the Android extensions for the Google API client library.
        implementation(group: 'com.google.api-client', name: 'google-api-client-android', version: '1.25.0') {
                   // Exclude play services, since we're not using this yet.
                  exclude(group: 'com.google.android.gms:play-services', module: 'google-play-services')
        }
        // END Google APIs
        // The following client libraries make HTTP/JSON on Android easier.
        // Android extensions for Google HTTP Client.
        implementation('com.google.http-client:google-http-client-android:1.21.0') {
            exclude(group: 'com.google.android', module: 'android')
        }
        implementation 'com.google.http-client:google-http-client-gson:1.21.0'
        // This is used by the Google HTTP client library.
        implementation 'com.google.guava:guava:18.0+'
        implementation files('libs/echo-v1-1.25.0-SNAPSHOT.jar')
    }
    
    

    com.mycompany.myapp 替换为您自己的值。

  3. 点击文件 (File) > 全部保存 (Save All),然后退出 Android Studio 并进行重启。

将客户端库添加到项目中

要添加客户端库到 Android 项目,请执行以下操作:

  1. /libs 目录添加到项目中(如果项目中尚无该目录)。它是 /src 目录的对等目录。

  2. 将通过后端 API 生成的客户端库复制到 /libs 中。

  3. 右键点击刚刚添加的库,然后选择添加为库 (Add As Library),将其添加到您的项目中。

创建服务对象

在项目代码中,您必须使用服务对象向后端 API 发出请求。对于未经身份验证的请求,请按如下方式构造服务对象:

BACKEND_API_NAME.Builder builder = new BACKEND_API_NAME.Builder(
    NetHttpTransport(), new GsonFactory(), null);
service = builder.build();

BACKEND_API_NAME 替换为您的后端 API 名称。

调用后端 API

在项目中,使用服务对象调用 API。例如:

ScoreCollection scores = service.scores().list().execute();

在此代码段中,您将请求服务器上所有 Score 对象的列表。如果 list 需要使用参数或请求正文,请通过命令提供。Android Studio 提供代码补全功能,可识别可用的方法调用及其必需的参数。

请务必注意,由于 API 调用会通过网络生成请求,因此您需要在其自己的线程中发出请求。(此需求已添加到最新版本的 Android 中,但即使在旧版本中,这样也是最佳做法。)为此,您应使用 ThreadAsyncTask。例如:

private class QueryScoresTask extends AsyncTask<Void, Void, ScoreCollection>{
  Context context;

  public QueryScoresTask(Context context) {
    this.context = context;
  }

  protected Scores doInBackground(Void... unused) {
    ScoreCollection scores = null;
    try {
      scores = service.scores().list().execute();
    } catch (IOException e) {
      Log.d("TicTacToe", e.getMessage(), e);
    }
    return scores;
  }

  protected void onPostExecute(ScoreCollection scores) {
    // Do something with the result.
  }
}

进行经过身份验证的调用

以下说明仅涵盖您需要添加的客户端编码。说明假设您已经按照对用户进行身份验证所述,针对身份验证添加了 Endpoints Frameworks 支持。

如果您的 Android 客户端将调用需要身份验证的端点,您必须:

  • 配置您的 Android 客户端以向服务对象提供凭据。
  • 使用账号选择器支持用户的登录账号选择。

以下部分将作详细介绍。

配置您的 Android 客户端以提供凭据

要支持向需要身份验证的后端 API 发送请求,您的 Android 客户端需要获取用户凭据并将其传递给服务对象。

如果您要获取用户凭据并使用账号选择器,则需要具备以下 Android 权限:

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

要获取用户凭据,请按以下方式调用 GoogleAccountCredential.usingAudience

// Inside your Activity class onCreate method
settings = getSharedPreferences(
    "TicTacToeSample", 0);
credential = GoogleAccountCredential.usingAudience(this,
    "server:client_id:1-web-app.apps.googleusercontent.com");

其中,调用的第二个参数是前缀 server:client_id,前置于后端 API 的 Web 客户端 ID。

示例代码:获取服务对象的凭据

以下代码展示了如何获取凭据并将其传递给服务对象:

// Inside your Activity class onCreate method
settings = getSharedPreferences("TicTacToeSample", 0);
credential = GoogleAccountCredential.usingAudience(this,
    "server:client_id:1-web-app.apps.googleusercontent.com");
setSelectedAccountName(settings.getString(PREF_ACCOUNT_NAME, null));

Tictactoe.Builder builder = new Tictactoe.Builder(
    NetHttpTransport(), new GsonFactory(),
    credential);
service = builder.build();

if (credential.getSelectedAccountName() != null) {
  // Already signed in, begin app!
} else {
  // Not signed in, show login window or request an account.
}

// setSelectedAccountName definition
private void setSelectedAccountName(String accountName) {
  SharedPreferences.Editor editor = settings.edit();
  editor.putString(PREF_ACCOUNT_NAME, accountName);
  editor.commit();
  credential.setSelectedAccountName(accountName);
  this.accountName = accountName;
}

上述示例代码会查找 Android 应用存储的任何共享首选项,并尝试查找用户想用来进行应用身份验证的账号的名称。成功之后,该代码将创建一个凭据对象并将其传递给您的服务对象。您的 Android 应用可使用这些凭据将相应的令牌传递给后端。

请注意,代码示例会检查 Android 应用是否已知道要使用的账号。如果应用知道要使用哪个账号,则逻辑流会继续并运行 Android 应用。如果应用不知道要使用哪个账号,则应用会显示登录屏幕或提示用户选择账号

最后,该示例展示了如何创建一个凭据对象并将其传递给服务对象。您的 Android 应用可以使用这些凭据将相应的令牌传递到 App Engine Web 应用。

使用账号选择器

Android 提供了一个 intent 来选择用户账号。您可以按如下方式调用此 intent:

static final int REQUEST_ACCOUNT_PICKER = 2;

void chooseAccount() {
  startActivityForResult(credential.newChooseAccountIntent(),
      REQUEST_ACCOUNT_PICKER);
}

用于解释此 intent 结果的处理程序如下所示:

@Override
protected void onActivityResult(int requestCode, int resultCode,
   Intent data) {
 super.onActivityResult(requestCode, resultCode, data);
 switch (requestCode) {
   case REQUEST_ACCOUNT_PICKER:
     if (data != null && data.getExtras() != null) {
       String accountName =
           data.getExtras().getString(
               AccountManager.KEY_ACCOUNT_NAME);
       if (accountName != null) {
         setSelectedAccountName(accountName);
         SharedPreferences.Editor editor = settings.edit();
         editor.putString(PREF_ACCOUNT_NAME, accountName);
         editor.commit();
         // User is authorized.
       }
     }
     break;
  }
}

针对本地开发服务器测试 Android 客户端

您可以随时针对在生产 App Engine 中运行的后端 API 测试客户端,而无需进行任何更改。但是,如果要针对在本地开发服务器上运行的后端 API 测试客户端,则需要更改客户端中的代码行,以指向运行本地开发服务器的计算机的 IP 地址。

要进行必要的更改并使用本地开发服务器进行测试,请执行以下操作:

  1. 记下运行本地开发服务器的机器的 IP 地址。在将代码添加到 Android 客户端时,将会用到此信息。

  2. 按照在本地运行和测试 API 后端所述,启动本地开发服务器。

  3. 在 Android Studio 客户端项目中,找到用于获取后端 API 服务处理程序的代码。通常,此代码使用 Builder 来设置 API 请求。

  4. 通过添加以下行来替换 Builder 对象中的根网址(即 Android 客户端在后端 API 调用中连接到的网址):

    yourBuilderObject.setRootUrl("http://YOUR_MACHINE_IP_ADDRESS:8080/_ah/api");
    

    例如:

    public static Helloworld getApiServiceHandle(@Nullable GoogleAccountCredential credential) {
      // Use a builder to help formulate the API request.
      Helloworld.Builder helloWorld = new Helloworld.Builder(AppConstants.HTTP_TRANSPORT,
          AppConstants.JSON_FACTORY,credential);
    
      helloWorld.setRootUrl("http://YOUR_MACHINE_IP_ADDRESS:8080/_ah/api");
      return helloWorld.build();
    }
    

    YOUR_MACHINE_IP_ADDRESS 替换为您的系统的 IP 地址。

  5. 重新构建您的 Android 客户端项目。

  6. 如果要在 AVD 模拟器上运行客户端应用,请执行以下操作:

    1. 在 Android Studio 中,转到工具 (Tools) > Android > AVD 管理器 (AVD Manager) 并启动现有的 AVD(如果有),否则就创建一个 AVD 再进行启动。
    2. 转到运行 (Run) > 调试 YOUR_PROJECT_NAME (Debug YOUR_PROJECT_NAME),其中 YOUR_PROJECT_NAME 代表 Google Cloud 项目的名称。
    3. 当系统提示您选择设备时,请选择您的 AVD。
    4. 测试您的客户端。
  7. 如果您要在 Android 真机设备上运行客户端应用,请执行以下操作:

    1. 确保您的 Android 设备已启用调试功能
    2. 在 Android Studio 中,转到运行 (Run) > 调试 YOUR_PROJECT_NAME
    3. 当系统提示您选择设备时,请选择您的 Android 真机设备。
    4. 测试您的客户端。

示例客户端源代码

如需了解示例代码,请参阅 Android Cloud Endpoints v2.0 示例