בעזרת השלבים במדריך הזה תוכלו לגשת לחבילות הנכסים של האפליקציה מקוד ה-Java.
פיתוח גרסאות build ל-Kotlin ול-Java
כדי לבנות את Play Asset Delivery במכשיר Android של הפרויקט, צריך לפעול לפי השלבים הבאים קובץ App Bundle אין צורך להשתמש ב-Android Studio כדי לבצע את השלבים האלה.
מעדכנים את הגרסה של הפלאגין Android Gradle בקובץ
build.gradle
של הפרויקט ל-4.0.0
ואילך.בספרייה ברמה העליונה של הפרויקט, יוצרים ספרייה של הנכס . שם הספרייה הזה משמש כשם של חבילת הנכסים. שמות של חבילות נכסים חייבים להתחיל באות ויכולים להכיל רק אותיות, מספרים וקו תחתון.
בספרייה של חבילת הנכסים, יוצרים קובץ
build.gradle
ומוסיפים את באמצעות הקוד הבא. חשוב לציין את השם של חבילת הנכסים ורק סוג העברה אחד:Groovy
// 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
של אפליקציית הפרויקט, צריך להוסיף את השם של כל חבילת נכסים בפרויקט שלכם, כפי שמוצג בהמשך:Groovy
// 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
של הפרויקט, צריך לכלול את כל חבילות הנכסים בפרויקט, כפי שמתואר בהמשך:Groovy
// 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. בחבילת האפליקציות שנוצרה, התיקייה ברמת השורש כוללת עכשיו את הפריטים הבאים:
asset-pack-name/manifest/AndroidManifest.xml
: הגדרת המזהה ושל אופן המסירה של חבילת הנכסיםasset-pack-name/assets/your-asset-directories
: הספרייה שמכילה את כל הנכסים שנשלחים כחלק מחבילת הנכסים
Gradle יוצר את המניפסט לכל חבילת נכסים ומפיק את הספרייה
assets/
בשבילכם.(אופציונלי) אם אתם מתכננים להשתמש בהעברה מסוג fast-follow ובהעברה על פי דרישה, צריך לכלול את ספריית העברת הנכסים של Play.
Groovy
implementation "com.google.android.play:asset-delivery:2.3.0" // For Kotlin use asset-delivery-ktx implementation "com.google.android.play:asset-delivery-ktx:2.3.0"
Kotlin
implementation("com.google.android.play:asset-delivery:2.3.0") // For Kotlin use core-ktx implementation("com.google.android.play:asset-delivery-ktx:2.3.0")
(אופציונלי) מגדירים את ה-App Bundle כך שיתמוך במרקם שונה דחיסה.
שילוב עם Play Asset Delivery API
Play Asset Delivery Java API מספק את הכיתה AssetPackManager
לשליחת בקשות לקבלת חבילות נכסים, לניהול ההורדות ולגישה לנכסים. חשוב להוסיף את ספריית Play Asset Delivery לפרויקט לפני כן.
מטמיעים את ה-API הזה בהתאם לסוג המסירה של חבילת הנכסים שאליה רוצים לגשת. השלבים האלו מוצגים בתרשים הזרימה הבא.
איור 1. תרשים זרימה לגישה לחבילות נכסים
מסירה בזמן ההתקנה
חבילות נכסים שהוגדרו כ-install-time
זמינות באופן מיידי באפליקציה
בהשקה. משתמשים ב-AssetManager API של Java כדי לגשת לנכסים שמוצגים במצב הזה:
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
מספקות את גודל חבילת הנכסים, את כמות הנתונים שהורדתם עד כה (אם ביקשת זאת) ואת הסכום שכבר הועבר לאפליקציה:
כדי לקבל את הסטטוס של חבילת נכסים, צריך להשתמש בפונקציה
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()
במקרה כזה, האפליקציה תעודכן. לאחר העדכון, יהיה עליך
כדי לבקש שוב את הנכסים.
דוגמה להטמעה של מאזין:
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
באמצעות ה-method הנוחה 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 Asset Delivery באופן מקומי ומ-Google Play.