כדי לגשת לחבילות ה-Asset Pack של האפליקציה מקוד Java, צריך לפעול לפי השלבים במדריך הזה.
פיתוח ב-Kotlin וב-Java
כדי להטמיע את התכונה 'העברת נכסים ב-Play' ב-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.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
זמינות מיידית כשמפעילים את האפליקציה. משתמשים ב-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 כדי להתחיל את ההורדה ואיך לגשת לחבילות שהורדו. הקטעים האלה רלוונטיים לחבילות Asset Pack של fast-follow
ושל on-demand
.
בדיקת הסטטוס
כל חבילת נכסים מאוחסנת בתיקייה נפרדת באחסון הפנימי של האפליקציה.
משתמשים ב-method 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
מוחזר הגודל של חבילת ה-Asset Pack, הכמות שהורדה עד כה (אם נדרש), והכמות שכבר הועברה לאפליקציה:
כדי לקבל את הסטטוס של חבילת נכסים, משתמשים בשיטה status()
, שמחזירה את הסטטוס כמספר שלם שתואם לשדה קבוע במחלקה AssetPackStatus
. חבילת נכסים שעדיין לא הותקנה מסומנת בסטטוס AssetPackStatus.NOT_INSTALLED
.
אם בקשה נכשלת, צריך להשתמש בשיטה errorCode()
, שערך ההחזרה שלה תואם לשדה קבוע במחלקה 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 – לדוגמה, אם האפליקציה הותקנה ממקור לא ידוע.
שימו לב: במקרה הזה, הפעלת הפונקציה call
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
בתוך ספריית הבסיס של חבילת הנכסים. אפשר לקבל את הנתיב לספרייה 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.