Wykonaj czynności opisane w tym przewodniku, aby uzyskać dostęp do pakietów zasobów aplikacji w języku Java w kodzie.
Kompilacja dla Kotlin i Javy
Aby wbudować usługę Play Asset Delivery w Androida w projekcie, wykonaj te czynności: pakiet aplikacji. Nie musisz używać Android Studio, aby wykonać te czynności.
Zaktualizuj wersję wtyczki Androida do obsługi Gradle w pliku
build.gradle
plik do wersji4.0.0
lub nowszej.W katalogu najwyższego poziomu projektu utwórz katalog zasobu. Ta nazwa katalogu jest używana jako nazwa pakietu zasobów. Nazwy pakietów zasobów musi zaczynać się od litery i może zawierać tylko litery, cyfry i podkreśleń.
W katalogu pakietów zasobów utwórz plik
build.gradle
i dodaj do niego atrybut tego kodu. Pamiętaj, aby podać nazwę pakietu zasobów i tylko jeden typ dostawy:Odlotowe
// 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
build.gradle
aplikacji projektu dodaj nazwę każdego pakietu zasobów w swoim projekcie, jak pokazano poniżej:Odlotowe
// 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 zasobów w pliku projekt, jak pokazano poniżej:Odlotowe
// 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 pakietów zasobów utwórz ten podkatalog:
src/main/assets
Umieść zasoby w katalogu
src/main/assets
. Możesz utworzyć podkatalogi. Struktura katalogów aplikacji powinna będzie 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 główny zawiera teraz sekcję :
asset-pack-name/manifest/AndroidManifest.xml
: Konfiguruje identyfikator pakietu zasobów i tryb dostawyasset-pack-name/assets/your-asset-directories
: Katalog, który zawiera wszystkie zasoby dostarczone w ramach pakietu zasobów
Gradle generuje plik manifestu dla każdego pakietu zasobów i wyświetla
assets/
katalogu.(Opcjonalnie) Dołącz Play Asset Delivery Library, jeśli planujesz korzystać z szybkiej dostawy i na żądanie.
Odlotowe
implementation "com.google.android.play:asset-delivery:2.2.2" // For Kotlin use asset-delivery-ktx implementation "com.google.android.play:asset-delivery-ktx:2.2.2"
Kotlin
implementation("com.google.android.play:asset-delivery:2.2.2") // For Kotlin use core-ktx implementation("com.google.android.play:asset-delivery-ktx:2.2.2")
(Opcjonalnie) Skonfiguruj pakiet aplikacji, aby obsługiwał różne tekstury formatów kompresji.
Integracja z interfejsem Play Asset Delivery API
Interfejs Play Asset Delivery Java API.
zapewnia
AssetPackManager
.
do wysyłania żądań pakietów zasobów, zarządzania pobieraniem i uzyskiwania dostępu do zasobów. Pamiętaj, aby najpierw dodać do projektu bibliotekę Play Asset Delivery.
Implementujesz ten interfejs API zgodnie z typem dostawy wybranego pakietu zasobów aby uzyskać dostęp. Te kroki zostały pokazane na poniższym schemacie blokowym.
Rysunek 1. Schemat procesu uzyskiwania dostępu do pakietów zasobów
Dostawa w czasie instalacji
Pakiety zasobów skonfigurowane jako install-time
są od razu dostępne w aplikacji
Korzystanie z Javy
Interfejs AssetManager API umożliwiający dostęp do zasobów.
wyświetlane w tym trybie:
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 śledzenie i dostawy na żądanie
W sekcjach poniżej dowiesz się, jak uzyskać informacje o pakietach zasobów przed
jak je pobrać, jak wywołać interfejs API w celu rozpoczęcia pobierania i jak
uzyskać dostęp do pobranych pakietów. Te sekcje dotyczą usług fast-follow
i
Pakiety zasobów (on-demand
).
Sprawdź stan
Każdy pakiet zasobów jest przechowywany w osobnym folderze w pamięci wewnętrznej aplikacji.
Użyj
getPackLocation()
aby określić folder główny pakietu zasobów. Ta metoda zwraca błąd
następujące wartości:
Zwracana wartość | Stan |
---|---|
Prawidłowy obiekt AssetPackLocation |
Folder główny pakietu zasobów jest gotowy do natychmiastowego dostępu pod adresem assetsPath() |
null |
Nieznany pakiet lub zasoby są niedostępne |
Pobieranie informacji o pakietach zasobów
Przed pobraniem zasobu aplikacje muszą informować o rozmiarze pobieranego pliku.
Użyj
requestPackStates()
lub getPackStates()
określa rozmiar pobieranego pliku i sprawdza, czy pakiet
pobieranie.
Kotlin
suspend fun requestPackStates(packNames: List<String>): AssetPackStates
Java
Task<AssetPackStates> getPackStates(List<String> packNames)
requestPackStates()
to funkcja zawieszenia zwracająca
AssetPackStates
.
, a metoda getPackStates()
jest metodą asynchroniczną, która zwraca Task<AssetPackStates>
.
packStates()
obiektu AssetPackStates
zwraca wartość Map<String,
AssetPackState>
. Ta mapa zawiera stan każdego żądanego zasobu
klucz z nazwą:
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; })
Poniżej
AssetPackState
podają rozmiar pakietu zasobów, ilość pobranej do tej pory (jeśli
), a kwota została już przekazana do aplikacji:
Aby sprawdzić stan pakietu zasobów, użyj
status()
, która zwraca stan jako liczbę całkowitą odpowiadającą stałej
w polu
AssetPackStatus
zajęcia. Pakiet zasobów, który nie został jeszcze zainstalowany, ma stan
AssetPackStatus.NOT_INSTALLED
Jeśli żądanie nie zostanie zrealizowane, użyj metody
errorCode()
, której wartość zwracana odpowiada polu stałemu w funkcji
AssetPackErrorCode
zajęcia.
Zainstaluj
Użyj klawiszy requestFetch()
lub
fetch()
pobierania pakietu zasobów po raz pierwszy lub wywoływania aktualizacji pliku
pakiet zasobów do uzupełnienia:
Kotlin
suspend fun AssetPackManager.requestFetch(packs: List<String>): AssetPackStates
Java
Task<AssetPackStates> fetch(List<String> packNames)
Ta metoda zwraca błąd
AssetPackStates
obiekt z listą pakietów wraz z ich początkowymi stanami i rozmiarami pobierania.
Jeśli pakiet zasobów zażądany przez requestFetch()
lub fetch()
jest już pobierany,
jest zwracany stan i nie rozpoczyna się kolejne pobieranie.
Monitorowanie stanu pobierania
Zaimplementuj tag
AssetPackStateUpdatedListener
śledzić postęp instalacji zasobu
Aktualizacje stanu są podzielone na pakiety, aby ułatwić śledzenie
poszczególnych pakietów zasobów. Możesz zacząć korzystać z dostępnych pakietów zasobów
przed zakończeniem pobierania wszystkich innych plików związanych z Twoim żądaniem.
Kotlin
fun registerListener(listener: AssetPackStateUpdatedListener) fun unregisterListener(listener: AssetPackStateUpdatedListener)
Java
void registerListener(AssetPackStateUpdatedListener listener) void unregisterListener(AssetPackStateUpdatedListener listener)
Duże pliki do pobrania
Jeśli rozmiar pobieranego pliku przekracza 200 MB, a użytkownik nie korzysta z Wi-Fi,
nie rozpocznie się, dopóki użytkownik wyraźnie nie wyrazi zgody na
pobieranie przy użyciu komórkowego połączenia danych. Podobnie, jeśli pobrany plik jest duży
Jeśli użytkownik utraci połączenie z Wi-Fi, pobieranie zostanie wstrzymane i wymagana jest wyraźna zgoda na
użyj komórkowego połączenia transmisji danych. Wstrzymano pakiet ma stan
WAITING_FOR_WIFI
Aby w interfejsie użytkownika wyświetlały się prośby o zgodę na wykorzystanie danych, użyj
showConfirmationDialog()
.
Pamiętaj, że jeśli aplikacja nie wywoła tej metody, pobieranie zostanie wstrzymane i nastąpi jest wznawiane automatycznie tylko 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
idź dalej, dopóki użytkownik nie zaakceptuje okna, które wyświetla się
showConfirmationDialog()
Ten stan może wystąpić, gdy aplikacja nie zostanie rozpoznana przez Google Play – na przykład
czy aplikacja została zainstalowana z innego urządzenia.
Pamiętaj, że funkcja
showConfirmationDialog()
w takim przypadku spowoduje aktualizację aplikacji. Po aktualizacji konieczne będzie
, aby ponownie poprosić o ich przesłanie.
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; } } }
Ewentualnie możesz użyć atrybutu
getPackStates()
, by poznać stan aktualnie pobranych plików.
AssetPackStates
zawiera informacje o postępie pobierania, stan pobierania i kody błędów niepowodzenia.
Dostęp do pakietów zasobów
Dostęp do pakietu zasobów możesz uzyskać za pomocą wywołań systemu plików po przesłaniu prośby o pobranie
dociera do
COMPLETED
stanu. Użyj
getPackLocation()
aby uzyskać folder główny pakietu zasobów.
Zasoby są przechowywane w katalogu assets
w katalogu głównym pakietu zasobów
katalogu. Ścieżkę do katalogu assets
możesz uzyskać za pomocą polecenia
metoda zapewniająca wygodę
assetsPath()
Aby uzyskać ścieżkę do konkretnego zasobu, użyj tej metody:
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
Poniżej znajdziesz dodatkowe metody interfejsu API, których możesz użyć w swojej aplikacji.
Anuluj prośbę
Używaj
cancel()
aby anulować aktywne żądanie pakietu zasobów. Pamiętaj, że ta prośba dołoży wszelkich starań,
.
Usuń pakiet zasobów
Używaj
requestRemovePack()
lub
removePack()
aby zaplanować usunięcie pakietu zasobów.
Pobieranie lokalizacji wielu pakietów zasobów
Używaj
getPackLocations()
aby zbiorczo sprawdzić stan wielu pakietów zasobów, co zwróci mapę
pakietów zasobów i ich lokalizacji. Mapa zwrócona przez użytkownika getPackLocations()
zawiera wpis dotyczący każdego pakietu, który jest obecnie pobrany i aktualny.
Następny krok
Przetestuj Play Asset Delivery lokalnie i w Google Play.