আপনার জাভা কোড থেকে অ্যাপের অ্যাসেট প্যাকগুলো অ্যাক্সেস করতে এই গাইডের ধাপগুলো ব্যবহার করুন।
কোটলিন এবং জাভার জন্য তৈরি করুন
আপনার প্রোজেক্টের অ্যান্ড্রয়েড অ্যাপ বান্ডেলে প্লে অ্যাসেট ডেলিভারি যুক্ত করতে নিম্নলিখিত ধাপগুলো অনুসরণ করুন। এই ধাপগুলো সম্পন্ন করার জন্য আপনার অ্যান্ড্রয়েড স্টুডিও ব্যবহার করার প্রয়োজন নেই।
আপনার প্রোজেক্টের
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 ]" } }
কোটলিন
// 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 ]") } }
প্রজেক্টের app
build.gradleফাইলে, নিচে দেখানো অনুযায়ী আপনার প্রজেক্টের প্রতিটি অ্যাসেট প্যাকের নাম যোগ করুন:গ্রুভি
// In the app build.gradle file: android { ... assetPacks = [":asset-pack-name", ":asset-pack2-name"] }
কোটলিন
// 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'
কোটলিন
// 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
-
Gradle ব্যবহার করে অ্যান্ড্রয়েড অ্যাপ বান্ডেলটি বিল্ড করুন । তৈরি হওয়া অ্যাপ বান্ডেলের রুট-লেভেল ডিরেক্টরিতে এখন নিম্নলিখিত বিষয়গুলো অন্তর্ভুক্ত থাকবে:
-
asset-pack-name /manifest/AndroidManifest.xml: অ্যাসেট প্যাকের শনাক্তকারী এবং ডেলিভারি মোড কনফিগার করে। -
asset-pack-name /assets/ your-asset-directories: এই ডিরেক্টরিতে অ্যাসেট প্যাকের অংশ হিসেবে সরবরাহ করা সমস্ত অ্যাসেট থাকে
Gradle প্রতিটি অ্যাসেট প্যাকের জন্য ম্যানিফেস্ট তৈরি করে এবং আপনার জন্য
assets/ডিরেক্টরিটি আউটপুট করে দেয়।-
(ঐচ্ছিক) আপনি যদি ফাস্ট-ফলো এবং অন-ডিমান্ড ডেলিভারি ব্যবহার করার পরিকল্পনা করেন, তাহলে প্লে অ্যাসেট ডেলিভারি লাইব্রেরিটি অন্তর্ভুক্ত করুন।
গ্রুভি
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"
কোটলিন
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")
(ঐচ্ছিক) বিভিন্ন টেক্সচার কম্প্রেশন ফরম্যাট সমর্থন করার জন্য আপনার অ্যাপ বান্ডেলটি কনফিগার করুন।
প্লে অ্যাসেট ডেলিভারি এপিআই-এর সাথে একীভূত করুন
প্লে অ্যাসেট ডেলিভারি জাভা এপিআই অ্যাসেট প্যাক অনুরোধ করা, ডাউনলোড পরিচালনা করা এবং অ্যাসেট অ্যাক্সেস করার জন্য AssetPackManager ক্লাস প্রদান করে। প্রথমে আপনার প্রজেক্টে প্লে অ্যাসেট ডেলিভারি লাইব্রেরিটি যুক্ত করে নিন।
আপনি যে অ্যাসেট প্যাকটি অ্যাক্সেস করতে চান, তার ডেলিভারি টাইপ অনুযায়ী এই API-টি প্রয়োগ করবেন। এই ধাপগুলো নিম্নলিখিত ফ্লোচার্টে দেখানো হয়েছে।

