Uygulamanızın öğe paketlerine Java kodunuzdan erişmek için bu kılavuzdaki adımları uygulayın.
Kotlin ve Java için derleme
Play Asset Delivery'yi projenizin Android App Bundle'ına eklemek için aşağıdaki adımları uygulayın. Bu adımları gerçekleştirmek için Android Studio'yu kullanmanız gerekmez.
Projenizin
build.gradledosyasındaki Android Gradle eklentisinin sürümünü4.0.0veya sonraki bir sürüme güncelleyin.Projenizin üst düzey dizininde öğe paketi için bir dizin oluşturun. Bu dizin adı, öğe paketi adı olarak kullanılır. Öğe paketi adları bir harfle başlamalı ve yalnızca harf, rakam ve alt çizgi içermelidir.
Öğe paketi dizininde bir
build.gradledosyası oluşturun ve aşağıdaki kodu ekleyin. Öğe paketinin adını ve yalnızca bir yayınlama türü belirttiğinizden emin olun:Modern
// 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 ]") } }
Projenin uygulama
build.gradledosyasında, projenizdeki her öğe paketinin adını aşağıda gösterildiği gibi ekleyin:Modern
// 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") }
Projenin
settings.gradledosyasında, projenizdeki tüm öğe paketlerini aşağıda gösterildiği gibi ekleyin:Modern
// 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")
Öğe paketi dizininde şu alt dizini oluşturun:
src/main/assets.Öğeleri
src/main/assetsdizinine yerleştirin. Burada alt dizinler de oluşturabilirsiniz. Uygulamanızın dizin yapısı artık aşağıdaki gibi görünmelidir:build.gradlesettings.gradleapp/asset-pack-name/build.gradleasset-pack-name/src/main/assets/your-asset-directories
Android App Bundle'ı Gradle ile derleyin. 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 paketinin bir parçası olarak yayınlanan tüm öğeleri içeren dizin
Gradle, her öğe paketi için manifest oluşturur ve
assets/dizinini sizin için çıkarır.(İsteğe bağlı) Hızlı takip ve isteğe bağlı yayınlama özelliklerini kullanmayı planlıyorsanız Play Asset Delivery Kitaplığı'nı ekleyin.
Modern
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")
(İsteğe bağlı) Uygulama paketinizi farklı doku sıkıştırma biçimlerini destekleyecek şekilde yapılandırın.
Play Asset Delivery API ile entegrasyon
Play Asset Delivery Java API, öğ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österilmiştir.
Şekil 1. Öğe paketlerine erişim için akış şeması
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ı teslimat
Aşağıdaki bölümlerde, öğe paketlerini indirmeden önce bunlar hakkında nasıl bilgi alacağınız, indirme işlemini 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 kontrol et
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ü, assetsPath() adresinde hemen erişime hazır. |
null |
Bilinmeyen öğe paketi veya öğeler kullanılamıyor |
Öğe paketleriyle ilgili indirme bilgilerini alma
Uygulamaların, öğe paketini getirmeden önce indirme boyutunu açıklaması gerekir. İndirme boyutunu ve paketin 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, bir Map<String,
AssetPackState> döndürür. Bu harita, istenen her öğe paketinin durumunu içerir ve adı anahtar olarak kullanılır:
Kotlin
AssetPackStates#packStates(): Map<String, AssetPackState>
Java
Map<String, AssetPackState> AssetPackStates#packStates()
Nihai istek aşağıdaki gibi görünür:
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öntemleri, öğe paketinin boyutunu, şu ana kadar indirilen miktarı (istenirse) ve uygulamaya aktarılmış olan miktarı sağlar:
Bir öğe paketinin durumunu öğrenmek için status() yöntemini kullanın. Bu yöntem, durumu AssetPackStatus sınıfındaki sabit bir alana karşılık gelen 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 bir öğe paketinin güncellemesini tamamlamak için requestFetch() veya 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 ve ilk indirme durumları ile boyutlarını içeren bir AssetPackStates nesnesi döndürür.
requestFetch() veya fetch() aracılığıyla istenen bir öğe paketi zaten indiriliyorsa indirme durumu döndürülür ve ek indirme başlatılmaz.
İndirme durumlarını izleme
Öğe paketlerinin yükleme ilerleme durumunu izlemek için bir AssetPackStateUpdatedListener uygulamanız gerekir. Durum güncellemeleri, her bir öğe paketinin durumunun takip edilmesini desteklemek için paketlere göre ayrılır. İsteğinizle ilgili diğer tüm indirme işlemleri tamamlanmadan önce mevcut öğ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 ağa bağlı değilse indirme işlemi, kullanıcı mobil veri bağlantısı kullanarak indirme işlemine devam etmek için açıkça izin verene kadar başlamaz. Benzer şekilde, indirme işlemi büyükse ve kullanıcının kablosuz bağlantısı kesilirse indirme işlemi duraklatılır ve mobil veri bağlantısı kullanılarak devam etmek için açık izin gerekir. Duraklatılmış bir paketin durumu WAITING_FOR_WIFI olur. Kullanıcıdan izin istemek üzere kullanıcı arayüzü akışını tetiklemek için showConfirmationDialog() yöntemini kullanın.
Uygulama bu yöntemi çağırmazsa indirme işlemi duraklatılır ve yalnızca kullanıcı tekrar kablosuz bağlantıya geçtiğinde otomatik olarak devam eder.
Kullanıcı onayı gereklidir
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 Google Play tarafından tanınmadığında (ör. uygulama başka cihazdan yüklendiyse) ortaya çıkabilir.
Bu durumda showConfirmationDialog() yöntemini çağırmanın uygulamanın güncellenmesine neden olacağını unutmayın. Güncellemeden sonra öğeleri
tekrar istemeniz gerekir.
Aşağıda, dinleyici uygulamasına dair bir örnek 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 indirme işlemlerinin durumunu öğrenmek için
getPackStates()
yöntemini kullanabilirsiniz.
AssetPackStates
indirme işleminin ilerleme durumunu, indirme durumunu ve tüm 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 öğ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 depolanır. assetsPath() kolaylık yöntemini kullanarak assets dizininin yolunu 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
Aşağıda, uygulamanızda kullanmak isteyebileceğiniz bazı ek API yöntemleri verilmiştir.
İsteği iptal et
Etkin bir öğe paketi isteğini iptal etmek için
cancel()
kullanın. Bu isteğin, en iyi çaba ilkesine göre 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 konumunu alma
Birden fazla öğe paketinin durumunu toplu olarak sorgulamak için getPackLocations() yöntemini kullanın. Bu yöntem, öğ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.