Play for On-device AI (Beta 版)

簡介

Play for On-device AI 結合了 Android App Bundle 和 Google Play 放送的優點,可放送自訂 ML 模型,讓您以較少的裝置生態系統複雜度提升模型效能,且無須額外付費。您可透過這項功能將包含程式碼、資產和機器學習模型的單一構件發布至 Play,並從多種提交模式和目標對象選項中選擇。

優點

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

注意事項

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

如何使用 Play for On-device AI

Play for On-device AI 會使用 AI 套件。您可以在應用程式套件的 AI 套件中,封裝準備好發布的自訂模型。您可以選擇在安裝時提供、以快速追蹤的方式提供,或是隨選提供 AI 包。

將 AI 套件與應用程式套件一起封裝後,您就能使用 Play 現有的所有測試和發布工具,例如測試群組和階段性發布,藉此管理應用程式的發布作業,並使用自訂模型。

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

AI 套件只包含模型,不允許使用 Java/Kotlin 和原生程式庫。 如要運送程式庫或程式碼來執行 ML 模型,請將其移至基本模組或功能模組。您可以設定功能模組,使其下載和目標設定與 AI 套件相同。

搭配 AI 資產包使用 LiteRT 和 MediaPipe

您可以搭配 AI 套件使用 LiteRT 和 MediaPipe。將模型封裝在 AI 包中,然後按照安裝時提供包以快速追蹤的方式提供及隨選提供包的說明存取模型。

延伸閱讀:

開始使用 AI 套件

如要開始使用 Play for On-device AI,大致上需要完成下列步驟:

  1. 將模型封裝到 Android App Bundle 的 AI 套件中,並指定 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 類別中的特定常數欄位。

安裝

若是第一次下載 AI 資產包,或若要呼叫以完成 AI 資產包更新作業,請使用 fetch() 方法:

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:要納入這個選取條件的裝置型號(每個群組最多 10000 個 device_ids)。如果裝置符合清單中的任何 device_id,就會滿足這項屬性。
    • build_brand:裝置製造商
    • build_device:裝置型號代碼
  • excluded_device_ids:要在這個選取條件中排除的裝置型號(每個群組最多 10000 個 device_ids)。如果裝置與清單中的任何 device_id 都不相符,就會滿足這項屬性。
    • build_brand:裝置製造商
    • build_device:裝置型號代碼
  • required_system_features:裝置必須具有的功能(每個群組最多 100 項功能),才能納入此選取條件中。裝置必須具有這個清單中的所有系統功能,才能符合這項屬性。

    系統功能參考資料

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

    系統功能參考資料

    • name:系統功能
  • 晶片系統:要納入這個選取器的晶片系統。裝置必須具備這個清單中的任一晶片,才能符合這項屬性。

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

<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/ 下的所有資產。

如果裝置不屬於 myCustomGroup1myCustomGroup2,則會收到空的 ai-pack-name 包裝盒。

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

下載 AI 包後,您可以針對安裝時提供的包使用 AssetManager,或針對快速追蹤和隨選包使用 AiPackManager,檢查模型是否存在。範例應用程式會顯示所有傳送模式的相關範例。

為功能模組指定裝置

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

如要將功能模組提供給屬於 myCustomGroup1myCustomGroup2 的裝置,請修改其 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

請注意,您只會在清單中看到由功能模組和安裝時 AI 套件製作的 APK。隨選和快速追蹤 AI 套件不會以 APK 形式安裝。

在 Google Play 上測試及發布

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

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

使用 Play for On-device AI 的範例應用程式

下載範例應用程式

說明如何使用各項放送模式,以及裝置指定目標設定。如要開始使用,請參閱「本機測試」一節。

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