Play לטכנולוגיית AI מובנית במכשיר (בטא)

מבוא

‫Play for On-device AI מאפשר לכם ליהנות מהיתרונות של קובצי Android App Bundle ושל ההפצה ב-Google Play, ולהפיץ מודלים מותאמים אישית של למידת מכונה. כך אתם יכולים לשפר את הביצועים של המודלים בלי עלות נוספת, ובלי להתמודד עם המורכבות של סביבת המכשירים. היא מאפשרת לכם לפרסם ב-Play פריט מידע שנוצר בתהליך הפיתוח (artifact) שמכיל את הקוד, הנכסים והמודלים של למידת המכונה, ולבחור מתוך כמה מצבי הצגה ואפשרויות טירגוט.

יתרונות

  • מעלים פריט פרסום אחד ל-Google Play ומאצילים ל-Play את הסמכות לאירוח, להפצה, לעדכונים ולטירגוט ללא עלות נוספת.
  • אתם יכולים להטמיע את המודלים של ML בזמן ההתקנה, ב-Fast-Follow או על פי דרישה.
    • העברה בזמן ההתקנה יכולה להבטיח שמודל גדול מאוד יהיה זמין כשהאפליקציה נפתחת. המודל יותקן כ-APK.
    • מסירת Fast-Follow מתרחשת באופן אוטומטי ברקע אחרי שהאפליקציה מותקנת. יכול להיות שהמשתמשים יפתחו את האפליקציה לפני שהמודל ירד במלואו. המודל יורד לנפח האחסון הפנימי של האפליקציה.
    • הורדה על פי דרישה מאפשרת לבקש את המודל בזמן הריצה, וזה שימושי אם המודל נדרש רק למסלולי משתמש מסוימים. המודל יורד לאחסון הפנימי של האפליקציה.
  • להפיץ גרסאות של מודלים של ML שמטורגטים למכשירים ספציפיים על סמך דגם המכשיר, מאפייני המערכת או זיכרון ה-RAM.
  • כדאי לשמור על עדכוני אפליקציות קטנים ואופטימליים באמצעות תיקון אוטומטי של Play, כלומר צריך להוריד רק את ההבדלים בקבצים.

שיקולים

  • השימוש ב-Play for On-device AI מבטא את ההסכמה שלך לתנאים של הסכם ההפצה למפתחים של Google Play ושל התנאים וההגבלות של ערכת פיתוח התוכנה Play Core.
  • האפליקציות שלכם צריכות להשתמש רק במודלים שהורדו על ידי Play ל-AI במכשיר. אסור להציע מודלים לאפליקציות אחרות.
  • חבילות AI נפרדות יכולות להיות בגודל של עד 1.5GB, בהתאם לגודל ההורדה הדחוסה שלהן. הגודל המצטבר המקסימלי של כל גרסה של האפליקציה שנוצרה מ-App Bundle הוא 4GB.
  • באפליקציות בגודל של יותר מ-1GB, צריך להגדיר את רמת ה-SDK המינימלית ל-21 ומעלה.

איך משתמשים ב-Play לטכנולוגיית AI מובנית במכשיר

‫Play ל-AI במכשיר משתמש בחבילות AI. אתם אורזים מודלים בהתאמה אישית שמוכנים להפצה בחבילות AI ב-App Bundle. אתם יכולים לבחור אם חבילת ה-AI תועבר בזמן ההתקנה, ב-Fast-Follow או על פי דרישה.

כשאתם מוסיפים חבילות AI ל-App Bundle, אתם יכולים להשתמש בכל הכלים הקיימים של Play לבדיקה ולהפצה, כמו מסלולי בדיקה והשקות מדורגות, כדי לנהל את הפצת האפליקציה עם המודלים בהתאמה אישית.

חבילות ה-AI מתעדכנות יחד עם הקובץ הבינארי של האפליקציה. אם גרסת האפליקציה החדשה לא כוללת שינויים בחבילת ה-AI, תהליך התיקון האוטומטי של Play יבטיח שהמשתמש לא יצטרך להוריד אותה מחדש. כשהאפליקציה תתעדכן, Play יוריד רק את מה שהשתנה.

חבילות AI מכילות רק מודלים. אסור להשתמש בספריות Java/Kotlin ו-Native. אם אתם צריכים לשלוח ספריות או קוד כדי להריץ את מודל ה-ML, העבירו אותם למודול הבסיס או למודול של תכונות. אתם יכולים להגדיר את מודול התכונות כך שיהיו לו אותן הגדרות הורדה וטירגוט כמו לחבילת ה-AI.

שימוש ב-LiteRT וב-MediaPipe עם חבילות AI

אתם יכולים להשתמש ב-LiteRT וב-MediaPipe עם חבילות AI. אורזים את המודל בחבילת AI ואז ניגשים אליו לפי ההוראות לחבילות שמועברות בזמן ההתקנה או לחבילות שמועברות ב-Fast-Follow ועל פי דרישה.

