অ্যাসেট ডেলিভারি ইন্টিগ্রেট করা (Kotlin এবং Java)

আপনার Java কোড থেকে অ্যাপের অ্যাসেট প্যাক অ্যাক্সেস করতে এই গাইডের ধাপগুলি অনুসরণ করুন।

Kotlin ও Java-এর জন্য তৈরি করুন

আপনার প্রোজেক্টের Android App Bundle-এ Play Asset Delivery তৈরি করতে নিম্নলিখিত ধাপগুলি অনুসরণ করুন। এইসব ধাপ সম্পূর্ণ করার জন্য আপনাকে Android Studio ব্যবহার করতে হবে না।

  1. আপনার প্রোজেক্টের build.gradle ফাইলে Android Gradle প্লাগ-ইনের ভার্সন আপডেট করে 4.0.0 বা তার পরবর্তী ভার্সন করুন।

  2. আপনার প্রোজেক্টের টপ-লেভেল ডিরেক্টরিতে, অ্যাসেট প্যাকের জন্য একটি ডিরেক্টরি তৈরি করুন। এই ডিরেক্টরির নাম অ্যাসেট প্যাকের নাম হিসেবে ব্যবহার করা হয়। অ্যাসেট প্যাকের নাম অবশ্যই কোনও অক্ষর দিয়ে শুরু হতে হবে এবং এতে শুধু অক্ষর, সংখ্যা ও আন্ডারস্কোর থাকতে পারে।

  3. অ্যাসেট প্যাক ডিরেক্টরিতে, একটি 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 ]")
      }
    }
  4. প্রোজেক্টের অ্যাপ 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")
    }
  5. প্রোজেক্টের 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")
  6. অ্যাসেট প্যাক ডিরেক্টরিতে, নিম্নলিখিত সাবডিরেক্টরি তৈরি করুন: src/main/assets।

  7. src/main/assets ডিরেক্টরিতে অ্যাসেট রাখুন। আপনি এখানেও সাবডিরেক্টরি তৈরি করতে পারবেন। আপনার অ্যাপের ডিরেক্টরি স্ট্রাকচার এখন নিম্নলিখিতটির মতো দেখতে হওয়া উচিত:

    • build.gradle
    • settings.gradle
    • app/
    • asset-pack-name/build.gradle
    • asset-pack-name/src/main/assets/your-asset-directories
  8. Gradle-এর সাহায্যে Android অ্যাপ বান্ডেল তৈরি করুন। জেনারেট করা অ্যাপ বান্ডেলে, রুট-লেভেল ডিরেক্টরিতে এখন নিম্নলিখিতগুলি অন্তর্ভুক্ত থাকে:

    • asset-pack-name/manifest/AndroidManifest.xml: অ্যাসেট প্যাকের শনাক্তকারী এবং ডেলিভারি মোড কনফিগার করে
    • asset-pack-name/assets/your-asset-directories: অ্যাসেট প্যাকের অংশ হিসেবে ডেলিভার করা সব অ্যাসেট যে ডিরেক্টরিতে থাকে

    Gradle প্রতিটি অ্যাসেট প্যাকের জন্য ম্যানিফেস্ট তৈরি করে এবং আপনার জন্য assets/ ডিরেক্টরি আউটপুট করে।

  9. (ঐচ্ছিক) আপনি যদি ফাস্ট-ফলো এবং অন-ডিমান্ড ডেলিভারি ব্যবহার করার পরিকল্পনা করেন, তাহলে 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")

  10. (ঐচ্ছিক) বিভিন্ন টেক্সচার কম্প্রেশন ফর্ম্যাট সাপোর্ট করার জন্য আপনার অ্যাপ বান্ডেল কনফিগার করুন।

Play Asset Delivery API-এর সাথে ইন্টিগ্রেট করা

Play Asset Delivery Java API অ্যাসেট প্যাকের অনুরোধ, ডাউনলোড ম্যানেজ ও অ্যাসেট অ্যাক্সেস করার জন্য AssetPackManager ক্লাস প্রদান করে। প্রথমে আপনার প্রোজেক্টে Play Asset Delivery লাইব্রেরি যোগ করতে ভুলবেন না।

