Play for On-device AI (Beta 版)

簡介

Play for 裝置端 AI 結合 Android App Bundle 和 Google Play 傳遞機制的優點,可自訂機器學習模型發布方式,讓您在不增加裝置生態系統複雜度的情況下,提升模型效能,且不需額外付費。您可以將包含程式碼、資產和機器學習模型的單一構件發布至 Play,並從多種傳送模式和指定目標選項中進行選擇。

優點

  • 將單一發布構件上傳至 Google Play,並將託管、推送、更新和指定目標等作業委託給 Play,無須額外付費。
  • 在安裝時、快速追蹤或隨選提供機器學習模型。
    • 安裝時提供可確保在開啟應用程式時,大型模型已存在。模型會以 APK 形式安裝。
    • 應用程式安裝完成後,系統會在背景自動執行快速追蹤傳送。使用者可能會在模型完全下載前開啟應用程式。模型會下載到應用程式的內部儲存空間。
    • 隨選推送功能可讓您在執行階段要求模型,如果模型僅適用於特定使用者流程,這項功能就非常實用。模型會下載到應用程式的內部儲存空間。
  • 根據裝置型號、系統屬性或 RAM,提供指定特定裝置的機器學習模型變化版本。
  • Play 的自動修補功能只會下載檔案差異,因此應用程式更新檔案較小,且經過最佳化。

注意事項

  • 使用 Play for 裝置端 AI,即表示您同意《Google Play 開發人員發行協議》和《Play Core 軟體開發套件服務條款》中的條款。
  • Play for 裝置端 AI 下載的模型只能由您的應用程式使用。模型不應提供給其他應用程式。
  • 個別 AI 套件的壓縮下載大小上限為 1.5 GB。從 App Bundle 產生的任何應用程式版本,累計大小上限為 4 GB。
  • 如果應用程式大小超過 1 GB,則必須將 SDK 最低級別設為 21 以上。

如何使用 Play 裝置端 AI

Play for 裝置端 AI 使用 AI 套件。您可以在應用程式套件中,將自訂模型封裝成可發布的 AI 套件。您可以選擇在安裝時、快速追蹤或隨選提供 AI 套件。

將 AI 套件與應用程式套件一併封裝,即可使用 Play 現有的所有測試和發布工具 (例如測試群組和階段推出),管理自訂模型的應用程式發布作業。

AI 套件會與應用程式二進位檔一併更新。如果新版應用程式未變更 AI 套件,Play 的自動修補程序會確保使用者不必重新下載。更新應用程式時,Google Play 只會下載變更的部分。

AI 套件僅包含模型。不允許使用 Java/Kotlin 和原生資料庫。如需提供程式庫或程式碼來執行機器學習模型,請將其移至基本模組或功能模組。您可以設定功能模組,使其具有與 AI 套件相同的下載和指定設定。

搭配使用 LiteRT、MediaPipe 和 AI 資產包

LiteRT 和 MediaPipe 可與 AI 套件搭配使用。將模型封裝至 AI 套件,然後按照安裝時套件或快速追蹤和隨選套件的操作說明存取模型。

延伸閱讀:

開始使用 AI 套件

Play for On-device AI 的使用方式大致如下:

  1. 將模型封裝成 AI 套件,並加入 Android App Bundle,然後指定 AI 套件的推送方式。
  2. [選用] 如要將不同模型提供給不同裝置,可以為 AI 套件設定指定裝置。舉例來說,您可以將 AI 套件 A 傳送至特定裝置型號,將 AI 套件 B 傳送至 RAM 至少 6 GB 的裝置,而所有其他裝置則不接收任何模型。
  3. [選用] 如果您使用隨選或快速追蹤提供功能,請將 Play AI Delivery 程式庫整合至應用程式,以便視需要下載 AI 套件。
  4. 測試應用程式套件,並發布至 Google Play。

查看 Android Gradle 外掛程式版本

如要使用 AI 套件,請確認 Android Gradle 外掛程式 (AGP) 版本至少為 8.8。這個版本隨附於 Android Studio Ladybug 2。

將模型擷取至 AI 資產包