קריאה נוספת:

איך מתחילים להשתמש בחבילות AI

כך מתחילים להשתמש ב-Play לטכנולוגיית AI מובנית במכשיר:

  1. אורזים את המודלים בחבילות AI בתוך קובץ ה-Android App Bundle ומציינים איך חבילות ה-AI צריכות להימסר.
  2. [אופציונלי] אם רוצים להפיץ מודלים שונים למכשירים שונים, אפשר להגדיר טירגוט לפי מכשיר לחבילות ה-AI. לדוגמה, אפשר להעביר את חבילת ה-AI מסוג א' לדגם מכשיר ספציפי, את חבילת ה-AI מסוג ב' למכשירים עם זיכרון RAM בנפח של 6GB לפחות, ולכל שאר המכשירים לא להעביר אף מודל.
  3. [אופציונלי] אם אתם משתמשים בהפצה על פי דרישה או בהפצה מסוג Fast-Follow, אתם צריכים לשלב באפליקציה את ספריית Play AI Delivery כדי להוריד את חבילות ה-AI לפי הצורך.
  4. בודקים את ה-App Bundle ומפרסמים אותו ב-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 נמסרות. בהמשך מופיעות הוראות לגבי install-time ו-fast-follow/על פי דרישה.

  8. [אופציונלי] מגדירים טירגוט לפי מכשיר כדי להפיץ מודלים שונים למכשירים שונים.

  9. יוצרים את קובץ ה-Android App Bundle באמצעות Gradle. ב-App Bundle שנוצר, ספריית הרמה הבסיסית כוללת עכשיו את הפריטים הבאים:

    • ‫ai-pack-name/manifest/AndroidManifest.xml: מגדיר את המזהה ואת מצב ההעברה של חבילת ה-AI
    • ‫ai-pack-name/assets/your-model-directories: הספרייה שמכילה את כל הנכסים שסופקו כחלק מחבילת ה-AI

    ‫Gradle יוצר את המניפסט לכל חבילת נכסי AI ומוציא את הספרייה assets/ בשבילכם.

הגדרת מסירה בזמן ההתקנה

חבילות AI שמוגדרות להורדה בזמן ההתקנה זמינות מיד כשהאפליקציה מופעלת. כדי לגשת לחבילות AI שמוצגות במצב הזה, משתמשים ב-Java AssetManager API:

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

הגדרת מסירה מסוג Fast-Follow ועל פי דרישה

כדי להוריד חבילות AI באמצעות העברה מסוג Fast-Follow או העברה על פי דרישה, צריך להשתמש בספריית Play AI Delivery.

הצהרה על תלות בספריית Play AI Delivery

בקובץ build.gradle של האפליקציה, מצהירים על תלות בספריית Play AI Delivery:

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

בדיקת הסטטוס

כל חבילת AI מאוחסנת בתיקייה נפרדת באחסון הפנימי של האפליקציה. משתמשים ב-method‏ getPackLocation() כדי לקבוע את תיקיית הבסיס של חבילת ה-AI. השיטה הזו מחזירה את הערכים הבאים:

הערך המוחזר סטטוס
אובייקט AiPackLocation תקין תיקיית הבסיס של חבילת ה-AI מוכנה לגישה מיידית בכתובת assetsPath()
null חבילת AI לא ידועה או שחבילות AI לא זמינות

איך מורידים חבילות AI

משתמשים ב-method‏
getPackStates() כדי לקבוע את גודל ההורדה ולבדוק אם החבילה כבר בתהליך הורדה.

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

‫getPackStates() היא שיטה אסינכרונית שמחזירה Task<AiPackStates>. ה-method‏ packStates() של אובייקט AiPackStates מחזירה 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, משתמשים ב-method‏ status(), שמחזירה את הסטטוס כמספר שלם שתואם לשדה קבוע במחלקה AiPackStatus. חבילת AI שעדיין לא הותקנה תופיע בסטטוס AiPackStatus.NOT_INSTALLED.

אם הבקשה נכשלת, משתמשים ב-method‏ errorCode(), שהערך המוחזר שלה תואם לשדה קבוע במחלקה AiPackErrorCode.

התקנה

משתמשים ב-method‏ fetch() כדי להוריד חבילת AI בפעם הראשונה או כדי להשלים את העדכון של חבילת AI:

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

השיטה הזו מחזירה אובייקט AiPackStates שמכיל רשימה של חבילות, מצבי ההורדה הראשוניים שלהן והגדלים שלהן. אם חבילת AI שהתבקשה דרך fetch() כבר נמצאת בתהליך הורדה, סטטוס ההורדה מוחזר ולא מתחילה הורדה נוספת.

