פועלים לפי השלבים במדריך הזה כדי לגשת לחבילות הנכסים של האפליקציה מ-Java
פיתוח כלים ל-Kotlin ו-Java
כדי לבנות את Play Asset Delivery במכשיר Android של הפרויקט, צריך לפעול לפי השלבים הבאים קובץ App Bundle לא צריך להשתמש ב-Android Studio כדי לבצע את השלבים האלה.
מעדכנים את גרסת הפלאגין של Android Gradle בפרויקט קובץ
build.gradle
אל4.0.0
ואילך.בספרייה ברמה העליונה של הפרויקט, יוצרים ספרייה של הנכס . שם הספרייה הזה משמש בתור השם של חבילת הנכסים. שמות של חבילות נכסים חייב להתחיל באות ויכול להכיל רק אותיות, מספרים וגם קווים תחתונים.
בספרייה של חבילת הנכסים, יוצרים קובץ
build.gradle
ומוסיפים את באמצעות הקוד הבא. חשוב לציין את השם של חבילת הנכסים ורק אחת סוג משלוח:מגניב
// In the asset pack's build.gradle file: plugins { id 'com.android.asset-pack' } assetPack { packName = "asset-pack-name" // Directory name for the asset pack dynamicDelivery { deliveryType = "[ install-time | fast-follow | on-demand ]" } }
Kotlin
// In the asset pack's build.gradle.kts file: plugins { id("com.android.asset-pack") } assetPack { packName.set("asset-pack-name") // Directory name for the asset pack dynamicDelivery { deliveryType.set("[ install-time | fast-follow | on-demand ]") } }
בקובץ
build.gradle
של אפליקציית הפרויקט, צריך להוסיף את השם של כל חבילת נכסים בפרויקט שלכם, כפי שמוצג בהמשך:מגניב
// In the app build.gradle file: android { ... assetPacks = [":asset-pack-name", ":asset-pack2-name"] }
Kotlin
// In the app build.gradle.kts file: android { ... assetPacks += listOf(":asset-pack-name", ":asset-pack2-name") }
בקובץ
settings.gradle
של הפרויקט, יש לכלול את כל חבילות הנכסים פרויקט כפי שמוצג בהמשך:מגניב
// In the settings.gradle file: include ':app' include ':asset-pack-name' include ':asset-pack2-name'
Kotlin
// In the settings.gradle.kts file: include(":app") include(":asset-pack-name") include(":asset-pack2-name")
בספרייה של חבילת הנכסים, יוצרים את ספריית המשנה הבאה:
src/main/assets
מציבים נכסים בספרייה
src/main/assets
. אפשר ליצור גם את ספריות המשנה. מבנה הספריות באפליקציה שלך צריך להיות עכשיו ייראה כך:build.gradle
settings.gradle
app/
asset-pack-name/build.gradle
asset-pack-name/src/main/assets/your-asset-directories
איך מפתחים את קובץ Android App Bundle באמצעות Gradle ב-App Bundle שנוצר, הספרייה ברמת השורש כוללת עכשיו את הקוד הבאים:
asset-pack-name/manifest/AndroidManifest.xml
: הגדרת המזהה של חבילת הנכסים ומצב ההעברהasset-pack-name/assets/your-asset-directories
: ספרייה שמכילה את כל הנכסים שהועברו כחלק מחבילת הנכסים
Gradle יוצרת את המניפסט לכל חבילת נכסים ומפיקה את הפלט של
assets/
במיוחד בשבילך.(אופציונלי) יש לכלול את ספריית Play Asset Delivery אם אתם מתכננים להשתמש במעקב מהיר ובמשלוח על פי דרישה.
מגניב
implementation "com.google.android.play:asset-delivery:2.2.2" // For Kotlin use asset-delivery-ktx implementation "com.google.android.play:asset-delivery-ktx:2.2.2"
Kotlin
implementation("com.google.android.play:asset-delivery:2.2.2") // For Kotlin use core-ktx implementation("com.google.android.play:asset-delivery-ktx:2.2.2")
(אופציונלי) מגדירים את ה-App Bundle כך שיתמוך במרקם שונה דחיסה.
שילוב עם Play Asset Delivery API
ממשק ה-API של Java ל-Play Asset Delivery
מספקת
AssetPackManager
class לשליחה של בקשות לחבילות נכסים, ניהול הורדות וגישה לנכסים. קודם צריך להוסיף את הספרייה ל-Play Asset Delivery לפרויקט.
הטמעת ה-API הזה בהתאם לסוג ההעברה של חבילת הנכסים הרצויה כדי לגשת אליה. השלבים האלו מוצגים בתרשים הזרימה הבא.
איור 1. תרשים זרימה לגישה לחבילות נכסים
מסירה בזמן ההתקנה
חבילות נכסים שהוגדרו כ-install-time
זמינות באופן מיידי באפליקציה
בהשקה. שימוש ב-Java
AssetManager API כדי לגשת לנכסים
מוצג במצב הזה:
Kotlin
import android.content.res.AssetManager ... val context: Context = createPackageContext("com.example.app", 0) val assetManager: AssetManager = context.assets val stream: InputStream = assetManager.open("asset-name")
Java
import android.content.res.AssetManager; ... Context context = createPackageContext("com.example.app", 0); AssetManager assetManager = context.getAssets(); InputStream is = assetManager.open("asset-name");
משלוח מהיר ועל פי דרישה
בקטעים הבאים מוסבר איך לקבל מידע על חבילות נכסים לפני
שמורידים אותם, איך קוראים ל-API כדי להתחיל את ההורדה, ואז איך
לגשת לחבילות שהורדתם. הקטעים האלה חלים על fast-follow
ועל
on-demand
חבילות נכסים.
בדיקת הסטטוס
כל חבילת נכסים מאוחסנת בתיקייה נפרדת באחסון הפנימי של האפליקציה.
משתמשים ב
getPackLocation()
כדי לקבוע את תיקיית הבסיס של חבילת נכסים. השיטה הזו מחזירה את הערך
הערכים הבאים:
הערך המוחזר | סטטוס |
---|---|
אובייקט AssetPackLocation תקין |
תיקיית הבסיס של חבילת הנכסים מוכנה לגישה מיידית בכתובת assetsPath() |
null |
חבילת נכסים לא ידועה או נכסים לא זמינים |
קבלת מידע על הורדות על חבילות נכסים
האפליקציות נדרשות לציין את גודל ההורדה לפני אחזור הנכס
. משתמשים ב
requestPackStates()
או getPackStates()
כדי לקבוע את גודל ההורדה ואם החבילה כבר
מתבצעת הורדה.
Kotlin
suspend fun requestPackStates(packNames: List<String>): AssetPackStates
Java
Task<AssetPackStates> getPackStates(List<String> packNames)
requestPackStates()
היא פונקציית השעיה שמחזירה
AssetPackStates
ו-getPackStates()
היא שיטה אסינכרונית שמחזירה Task<AssetPackStates>
.
packStates()
של אובייקט AssetPackStates
, מחזירה Map<String,
AssetPackState>
. המפה הזו מכילה את המצב של כל נכס מבוקש
חבילה, מקודדת לפי השם שלה:
Kotlin
AssetPackStates#packStates(): Map<String, AssetPackState>
Java
Map<String, AssetPackState> AssetPackStates#packStates()
הבקשה הסופית מוצגת כך:
Kotlin
const val assetPackName = "assetPackName" coroutineScope.launch { try { val assetPackStates: AssetPackStates = manager.requestPackStates(listOf(assetPackName)) val assetPackState: AssetPackState = assetPackStates.packStates()[assetPackName] } catch (e: RuntimeExecutionException) { Log.d("MainActivity", e.message) } }
Java
final String assetPackName = "myasset"; assetPackManager .getPackStates(Collections.singletonList(assetPackName)) .addOnCompleteListener(new OnCompleteListener<AssetPackStates>() { @Override public void onComplete(Task<AssetPackStates> task) { AssetPackStates assetPackStates; try { assetPackStates = task.getResult(); AssetPackState assetPackState = assetPackStates.packStates().get(assetPackName); } catch (RuntimeExecutionException e) { Log.d("MainActivity", e.getMessage()); return; })
הבאים
AssetPackState
methods מספקות את הגודל של חבילת הנכסים, את הסכום שהורדתם עד עכשיו (אם
והסכום שכבר הועבר לאפליקציה:
כדי לקבל את הסטטוס של חבילת נכסים, צריך להשתמש בפונקציה
status()
method, שמחזירה את הסטטוס כמספר שלם שתואם למספר קבוע
בשדה
AssetPackStatus
בכיתה. הסטטוס של חבילת נכסים שעדיין לא הותקנה נמצא בסטטוס
AssetPackStatus.NOT_INSTALLED
אם בקשה מסוימת נכשלת, משתמשים
errorCode()
ש-method עם הערך המוחזר תואם לשדה קבוע
AssetPackErrorCode
בכיתה.
התקנה
משתמשים בrequestFetch()
או
fetch()
להורדת חבילת נכסים בפעם הראשונה או קריאה לעדכון של
חבילת נכסים שצריך להשלים:
Kotlin
suspend fun AssetPackManager.requestFetch(packs: List<String>): AssetPackStates
Java
Task<AssetPackStates> fetch(List<String> packNames)
השיטה הזו מחזירה
AssetPackStates
שמכיל רשימה של חבילות ואת גודל ומצבי ההורדה הראשוניים שלהן.
אם כבר מתבצעת הורדה של חבילת נכסים דרך requestFetch()
או fetch()
, ההורדה
הסטטוס מוחזר ולא מתחילה הורדה נוספת.
מעקב אחרי מצבי ההורדה
עליך ליישם
AssetPackStateUpdatedListener
לעקוב אחר התקדמות ההתקנה של הנכס
חבילות. עדכוני הסטטוס מפורטים לפי חבילה כדי לתמוך במעקב
הסטטוס של חבילות נכסים בודדות. אפשר להתחיל להשתמש בחבילות הנכסים הזמינות
לפני שכל ההורדות האחרות שקשורות לבקשה שלך יסתיימו.
Kotlin
fun registerListener(listener: AssetPackStateUpdatedListener) fun unregisterListener(listener: AssetPackStateUpdatedListener)
Java
void registerListener(AssetPackStateUpdatedListener listener) void unregisterListener(AssetPackStateUpdatedListener listener)
הורדות גדולות
אם קובץ ההורדה גדול מ- 200MB והמשתמש לא מחובר לרשת Wi-Fi, קובץ ההורדה
לא מתחיל לפני שהמשתמש מביע הסכמה באופן מפורש להמשיך
להוריד באמצעות חיבור לחבילת גלישה. באופן דומה, אם ההורדה גדולה
המשתמש מאבד את חיבור ה-Wi-Fi, ההורדה מושהית ונדרשת הסכמה מפורשת
להמשיך באמצעות חיבור לחבילת גלישה. יש מצב של חבילה מושהית
WAITING_FOR_WIFI
כדי להפעיל את התהליך בממשק המשתמש ולבקש מהמשתמשים להביע הסכמה, צריך להשתמש ב
showConfirmationDialog()
.
שימו לב שאם האפליקציה לא קוראת לשיטה הזו, ההורדה מושהית חידוש אוטומטי רק כשהמשתמש מתחבר שוב לרשת Wi-Fi.
נדרש אישור משתמש
אם החבילה היא בסטטוס REQUIRES_USER_CONFIRMATION
, ההורדה לא תתבצע
ממשיכים עד שהמשתמש יאשר את תיבת הדו-שיח שמוצגת עם
showConfirmationDialog()
.
הסטטוס הזה יכול להופיע כשהאפליקציה לא מזוהה על ידי Play – לדוגמה, אם
האפליקציה נטענה ממקור לא ידוע.
חשוב לזכור ששיחות טלפון
showConfirmationDialog()
במקרה כזה, האפליקציה תעודכן. לאחר העדכון, יהיה עליך
כדי לבקש שוב את הנכסים.
הדוגמה הבאה היא הטמעה של listener:
Kotlin
private val activityResultLauncher = registerForActivityResult( ActivityResultContracts.StartIntentSenderForResult() ) { result -> if (result.resultCode == RESULT_OK) { Log.d(TAG, "Confirmation dialog has been accepted.") } else if (result.resultCode == RESULT_CANCELED) { Log.d(TAG, "Confirmation dialog has been denied by the user.") } } assetPackManager.registerListener { assetPackState -> when(assetPackState.status()) { AssetPackStatus.PENDING -> { Log.i(TAG, "Pending") } AssetPackStatus.DOWNLOADING -> { val downloaded = assetPackState.bytesDownloaded() val totalSize = assetPackState.totalBytesToDownload() val percent = 100.0 * downloaded / totalSize Log.i(TAG, "PercentDone=" + String.format("%.2f", percent)) } AssetPackStatus.TRANSFERRING -> { // 100% downloaded and assets are being transferred. // Notify user to wait until transfer is complete. } AssetPackStatus.COMPLETED -> { // Asset pack is ready to use. Start the game. } AssetPackStatus.FAILED -> { // Request failed. Notify user. Log.e(TAG, assetPackState.errorCode()) } AssetPackStatus.CANCELED -> { // Request canceled. Notify user. } AssetPackStatus.WAITING_FOR_WIFI, AssetPackStatus.REQUIRES_USER_CONFIRMATION -> { if (!confirmationDialogShown) { assetPackManager.showConfirmationDialog(activityResultLauncher); confirmationDialogShown = true } } AssetPackStatus.NOT_INSTALLED -> { // Asset pack is not downloaded yet. } AssetPackStatus.UNKNOWN -> { Log.wtf(TAG, "Asset pack status unknown") } } }
Java
assetPackStateUpdateListener = new AssetPackStateUpdateListener() { 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(AssetPackState assetPackState) { switch (assetPackState.status()) { case AssetPackStatus.PENDING: Log.i(TAG, "Pending"); break; case AssetPackStatus.DOWNLOADING: long downloaded = assetPackState.bytesDownloaded(); long totalSize = assetPackState.totalBytesToDownload(); double percent = 100.0 * downloaded / totalSize; Log.i(TAG, "PercentDone=" + String.format("%.2f", percent)); break; case AssetPackStatus.TRANSFERRING: // 100% downloaded and assets are being transferred. // Notify user to wait until transfer is complete. break; case AssetPackStatus.COMPLETED: // Asset pack is ready to use. Start the game. break; case AssetPackStatus.FAILED: // Request failed. Notify user. Log.e(TAG, assetPackState.errorCode()); break; case AssetPackStatus.CANCELED: // Request canceled. Notify user. break; case AssetPackStatus.WAITING_FOR_WIFI: case AssetPackStatus.REQUIRES_USER_CONFIRMATION: if (!confirmationDialogShown) { assetPackManager.showConfirmationDialog(activityResultLauncher); confirmationDialogShown = true; } break; case AssetPackStatus.NOT_INSTALLED: // Asset pack is not downloaded yet. break; case AssetPackStatus.UNKNOWN: Log.wtf(TAG, "Asset pack status unknown") break; } } }
לחלופין, אפשר להשתמש
getPackStates()
כדי לקבל את הסטטוס של ההורדות הנוכחיות.
AssetPackStates
מכילה את התקדמות ההורדה, את סטטוס ההורדה ואת כל קודי השגיאה של כשלים.
גישה לחבילות נכסים
אפשר לגשת לחבילת נכסים באמצעות קריאות למערכת הקבצים לאחר בקשת ההורדה
מגיע אל
COMPLETED
. משתמשים ב
getPackLocation()
כדי לקבל את תיקיית הבסיס של חבילת הנכסים.
הנכסים מאוחסנים בספרייה assets
ברמה הבסיסית (root) של חבילת הנכסים
אפשר למצוא את הנתיב לספרייה assets
באמצעות
שיטת נוחות
assetsPath()
.
כדי למצוא את הנתיב לנכס ספציפי, משתמשים בשיטה הבאה:
Kotlin
private fun getAbsoluteAssetPath(assetPack: String, relativeAssetPath: String): String? { val assetPackPath: AssetPackLocation = assetPackManager.getPackLocation(assetPack) // asset pack is not ready ?: return null val assetsFolderPath = assetPackPath.assetsPath() // equivalent to: FilenameUtils.concat(assetPackPath.path(), "assets") return FilenameUtils.concat(assetsFolderPath, relativeAssetPath) }
Java
private String getAbsoluteAssetPath(String assetPack, String relativeAssetPath) { AssetPackLocation assetPackPath = assetPackManager.getPackLocation(assetPack); if (assetPackPath == null) { // asset pack is not ready return null; } String assetsFolderPath = assetPackPath.assetsPath(); // equivalent to: FilenameUtils.concat(assetPackPath.path(), "assets"); String assetPath = FilenameUtils.concat(assetsFolderPath, relativeAssetPath); return assetPath; }
שיטות אחרות של Play Asset Delivery API
בהמשך מפורטות כמה שיטות API נוספות שכדאי להשתמש בהן באפליקציה.
ביטול הבקשה
כדאי להשתמש
cancel()
כדי לבטל בקשה פעילה לחבילת נכסים. לתשומת ליבך, הבקשה הזו היא המטרה הטובה ביותר
פעולה.
הסרה של חבילת נכסים
כדאי להשתמש
requestRemovePack()
או
removePack()
כדי לתזמן הסרה של חבילת נכסים.
אחזור של מיקומים של מספר חבילות נכסים
כדאי להשתמש
getPackLocations()
כדי לשלוח שאילתה על הסטטוס של כמה חבילות נכסים בכמות גדולה, שמחזירה מפה של
חבילות נכסים והמיקומים שלהן. המפה הוחזרה על ידי getPackLocations()
מכיל רשומה עבור כל חבילה שהורדו ומעודכנים כרגע.
השלב הבא
בדיקה של העברת נכסים ב-Play באופן מקומי ודרך Google Play.