用于按条件分发模块的设备定位

什么是用于按条件分发模块的设备定位?

借助设备定位,您可以根据设备的硬件向其分发按条件分发的功能模块。例如,您可以选择将某功能仅分发给高端设备,而不分发给无法使用该功能的设备,进而节省这些设备上的空间。这种做法基于 Play Feature Delivery 中的功能模块概念。正如下文所述,您可以定义定位条件(目前可基于 RAM、特定设备型号或可用系统功能来定义),并将模块定位到特定的设备组。

开发者流程

概括而言,如需将设备定位集成到现有应用中,您需要执行以下步骤:

  1. 开发一项您希望根据设备的硬件仅分发给一组设备的功能。
    • 将此功能实现为功能模块
    • 在 AndroidManifest.xml 的模块条件部分,指定应将该模块分发给哪些设备组。
  2. 创建设备定位配置,告诉 Play 如何将您的功能模块分发给用户设备。
    • 设置 Google Play Developer API(如果尚未完成此设置),您将使用该 API 将设备定位配置发送到 Play。
    • 按步骤完成设备定位配置的创建。
  3. 将 AAB 文件上传到 Play,并进行测试以确保各项配置正确无误。

本文档将介绍如何使用 Android Gradle 插件添加设备定位,以便按条件分发模块。

创建通过设备定位按条件分发的功能模块

将功能模块添加到应用中

Play Feature Delivery 让您可以按条件分发或按需下载应用的某些功能,请阅读此处的相关概览。 将设备分配到提供的设备组,即可通过设备定位按条件将功能分发给组中的设备。

如需使用设备定位来按条件分发模块,您必须使用 bundletool 1.7.0 版及更高版本。为此,您需要为 Android Gradle 插件明确指定 bundletool 版本。可以在根 build.gradle 文件的 buildscript 部分进行此项指定:

buildscript {
  dependencies {
    classpath "com.android.tools.build:bundletool:1.7.0"
    ...
  }
  ...
}

如需创建功能模块,请按照关于模块化 Android 应用的说明操作。

功能开发完成后,您可以在功能的 AndroidManifest.xml 中基于设备定位指定分发条件。您需要在 dist:module 元素的 dist:conditions 内提供设备组条件。点击此处可查看关于条件的一般信息。对于设备组,您可以使用新条件来指定应向其分发此功能的所有组:

<dist:device-groups>
  <dist:device-group dist:name="..." />
  <dist:device-group dist:name="..." />
  ...
</dist:device-groups>

例如,假设您已定义一个名为 _my_group1 的设备组(下文创建设备定位配置部分将介绍具体定义方式)。如果应将功能模块仅分发给属于 _my_group1 设备组的设备,其 AndroidManifest.xml 应如下所示:

<manifest ...>
  ...
  <dist:module dist:title="...">
    <dist:delivery>
      <dist:install-time>
        <dist:conditions>
          <dist:device-groups>
            <dist:device-group dist:name="my_group_1"/>
          </dist:device-groups>
          ...
        </dist:conditions>
      </dist:install-time>
    </dist:delivery>
  </dist:module>
  ...
</manifest>

如果某个功能同时定位 _my_group1 和 _my_group2,其 AndroidManifest.xml 将如下所示:

<manifest ...>
  ...
  <dist:module dist:title="...">
    <dist:delivery>
      <dist:install-time>
        <dist:conditions>
          <dist:device-groups>
            <dist:device-group dist:name="my_group_1"/>
            <dist:device-group dist:name="my_group_2"/>
          </dist:device-groups>
          ...
        </dist:conditions>
      </dist:install-time>
    </dist:delivery>
  </dist:module>
  ...
</manifest>

完成后,您便可以构建 Android App Bundle (AAB) 文件了。

本地测试