מעקב אחרי מצבי ההורדה

כדי לעקוב אחרי התקדמות ההתקנה של חבילות ה-AI, צריך להטמיע AiPackStateUpdateListener. עדכוני הסטטוס מחולקים לפי חבילה כדי לתמוך במעקב אחרי הסטטוס של חבילות AI נפרדות. אתם יכולים להתחיל להשתמש בחבילות ה-AI הזמינות לפני שכל ההורדות האחרות של הבקשה שלכם הושלמו.

void registerListener(AiPackStateUpdateListener listener)
void unregisterListener(AiPackStateUpdateListener listener)
הורדות גדולות

אם גודל ההורדה הוא יותר מ-200MB והמשתמש לא מחובר ל-Wi-Fi, ההורדה לא תתחיל עד שהמשתמש יאשר במפורש להמשיך בהורדה באמצעות חיבור לחבילת גלישה. באופן דומה, אם ההורדה גדולה והמשתמש מאבד את החיבור ל-Wi-Fi, ההורדה מושהית ונדרשת הסכמה מפורשת כדי להמשיך באמצעות חיבור לחבילת גלישה. חבילה מושהית נמצאת במצב WAITING_FOR_WIFI. כדי להפעיל את תהליך ממשק המשתמש שבו מוצגת למשתמש בקשה להסכמה, משתמשים ב-method‏ showConfirmationDialog().

חשוב לדעת: אם האפליקציה לא קוראת ל-method הזה, ההורדה מושהית ותתחדש באופן אוטומטי רק כשהמשתמש יתחבר שוב לחיבור 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;
      }
    }
}

לחלופין, אפשר להשתמש ב-method‏ getPackStates() כדי לקבל את הסטטוס של ההורדות הנוכחיות. AiPackStates מכיל את התקדמות ההורדה, סטטוס ההורדה וקודי שגיאה של כשלים.

גישה לחבילות AI

אפשר לגשת לחבילת ה-AI באמצעות קריאות למערכת הקבצים אחרי שבקשת ההורדה מגיעה למצב COMPLETED. משתמשים ב-method‏ getPackLocation() כדי לאתר את תיקיית הבסיס של חבילת ה-AI.

חבילות ה-AI מאוחסנות בספרייה assets בתוך תיקיית השורש של חבילת ה-AI. כדי לקבל את הנתיב לספרייה assets, אפשר להשתמש ב-method הנוחה assetsPath(). כדי לקבל את הנתיב לנכס ספציפי, משתמשים בשיטה הבאה:

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 נוספות שאולי תרצו להשתמש בהן באפליקציה.

ביטול הבקשה

כדי לבטל בקשה פעילה לחבילת AI, משתמשים ב-cancel(). חשוב לדעת שהבקשה הזו היא פעולה שמתבצעת כמיטב היכולת.

הסרה של חבילת AI

כדי לתזמן הסרה של חבילת AI, משתמשים ב-removePack().

קבלת מיקומים של כמה חבילות AI

משתמשים ב-getPackLocations() כדי לשלוח שאילתה על הסטטוס של כמה חבילות AI בבת אחת. הפעולה מחזירה מפה של חבילות ה-AI והמיקומים שלהן. המפה שמוחזרת על ידי getPackLocations() מכילה רשומה לכל חבילה שהורדה ועדכנית כרגע.

מיקוד למכשירים

טירגוט לפי מכשיר מאפשר לכם להחליט אילו חלקים של ה-App Bundle יועברו למכשירים ספציפיים. לדוגמה, אתם יכולים לוודא שמודל גדול יועבר רק למכשירים עם זיכרון 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 שמכילה את כל המכשירים עם מערכת על שבב (SoC) מסוג 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_id כלשהו ברשימה.
    • ‫build_brand: יצרן המכשיר
    • ‫build_device: קוד דגם המכשיר
  • ‫excluded_device_ids: דגמי המכשירים שיוחרגו בבורר הזה (עד 10,000 מזהי מכשירים בכל קבוצה). המאפיין הזה מתקיים אם המכשיר לא תואם לאף 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 Console באחת מהדרכים הבאות:

  • בודקים מכשירים ספציפיים באמצעות קטלוג המכשירים, ומחפשים את קוד היצרן והדגם במיקומים שמוצגים בדוגמה הבאה (ב-Google Pixel 4a, היצרן הוא Google וקוד הדגם הוא sunfish).

    דף של Pixel 4a בקטלוג המכשירים

    דף של Pixel 4a בקטלוג המכשירים

  • מורידים קובץ CSV של מכשירים נתמכים, ומשתמשים ביצרן ובקוד הדגם בשדות build_brand ו-build_device, בהתאמה.

כוללים את קובץ התצורה של הטירגוט לפי מכשיר ב-App Bundle