চিত্র ১. অ্যাসেট প্যাক অ্যাক্সেস করার ফ্লো ডায়াগ্রাম
ইনস্টল-টাইম ডেলিভারি
install-time হিসেবে কনফিগার করা অ্যাসেট প্যাকগুলো অ্যাপ চালু হওয়ার সাথে সাথেই উপলব্ধ হয়। এই মোডে পরিবেশিত অ্যাসেটগুলো অ্যাক্সেস করতে জাভা অ্যাসেটম্যানেজার এপিআই (Java AssetManager API) ব্যবহার করুন:
কোটলিন
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")
জাভা
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() মেথড ব্যবহার করুন।
কোটলিন
suspend fun requestPackStates(packNames: List<String>): AssetPackStates
জাভা
Task<AssetPackStates> getPackStates(List<String> packNames)
requestPackStates() হলো একটি সাসপেন্ড ফাংশন যা একটি AssetPackStates অবজেক্ট রিটার্ন করে, অন্যদিকে getPackStates() হলো একটি অ্যাসিঙ্ক্রোনাস মেথড যা একটি Task<AssetPackStates> রিটার্ন করে। একটি AssetPackStates অবজেক্টের packStates() মেথড একটি Map<String, AssetPackState> রিটার্ন করে। এই ম্যাপটিতে অনুরোধ করা প্রতিটি অ্যাসেট প্যাকের অবস্থা থাকে, যা তার নাম দ্বারা কী করা হয়:
কোটলিন
AssetPackStates#packStates(): Map<String, AssetPackState>
জাভা
Map<String, AssetPackState> AssetPackStates#packStates()
চূড়ান্ত অনুরোধটি নিম্নরূপ:
কোটলিন
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) } }
জাভা
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() মেথডটি ব্যবহার করুন, যা AssetPackStatus ক্লাসের একটি কনস্ট্যান্ট ফিল্ডের সাথে সঙ্গতিপূর্ণ একটি ইন্টিজার হিসেবে স্ট্যাটাসটি রিটার্ন করে। যে অ্যাসেট প্যাকটি এখনও ইনস্টল করা হয়নি, তার স্ট্যাটাস হলো AssetPackStatus.NOT_INSTALLED ।
যদি কোনো অনুরোধ ব্যর্থ হয়, তাহলে errorCode() মেথডটি ব্যবহার করুন, যার রিটার্ন ভ্যালুটি AssetPackErrorCode ক্লাসের একটি কনস্ট্যান্ট ফিল্ডের সাথে সঙ্গতিপূর্ণ।
ইনস্টল করুন
প্রথমবার কোনো অ্যাসেট প্যাক ডাউনলোড করতে অথবা অ্যাসেট প্যাকের আপডেট সম্পন্ন করার জন্য requestFetch() বা fetch() মেথড ব্যবহার করুন:
কোটলিন
suspend fun AssetPackManager.requestFetch(packs: List<String>): AssetPackStates
জাভা
Task<AssetPackStates> fetch(List<String> packNames)
এই মেথডটি একটি AssetPackStates অবজেক্ট রিটার্ন করে, যাতে প্যাকগুলোর একটি তালিকা এবং তাদের প্রাথমিক ডাউনলোড অবস্থা ও সাইজ থাকে। যদি requestFetch() বা fetch() এর মাধ্যমে অনুরোধ করা কোনো অ্যাসেট প্যাক আগে থেকেই ডাউনলোড হতে থাকে, তাহলে ডাউনলোডের স্ট্যাটাসটি রিটার্ন করা হয় এবং কোনো অতিরিক্ত ডাউনলোড শুরু করা হয় না।
মনিটর ডাউনলোড অবস্থা
অ্যাসেট প্যাকগুলির ইনস্টলেশনের অগ্রগতি ট্র্যাক করার জন্য আপনার একটি AssetPackStateUpdatedListener ইমপ্লিমেন্ট করা উচিত। প্রতিটি অ্যাসেট প্যাকের স্ট্যাটাস ট্র্যাক করার সুবিধার্থে স্ট্যাটাস আপডেটগুলি প্যাক অনুযায়ী আলাদাভাবে দেখানো হয়। আপনার অনুরোধের জন্য অন্য সব ডাউনলোড সম্পূর্ণ হওয়ার আগেই আপনি উপলব্ধ অ্যাসেট প্যাকগুলি ব্যবহার করা শুরু করতে পারেন।
কোটলিন
fun registerListener(listener: AssetPackStateUpdatedListener) fun unregisterListener(listener: AssetPackStateUpdatedListener)
জাভা
void registerListener(AssetPackStateUpdatedListener listener) void unregisterListener(AssetPackStateUpdatedListener listener)
বড় ডাউনলোড
যদি ডাউনলোডের আকার ২০০ মেগাবাইটের বেশি হয় এবং ব্যবহারকারী ওয়াই-ফাই সংযোগে না থাকেন, তাহলে মোবাইল ডেটা সংযোগ ব্যবহার করে ডাউনলোড চালিয়ে যাওয়ার জন্য ব্যবহারকারী সুস্পষ্টভাবে সম্মতি না দেওয়া পর্যন্ত ডাউনলোড শুরু হয় না। একইভাবে, যদি ডাউনলোডের আকার বড় হয় এবং ব্যবহারকারী ওয়াই-ফাই সংযোগ হারান, তাহলে ডাউনলোডটি থেমে যায় এবং মোবাইল ডেটা সংযোগ ব্যবহার করে ডাউনলোড চালিয়ে যাওয়ার জন্য সুস্পষ্ট সম্মতির প্রয়োজন হয়। একটি থেমে থাকা প্যাকের অবস্থা হলো WAITING_FOR_WIFI । ব্যবহারকারীর কাছে সম্মতির জন্য অনুরোধ জানাতে UI ফ্লোটি চালু করার জন্য showConfirmationDialog() মেথডটি ব্যবহার করুন।
মনে রাখবেন যে, অ্যাপটি যদি এই মেথডটি কল না করে, তাহলে ডাউনলোডটি থেমে যাবে এবং ব্যবহারকারী ওয়াই-ফাই সংযোগে ফিরে এলেই তা স্বয়ংক্রিয়ভাবে পুনরায় শুরু হবে।
ব্যবহারকারীর নিশ্চিতকরণ প্রয়োজন
যদি কোনো প্যাকের স্ট্যাটাস REQUIRES_USER_CONFIRMATION হয়, তাহলে showConfirmationDialog() দিয়ে দেখানো ডায়ালগটি ব্যবহারকারী গ্রহণ না করা পর্যন্ত ডাউনলোড শুরু হবে না। এই স্ট্যাটাসটি তখন হতে পারে যখন অ্যাপটি প্লে (Play) দ্বারা স্বীকৃত হয় না—উদাহরণস্বরূপ, যদি অ্যাপটি সাইড-লোড করা হয়ে থাকে। মনে রাখবেন যে, এই ক্ষেত্রে showConfirmationDialog() কল করলে অ্যাপটি আপডেট হয়ে যাবে। আপডেটের পরে, আপনাকে অ্যাসেটগুলোর জন্য আবার অনুরোধ করতে হবে।
নিম্নলিখিতটি একটি লিসেনারের বাস্তবায়নের উদাহরণ:
কোটলিন
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") } } }
জাভা
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 ডিরেক্টরিতে সংরক্ষিত থাকে। আপনি assetsPath() সুবিধাজনক মেথডটি ব্যবহার করে assets ডিরেক্টরির পাথ পেতে পারেন। কোনো নির্দিষ্ট অ্যাসেটের পাথ পেতে নিম্নলিখিত মেথডটি ব্যবহার করুন:
কোটলিন
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) }
জাভা
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; }
অন্যান্য প্লে অ্যাসেট ডেলিভারি এপিআই পদ্ধতি
নিম্নলিখিতগুলি হল কিছু অতিরিক্ত API পদ্ধতি যা আপনি আপনার অ্যাপে ব্যবহার করতে চাইতে পারেন।
অনুরোধ বাতিল করুন
একটি সক্রিয় অ্যাসেট প্যাক অনুরোধ বাতিল করতে cancel() ব্যবহার করুন। মনে রাখবেন, এই অনুরোধটি একটি বেস্ট-এফোর্ট অপারেশন।
একটি অ্যাসেট প্যাক সরান
কোনো অ্যাসেট প্যাক অপসারণের সময় নির্ধারণ করতে requestRemovePack() বা removePack() ব্যবহার করুন।
একাধিক অ্যাসেট প্যাকের অবস্থান জানুন
একসাথে একাধিক অ্যাসেট প্যাকের অবস্থা জানতে getPackLocations() ব্যবহার করুন, যা অ্যাসেট প্যাক এবং তাদের অবস্থানের একটি মানচিত্র ফেরত দেয়। getPackLocations() দ্বারা ফেরত আসা মানচিত্রটিতে বর্তমানে ডাউনলোড করা এবং হালনাগাদ থাকা প্রতিটি প্যাকের জন্য একটি করে এন্ট্রি থাকে।
পরবর্তী পদক্ষেপ
স্থানীয়ভাবে এবং গুগল প্লে থেকে অ্যাসেট ডেলিভারি টেস্ট প্লে করুন ।