在继续下一步之前,建议您在本地测试 app bundle,确保各项设置正确无误。使用 bundletool,您可以在本地构建和测试应用,并明确指定正确的设备组。您需要先使用 build-apks 生成一组 .apks 文件,然后使用 install-apks 将应用部署到已连接的设备。此外,您还可以通过 device-groups 标志指定要进行安装的组。如需详细了解此本地测试方法,请点击此处。请注意,此页面尚未针对有关设备定位的内容进行更新,因此缺少 device-groups 标志。

bundletool build-apks --bundle=/path/to/app.aab --output=/path/to/app.apks --local-testingbundletool install-apks --apks=/path/to/app.apks --device-groups=my_group_1,my_group_2

替代方案:您也可以使用 extract-apks 为特定设备(使用 get-device-spec 并指定该设备的设备组)提取一组 APK。

bundletool get-device-spec --output=/path/to/device-spec.json --device-groups=my_group_1,my_group_2bundletool extract-apks --apks=/path/to/existing_APK_set.apks --output-dir=/path/to/device_specific_APK_set.apks --device-spec=/path/to/device-spec.json

通过 Google Play Developer API 创建设备定位配置

开始使用 Google Play Developer API(如果尚未开始使用)

如需配置设备定位(定义设备组),需要使用 Android Publisher API 将配置上传到 Google Play。您可以点击上面的链接详细了解该 API。若要开始使用该 API,需要按照以下几个步骤操作

  1. 创建(如果需要)API 项目并将其关联到 Google Play 管理中心
  2. 设置 API 访问客户端

您可在此处找到 API 参考文档。稍后,如果您选择通过该 API 上传 build,需要使用 Edits 方法。此外,建议在使用该 API 之前先查看此页面

使用 Device Targeting Configuration API

您可以使用以下 API 调用来创建设备定位配置:

创建设备定位配置

HTTP 请求 POST https://androidpublisher.googleapis.com/androidpublisher/v3/applications/{packageName}/deviceTierConfigs
路径参数 不适用
请求正文 设备定位配置
响应正文 设备定位配置
设备定位配置对象
{
  device_groups: [
    {
      name: string,
      device_selectors: [
        {
          device_ram : {
            min_bytes: integer
            max_bytes: integer
          },
          included_device_ids: [
            {
              build_brand: string,
              build_device: string
            }
          ],
          excluded_device_ids: [
            {
              build_brand: string,
              build_device: string
            }
          ],
          required_system_features: [
            {
              name: string
            }
          ],
          forbidden_system_features: [
            {
              name: string
            }
          ]
        }
      ]
    }
  ]
}

字段:

  • device_tier_config_id(整数):与此设备定位配置对应的 ID
  • device_groups(对象):组定义

    • name(字符串):设备组的名称(您定义的字符串 ID)
    • device_selectors(对象):对属于该组的设备的设备要求。
    • device_ram(对象):设备 RAM 要求
      • min_bytes(整数):要求的最低 RAM(单位:字节)
      • max_bytes(整数):要求的最高 RAM(单位:字节)
    • included_device_ids(对象):此选择器中要包含的设备型号(每组最多 10000 个 device_ids)。设备需要在此列表中才能匹配该选择器。这是匹配整个选择器的必要但非充分条件(请参阅下文说明,了解如何在选择器中组合使用多项要求)。
      • build_brand(字符串):设备制造商
      • build_device(字符串):设备型号代码
    • excluded_device_ids(对象):此选择器中要排除的设备型号(每组最多 10000 个 device_ids)。此列表中的设备即使符合该选择器中的所有其他要求,也不会匹配该选择器。
      • build_brand(字符串):设备制造商
      • build_device(字符串):设备型号代码
    • required_system_features(对象):设备想要包含在此选择器中所需要具备的功能。(每组最多 100 项功能)。设备需要具备此列表中的所有系统功能才能匹配该选择器。这是匹配整个选择器的必要但非充分条件(请参阅下文说明,了解如何在选择器中组合使用多项要求)。

      系统功能参考

      • name(字符串):系统功能
    • forbidden_system_features(对象):设备想要包含在此选择器中就不能具备的功能(每组最多 100 项功能)。设备如果具备此列表中的任何系统功能,即使符合该选择器中的所有其他要求,也不匹配该选择器。

      系统功能参考

      • name(字符串):系统功能