執行下列步驟時,不必使用 Android Studio。

  1. 在專案的頂層目錄中,為 AI 套件建立目錄。系統會使用這個目錄名稱做為 AI 封包名稱。AI 套件名稱開頭須為英文字母,而且只能使用英文字母、數字和底線。
  2. 在 AI 套件目錄中建立 build.gradle 檔案,並新增下列程式碼。請務必指定 AI 資產包的名稱,且只使用一種提交類型:

    // In the AI pack's build.gradle file:
    plugins {
      id 'com.android.ai-pack'
    }
    
    aiPack {
        packName = "ai-pack-name" // Directory name for the AI pack
        dynamicDelivery {
            deliveryType = "[ install-time | fast-follow | on-demand ]"
        }
    }
    
  3. 在專案的應用程式 build.gradle 檔案中,新增專案中每個 AI 封包的名稱,如下所示:

    // In the app build.gradle file:
    android {
        ...
        assetPacks = [":ai-pack-name", ":ai-pack2-name"]
    }
    
  4. 在專案的 settings.gradle 檔案中,納入專案中的所有 AI 檔案包,如下所示:

    // In the settings.gradle file:
    include ':app'
    include ':ai-pack-name'
    include ':ai-pack2-name'
    
  5. 在 AI 套件中建立 src/main/assets/ 目錄。

  6. 將模型放在 src/main/assets 目錄中。您也可以在其中建立子目錄。目前應用程式的目錄結構應如下所示:

    • build.gradle
    • settings.gradle
    • app/
    • ai-pack-name/build.gradle
    • ai-pack-name/src/main/assets/your-model-directories
  7. 新增程式碼,載入並執行模型。具體做法取決於 AI 套件的推送模式。請參閱下方安裝時和快速追蹤/隨選的操作說明。

  8. [選用] 設定指定裝置,為不同裝置提供不同模型。

  9. 使用 Gradle 建構 Android App Bundle。在產生的應用程式套件中,根層級目錄現在包含下列項目:

    • ai-pack-name/manifest/AndroidManifest.xml:設定 AI 模型的 ID 和提供模式
    • ai-pack-name/assets/your-model-directories:此目錄包含透過 AI 套件提供的所有資產

    Gradle 會為每個 AI 套件產生資訊清單,並為您輸出 assets/ 目錄。

設定安裝時提供功能

設定為安裝時提供的 AI 套件,可在應用程式啟動時立即使用。使用 Java AssetManager API 存取在此模式下提供的 AI 檔案包:

import android.content.res.AssetManager;
...
Context context = createPackageContext("com.example.app", 0);
AssetManager assetManager = context.getAssets();
InputStream is = assetManager.open("model-name");

設定快速追蹤及隨選提供功能

如要下載快速追蹤或隨選提供的 AI 套件,請使用 Play AI Delivery 程式庫。

宣告 Play AI Delivery 程式庫的依附元件

在應用程式的 build.gradle 檔案中,宣告 Play AI Delivery 程式庫的依附元件:

dependencies {
  ...
  implementation "com.google.android.play:ai-delivery:0.1.1-alpha01"
}

檢查狀態

每個 AI 套件會儲存在應用程式內部儲存空間的獨立資料夾中。使用 getPackLocation() 方法判斷 AI 封包的根資料夾。這個方法會回傳下列值:

傳回值 狀態
有效的 AiPackLocation 物件 隨時可在 assetsPath() 立即存取 AI 套件根資料夾
null 無法使用未知的 AI 資產包或 AI 資產包

取得 AI 套件的下載資訊

使用
getPackStates() 方法來判定下載內容的大小,以及是否正在下載資產包。

Task<AiPackStates> getPackStates(List<String> packNames)

getPackStates() 是會傳回 Task<AiPackStates> 的非同步方法。AiPackStates 物件的 packStates() 方法會回傳 Map<String, AiPackState>。此對應包含每個要求 AI 模型的狀態,並以名稱做為索引鍵:

Map<String, AiPackState> AiPackStates#packStates()

最終要求如下所示:

final String aiPackName = "myAiPackName";

