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

מבוא

התכונה 'Play ל-AI במכשיר' מאפשרת ליהנות מהיתרונות של Android App Bundles ושל מודל ההפצה של Google Play בהפצה של מודלים מותאמים אישית של ML. כך אפשר לשפר את ביצועי המודלים עם פחות מורכבות במערכת האקולוגית של המכשיר, ללא עלות נוספת. הוא מאפשר לכם לפרסם ב-Play ארטיפקט יחיד שמכיל את הקוד, הנכסים ומודלים של ML, ולבחור מתוך מספר מצבי מסירה ואפשרויות טירגוט.

יתרונות

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

שיקולים

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

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

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

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

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

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

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

אפשר להשתמש ב-LiteRT וב-MediaPipe עם חבילות AI. אורזים את המודל בחבילת AI ואז ניגשים אליו באמצעות ההוראות לחבילות install-time או לחבילות fast-follow ועל פי דרישה.

קריאה נוספת:

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

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

  1. אורזים את המודלים בחבילות AI ב-Android App Bundle ומציינים איך חבילות ה-AI צריכות להישלח.
  2. [אופציונלי] אם רוצים להפיץ מודלים שונים למכשירים שונים, אפשר להגדיר טירגוט לפי מכשיר לחבילות ה-AI. לדוגמה, אפשר להקצות חבילת AI A למודל מכשיר ספציפי, חבילת AI B למכשירים עם זיכרון RAM בנפח של 6GB לפחות, ולכל שאר המכשירים לא להקצות אף מודל.
  3. [אופציונלי] אם אתם משתמשים באספקת תוכן על פי דרישה או באספקת תוכן מהירה, אתם יכולים לשלב את ספריית אספקת התוכן מבוסס ה-AI של Play באפליקציה כדי להוריד את חבילות ה-AI לפי הצורך.
  4. בודקים את קובץ ה-App Bundle ומשחררים אותו ל-Google Play.

בדיקת הגרסה של Android Gradle Plugin

כדי להשתמש בחבילות AI, צריך לוודא שגרסת Android Gradle Plugin ‏ (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. איך יוצרים קובץ 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 שמוצגות במצב הזה, משתמשים בממשק ה-API של Java AssetManager:

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

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

קבלת מידע על הורדה של חבילות AI

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

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

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

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

התקנה

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

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

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

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

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

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

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

שימו לב: אם האפליקציה לא קוראת לשיטה הזו, ההורדה מושהית ותתחדש אוטומטית רק כשהמשתמש יתחבר שוב ל-Wi-Fi.

נדרש אישור מהמשתמש

אם החבילה בסטטוס REQUIRES_USER_CONFIRMATION, ההורדה לא תמשיך עד שהמשתמש יאשר את תיבת הדו-שיח שמוצגת עם showConfirmationDialog(). הסטטוס הזה יכול להופיע אם האפליקציה לא מזוהה על ידי Play – למשל, אם האפליקציה הועברה למכשיר בשיטת Sideloading. שימו לב: במקרה הזה, הפעלת הפונקציה call 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

אפשר לגשת לחבילת ה-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

אפשר להשתמש ב‐removePack() כדי לתזמן את ההסרה של חבילת AI.

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

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

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

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

אפשר לטרגט מאפייני מכשיר כמו:

  • פרטי CPU ו-GPU ‏(System on Chip)
  • דגם המכשיר
  • זיכרון RAM של המכשיר
  • תכונות מערכת

סקירה כללית של השלבים הנדרשים

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

  1. מגדירים את קבוצות המכשירים בקובץ XML.
  2. מציינים אילו חלקים בחבילה ישויכו לאילו קבוצות מכשירים.
  3. [אופציונלי] בודקים את ההגדרה באופן מקומי.
  4. מעלים את חבילת האפליקציה (שמכילה את קובץ ה-XML) אל Google Play.

בדיקת הגרסה של Android Gradle Plugin

כדי להשתמש בטירגוט למכשירים, צריך לוודא שגרסת Android Gradle Plugin ‏ (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 מזהי מכשירים לכל קבוצה). התנאי הזה מתקיים אם המכשיר תואם לאחד ממזהי המכשירים ברשימה.
    • 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 של מכשירים נתמכים ושימוש בערכים של Manufacturer (יצרן) ו-Model Code (קוד דגם) בשדות 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 הוא הנתיב של קובץ ההגדרות ביחס למודול הראשי. כך אפשר לוודא שקובץ התצורה נארז עם חבילת האפליקציה.

סעיף 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>

בדיקה מקומית

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

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

התכונה 'שיתוף אפליקציות פנימי' מאפשרת להשתמש בחבילת אפליקציות כדי ליצור במהירות כתובת 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 לפי דרישה וחבילות AI מהירות לא מותקנות כקובצי APK.

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

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

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

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

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

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

מידע נוסף על קובצי Android App Bundle ועל AI Delivery SDK