您可以通过以下任一种方式,使用 Google Play 管理中心的设备目录查找设备制造商和型号代码的正确格式:

  • 使用设备目录检查各个设备,在下例中所示的位置找到制造商和型号代码(以 Google Pixel 4a 为例,制造商为“Google”,型号代码为“sunfish”)

    设备目录中的 Pixel 4a 页面

    设备目录中的 Pixel 4a 页面

  • 下载受支持的设备的 CSV 文件,build_brand 和 build_device 字段分别表示制造商和型号代码。

例如,下面的组匹配 RAM 超过 4GB 的所有设备但排除 Pixel 5 (google redfin),另外还包括 Pixel 3(Google Blueline,其 RAM 不到 4GB)。

device_groups: [
  {
    name: "my_group_1",
    device_selectors: [
      {
        device_ram: {
          min_bytes: 4294967296
        },
        excluded_device_ids: [
          {
            build_brand: "google",
            build_device: "redfin"
          }
        ]
      },
      {
        included_device_ids: [
          {
            build_brand: "google",
            build_device: "blueline"
          }
        ]
      }
    ]
  }
]

您可以将其理解为:

[ (RAM > 4GB) AND NOT (google redfin) ] OR [ (google blueline) ]

您可以先按照以下说明验证设备定位配置,然后再将其上传到 Google Play。

按 ID 获取设备定位配置

您可以使用以下调用按 ID 检索特定的设备定位配置:

HTTP 请求 GEThttps://androidpublisher.googleapis.com/androidpublisher/v3/applications/{packageName}/deviceTierConfigs/{deviceTierConfigId}
路径参数 不适用
请求正文 不适用
响应正文 设备定位配置

获取设备定位配置列表

您可以通过以下调用获取最近 10 个设备定位配置(或者,最好使用 page_token 查询参数指定一组 10 个设备定位配置):

HTTP 请求 GEThttps://androidpublisher.googleapis.com/androidpublisher/v3/applications/{packageName}/deviceTierConfigs
路径参数 不适用
查询参数 page_token(可选)- 用于指定具体的一组 10 个 DTC。如果您创建的 DTC 超过 10 个,而您希望查看在最近 10 个 DTC 之前创建的 DTC,此参数就会非常有用。
请求正文 不适用
响应正文 设备定位配置列表

page_token

验证设备定位配置

bundletool 包含两个命令,可帮助您验证设备定位配置在上传到 Play 之前是否按预期运行。

使用 bundletool print-device-targeting-config,您可以验证 JSON 文件的语法是否正确,并以更易于用户看懂的格式直观地呈现设备组。

bundletool print-device-targeting-config --config=mydtc.json

借助 bundletool evaluate-device-targeting-config,您可以评估哪些组与特定设备匹配。将目标设备连接到工作站并使用 --connected-device 标志;或者,手动编译包含设备属性的 JSON 文件并通过 --device-properties 标志提供该文件。

bundletool evaluate-device-targeting-config --config=mydtc.json --connected-device
bundletool evaluate-device-targeting-config --config=mydtc.json --device-properties=deviceproperties.json

设备属性文件应该是遵循 DeviceProperties protobuf 结构的 JSON 文件。例如:

{
  "ram": 2057072640,
  "device_id": {
    "build_brand":"google",
    "build_device":"redfin"
  },
  "system_features": [
    {
      "name":"android.hardware.bluetooth"
    },
    {
      "name":"android.hardware.camera"
    }
  ]
}

将 Android App Bundle 文件上传到 Google Play

通过 API