מוסיפים את הקוד הבא לקובץ 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 הוא הנתיב של קובץ התצורה ביחס למודול הראשי. כך קובץ התצורה ייארז עם ה-App Bundle.

הסעיף deviceGroup מבטיח שקובצי ה-APK שנוצרים מה-bundle מפוצלים לפי קבוצות מכשירים.

שימוש בטירגוט לפי מכשיר בחבילות ה-AI

כדי לשמור על גודל אופטימלי במכשירים, אתם יכולים להעביר את המודלים הגדולים רק למכשירים שיכולים להריץ אותם.

כדי לחלק את חבילות ה-AI לקבוצות מכשירים, לוקחים את התיקיות הקיימות של חבילות ה-AI שנוצרו בשלב הקודם, ומוסיפים את הסיומת המתאימה לתיקיות (כפי שמתואר בהמשך) עם ‎ #group_myCustomGroup1, ‏ ‎#group_myCustomGroup2 וכו'. כשמשתמשים בחבילות ה-AI באפליקציה, לא צריך להוסיף את הסיומת לתיקיות (במילים אחרות, הסיומת מוסרת באופן אוטומטי במהלך תהליך ה-build).

אחרי השלב הקודם, זה יכול להיראות כך:

...
.../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 לחבילות מסוג Fast-Follow ולחבילות על פי דרישה. באפליקציה לדוגמה מוצגות דוגמאות לכל מצבי ההעברה.

שימוש בטירגוט לפי מכשיר במודולים של תכונות

אפשר גם להשתמש בטירגוט לפי מכשיר למודולים של תכונות. במקום לחלק את המודולים של התכונות לפי קבוצת מכשירים, אתם מציינים אם המודול כולו צריך להישלח על סמך החברות בקבוצת המכשירים.

כדי להפיץ מודול של תכונות למכשירים ששייכים ל-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>

בדיקה מקומית

לפני שיוצרים גרסה ל-App Bundle החדש, אפשר לבדוק אותו באופן מקומי באמצעות שיתוף פנימי של אפליקציות או Bundletool.

שיתוף פנימי של אפליקציות

התכונה "שיתוף פנימי של אפליקציות" מאפשרת לכם להשתמש ב-App Bundle כדי ליצור במהירות כתובת URL. אתם יכולים ללחוץ על כתובת ה-URL במכשיר מקומי כדי להתקין בדיוק את מה ש-Google Play הייתה מתקינה במכשיר הזה אם גרסת האפליקציה הזו הייתה פעילה במסלול בדיקה או במסלול ייצור.

הוראות לשיתוף פנימי של אפליקציות

כלי Bundletool

אפשר גם ליצור קובצי APK באמצעות bundletool (גרסה 1.18.0 ואילך) ולהוריד אותם למכשיר ממקורות לא רשמיים. כדי לבדוק את האפליקציה באופן מקומי באמצעות bundletool, פועלים לפי השלבים הבאים:

  1. יוצרים את ה-App Bundle באמצעות Android Studio או bundletool.

  2. יוצרים קובצי APK עם הדגל --local-testing:

    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. כלומר, הן לא יאוחזרו באופן אוטומטי כשהאפליקציה תותקן ממקור לא מוכר. המפתחים צריכים לבקש אותן באופן ידני כשהאפליקציה מופעלת. לא נדרשים שינויים בקוד של האפליקציה.
  • החבילות נשלפות מאחסון חיצוני במקום מ-Play, כך שאי אפשר לבדוק איך הקוד מתנהג במקרה של שגיאות בחיבור לרשת.
  • בדיקה מקומית לא מכסה את התרחיש של המתנה ל-Wi-Fi.
  • אין תמיכה בעדכונים. לפני שמתקינים גרסה חדשה של ה-build, צריך להסיר ידנית את הגרסה הקודמת.

מוודאים שמותקנים קובצי ה-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 שנוצרו ממודולים של תכונות ומחבילות AI שמותקנות בזמן ההתקנה. חבילות AI מסוג 'על פי דרישה' ו-Fast-Follow לא מותקנות כקובצי APK.

בדיקה ופרסום ב-Google Play

מומלץ לבדוק את האפליקציה מקצה לקצה ב-Google Play באמצעות מסלול לבדיקה פנימית.

אחרי שתעשו את זה, תוכלו להשיק את העדכון לאפליקציה בהדרגה בסביבת הייצור באמצעות השקות מדורגות.

אפליקציה לדוגמה שמשתמשת ב-Play ל-AI במכשיר

מורידים את האפליקציה לדוגמה.

הוא מדגים איך להשתמש בכל אחד ממצבי ההצגה וגם בהגדרות הטירגוט לפי מכשיר. כדי להתחיל, עיינו בקטע בדיקה מקומית.

מידע נוסף על קובצי Android App Bundle וחומרי עזר בנושא AI Delivery SDK