aiPackManager
    .getPackStates(Collections.singletonList(aiPackName))
    .addOnCompleteListener(new OnCompleteListener<AiPackStates>() {
        @Override
        public void onComplete(Task<AiPackStates> task) {
            AiPackStates aiPackStates;
            try {
                aiPackStates = task.getResult();
                AiPackState aiPackState =
                    aiPackStates.packStates().get(aiPackName);
            } catch (RuntimeExecutionException e) {
                Log.d("MainActivity", e.getMessage());
                return;
            });

下列 AiPackState 方法提供 AI 檔案包的大小、目前為止的下載數量 (如有要求),以及已轉移到應用程式的數量:

如要取得 AI 封包的狀態,請使用 status() 方法傳回整數形式的狀態,而此整數會對應至 AiPackStatus 類別中的特定常數欄位。尚未安裝的 AI 套件處於 AiPackStatus.NOT_INSTALLED 狀態。

如果要求失敗,請使用 errorCode() 方法,其傳回值會對應至 AiPackErrorCode 類別中的特定常數欄位。

安裝

首次使用 fetch() 方法下載 AI 封包,或要求更新 AI 封包:

Task<AiPackStates> fetch(List<String> packNames)

這個方法會回傳 AiPackStates 物件,其中包含資產包清單,以及其初始下載狀態和大小。如果正在下載透過 fetch() 要求的 AI 檔案包,系統會回傳下載狀態,且不會開始其他下載作業。

監控下載狀態

您應實作 AiPackStateUpdateListener,追蹤 AI 模型的安裝進度。系統會按照每個資產包細分狀態更新內容,支援個別 AI 資產包的狀態追蹤功能。您可以開始使用可用的 AI 套件,不必等到要求的所有其他下載作業完成。

void registerListener(AiPackStateUpdateListener listener)
void unregisterListener(AiPackStateUpdateListener listener)
大型下載內容

如果下載內容超過 200 MB,且使用者未透過 Wi-Fi 網路下載,則系統會等到使用者明確同意使用行動數據連線執行下載時,才會啟動下載作業。同樣,如果下載內容較大,且使用者未連接 Wi-Fi 網路,則系統會暫停下載並明確取得同意,才能透過行動數據連線進行下載。已暫停的資產包處於 WAITING_FOR_WIFI 狀態。如要觸發使用者介面流程來提示使用者同意聲明,請使用 showConfirmationDialog() 方法。

請注意,如果應用程式未呼叫這個方法,下載作業就會暫停,且只在使用者再次連上 Wi-Fi 連線時,才會自動繼續下載。

需要使用者確認

如果資產包處於 REQUIRES_USER_CONFIRMATION 狀態,則必須等到使用者接受 showConfirmationDialog() 顯示的對話方塊後,才會繼續下載。如果 Play 無法辨識應用程式 (例如側載的應用程式),就會出現這個狀態。請注意,在這種情況下呼叫 showConfirmationDialog() 會導致應用程式更新。更新後,您需要再次申請 AI 套件。

以下是事件監聽器的實作範例:

AiPackStateUpdateListener aiPackStateUpdateListener = new AiPackStateUpdateListener() {
    private final ActivityResultLauncher<IntentSenderRequest> activityResultLauncher =
      registerForActivityResult(
          new ActivityResultContracts.StartIntentSenderForResult(),
          new ActivityResultCallback<ActivityResult>() {
            @Override
            public void onActivityResult(ActivityResult result) {
              if (result.getResultCode() == RESULT_OK) {
                Log.d(TAG, "Confirmation dialog has been accepted.");
              } else if (result.getResultCode() == RESULT_CANCELED) {
                Log.d(TAG, "Confirmation dialog has been denied by the user.");
              }
            }
          });

    @Override
    public void onStateUpdate(AiPackState aiPackState) {
      switch (aiPackState.status()) {
        case AiPackStatus.PENDING:
          Log.i(TAG, "Pending");
          break;

        case AiPackStatus.DOWNLOADING:
          long downloaded = aiPackState.bytesDownloaded();
          long totalSize = aiPackState.totalBytesToDownload();
          double percent = 100.0 * downloaded / totalSize;

          Log.i(TAG, "PercentDone=" + String.format("%.2f", percent));
          break;

        case AiPackStatus.TRANSFERRING:
          // 100% downloaded and assets are being transferred.
          // Notify user to wait until transfer is complete.
          break;

        case AiPackStatus.COMPLETED:
          // AI pack is ready to use. Run the model.
          break;

        case AiPackStatus.FAILED:
          // Request failed. Notify user.
          Log.e(TAG, aiPackState.errorCode());
          break;

        case AiPackStatus.CANCELED:
          // Request canceled. Notify user.
          break;

        case AiPackStatus.WAITING_FOR_WIFI:
        case AiPackStatus.REQUIRES_USER_CONFIRMATION:
          if (!confirmationDialogShown) {
            aiPackManager.showConfirmationDialog(activityResultLauncher);
            confirmationDialogShown = true;
          }
          break;

        case AiPackStatus.NOT_INSTALLED:
          // AI pack is not downloaded yet.
          break;
        case AiPackStatus.UNKNOWN:
          Log.wtf(TAG, "AI pack status unknown")
          break;
      }
    }
}

您也可以使用 getPackStates() 方法取得目前下載作業的狀態。AiPackStates 包含下載進度、下載狀態和任何失敗錯誤代碼。

存取 AI 資產包

下載要求達到 COMPLETED 狀態後,您可以使用檔案系統呼叫來存取 AI 檔案包。使用 getPackLocation() 方法取得 AI 封包的根資料夾。

AI 套件會儲存在 AI 套件根目錄的 assets 目錄中。您可以使用便利的方法 assetsPath(),取得 assets 目錄的路徑。請使用以下方法取得特定資產的路徑:

private String getAbsoluteAiAssetPath(String aiPack, String relativeAiAssetPath) {
    AiPackLocation aiPackPath = aiPackManager.getPackLocation(aiPack);

    if (aiPackPath == null) {
        // AI pack is not ready
        return null;
    }

    String aiAssetsFolderPath = aiPackPath.assetsPath();
    // equivalent to: FilenameUtils.concat(aiPackPath.path(), "assets");
    String aiAssetPath = FilenameUtils.concat(aiAssetsFolderPath, relativeAiAssetPath);
    return aiAssetPath;
}

設定指定裝置

您可以按照指定裝置操作說明,指定應接收 AI 套件的裝置或裝置群組。

其他 Play AI Delivery API 方法

以下列出一些其他您可能想在應用程式中使用的 API 方法。

取消要求

使用 cancel() 取消進行中的 AI 封包要求。請注意,我們會盡可能履行這項要求。

移除 AI 套件

使用 removePack() 安排移除 AI 封包。

取得多個 AI 套件的位置

使用 getPackLocations() 查詢多個 AI 檔案包的狀態,進而回傳 AI 檔案包及其位置的對應圖。getPackLocations() 傳回的對應圖包含每個已下載且處於最新狀態的資產包的輸入項。

指定裝置

指定裝置功能可讓您更精細地控管要將應用程式套件的哪些部分提供給特定裝置。舉例來說,您可以確保大型模型只提供給 RAM 較高的裝置,或將不同版本的模型提供給不同裝置。

您可以指定目標裝置屬性,例如:

必要步驟總覽

如要啟用指定裝置,請按照下列步驟操作:

  1. 在 XML 檔案中定義裝置群組。
  2. 指定套件的哪些部分應傳送至哪些裝置群組。
  3. [選用] 在本機測試設定。
  4. 將套件 (包含 XML 檔案) 上傳至 Google Play。

查看 Android Gradle 外掛程式版本

如要使用指定裝置功能,請確認 Android Gradle 外掛程式 (AGP) 版本至少為 8.10.0。這項工具隨附於 Android Studio (Meerkat 2 以上版本)。下載最新穩定版 Android Studio。

在 Android Gradle 外掛程式中啟用這項功能

您必須在 gradle.properties 檔案中明確啟用指定裝置功能:

android.experimental.enableDeviceTargetingConfigApi=true

建立指定裝置設定 XML 檔案

指定裝置設定檔是 XML 檔案,可用於定義自訂裝置群組。舉例來說,您可以定義名為 qti_v79 的裝置群組,其中包含所有搭載 Qualcomm SM8750 晶片系統的裝置:

<config:device-targeting-config
    xmlns:config="http://schemas.android.com/apk/config">

    <config:device-group name="qti_v79">
        <config:device-selector>
            <config:system-on-chip manufacturer="QTI" model="SM8750"/>
        </config:device-selector>
    </config:device-group>

</config:device-targeting-config>

裝置群組最多可由 5 個裝置選取條件組成。如果裝置符合任何裝置選取條件,就會納入裝置群組。

裝置選取條件可以有一或多個裝置屬性。如果裝置符合選取條件的所有裝置屬性,就會獲選。

如果裝置與多個群組相符,就會取得 XML 檔案中第一個定義的群組內容。您在 XML 檔案中定義群組的順序就是優先順序。

如果裝置不符合任何群組,則會收到預設的「其他」群組。這個群組會自動產生,不應明確定義。

可用的裝置屬性

  • device_ram:裝置 RAM 需求
    • min_bytes (含下限):RAM 需求下限 (以位元組為單位)
    • max_bytes (不含上限):RAM 需求上限 (以位元組為單位)
  • included_device_ids:要納入這個選取條件的裝置型號(每個群組最多 10,000 個 device_ids)。如果裝置與清單中的任何 device_id 相符,即符合這項屬性。
    • build_brand:裝置製造商
    • build_device:裝置型號代碼
  • excluded_device_ids:這個選取條件所排除的裝置型號(每個群組最多 10,000 個 device_ids)。如果裝置不符合清單中的任何 device_id,則符合這項屬性。
    • build_brand:裝置製造商
    • build_device:裝置型號代碼
  • required_system_features:裝置必須具有的功能(每個群組最多 100 項功能)。如果裝置沒有這些功能,選取條件就不會納入該裝置。裝置必須具備這份清單中的所有系統功能,才符合這項屬性。

    系統功能參考資料

    • name:系統功能
  • forbidden_system_features:裝置不得具有指定的功能(每個群組最多 100 項功能),才能納入此選取條件中。如果裝置具有這個清單中的任何系統功能,就不符合這項屬性。

    系統功能參考資料

    • name:系統功能
  • system-on-chip:這個選取條件要納入的晶片系統。裝置必須具備這份清單中的任何晶片,才能符合這項屬性。

以下範例顯示所有可能的裝置屬性:

<config:device-targeting-config
    xmlns:config="http://schemas.android.com/apk/config">

    <config:device-group name="myCustomGroup1">
      <config:device-selector ram-min-bytes="8000000000">
        <config:included-device-id brand="google" device="redfin"/>
        <config:included-device-id brand="google" device="sailfish"/>
        <config:included-device-id brand="good-brand"/>
        <config:excluded-device-id brand="google" device="caiman"/>
        <config:system-on-chip manufacturer="Sinclair" model="ZX80"/>
        <config:system-on-chip manufacturer="Commodore" model="C64"/>
      </config:device-selector>
      <config:device-selector ram-min-bytes="16000000000"/>
    </config:device-group>

    <config:device-group name="myCustomGroup2">
      <config:device-selector ram-min-bytes="4000000000" ram-max-bytes="8000000000">
        <config:required-system-feature name="android.hardware.bluetooth"/>
        <config:required-system-feature name="android.hardware.location"/>
        <config:forbidden-system-feature name="android.hardware.camera"/>
        <config:forbidden-system-feature name="mindcontrol.laser"/>
      </config:device-selector>
    </config:device-group>

</config:device-targeting-config>

官方裝置製造商和裝置型號代碼

您可以使用 Google Play 管理中心的裝置目錄,以下列任一方式找出裝置製造商和型號代碼的正確格式:

  • 透過「裝置目錄」查看個別裝置,找出裝置的製造商和型號代碼,這些資訊的位置如以下範例所示 (Google Pixel 4a 的製造商為「Google」,型號代碼為「sunfish」)。

    裝置目錄中的 Pixel 4a 頁面

    裝置目錄中的 Pixel 4a 頁面

  • 下載支援裝置的 CSV 檔案,並將「製造商」和「型號代碼」資訊分別用於「build_brand」和「build_device」欄位。

在應用程式套件中加入裝置指定設定檔

在主要模組的 build.gradle 檔案中加入以下內容:

android {
  ...
  bundle {
    deviceTargetingConfig = file('device_targeting_config.xml')
    deviceGroup {
      enableSplit = true   // split bundle by #group
      defaultGroup = "other"  // group used for standalone APKs
    }
  }
  ...
}

device_targeting_config.xml 是設定檔相對於主模組的路徑。這可確保設定檔與應用程式套件一併封裝。

deviceGroup 子句可確保從套件產生的 APK 會依裝置群組分割。

為 AI 套件指定裝置

您可以只將大型模型提供給可執行的裝置,讓裝置上的大小保持最佳狀態。

如要依裝置群組細分 AI 套件,請使用上一步建立的「現有」AI 套件目錄,並在適當的資料夾 (如下所述) 後方加上 #group_myCustomGroup1、#group_myCustomGroup2 等後置字串。在應用程式中使用 AI 套件時,您不需要依後置字串來處理資料夾 (換句話說,後置字串會在建構過程中自動移除)。

完成上一個步驟後,結果可能如下所示:

...
.../ai-pack-name/src/main/assets/image-classifier#group_myCustomGroup1/
.../ai-pack-name/src/main/assets/image-classifier#group_myCustomGroup2/
...

在這個範例中,您會參照 ai-pack-name/assets/image-classifier/,不含任何後置字串。

myCustomGroup1 中的裝置會收到 image-classifier#group_myCustomGroup1/ 下的所有資產,而 myCustomGroup2 中的裝置會收到 image-classifier#group_myCustomGroup2/ 下的所有資產。

不屬於 myCustomGroup1 或 myCustomGroup2 的裝置會收到空白的 ai-pack-name 套件。

這是因為不符合任何裝置群組的裝置,會收到 AI 資產包的預設變化版本。這包括任何不在含有 #group_suffix 的目錄中的內容。

下載 AI 套件後,您可以使用 AssetManager (適用於安裝時套件) 或 AiPackManager (適用於快速追蹤和隨選套件),檢查模型是否存在。範例應用程式中會顯示所有傳送模式的範例。

為功能模組指定裝置

您也可以為功能模組指定裝置。您不必依裝置群組細分功能模組,而是指定是否要根據裝置群組成員資格提供整個模組。

如要將功能模組提供給屬於 myCustomGroup1 或 myCustomGroup2 的裝置,請修改其 AndroidManifest.xml:

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

在本機測試

為新套件建立版本前,您可以使用內部應用程式分享功能或 Bundletool 在本機測試。

內部應用程式分享

透過內部應用程式分享功能,您可以使用應用程式套件快速產生網址,並在本機裝置上輕觸該網址,安裝 Google Play 為該裝置安裝的內容,就像該版本的應用程式已在測試或正式版群組中上線一樣。

請參閱內部應用程式分享操作說明。

Bundletool

或者,您也可以使用 bundletool (1.18.0 以上版本) 產生 APK,並側載到裝置上。請按照下列步驟,使用 bundletool 在本機測試應用程式:

  1. 使用 Android Studio 或 bundletool 建構應用程式套件。

  2. 使用 --local-testing 旗標產生 APK:

    java -jar bundletool-all.jar build-apks --bundle=path/to/your/bundle.aab \
      --output=output.apks --local-testing
    
  3. 連結裝置並執行 bundletool,側載 APK:

    # Example without Device Targeting Configuration
    java -jar bundletool.jar install-apks --apks=output.apks
    
    # Example with Device Targeting Configuration (you must specify which groups the connected device belongs to)
    java -jar bundletool.jar install-apks --apks=output.apks --device-groups=myCustomGroup1,myCustomGroup2
    

使用 bundletool 進行本機測試的限制

以下是使用 bundletool 進行本機測試的限制:

  • fast-follow 套件的行為與 on-demand 套件相同。也就是說,在側載應用程式的過程中,並不會自動擷取這些軟體包。應用程式啟動時,開發人員需要手動要求這些軟體包;此操作不需要在應用程式中變更任何程式碼。
  • 軟體包從外部儲存空間 (而非 Google Play) 擷取,因此,在網路發生錯誤的情況下,就無法測試程式碼的行為。
  • 本機測試不涵蓋 Wi-Fi 連線等候狀況。
  • 不支援更新內容。安裝新版之前,請先手動解除安裝舊版。

確認已安裝正確的 APK

請使用以下方法,確保只在裝置上安裝正確的 APK

adb shell pm path {packageName}

您應該會看到類似下方的內容:

package:{...}/base.apk
package:{...}/split_config.en.apk
package:{...}/split_config.xxhdpi.apk
package:{...}/split_main_ai-pack-name.apk
package:{...}/split_main_ai-pack-name.config.group_myCustomGroup1.apk

請注意,這份清單只會顯示 APK,這些 APK 是由功能模組和安裝時 AI 套件組成。隨選和快速追蹤 AI 套件不會以 APK 形式安裝。

在 Google Play 測試及發布

建議您在 Google Play 上使用內部測試群組,對應用程式進行端對端測試。

完成後,您就可以透過階段推出,逐步將應用程式更新發布至正式版。

使用 Play 裝置端 AI 的範例應用程式

下載範例應用程式。

示範如何使用各個傳送模式,以及指定裝置設定。請參閱本機測試一節,瞭解如何開始。

進一步瞭解 Android App Bundle,並參閱 AI Delivery SDK 參考資料。