您可以使用 Google Play Developer API 将 Android App Bundle 文件上传到 Google Play,并将特定的设备定位配置关联到您的 build。

此处简要介绍了 Edits 方法,还有关于如何发布到 Google Play 管理中心内不同轨道的深入示例(对于后一个链接,您需要使用适合 AAB 文件的 API,而非该页面中列出的适合 APK 的 API)。如需为 build 指定设备定位配置,需要在调用 edits.bundle.upload 方法时将配置 ID 添加到 deviceTierConfigId 查询参数中,如下所示:

https://androidpublisher.googleapis.com/upload/androidpublisher/v3/applications/{packageName}/edits/{editId}/bundles?deviceTierConfigId="{deviceTierConfigId}"

通过 Google Play 管理中心

您可以按照此处的说明上传 Android App Bundle 文件。系统会将最新 DTC 配置应用于您的 App Bundle 文件。

辅助示例

快速入门:使用 curl

以下示例(使用命令行工具 curl)首先创建新的设备定位配置,接着使用 Edits API 创建新修改,上传新 AAB 文件(将其与特定设备定位配置关联),设置轨道/发布配置,然后提交修改(从而公开更改内容)。确保您有以下内容的位置:

  • 与您的 API 客户端相对应的密钥
  • 您的应用的软件包名称

首先,创建一个设备定位配置,并记下调用成功后收到的 deviceTierConfigId。

curl -H "$(oauth2l header --json $HOME/{apiKey} androidpublisher)" -XPOST -H "Content-Type: application/json" -d "{ device_groups: [ { name: "my_group_1", device_selectors: [ { device_ram: { min_bytes: 4294967296 }, excluded_device_ids: [ { build_brand: "google", build_device: "redfin" } ] }, { included_device_ids: [ { build_brand: "google", build_device: "blueline" } ] } ] } ] }" https://androidpublisher.googleapis.com/androidpublisher/v3/applications/{packageName}/deviceTierConfigs

开始修改 - 您将获得该修改的 ID 和过期时间。请保存该 ID,用于接下来的调用。

curl -H "$(oauth2l header --json $HOME/{apiKey} androidpublisher)" -XPOST https://androidpublisher.googleapis.com/androidpublisher/v3/applications/{packageName}/edits

上传 AAB 文件,将设备定位配置 (deviceTierConfigId) 指定为查询参数 - 如果调用成功,您将看到 build 的版本号、sha1 值和 sha256 值。请保存该版本号,用于下一个调用。

curl -H "$(oauth2l header --json $HOME/{apiKey} androidpublisher)" --data-binary @$HOME/{aabFile} -H "Content-Type: application/octet-stream" -XPOST https://androidpublisher.googleapis.com/upload/androidpublisher/v3/applications/{packageName}/edits/{editID}/bundles?deviceTierConfigId="{deviceTierConfigId}

将 AAB 文件分配到所需轨道(出于测试目的,建议使用内部测试轨道,但您可以在此处详细了解不同的轨道),我们在这里只进行了简单发布,未提供版本说明,但您可以阅读此页面,详细了解何为分阶段发布、草稿版本和版本说明。如果这是您第一次使用 Publisher API,建议您将此创建为草稿版本,并在 Google Play 管理中心完成发布,以确保各项配置正确无误

curl -H "$(oauth2l header --json $HOME/{apiKey} androidpublisher)" -XPUT -H "Content-Type: application/json" -d "{ releases: [{status: '{status}', versionCodes: ['{versionCode}'] }]}" https://androidpublisher.googleapis.com/androidpublisher/v3/applications/{packageName}/edits/{editID}/tracks/{track}

提交更改(请谨慎操作,因为此操作会将所有更改发布到 Play 中的所需轨道

curl -H "$(oauth2l header --json $HOME/{apiKey} androidpublisher)" -XPOST https://androidpublisher.googleapis.com/androidpublisher/v3/applications/{packageName}/edits/{editID}:commit