从 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 (Debug)。
    3. 当系统提示您选择设备时,请选择您的 Android 真机设备。
    4. 测试您的客户端。

示例客户端源代码

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