Öğe teslimini entegre etme (Kotlin ve Java)

Uygulamanızın öğe paketlerine Java kodunuzdan erişmek için bu kılavuzdaki adımları uygulayın.

Kotlin ve Java için geliştirme

Play Asset Delivery'yi projenizin Android App Bundle'ına entegre etmek için aşağıdaki adımları uygulayın. Bu adımları uygulamak için Android Studio'yu kullanmanız gerekmez.

  1. Projenizin build.gradle dosyasındaki Android Gradle eklentisinin sürümünü 4.0.0 veya sonraki bir sürüme güncelleyin.

  2. Projenizin en üst düzey dizininde, varlık paketi için bir dizin oluşturun. Bu dizin adı, öğe paketi adı olarak kullanılır. Öğe paketi adları harfle başlamalıdır ve yalnızca harf, rakam ve alt çizgi içerebilir.

  3. Öğe paketi dizininde bir build.gradle dosyası oluşturun ve aşağıdaki kodu ekleyin. Öğe paketinin adını ve yalnızca bir teslimat türünü belirttiğinizden emin olun:

    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 ]")
      }
    }
  4. Projenin uygulama build.gradle dosyasında, projenizdeki her bir öğe paketinin adını aşağıdaki örnekte gösterildiği gibi ekleyin:

    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")
    }
  5. Projenin settings.gradle dosyasında, aşağıdaki örnekte gösterildiği gibi projenizdeki tüm öğe paketlerini ekleyin:

    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")
  6. Öğe paketi dizininde aşağıdaki alt dizini oluşturun: src/main/assets.

  7. Öğeleri src/main/assets dizinine yerleştirin. Burada alt dizinler de oluşturabilirsiniz. Uygulamanızın dizin yapısı artık aşağıdaki gibi görünmelidir:

    • build.gradle
    • settings.gradle
    • app/
    • asset-pack-name/build.gradle
    • asset-pack-name/src/main/assets/your-asset-directories
  8. Gradle ile Android App Bundle'ı oluşturun. Oluşturulan uygulama paketinde, kök düzeyindeki dizin artık şunları içerir:

    • asset-pack-name/manifest/AndroidManifest.xml: Öğe paketinin tanımlayıcısını ve yayınlama modunu yapılandırır.
    • asset-pack-name/assets/your-asset-directories: Öğe paketi kapsamında sunulan tüm öğeleri içeren dizin

    Gradle, her bir öğe paketi için manifest oluşturur ve assets/ dizini sizin için çıkarır.

  9. (İsteğe bağlı) Hızlı takip ve isteğe bağlı yayınlama kullanmayı planlıyorsanız Play Asset Delivery Kitaplığı'nı ekleyin.

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

  10. (İsteğe bağlı) Uygulama paketinizi farklı doku sıkıştırma biçimlerini destekleyecek şekilde yapılandırın.

başlıklı makaleyi inceleyin.

Play Asset Delivery API ile entegrasyon

Play Asset Delivery Java API'si, öğe paketlerini istemek, indirmeleri yönetmek ve öğelere erişmek için AssetPackManager sınıfını sağlar. Öncelikle projenize Play Asset Delivery kitaplığını eklediğinizden emin olun.

Bu API'yi, erişmek istediğiniz öğe paketinin yayınlama türüne göre uygularsınız. Bu adımlar aşağıdaki akış şemasında gösterilmektedir.

Java programlama dili için öğe paketi akış şeması

1.şekil Öğe paketlerine erişim akış diyagramı

Yükleme sırasında yayınlama

install-time olarak yapılandırılan öğe paketleri, uygulama başlatıldığında hemen kullanılabilir. Bu modda sunulan öğelere erişmek için Java AssetManager API'yi kullanın:

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

Hızlı takip ve isteğe bağlı yayın

Aşağıdaki bölümlerde, indirmeden önce öğe paketleri hakkında nasıl bilgi alacağınız, indirmeyi başlatmak için API'yi nasıl çağıracağınız ve ardından indirilen paketlere nasıl erişeceğiniz gösterilmektedir. Bu bölümler fast-follow ve on-demand öğe paketleri için geçerlidir.

Durumu denetle

Her öğe paketi, uygulamanın dahili depolama alanında ayrı bir klasörde saklanır. Bir öğe paketinin kök klasörünü belirlemek için getPackLocation() yöntemini kullanın. Bu yöntem aşağıdaki değerleri döndürür:

Döndürülen değer Durum
Geçerli bir AssetPackLocation nesnesi Öğe paketi kök klasörüne assetsPath() adresinden hemen erişebilirsiniz.
null Bilinmeyen öğe paketi veya öğeler kullanılamıyor

Öğe paketleri hakkında indirme bilgilerini alma

Uygulamalar, öğe paketini getirmeden önce indirme boyutunu belirtmelidir. İndirmenin boyutunu ve paketin zaten indirilip indirilmediğini belirlemek için requestPackStates() veya getPackStates() yöntemini kullanın.

Kotlin

suspend fun requestPackStates(packNames: List<String>): AssetPackStates

Java

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

requestPackStates(), AssetPackStates nesnesi döndüren bir askıya alma işlevidir. getPackStates() ise Task<AssetPackStates> döndüren eşzamansız bir yöntemdir. Bir AssetPackStates nesnesinin packStates() yöntemi Map<String, AssetPackState> döndürür. Bu harita, istenen her varlık paketinin durumunu içerir. Durumlar, adlarına göre anahtarlanır:

Kotlin

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

Java

Map<String, AssetPackState> AssetPackStates#packStates()