আপনি যে অ্যাসেট প্যাক অ্যাক্সেস করতে চান, তার ডেলিভারির ধরন অনুযায়ী এই API প্রয়োগ করতে হবে। এইসব ধাপ নিচের ফ্লোচার্টে দেখানো হয়েছে।

Java প্রোগ্রামিং ল্যাঙ্গুয়েজের জন্য অ্যাসেট প্যাক ফ্লো ডায়াগ্রাম

ছবি ১. অ্যাসেট প্যাক অ্যাক্সেস করার জন্য ফ্লো ডায়াগ্রাম

ইনস্টল-টাইম ডেলিভারি

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")

জাভা

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

জাভা

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

requestPackStates() হল একটি সাসপেন্ড ফাংশন যা একটি AssetPackStates অবজেক্ট রিটার্ন করে, যেখানে getPackStates() হল একটি অ্যাসিঙ্ক্রোনাস পদ্ধতি যা একটি Task<AssetPackStates> রিটার্ন করে। AssetPackStates অবজেক্টের packStates() পদ্ধতি Map<String, AssetPackState> রিটার্ন করে। এই ম্যাপে প্রতিটি অনুরোধ করা অ্যাসেট প্যাকের স্ট্যাটাস আছে, যা এর নাম দ্বারা চিহ্নিত করা হয়েছে:

Kotlin

AssetPackStates#packStates(): Map<String, AssetPackState>

জাভা

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)
  }
}

জাভা

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() পদ্ধতি ব্যবহার করুন:

Kotlin

suspend fun AssetPackManager.requestFetch(packs: List<String>): AssetPackStates

জাভা

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

এই পদ্ধতিটি একটি AssetPackStates অবজেক্ট রিটার্ন করে যাতে প্যাকের তালিকা এবং তাদের প্রাথমিক ডাউনলোড স্ট্যাটাস এবং সাইজ থাকে। requestFetch() বা fetch()-এর মাধ্যমে অনুরোধ করা কোনও অ্যাসেট প্যাক আগে থেকেই ডাউনলোড করা হতে থাকলে, ডাউনলোডের স্ট্যাটাস দেখানো হয় এবং অতিরিক্ত কোনও ডাউনলোড শুরু করা হয় না।

ডাউনলোডের স্ট্যাটাস মনিটর করা

অ্যাসেট প্যাকের ইনস্টলেশন প্রোগ্রেস ট্র্যাক করতে আপনাকে AssetPackStateUpdatedListener প্রয়োগ করতে হবে। প্রতিটি অ্যাসেট প্যাকের স্ট্যাটাস ট্র্যাক করার জন্য স্ট্যাটাস আপডেটকে প্যাক অনুযায়ী ভাগ করা হয়। আপনার অনুরোধের জন্য অন্যান্য সব ডাউনলোড সম্পূর্ণ হওয়ার আগে আপনি উপলভ্য অ্যাসেট প্যাক ব্যবহার করা শুরু করতে পারেন।

Kotlin

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() কল করলে অ্যাপ আপডেট হয়ে যাবে। আপডেট করার পরে, আপনাকে আবার অ্যাসেটের জন্য অনুরোধ করতে হবে।

নিচে লিসনার প্রয়োগের একটি উদাহরণ দেওয়া হল:

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")
    }
  }
}

জাভা

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 ডিরেক্টরির পাথ পেতে পারেন। নির্দিষ্ট অ্যাসেটের পাথ পেতে নিম্নলিখিত পদ্ধতি ব্যবহার করুন:

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)
}

জাভা

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()-এর মাধ্যমে ফেরত পাঠানো ম্যাপে বর্তমানে ডাউনলোড করা এবং আপ-টু-ডেট থাকা প্রতিটি প্যাকের জন্য একটি এন্ট্রি থাকে।

পরবর্তী ধাপ

স্থানীয়ভাবে এবং Google Play থেকে Play Asset Delivery টেস্ট করুন।