ऐसेट डिलीवरी को इंटिग्रेट करना (Kotlin और Java)

अपने Java कोड से, अपने ऐप्लिकेशन के ऐसेट पैक ऐक्सेस करने के लिए, इस गाइड में दिया गया तरीका अपनाएं.

Kotlin और Java के लिए बिल्ड करना

अपने प्रोजेक्ट के Android ऐप्लिकेशन बंडल में, Play ऐसेट डिलीवरी को शामिल करने के लिए, यह तरीका अपनाएं. इसके लिए, आपको 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 ऐसेट डिलीवरी लाइब्रेरी को शामिल करें

    शानदार

    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 ऐसेट डिलीवरी एपीआई के साथ इंटिग्रेट करना

Play ऐसेट डिलीवरी Java API ऐसेट पैक का अनुरोध करने, डाउनलोड मैनेज करने, और ऐसेट ऐक्सेस करने के लिए, AssetPackManager क्लास उपलब्ध कराता है. सबसे पहले, अपने प्रोजेक्ट में Play ऐसेट डिलीवरी लाइब्रेरी जोड़ें.

इस एपीआई को, उस ऐसेट पैक के डिलीवरी टाइप के हिसाब से लागू करें जिसे आपको ऐक्सेस करना है. यह तरीका, यहां दिए गए फ़्लोचार्ट में दिखाया गया है.

install-time

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

Java

import android.content.res.AssetManager;
...
Context context = createPackageContext("com.example.app", 0);
AssetManager assetManager = context.getAssets();
InputStream is = assetManager.open("asset-name");

फ़ास्ट-फ़ॉलो और ऑन-डिमांड डिलीवरी

यहां दिए गए सेक्शन में, ऐसेट पैक डाउनलोड करने से पहले उनकी जानकारी पाने, डाउनलोड शुरू करने के लिए एपीआई को कॉल करने, और डाउनलोड किए गए पैक को ऐक्सेस करने का तरीका बताया गया है. ये सेक्शन, 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;
            })

The following AssetPackState तरीके, ऐसेट पैक का साइज़, अब तक डाउनलोड की गई मात्रा (अगर अनुरोध किया गया है), और ऐप्लिकेशन में पहले से ट्रांसफ़र की गई मात्रा की जानकारी देते हैं:

किसी ऐसेट पैक का स्टेटस पाने के लिए, 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)

बड़े डाउनलोड

अगर डाउनलोड का साइज़ 200 एमबी से ज़्यादा है और उपयोगकर्ता वाई-फ़ाई से कनेक्ट नहीं है, तो डाउनलोड तब तक शुरू नहीं होता, जब तक उपयोगकर्ता मोबाइल डेटा कनेक्शन का इस्तेमाल करके डाउनलोड जारी रखने के लिए साफ़ तौर पर अपनी सहमति नहीं देता. इसी तरह, अगर डाउनलोड का साइज़ बड़ा है और उपयोगकर्ता का वाई-फ़ाई कनेक्शन टूट जाता है, तो डाउनलोड रुक जाता है. साथ ही, मोबाइल डेटा कनेक्शन का इस्तेमाल करके डाउनलोड जारी रखने के लिए, साफ़ तौर पर सहमति की ज़रूरत होती है. रोके गए पैक का स्टेटस, WAITING_FOR_WIFI होता है. उपयोगकर्ता से सहमति लेने के लिए, यूज़र इंटरफ़ेस (यूआई) फ़्लो को ट्रिगर करने के लिए, 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")
    }
  }
}

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 डायरेक्ट्री का पाथ पाने के लिए, सुविधा के तौर पर उपलब्ध तरीके 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 ऐसेट डिलीवरी एपीआई के अन्य तरीके

यहां कुछ अन्य एपीआई तरीके दिए गए हैं जिनका इस्तेमाल, अपने ऐप्लिकेशन में किया जा सकता है.

अनुरोध रद्द करें

चालू ऐसेट पैक के अनुरोध को रद्द करने के लिए, cancel() का इस्तेमाल करें. ध्यान दें कि यह अनुरोध, सबसे बेहतर कोशिश के तौर पर किया जाता है.

कोई ऐसेट पैक हटाना

किसी ऐसेट पैक को हटाने के लिए, requestRemovePack() या removePack() का इस्तेमाल करें.

एक से ज़्यादा ऐसेट पैक की जगहें पाना

एक साथ कई ऐसेट पैक के स्टेटस की क्वेरी करने के लिए, getPackLocations() का इस्तेमाल करें. इससे ऐसेट पैक और उनकी जगहों का मैप मिलता है. getPackLocations() से मिलने वाले मैप में, फ़िलहाल डाउनलोड किए गए और अप-टू-डेट हर पैक के लिए एक एंट्री होती है.

अगला चरण

Play ऐसेट डिलीवरी की जांच, स्थानीय तौर पर और Google Play से करें.