Son istek aşağıdakilerle gösterilir:

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

Aşağıdaki AssetPackState yöntemler, öğe paketinin boyutunu, şu ana kadar indirilen miktarı (istenirse) ve uygulamaya aktarılan miktarı sağlar:

Bir öğe paketinin durumunu almak için status() yöntemini kullanın. Bu yöntem, durumu AssetPackStatus sınıfındaki sabit bir alana karşılık gelen bir tam sayı olarak döndürür. Henüz yüklenmemiş bir öğe paketinin durumu AssetPackStatus.NOT_INSTALLED olur.

Bir istek başarısız olursa dönüş değeri AssetPackErrorCode sınıfındaki sabit bir alana karşılık gelen errorCode() yöntemini kullanın.

Yükle

Bir öğe paketini ilk kez indirmek veya tamamlamak için bir öğe paketinin güncellenmesini istemek üzere requestFetch() ya da fetch() yöntemini kullanın:

Kotlin

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

Java

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

Bu yöntem, paketlerin listesini, ilk indirme durumlarını ve boyutlarını içeren bir AssetPackStates nesnesi döndürür. requestFetch() veya fetch() üzerinden istenen bir öğe paketi zaten indiriliyorsa indirme durumu döndürülür ve ek indirme işlemi başlatılmaz.

İndirme durumlarını izleme

Öğe paketlerinin yükleme ilerleme durumunu izlemek için bir AssetPackStateUpdatedListener uygulamanız gerekir. Durum güncellemeleri, bağımsız öğe paketlerinin durumunu izlemeyi desteklemek için paket bazında ayrıştırılır. İsteğinizle ilgili diğer tüm indirme işlemleri tamamlanmadan önce kullanılabilir öğe paketlerini kullanmaya başlayabilirsiniz.

Kotlin

fun registerListener(listener: AssetPackStateUpdatedListener)
fun unregisterListener(listener: AssetPackStateUpdatedListener)

Java

void registerListener(AssetPackStateUpdatedListener listener)
void unregisterListener(AssetPackStateUpdatedListener listener)

Büyük boyutlu indirmeler

İndirme işlemi 200 MB'tan büyükse ve kullanıcı kablosuz bağlantıya bağlı değilse indirme işlemi, kullanıcının mobil veri bağlantısı kullanarak indirme işlemine devam etme izni açıkça verilene kadar başlamaz. Benzer şekilde, indirme işlemi büyükse ve kullanıcı kablosuz bağlantısını kaybederse indirme işlemi duraklatılır ve mobil veri bağlantısı kullanılarak devam edilmesi için açık rıza gerekir. Duraklatılmış bir paketin durumu WAITING_FOR_WIFI olur. Kullanıcıdan izin istemek için kullanıcı arayüzü akışını tetiklemek üzere showConfirmationDialog() yöntemini kullanın.

Uygulama bu yöntemi çağırmazsa indirme işleminin duraklatılacağını ve yalnızca kullanıcı tekrar kablosuz bağlantıya döndüğünde otomatik olarak devam edeceğini unutmayın.

Kullanıcı onayı gerekiyor

Bir paketin durumu REQUIRES_USER_CONFIRMATION ise kullanıcı showConfirmationDialog() ile gösterilen iletişim kutusunu kabul edene kadar indirme işlemi devam etmez. Bu durum, uygulama Play tarafından tanınmadığında (ör. uygulama başka kaynaktan yüklendiyse) ortaya çıkabilir. Bu durumda arama yapmanın showConfirmationDialog() uygulamanın güncellenmesine neden olacağını unutmayın. Güncellemeden sonra öğeleri tekrar istemeniz gerekir.

Aşağıda, bir işleyicinin örnek uygulaması verilmiştir:

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

Alternatif olarak, mevcut indirmelerin durumunu almak için getPackStates() yöntemini kullanabilirsiniz. AssetPackStates İndirme ilerleme durumu, indirme durumu ve başarısızlık hata kodlarını içerir.

Öğe paketlerine erişme

İndirme isteği COMPLETED durumuna ulaştıktan sonra dosya sistemi çağrılarını kullanarak bir öğe paketine erişebilirsiniz. Öğe paketinin kök klasörünü almak için getPackLocation() yöntemini kullanın.

Öğeler, öğe paketi kök dizinindeki assets dizininde saklanır. assets dizininin yolunu assetsPath() kolaylık yöntemini kullanarak alabilirsiniz. Belirli bir öğenin yolunu almak için aşağıdaki yöntemi kullanın:

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

Diğer Play Asset Delivery API yöntemleri

Uygulamanızda kullanmak isteyebileceğiniz bazı ek API yöntemlerini aşağıda bulabilirsiniz.

İsteği iptal et

Etkin bir öğe paketi isteğini iptal etmek için cancel() simgesini kullanın. Bu isteğin, mümkün olan en iyi şekilde gerçekleştirilen bir işlem olduğunu unutmayın.

Öğe paketini kaldırma

Bir öğe paketinin kaldırılmasını planlamak için requestRemovePack() veya removePack() kullanın.

Birden fazla öğe paketinin konumlarını alma

Birden fazla öğe paketinin durumunu toplu olarak sorgulamak için getPackLocations() komutunu kullanın. Bu komut, öğe paketlerinin ve konumlarının haritasını döndürür. getPackLocations() tarafından döndürülen harita, şu anda indirilmiş ve güncel olan her paket için bir giriş içerir.

Sonraki adım

Play Asset Delivery'yi yerel olarak ve Google Play'den test edin.