Aby uzyskać dostęp do pakietów zasobów aplikacji z poziomu kodu w Javie, wykonaj czynności opisane w tym przewodniku.
Tworzenie aplikacji w językach Kotlin i Java
Aby włączyć dostarczanie zasobów Play do pakietu aplikacji na Androida w projekcie, wykonaj te czynności. Aby wykonać te czynności, nie musisz używać Androida Studio.
Zaktualizuj wersję wtyczki Androida do obsługi Gradle w pliku
build.gradle
projektu do wersji4.0.0
lub nowszej.W katalogu najwyższego poziomu projektu utwórz katalog pakietu zasobów. Nazwa tego katalogu jest używana jako nazwa pakietu zasobów. Nazwy pakietów zasobów muszą zaczynać się od litery i mogą zawierać tylko litery, cyfry i podkreślenia.
W katalogu pakietu zasobów utwórz plik
build.gradle
i dodaj ten kod: Podaj nazwę pakietu komponentów i tylko jeden typ dostawy: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 ]") } }
W pliku aplikacji projektu
build.gradle
dodaj nazwę każdego pakietu zasobów w projekcie, jak pokazano poniżej: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") }
W pliku
settings.gradle
projektu umieść wszystkie pakiety komponentów w projekcie, jak pokazano poniżej: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")
W katalogu pakietu komponentów utwórz ten podkatalog:
src/main/assets
Umieść zasoby w katalogu
src/main/assets
. Możesz tu też tworzyć podkatalogi. Struktura katalogów aplikacji powinna teraz wyglądać tak:build.gradle
settings.gradle
app/
asset-pack-name/build.gradle
asset-pack-name/src/main/assets/your-asset-directories
Utwórz pakiet Android App Bundle za pomocą Gradle W wygenerowanym pakiecie aplikacji katalog najwyższego poziomu zawiera teraz te elementy:
asset-pack-name/manifest/AndroidManifest.xml
: Konfiguruje identyfikator pakietu zasobów i tryb dostarczania.asset-pack-name/assets/your-asset-directories
: Katalog zawierający wszystkie komponenty dostarczone w ramach pakietu komponentów
Gradle generuje plik manifestu dla każdego pakietu zasobów i tworzy dla Ciebie katalog
assets/
.(Opcjonalnie) Jeśli planujesz korzystać z szybkiego wdrażania i dostarczania na żądanie, dodaj Play Asset Delivery Library.
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")
(Opcjonalnie) Skonfiguruj pakiet aplikacji tak, aby obsługiwał różne formaty kompresji tekstur.
Integracja z interfejsem Play Asset Delivery API
Interfejs Play Asset Delivery Java API
zawiera klasę
AssetPackManager
do wysyłania żądań dotyczących pakietów zasobów, zarządzania pobieraniem i uzyskiwania dostępu do zasobów. Najpierw dodaj do projektu bibliotekę Play Asset Delivery.
Ten interfejs API wdrażasz zgodnie z typem dostawy pakietu zasobów, do którego chcesz uzyskać dostęp. Te kroki przedstawia poniższy schemat blokowy.
Rysunek 1. Schemat blokowy dostępu do pakietów komponentów
Przesyłanie podczas instalacji
Pakiety zasobów skonfigurowane jako install-time
są dostępne natychmiast po uruchomieniu aplikacji. Aby uzyskać dostęp do komponentów wyświetlanych w tym trybie, użyj interfejsu AssetManager API w języku Java:
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");
Szybkie i na żądanie przesyłanie
W sekcjach poniżej znajdziesz informacje o tym, jak uzyskać informacje o pakietach zasobów przed ich pobraniem, jak wywołać interfejs API, aby rozpocząć pobieranie, a następnie jak uzyskać dostęp do pobranych pakietów. Te sekcje dotyczą pakietów zasobów fast-follow
i on-demand
.
Sprawdź stan
Każdy pakiet zasobów jest przechowywany w osobnym folderze w pamięci wewnętrznej aplikacji.
Użyj metody getPackLocation()
, aby określić folder główny pakietu zasobów. Ta metoda zwraca te wartości:
Zwracana wartość | Stan |
---|---|
prawidłowy obiekt AssetPackLocation , |
Folder główny pakietu komponentów jest gotowy do natychmiastowego dostępu pod adresem assetsPath() |
null |
Nieznany pakiet komponentów lub komponenty są niedostępne |
Pobieranie informacji o pobranych pakietach zasobów
Aplikacje muszą podać rozmiar pobieranego pakietu zasobów przed jego pobraniem. Użyj metody requestPackStates()
lub getPackStates()
, aby określić rozmiar pobieranego pakietu i sprawdzić, czy jest on już pobierany.
Kotlin
suspend fun requestPackStates(packNames: List<String>): AssetPackStates
Java
Task<AssetPackStates> getPackStates(List<String> packNames)
requestPackStates()
to funkcja zawieszająca, która zwraca obiekt AssetPackStates
, a getPackStates()
to metoda asynchroniczna, która zwraca Task<AssetPackStates>
. Metoda packStates()
obiektu AssetPackStates
zwraca Map<String,
AssetPackState>
. Ta mapa zawiera stan każdego żądanego pakietu zasobów, z którego kluczem jest jego nazwa:
Kotlin
AssetPackStates#packStates(): Map<String, AssetPackState>
Java
Map<String, AssetPackState> AssetPackStates#packStates()
Ostateczne żądanie wygląda tak:
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; })
Te metodyAssetPackState
podają rozmiar pakietu zasobów, pobraną do tej pory ilość (jeśli jest wymagana) i ilość już przesłaną do aplikacji:
Aby uzyskać stan pakietu komponentów, użyj metody status()
, która zwraca stan jako liczbę całkowitą odpowiadającą stałemu polu w klasie AssetPackStatus
. Pakiet zasobów, który nie jest jeszcze zainstalowany, ma stanAssetPackStatus.NOT_INSTALLED
.
Jeśli żądanie się nie powiedzie, użyj metody
errorCode()
, której wartość zwracana odpowiada stałemu polu w klasie
AssetPackErrorCode
.
Zainstaluj
Aby pobrać pakiet zasobów po raz pierwszy lub wywołać aktualizację pakietu zasobów, użyj metody requestFetch()
lub fetch()
:
Kotlin
suspend fun AssetPackManager.requestFetch(packs: List<String>): AssetPackStates
Java
Task<AssetPackStates> fetch(List<String> packNames)
Ta metoda zwraca obiekt AssetPackStates
zawierający listę pakietów oraz ich początkowe stany pobierania i rozmiary.
Jeśli pakiet zasobów zażądany za pomocą funkcji requestFetch()
lub fetch()
jest już pobierany, zwracany jest stan pobierania i nie rozpoczyna się żadne dodatkowe pobieranie.
Monitorowanie stanów pobierania
Aby śledzić postęp instalacji pakietów komponentów, zaimplementuj AssetPackStateUpdatedListener
. Aktualizacje stanu są podzielone na pakiety, aby można było śledzić stan poszczególnych pakietów zasobów. Możesz zacząć korzystać z dostępnych pakietów komponentów, zanim zostaną ukończone wszystkie inne pobierania związane z Twoją prośbą.
Kotlin
fun registerListener(listener: AssetPackStateUpdatedListener) fun unregisterListener(listener: AssetPackStateUpdatedListener)
Java
void registerListener(AssetPackStateUpdatedListener listener) void unregisterListener(AssetPackStateUpdatedListener listener)
Pobieranie dużych plików
Jeśli pobieranie przekracza 200 MB, a użytkownik nie korzysta z Wi-Fi, pobieranie nie rozpocznie się, dopóki użytkownik nie wyrazi wyraźnej zgody na pobieranie przy użyciu komórkowego połączenia transmisji danych. Podobnie jeśli pobieranie jest duże, a użytkownik utraci połączenie Wi-Fi, pobieranie zostanie wstrzymane i do kontynuowania pobierania przy użyciu mobilnej transmisji danych wymagana będzie wyraźna zgoda. Wstrzymany pakiet ma stanWAITING_FOR_WIFI
. Aby wywołać interfejs, który poprosi użytkownika o wyrażenie zgody, użyj metody showConfirmationDialog()
.
Jeśli aplikacja nie wywoła tej metody, pobieranie zostanie wstrzymane i wznowione automatycznie dopiero wtedy, gdy użytkownik ponownie połączy się z siecią Wi-Fi.
Wymagane potwierdzenie użytkownika
Jeśli pakiet ma stan REQUIRES_USER_CONFIRMATION
, pobieranie nie zostanie rozpoczęte, dopóki użytkownik nie zaakceptuje okna dialogowego wyświetlanego z ikoną showConfirmationDialog()
.
Ten stan może wystąpić, gdy aplikacja nie jest rozpoznawana przez Google Play, np. jeśli została zainstalowana z innego urządzenia.
Pamiętaj, że wywołanie
showConfirmationDialog()
w tym przypadku spowoduje zaktualizowanie aplikacji. Po aktualizacji musisz ponownie poprosić o komponenty.
Oto przykładowa implementacja odbiornika:
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; } } }
Możesz też użyć metody
getPackStates()
aby sprawdzić stan bieżących pobrań.
AssetPackStates
zawiera postęp pobierania, stan pobierania i kody błędów.
Dostęp do pakietów zasobów
Po osiągnięciu przez żądanie pobierania stanu COMPLETED
możesz uzyskać dostęp do pakietu komponentów za pomocą wywołań systemu plików. Aby uzyskać folder główny pakietu komponentów, użyj metody
getPackLocation()
.
Komponenty są przechowywane w katalogu assets
w katalogu głównym pakietu komponentów. Ścieżkę do katalogu assets
możesz uzyskać za pomocą metody pomocniczej assetsPath()
.
Aby uzyskać ścieżkę do konkretnego komponentu:
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; }
Inne metody interfejsu Play Asset Delivery API
Oto dodatkowe metody interfejsu API, których możesz używać w aplikacji.
Anuluj prośbę
Użyj
cancel()
aby anulować aktywną prośbę o pakiet komponentów. Pamiętaj, że ta prośba jest operacją wykonywaną w miarę możliwości.
Usuwanie pakietu komponentów
Użyj
requestRemovePack()
lub
removePack()
aby zaplanować usunięcie pakietu zasobów.
Pobieranie lokalizacji wielu pakietów komponentów
Użyj
getPackLocations()
do zbiorczego sprawdzania stanu wielu pakietów zasobów, co zwraca mapę pakietów zasobów i ich lokalizacji. Mapa zwrócona przez getPackLocations()
zawiera wpis dla każdego pakietu, który jest obecnie pobrany i aktualny.
Następny krok
Testuj Play Asset Delivery lokalnie i w Google Play.