Google Play wymaga, aby skompresowany plik APK pobierany przez użytkowników miał rozmiar nie większy niż 100 MB. W większości aplikacji wystarcza wystarczająco dużo miejsca na kod i zasoby. Niektóre aplikacje potrzebują jednak więcej miejsca na obrazy w wysokiej jakości, pliki multimedialne lub inne duże zasoby. Wcześniej, jeśli rozmiar skompresowanego pliku do pobrania aplikacji przekraczał 100 MB, trzeba było hostować i pobierać dodatkowych zasobów, gdy użytkownik uruchomi aplikację. Hosting i wyświetlanie dodatkowych plików może jest kosztowne, a wygoda użytkownika jest często niższa od idealnej. Aby ułatwić Ci ten proces i wygodniejsze dla użytkowników Google Play umożliwia dołączenie dwóch dużych plików rozszerzeń, uzupełniają pakiet APK.
Google Play przechowuje pliki rozszerzeń aplikacji i udostępnia je na urządzeniu pod adresem nie ponosisz żadnych kosztów. Pliki rozszerzeń są zapisywane w pamięci współdzielonej urządzenia (czyli karta SD lub partycja podłączana przez USB; zwany także „zewnętrznym” pamięci masowej), do której aplikacja ma dostęp . Na większości urządzeń Google Play pobiera pliki rozszerzające w tym samym czasie. pobiera plik APK, dzięki czemu aplikacja ma wszystko, czego potrzebuje, gdy użytkownik ją otworzy za pierwszym razem. W niektórych przypadkach aplikacja musi jednak pobrać pliki z Google Play. po uruchomieniu aplikacji.
Jeśli nie chcesz używać plików rozszerzających, a rozmiar skompresowanego pliku do pobrania aplikacji jest większy niż 100 MB, prześlij aplikację za pomocą aplikacji na Androida Pakiety, które umożliwiają pobranie skompresowanego pliku o wielkości do 200 MB. Ponadto, ponieważ użycie pakietów aplikacji opóźnia generowanie plików APK i podpisywanie ich w Google Play, użytkownicy pobierają zoptymalizowane pliki APK, tylko kod i zasoby, których potrzebują do uruchomienia aplikacji. Nie musisz budować, podpisywać zarządzać wieloma pakietami APK lub plikami rozszerzeń, dzięki czemu użytkownicy będą mogli pobierać mniejsze i lepiej zoptymalizowane pliki do pobrania.
Omówienie
Przy każdym przesyłaniu pliku APK w Konsoli Google Play możesz: dodaj jeden lub dwa pliki rozszerzające do pliku APK. Każdy plik może mieć maksymalnie 2 GB i może być w dowolnym formacie ale zalecamy korzystanie z skompresowanego pliku, by zmniejszyć przepustowość pobierania podczas pobierania. Każdy plik rozszerzeń pełni inną rolę:
- Główny plik rozszerzenia to główny plik rozszerzenia z dodatkowymi zasobami wymaganymi przez aplikację.
- Plik rozszerzenia poprawki jest opcjonalny i służy do wprowadzania niewielkich aktualizacji głównym pliku rozszerzenia.
Można ich używać w dowolny sposób, jednak zalecamy, by główny plik plik rozszerzenia dostarcza zasoby główne i powinien być rzadko aktualizowany, jeśli w ogóle jest aktualizowany; rozszerzenie z poprawką powinien być mniejszy i pełnić rolę „operatora poprawek” oraz być aktualizowany przy każdym głównym lub w razie potrzeby.
Jednak nawet wtedy, gdy aktualizacja aplikacji wymaga tylko nowego pliku rozszerzenia poprawki, nadal musisz
prześlij nowy plik APK ze zaktualizowanym plikiem versionCode
w pliku manifestu. (Parametr
Konsola Play nie umożliwia przesłania pliku rozszerzenia do istniejącego pakietu APK).
Uwaga: plik rozszerzenia poprawki pod względem semantycznym jest taki sam jak plik głównego pliku rozszerzenia – z każdego pliku możesz korzystać w dowolny sposób.
Format nazwy pliku
Przesyłany plik rozszerzenia może mieć dowolny wybrany format (ZIP, PDF, MP4 itp.). Możesz też użyj narzędzia JOBB, aby hermetyzować i szyfrować zbiór, plików zasobów i kolejnych poprawek dla tego zbioru. Niezależnie od typu pliku usługa Google Play traktuje je jako nieprzejrzyste binarne bloby i zmienia ich nazwy zgodnie z tym schematem:
[main|patch].<expansion-version>.<package-name>.obb
Schemat ten składa się z 3 elementów:
main
lubpatch
- Określa, czy plik jest głównym plikiem rozszerzenia, czy plikiem rozszerzenia z poprawką. Istnieje możliwość tylko jeden plik główny i jeden plik poprawki dla każdego pakietu APK.
<expansion-version>
- Liczba całkowita zgodna z kodem wersji pliku APK z rozwinięciem
pierwszy powiązany (pasuje do
android:versionCode
).„Pierwszy” jest wyróżniona, ponieważ chociaż Konsola Play umożliwia ponowne użycie przesłanego pliku rozszerzenia z nowym pakietem APK, nazwa pliku nie ulegnie zmianie – zachowuje wersję zastosowaną do pliku w chwili jego przesłania po raz pierwszy.
<package-name>
- Nazwa pakietu aplikacji w stylu Java.
Załóżmy, że wersja pakietu APK to 314159, a nazwa Twojego pakietu to com.example.app. Jeśli po przesłaniu głównego pliku rozszerzenia jego nazwa zostanie zmieniona na:
main.314159.com.example.app.obb
Lokalizacja pamięci
Gdy Google Play pobiera pliki rozszerzeń na urządzenie, zapisuje je w folderze lokalizację pamięci współdzielonej. Aby zapewnić prawidłowe działanie, nie wolno usuwać, przenosić ani zmieniać nazw plików rozszerzeń. w przypadku, gdy aplikacja musi pobrać aplikację z Google Play. musisz zapisać pliki dokładnie w tej samej lokalizacji.
Metoda getObbDir()
zwraca określoną lokalizację
plików rozszerzeń w takiej postaci:
<shared-storage>/Android/obb/<package-name>/
<shared-storage>
to ścieżka do współdzielonego miejsca na dane dostępna z poziomugetExternalStorageDirectory()
<package-name>
to dostępna nazwa pakietu Twojej aplikacji w stylu Java odgetPackageName()
.
W tym katalogu nie mogą znajdować się więcej niż 2 pliki rozszerzeń dla każdej aplikacji.
Jeden to główny plik rozszerzenia, a drugi to plik rozszerzenia poprawki (w razie potrzeby). Poprzedni
są zastępowane, gdy zaktualizujesz aplikację za pomocą nowych plików rozszerzeń. Od Androida
4.4 (poziom interfejsu API 19) aplikacje mogą odczytywać pliki rozszerzeń OBB
bez pamięci zewnętrznej
uprawnienia. Jednak niektóre implementacje Androida 6.0 (poziom interfejsu API 23) i nowszych nadal wymagają
więc musisz zadeklarować
READ_EXTERNAL_STORAGE
w manifeście aplikacji i spytaj o nie na stronie
środowiska wykonawczego w taki sposób:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
W przypadku Androida w wersji 6 lub nowszej musisz poprosić o uprawnienia do korzystania z pamięci zewnętrznej w czasie działania aplikacji. Niektóre implementacje Androida nie wymagają jednak uprawnień do odczytu plików OBB. ten fragment kodu pokazuje, jak sprawdzić dostęp do odczytu, zanim poprosisz o pamięć zewnętrzną uprawnienie:
Kotlin
val obb = File(obb_filename) var open_failed = false try { BufferedReader(FileReader(obb)).also { br -> ReadObbFile(br) } } catch (e: IOException) { open_failed = true } if (open_failed) { // request READ_EXTERNAL_STORAGE permission before reading OBB file ReadObbFileWithPermission() }
Java
File obb = new File(obb_filename); boolean open_failed = false; try { BufferedReader br = new BufferedReader(new FileReader(obb)); open_failed = false; ReadObbFile(br); } catch (IOException e) { open_failed = true; } if (open_failed) { // request READ_EXTERNAL_STORAGE permission before reading OBB file ReadObbFileWithPermission(); }
Jeśli musisz rozpakować zawartość plików rozszerzeń, nie usuwaj
OBB
w kolejnych plikach rozszerzeń i nie zapisuj danych bez pakietu
w tym samym katalogu. Zapisz rozpakowane pliki w katalogu
określona przez getExternalFilesDir()
. Pamiętaj jednak:
jeśli to możliwe, najlepiej używać formatu pliku rozszerzającego, który umożliwia odczyt bezpośrednio
pliku bez konieczności rozpakowywania danych. Udostępniliśmy na przykład bibliotekę
projekt o nazwie biblioteka ZIP rozszerzenia APK, która bezpośrednio odczytuje Twoje dane.
z pliku ZIP.
Uwaga: w przeciwieństwie do plików APK wszystkie pliki są zapisywane w pamięci współdzielonej może odczytać użytkownik i inne aplikacje.
Wskazówka: jeśli spakujesz pliki multimedialne do pliku ZIP, możesz użyć tej funkcji
odtwarzania plików z elementami sterującymi przesunięciem i długością (np. MediaPlayer.setDataSource()
i
SoundPool.load()
) bez parametru
musisz rozpakować plik ZIP. Aby to zadziałało, nie należy wykonywać dodatkowej kompresji na
plików multimedialnych podczas tworzenia pakietów ZIP. Na przykład w narzędziu zip
użyj opcji -n
, by określić sufiksy plików, które nie powinny
skompresowane:
zip -n .mp4;.ogg main_expansion media_files
Proces pobierania
W większości przypadków Google Play pobiera i zapisuje pliki rozszerzeń w tym samym czasie pobierze pakiet APK na urządzenie. Jednak w niektórych przypadkach Google Play nie można pobrać plików rozszerzeń lub użytkownik mógł usunąć wcześniej pobrane rozszerzenie . Aby móc poradzić sobie w tych sytuacjach, aplikacja musi mieć możliwość pobierania plików po rozpoczęciu głównej aktywności, przy użyciu adresu URL udostępnionego przez Google Play.
Ogólny proces pobierania wygląda tak:
- Użytkownik decyduje się zainstalować Twoją aplikację z Google Play.
- Jeśli Google Play może pobrać pliki rozszerzeń (w przypadku większości
urządzenia), pobiera je razem z plikiem APK.
Jeśli Google Play nie może pobrać plików rozszerzeń, Tylko plik APK.
- Gdy użytkownik uruchomi aplikację, musi ona sprawdzić, czy pliki rozszerzeń są
już zapisane na urządzeniu.
- Jeśli tak, aplikacja jest gotowa.
- Jeśli nie, aplikacja musi pobrać pliki rozszerzające z Google Play przez HTTP. Twoja aplikacja musi wysłać żądanie do klienta Google Play przy użyciu usługi licencjonowania aplikacji Google Play, która podaje w odpowiedzi nazwę, rozmiar pliku i adres URL każdego pliku rozszerzenia. Dzięki tym informacjom pobierz pliki i zapisz je w odpowiedniej lokalizacji pamięci.
Uwaga: konieczne jest podanie kodu niezbędnego do pobierz je z Google Play, jeśli nie znajdują się one jeszcze w na urządzeniu po uruchomieniu aplikacji. Jak wspominaliśmy w sekcji o pobieraniu plików rozszerzeń, udostępniliśmy bibliotekę, która pozwala znacznie upraszcza ten proces i umożliwia pobieranie plików z usługi przy kod od Ciebie.
Lista kontrolna programowania
Oto podsumowanie czynności, które musisz wykonać, by używać plików rozszerzeń ze aplikacja:
- Najpierw sprawdź, czy rozmiar skompresowanego pliku do pobrania Twojej aplikacji musi być większy niż 100 MB. Ilość miejsca jest ważna, dlatego całkowity rozmiar pobieranego pliku powinien być jak najmniejszy. Jeśli Twoja aplikacja wykorzystuje więcej niż 100 MB w celu przesłania wielu wersji zasobów graficznych na różne ekrany gęstości, rozważ opublikowanie wielu plików APK, w których każdy zawiera wyłącznie zasoby wymagane przez ekrany, na które jest kierowany. Aby uzyskać najlepsze wyniki, opublikuj w Google Play, prześlij pakiet Android App Bundle, który obejmuje cały skompilowany kod i zasoby aplikacji, ale opóźnia wygenerowanie i podpisanie plików APK przez Google Graj.
- Określ, które zasoby aplikacji należy oddzielić od pliku APK, i umieść je w pakiecie
który ma być używany jako główny plik rozszerzający.
Zazwyczaj przy aktualizacjach do głównego pliku rozszerzenia. Jeśli jednak zasoby przekraczają limit 2 GB dla głównego rozszerzenia, możesz użyć pliku poprawki dla pozostałych zasobów.
- Opracuj aplikację w taki sposób, aby wykorzystywała zasoby z plików rozszerzeń w
lokalizacja pamięci współdzielonej urządzenia.
Pamiętaj, że nie możesz usuwać i przenosić plików rozszerzeń ani zmieniać ich nazw.
Jeśli aplikacja nie wymaga konkretnego formatu, zalecamy tworzenie plików ZIP z plików rozszerzeń, a następnie odczytaj je za pomocą pliku APK Expansion Zip Biblioteka.
- Dodaj logikę do głównej aktywności w aplikacji, która sprawdza, czy pliki rozszerzeń
są na urządzeniu po uruchomieniu. Jeśli plików nie ma na urządzeniu, użyj usługi licencjonowania aplikacji w Google Play, aby poprosić o adresy URL.
a następnie pobierz i zapisz je.
Aby znacznie zmniejszyć ilość kodu, musisz pisać i zapewnić użytkownikom dobre wrażenia. w trakcie pobierania zalecamy skorzystanie z Programu do pobrania Biblioteka, aby wdrożyć sposób pobierania.
Jeśli zamiast korzystać z biblioteki tworzysz własną usługę pobierania, pamiętaj, że nie mogą zmieniać nazw plików rozszerzeń i muszą je zapisać w prawidłowym lokalizacji miejsca na dane.
Gdy skończysz tworzenie aplikacji, postępuj zgodnie z instrukcjami z przewodnika Testowanie Twoje pliki rozszerzeń.
Reguły i ograniczenia
Dodanie plików rozszerzeń APK to funkcja dostępna podczas przesyłania aplikacji za pomocą Konsola Play. Gdy przesyłasz aplikację po raz pierwszy lub aktualizujesz korzystających z plików rozszerzeń, musisz pamiętać o tych regułach i ograniczeniach:
- Każdy plik rozszerzający nie może być większy niż 2 GB.
- Aby pobrać pliki rozszerzeń z Google Play, użytkownik musi mieć pozyskali aplikację z Google Play. Google Play nie będzie podaj adresy URL plików rozszerzeń, jeśli aplikacja została zainstalowana w inny sposób.
- Podczas pobierania z aplikacji adres URL powiązany z kontem Google Play określony dla każdego pliku jest unikalny dla każdego pobieranego pliku, a każdy z nich wygasa wkrótce po do Twojej aplikacji.
- Gdy zaktualizujesz aplikację o nowy plik APK lub prześlesz wiele plików APK dla tego samego pliku APK aplikacji, możesz wybrać pliki rozszerzeń przesłane do poprzedniego pliku APK. nazwa pliku rozszerzenia nie zmienia się – zachowuje wersję otrzymaną przez plik APK, z którym plik był pierwotnie powiązany.
- Jeśli używasz plików rozszerzeń w połączeniu z wieloma pakietami APK,
musisz przesyłać oddzielne pliki APK dla różnych urządzeń,
dla każdego urządzenia, aby zapewnić unikalny
versionCode
i zadeklaruj różne filtry dla: każdego pliku APK. - Nie możesz przeprowadzić aktualizacji aplikacji, zmieniając pliki rozszerzeń
– musisz przesłać nowy plik APK, aby zaktualizować aplikację. Jeśli zmiany dotyczą tylko
dotyczące zasobów w plikach rozszerzeń, możesz zaktualizować pakiet APK, zmieniając ikonę
versionCode
(oraz (być może równieżversionName
). - Nie zapisuj innych danych na koncie
obb/
Katalog. Jeśli musisz rozpakować niektóre dane, zapisz je w lokalizacji podanej w zasadziegetExternalFilesDir()
. - Nie usuwaj pliku rozszerzenia
.obb
ani nie zmieniaj jego nazwy (chyba że przeprowadzanie aktualizacji). Jeśli to zrobisz, Google Play (lub sama aplikacja) będzie wielokrotnie działać pobierz plik rozszerzenia. - Przy ręcznym aktualizowaniu pliku rozszerzenia musisz usunąć poprzedni plik rozszerzenia.
Pobieranie plików rozszerzeń
W większości przypadków Google Play pobiera i zapisuje pliki rozszerzeń na urządzeniu w tym samym podczas instalacji lub aktualizacji pliku APK. Dzięki temu pliki rozszerzeń są dostępne, gdy przy pierwszym uruchomieniu aplikacji. Jednak w niektórych przypadkach aplikacja musi pobrać plików rozszerzających, żądając ich z adresu URL podanego w odpowiedzi w usłudze licencjonowania aplikacji w Google Play.
Podstawowa logika pobierania plików rozszerzeń jest następująca:
- Po uruchomieniu aplikacji odszukaj pliki rozszerzeń w lokalizacji pamięci współdzielonej (w
Android/obb/<package-name>/
).- Jeśli są tam pliki rozszerzeń, nie musisz nic więcej robić i możesz korzystać z aplikacji.
- Jeśli plików rozszerzeń nie ma na liście:
- Prześlij prośbę przy użyciu licencjonowania aplikacji Google Play, aby uzyskać nazw, rozmiarów i adresów URL plików rozszerzeń aplikacji.
- Użyj adresów URL dostarczonych przez Google Play, by pobrać pliki rozszerzeń i zapisać
plików rozszerzeń. Musisz zapisać pliki w lokalizacji pamięci współdzielonej
(
Android/obb/<package-name>/
) i użyj dokładnie podanej nazwy pliku odpowiedź Google Play.Uwaga: adres URL podany w Google Play na potrzeby Przy każdym pobieraniu jest on unikalny, a każdy z nich wygasa wkrótce po udostępnieniu do aplikacji.
Jeśli aplikacja jest bezpłatna (a nie płatna), prawdopodobnie nie korzystasz z usługi licencjonowania aplikacji. Jest to przede wszystkim stworzone z myślą o egzekwowaniu zasad zasadami licencjonowania aplikacji i upewnić się, że użytkownik ma prawo korzystają z aplikacji (osoba słusznie zapłaciła za nią w Google Play). Aby ułatwić plików rozszerzających, usługa licencjonowania została zwiększona, aby zapewnić do aplikacji z adresem URL hostowanych plików rozszerzeń aplikacji w Google Play. Dlatego nawet jeśli Twoja aplikacja jest bezpłatna dla użytkowników, musisz dodać do niej atrybut Biblioteka weryfikacji licencji (LVL) pozwalająca używać plików rozszerzeń APK. Jeśli Twoja aplikacja jest bezpłatna, nie trzeba wymuszać weryfikacji licencji. Wystarczy w celu zwrócenia adresów URL plików rozszerzeń.
Uwaga: bez względu na to, czy aplikacja jest bezpłatna, Google Play zwraca adresy URL plików rozszerzenia tylko wtedy, gdy użytkownik pozyskał Twoją aplikację z Google Play.
Oprócz kodu LVL potrzebujesz zestawu kodu do pobierania plików rozszerzeń przez połączenie HTTP i zapisuje je w odpowiedniej lokalizacji w pamięci współdzielonej urządzenia. Podczas wdrażania tej procedury w aplikacji musisz uwzględnić kilka problemów rozważanie zakupu:
- Na urządzeniu może być za mało miejsca na pliki rozszerzeń, dlatego sprawdź, przed rozpoczęciem pobierania i ostrzegać użytkownika, jeśli nie ma wystarczającej ilości miejsca.
- Pliki powinny być pobierane w usłudze w tle, aby uniknąć zablokowania użytkownika interakcji i pozwalają użytkownikowi opuścić aplikację w trakcie pobierania.
- Podczas przesyłania żądania i pobierania mogą wystąpić różne błędy z gracją.
- Połączenie sieciowe może ulec zmianie podczas pobierania i należy radzić sobie z nimi. jeśli pobieranie zostanie przerwane, w miarę możliwości wznów je.
- Podczas pobierania w tle należy przesłać powiadomienie, że: wskazuje postęp pobierania, powiadamia użytkownika o jego zakończeniu i przenosi z powrotem do Twojej aplikacji.
Aby ułatwić Ci pracę, stworzyliśmy Bibliotekę do pobierania, które wysyła do usługi licencjonowania adresy URL plików rozszerzeń, pobiera pliki rozszerzające wykonuje wszystkie zadania wymienione powyżej, a nawet umożliwia wstrzymanie i wznowienie pobierz. Po dodaniu do aplikacji biblioteki narzędzia Downloader i kilku punktów zaczepienia kodu niemal wszystkie jest już zakodowany. W związku z tym, aby zapewnić jak najlepszą jakość użytkowników przy minimalnym wysiłku, zalecamy korzystanie z biblioteki narzędzia do pobierania pobierz pliki rozszerzeń. W poniższych sekcjach znajdziesz informacje o tym, jak zintegrować do aplikacji.
Jeśli wolisz opracować własne rozwiązanie do pobierania plików rozszerzeń za pomocą narzędzia Google
URL-i Google Play, musisz przestrzegać
dokumentacji dotyczącej licencjonowania, która umożliwia wykonanie żądania licencji, a potem pobieranie nazw plików rozszerzeń.
rozmiarów reklam i adresów URL z dodatków do odpowiedzi. Do licencjonowania należy używać klasy APKExpansionPolicy
(dostępnej w bibliotece weryfikacji licencji)
który przechwytuje nazwy, rozmiary i adresy URL plików rozszerzeń z usługi licencjonowania.
Informacje o bibliotece narzędzia do pobierania
Aby używać w aplikacji plików rozszerzeń APK i zapewnić użytkownikom najlepsze wrażenia, zalecamy użycie biblioteki Downloader, która jest dostępna w Pakiet biblioteki rozszerzeń plików APK w Google Play. Ta biblioteka pobiera pliki rozszerzeń w usługa w tle, wyświetla powiadomienie użytkownika ze stanem pobierania, obsługuje sieć utratę połączenia, wznowienie pobierania, gdy będzie to możliwe i inne.
Aby zaimplementować pobieranie plików rozszerzeń za pomocą biblioteki narzędzia do pobierania, wystarczy, że:
- Rozszerza specjalną podklasę
Service
i podklasęBroadcastReceiver
, które wymagają tylko kilku kilka wierszy kodu. - Dodaj do głównej aktywności funkcję logiczną, która sprawdza, czy pliki rozszerzeń zostało już pobrane, a w przeciwnym razie wywołuje proces pobierania i wyświetla UI postępu.
- Zaimplementuj interfejs wywołania zwrotnego z kilkoma metodami w głównej aktywności, które otrzymuje aktualizacje na temat postępu pobierania.
W sekcjach poniżej wyjaśniamy, jak skonfigurować aplikację za pomocą biblioteki narzędzia do pobierania.
Przygotowanie do użycia biblioteki narzędzia do pobierania
Aby korzystać z biblioteki narzędzia do pobierania, musisz: pobierz dwa pakiety z SDK Manager i dodaj odpowiednie biblioteki do .
Najpierw otwórz Menedżera pakietów SDK na Androida. (Narzędzia > Menedżer SDK) oraz w sekcji Wygląd Zachowanie > Ustawienia systemu > SDK do Androida, wybierz kartę Narzędzia SDK, aby wybrać i pobrać:
- Pakiet biblioteki licencjonowania Google Play
- Pakiet biblioteki rozszerzeń plików APK w Google Play
Utwórz nowy moduł biblioteki na potrzeby biblioteki weryfikacji licencji i narzędzia do pobierania Biblioteka. Dla każdej biblioteki:
- Wybierz Plik > Nowe > Nowy moduł.
- W oknie Utwórz nowy moduł wybierz Biblioteka Androida, i kliknij Dalej.
- Podaj nazwę aplikacji lub biblioteki, na przykład „Biblioteka licencji Google Play”. i „Biblioteka pobierania Google Play”, wybierz Minimalny poziom pakietu SDK, a potem wybierz Zakończ.
- Wybierz Plik > Struktura projektu.
- Wybierz kartę Właściwości i otwórz Bibliotekę.
Repozytorium – wpisz bibliotekę z katalogu
<sdk>/extras/google/
(play_licensing/
w przypadku biblioteki weryfikacji licencji lubplay_apk_expansion/downloader_library/
w przypadku biblioteki narzędzia do pobierania). - Kliknij OK, aby utworzyć nowy moduł.
Uwaga: biblioteka narzędzia do pobierania zależy od licencji Biblioteka weryfikacji. Pamiętaj, aby dodać licencję z biblioteki Weryfikacja do właściwości projektu w bibliotece narzędzia do pobierania.
Możesz też z poziomu wiersza poleceń zaktualizować projekt, dodając do niego biblioteki:
- Przejdź do katalogu
<sdk>/tools/
. - Wykonaj polecenie
android update project
, korzystając z opcji--library
, aby dodać zarówno LVL i biblioteka narzędzia do pobierania w projekcie. Na przykład:android update project --path ~/Android/MyApp \ --library ~/android_sdk/extras/google/market_licensing \ --library ~/android_sdk/extras/google/market_apk_expansion/downloader_library
Po dodaniu biblioteki weryfikacji licencji i biblioteki narzędzia do pobierania do możesz szybko zintegrować możliwość pobierania plików rozszerzeń Google Play. wybrany format plików rozszerzeń i sposób ich odczytywania, z pamięci współdzielonej to oddzielny sposób, który musisz rozważyć, do potrzeb aplikacji.
Wskazówka: pakiet rozszerzenia APK zawiera próbkę aplikacja który pokazuje, jak korzystać w aplikacji z Biblioteki pobierania. W przykładzie użyto trzeciej biblioteki dostępne w pakiecie rozszerzeń APK o nazwie Biblioteka ZIP rozszerzenia APK. Jeśli planujesz plików ZIP w plikach ZIP, zalecamy również dodanie biblioteki ZIP rozszerzenia APK do do aplikacji. Więcej informacji znajdziesz w sekcji poniżej o używaniu biblioteki ZIP rozszerzenia APK.
Deklarowanie uprawnień użytkownika
Aby pobrać pliki rozszerzające, biblioteka pobierania Aplikacja wymaga kilku uprawnień, które należy zadeklarować w pliku manifestu aplikacji. Ta to:
<manifest ...> <!-- Required to access Google Play Licensing --> <uses-permission android:name="com.android.vending.CHECK_LICENSE" /> <!-- Required to download files from Google Play --> <uses-permission android:name="android.permission.INTERNET" /> <!-- Required to keep CPU alive while downloading files (NOT to keep screen awake) --> <uses-permission android:name="android.permission.WAKE_LOCK" /> <!-- Required to poll the state of the network connection and respond to changes --> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <!-- Required to check whether Wi-Fi is enabled --> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/> <!-- Required to read and write the expansion files on shared storage --> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> ... </manifest>
Uwaga: domyślnie biblioteka pobierania wymaga interfejsu API poziomu 4, ale biblioteka ZIP rozszerzenia APK wymaga poziomu API 5.
Wdrażanie usługi pobierania
Aby można było pobierać treści w tle, Biblioteka pobierania udostępnia
własnego podklasy Service
o nazwie DownloaderService
, którą należy rozszerzyć. W
(oprócz pobierania plików rozszerzeń) DownloaderService
:
- Rejestruje obiekt
BroadcastReceiver
, który nasłuchuje zmian w połączenie sieciowe urządzenia (CONNECTIVITY_ACTION
transmisji) w celu wstrzymania pobierania w razie potrzeby (np. z powodu utraty połączenia). wznów pobieranie, gdy będzie to możliwe (połączenie zostanie nabyte). - Planuje alarm o nazwie
RTC_WAKEUP
, który będzie próbował pobrać jeszcze raz w przypadku gdy usługa zostanie utracona. - Tworzy niestandardowy obiekt
Notification
, który wyświetla postęp pobierania oraz żadnych błędów ani zmian stanu. - Zezwala aplikacji na ręczne wstrzymywanie i wznawianie pobierania.
- Sprawdza, czy pamięć współdzielona jest podłączona i dostępna oraz czy pliki jeszcze nie istnieją. i wystarczającą ilość miejsca, zanim pobierzesz pliki rozszerzeń. Następnie powiadamia użytkownika jeśli któreś z nich nie jest prawdziwe.
Wystarczy, że utworzysz w aplikacji klasę, która rozszerza klasę DownloaderService
, i zastąp 3 metody, aby podać szczegółowe informacje o aplikacji:
getPublicKey()
- Musi to zwracać ciąg znaków, który jest kluczem publicznym RSA wydawcy zakodowanym w standardzie Base64 na stronie profilu w Konsoli Play (patrz Konfigurowanie licencjonowania).
getSALT()
- Musi to zwrócić tablicę losowych bajtów, do których używa licencji
Policy
utwórzObfuscator
. Sól gwarantuje, że zaciemniony kodSharedPreferences
będzie unikalny i niemożliwy do znalezienia. getAlarmReceiverClassName()
- Musi to zwrócić nazwę klasy klasy
BroadcastReceiver
w do aplikacji, która powinna otrzymać alarm informujący o tym, że ponownie uruchomione (co może się zdarzyć, gdy usługa pobierania nieoczekiwanie się zatrzyma).
Oto pełna implementacja interfejsu DownloaderService
:
Kotlin
// You must use the public key belonging to your publisher account const val BASE64_PUBLIC_KEY = "YourLVLKey" // You should also modify this salt val SALT = byteArrayOf( 1, 42, -12, -1, 54, 98, -100, -12, 43, 2, -8, -4, 9, 5, -106, -107, -33, 45, -1, 84 ) class SampleDownloaderService : DownloaderService() { override fun getPublicKey(): String = BASE64_PUBLIC_KEY override fun getSALT(): ByteArray = SALT override fun getAlarmReceiverClassName(): String = SampleAlarmReceiver::class.java.name }
Java
public class SampleDownloaderService extends DownloaderService { // You must use the public key belonging to your publisher account public static final String BASE64_PUBLIC_KEY = "YourLVLKey"; // You should also modify this salt public static final byte[] SALT = new byte[] { 1, 42, -12, -1, 54, 98, -100, -12, 43, 2, -8, -4, 9, 5, -106, -107, -33, 45, -1, 84 }; @Override public String getPublicKey() { return BASE64_PUBLIC_KEY; } @Override public byte[] getSALT() { return SALT; } @Override public String getAlarmReceiverClassName() { return SampleAlarmReceiver.class.getName(); } }
Uwaga: musisz zaktualizować wartość BASE64_PUBLIC_KEY
.
jako klucz publiczny należący do Twojego konta wydawcy. Klucz znajdziesz na stronie
Konsola w informacjach o profilu. Jest to konieczne nawet podczas testowania
pobrane pliki.
Pamiętaj, aby zadeklarować usługę w pliku manifestu:
<app ...> <service android:name=".SampleDownloaderService" /> ... </app>
Wdrażanie odbiornika alarmu
Aby monitorować postęp pobierania pliku i w razie potrzeby rozpocząć pobieranie od nowa, narzędzie
DownloaderService
planuje alarm o RTC_WAKEUP
, który:
dostarcza Intent
do BroadcastReceiver
w
. Aby wywołać interfejs API, musisz zdefiniować BroadcastReceiver
z biblioteki narzędzia do pobierania, która sprawdza stan pobierania i uruchamia się ponownie.
w razie potrzeby.
Wystarczy, że zastąpisz metodę onReceive()
, aby wywołać DownloaderClientMarshaller.startDownloadServiceIfRequired()
.
Na przykład:
Kotlin
class SampleAlarmReceiver : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { try { DownloaderClientMarshaller.startDownloadServiceIfRequired( context, intent, SampleDownloaderService::class.java ) } catch (e: PackageManager.NameNotFoundException) { e.printStackTrace() } } }
Java
public class SampleAlarmReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { try { DownloaderClientMarshaller.startDownloadServiceIfRequired(context, intent, SampleDownloaderService.class); } catch (NameNotFoundException e) { e.printStackTrace(); } } }
Zwróć uwagę, że jest to klasa, dla której musisz zwrócić nazwę
w metodzie getAlarmReceiverClassName()
Twojej usługi (zobacz poprzednią sekcję).
Pamiętaj, aby zadeklarować odbiorcę w pliku manifestu:
<app ...> <receiver android:name=".SampleAlarmReceiver" /> ... </app>
Rozpoczynanie pobierania
Główna aktywność w aplikacji (uruchomiona przez ikonę programu uruchamiającego) to odpowiada za sprawdzenie, czy pliki rozszerzeń znajdują się już na urządzeniu i inicjowanie, pobieranie.
Aby rozpocząć pobieranie za pomocą biblioteki narzędzia do pobierania, musisz spełnić te wymagania: procedury:
- Sprawdź, czy pliki zostały pobrane.
Biblioteka narzędzia do pobierania zawiera niektóre interfejsy API z klasy
Helper
do pomoc w tym procesie:getExpansionAPKFileName(Context, c, boolean mainFile, int versionCode)
doesFileExist(Context c, String fileName, long fileSize)
Na przykład przykładowa aplikacja udostępniona w pakiecie rozszerzenia Apk wywołuje tę metodę w metodzie
onCreate()
aktywności, aby sprawdzić, możesz sprawdzić, czy pliki rozszerzeń znajdują się już na urządzeniu:Kotlin
fun expansionFilesDelivered(): Boolean { xAPKS.forEach { xf -> Helpers.getExpansionAPKFileName(this, xf.isBase, xf.fileVersion).also { fileName -> if (!Helpers.doesFileExist(this, fileName, xf.fileSize, false)) return false } } return true }
Java
boolean expansionFilesDelivered() { for (XAPKFile xf : xAPKS) { String fileName = Helpers.getExpansionAPKFileName(this, xf.isBase, xf.fileVersion); if (!Helpers.doesFileExist(this, fileName, xf.fileSize, false)) return false; } return true; }
W tym przypadku każdy obiekt
XAPKFile
zawiera numer wersji i rozmiar pliku znanego oraz wartość logiczną określającą, czy jest to główny plik rozszerzenia. (Zobacz przykład: klasySampleDownloaderActivity
aplikacji, aby uzyskać więcej informacji).Jeśli ta metoda zwraca wartość fałsz, aplikacja musi rozpocząć pobieranie.
- Rozpocznij pobieranie od wywołania metody statycznej
DownloaderClientMarshaller.startDownloadServiceIfRequired(Context c, PendingIntent notificationClient, Class<?> serviceClass)
.Przyjmuje ona te parametry:
context
:Context
Twojej aplikacji.notificationClient
:PendingIntent
do rozpoczęcia głównego działania. Jest on używany wNotification
, w którym dyrektywaDownloaderService
i wyświetla postęp pobierania. Gdy użytkownik wybierze powiadomienie, wywołujePendingIntent
podany przez Ciebie w tym miejscu i powinien otworzyć aktywność pokazuje postęp pobierania (zwykle jest to to samo działanie, które zaczęło pobieranie).serviceClass
: obiektClass
dla Twojej implementacjiDownloaderService
, wymagane do uruchomienia usługi i rozpoczęcia pobierania w razie potrzeby.
Metoda zwraca liczbę całkowitą, która wskazuje, czy konieczne jest ich pobranie. Możliwe wartości to:
NO_DOWNLOAD_REQUIRED
: zwracany, jeśli pliki istnieje albo trwa pobieranie.LVL_CHECK_REQUIRED
: zwracany, jeśli weryfikacja licencji jest wymagane do uzyskania adresów URL plików rozszerzających.DOWNLOAD_REQUIRED
: zwracany, jeśli adresy URL plików rozszerzających są już znane, ale nie zostały pobrane.
Działanie funkcji
LVL_CHECK_REQUIRED
iDOWNLOAD_REQUIRED
to zasadniczo jest taka sama i nie musisz się o nie martwić. W swojej głównej aktywności, która wywołujestartDownloadServiceIfRequired()
, możesz po prostu sprawdzić, czy odpowiedź toNO_DOWNLOAD_REQUIRED
. Jeśli odpowiedź to inna niżNO_DOWNLOAD_REQUIRED
, Biblioteka narzędzia do pobierania rozpocznie pobieranie, dlatego musisz zaktualizować UI aktywności, wyświetlić postęp pobierania (patrz następny krok). Jeśli odpowiedź toNO_DOWNLOAD_REQUIRED
, pliki są dostępne i aplikacja może się uruchomić.Na przykład:
Kotlin
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // Check if expansion files are available before going any further if (!expansionFilesDelivered()) { val pendingIntent = // Build an Intent to start this activity from the Notification Intent(this, MainActivity::class.java).apply { flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP }.let { notifierIntent -> PendingIntent.getActivity( this, 0, notifierIntent, PendingIntent.FLAG_UPDATE_CURRENT ) } // Start the download service (if required) val startResult: Int = DownloaderClientMarshaller.startDownloadServiceIfRequired( this, pendingIntent, SampleDownloaderService::class.java ) // If download has started, initialize this activity to show // download progress if (startResult != DownloaderClientMarshaller.NO_DOWNLOAD_REQUIRED) { // This is where you do set up to display the download // progress (next step) ... return } // If the download wasn't necessary, fall through to start the app } startApp() // Expansion files are available, start the app }
Java
@Override public void onCreate(Bundle savedInstanceState) { // Check if expansion files are available before going any further if (!expansionFilesDelivered()) { // Build an Intent to start this activity from the Notification Intent notifierIntent = new Intent(this, MainActivity.getClass()); notifierIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP); ... PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notifierIntent, PendingIntent.FLAG_UPDATE_CURRENT); // Start the download service (if required) int startResult = DownloaderClientMarshaller.startDownloadServiceIfRequired(this, pendingIntent, SampleDownloaderService.class); // If download has started, initialize this activity to show // download progress if (startResult != DownloaderClientMarshaller.NO_DOWNLOAD_REQUIRED) { // This is where you do set up to display the download // progress (next step) ... return; } // If the download wasn't necessary, fall through to start the app } startApp(); // Expansion files are available, start the app }
- Gdy metoda
startDownloadServiceIfRequired()
zwraca dowolną inną wartość niżNO_DOWNLOAD_REQUIRED
, utwórz instancjęIStub
przez WywołujęDownloaderClientMarshaller.CreateStub(IDownloaderClient client, Class<?> downloaderService)
.IStub
tworzy powiązanie między Twoją aktywnością a narzędziem do pobierania tak aby Twoja aktywność odbierała wywołania zwrotne dotyczące postępu pobierania.Aby utworzyć instancję
IStub
, wywołując metodęCreateStub()
, musisz ją przekazać wdrożenie interfejsuIDownloaderClient
iDownloaderService
implementacji. W następnej sekcji o otrzymywaniu postępów pobierania interfejsuIDownloaderClient
, który zwykle należy wdrożyć w klasieActivity
, aby móc aktualizować interfejs aktywności po zmianie stanu pobierania.Zalecamy wywołanie metody
CreateStub()
, aby utworzyć wystąpienieIStub
podczas metodyonCreate()
aktywności postartDownloadServiceIfRequired()
rozpocznie pobieranie.Na przykład w poprzednim przykładowym kodzie dla funkcji
onCreate()
możesz odpowiedzieć na wynikstartDownloadServiceIfRequired()
w ten sposób:Kotlin
// Start the download service (if required) val startResult = DownloaderClientMarshaller.startDownloadServiceIfRequired( this@MainActivity, pendingIntent, SampleDownloaderService::class.java ) // If download has started, initialize activity to show progress if (startResult != DownloaderClientMarshaller.NO_DOWNLOAD_REQUIRED) { // Instantiate a member instance of IStub downloaderClientStub = DownloaderClientMarshaller.CreateStub(this, SampleDownloaderService::class.java) // Inflate layout that shows download progress setContentView(R.layout.downloader_ui) return }
Java
// Start the download service (if required) int startResult = DownloaderClientMarshaller.startDownloadServiceIfRequired(this, pendingIntent, SampleDownloaderService.class); // If download has started, initialize activity to show progress if (startResult != DownloaderClientMarshaller.NO_DOWNLOAD_REQUIRED) { // Instantiate a member instance of IStub downloaderClientStub = DownloaderClientMarshaller.CreateStub(this, SampleDownloaderService.class); // Inflate layout that shows download progress setContentView(R.layout.downloader_ui); return; }
Po powrocie metody
onCreate()
aktywność odbiera połączenie z numeremonResume()
– tam należy wtedy wywołajconnect()
wIStub
, przekazując przy tym wynikContext
Twojej aplikacji. I na odwrót, wywołajdisconnect()
w wywołaniu zwrotnymonStop()
Twojej aktywności.Kotlin
override fun onResume() { downloaderClientStub?.connect(this) super.onResume() } override fun onStop() { downloaderClientStub?.disconnect(this) super.onStop() }
Java
@Override protected void onResume() { if (null != downloaderClientStub) { downloaderClientStub.connect(this); } super.onResume(); } @Override protected void onStop() { if (null != downloaderClientStub) { downloaderClientStub.disconnect(this); } super.onStop(); }
Wywołanie funkcji
connect()
w narzędziuIStub
wiąże Twoją aktywność z instancjąDownloaderService
, dzięki czemu otrzymuje wywołania zwrotne dotyczące zmian w pobieranym pliku. za pomocą interfejsuIDownloaderClient
.
Odbieram informacje o postępie pobierania
Aby otrzymywać informacje o postępie pobierania i korzystać z narzędzia DownloaderService
, musisz wdrożyć interfejs IDownloaderClient
biblioteki pobierania.
Zwykle działanie rozpoczynające pobieranie powinno implementować ten interfejs,
wyświetlać postęp pobierania i wysyłać żądania do usługi.
Wymagane metody interfejsu dla IDownloaderClient
:
onServiceConnected(Messenger m)
- Po utworzeniu wystąpienia
IStub
w swojej aktywności otrzymasz połączenie która przekazuje obiektMessenger
połączony z Twoją instancją zDownloaderService
. Aby wysyłać żądania do usługi, na przykład wstrzymywać i wznawiać działanie pobierania, należy wywołać interfejsDownloaderServiceMarshaller.CreateProxy()
, aby uzyskać dostęp do interfejsuIDownloaderService
połączonego z usługą.Zalecana implementacja wygląda tak:
Kotlin
private var remoteService: IDownloaderService? = null ... override fun onServiceConnected(m: Messenger) { remoteService = DownloaderServiceMarshaller.CreateProxy(m).apply { downloaderClientStub?.messenger?.also { messenger -> onClientUpdated(messenger) } } }
Java
private IDownloaderService remoteService; ... @Override public void onServiceConnected(Messenger m) { remoteService = DownloaderServiceMarshaller.CreateProxy(m); remoteService.onClientUpdated(downloaderClientStub.getMessenger()); }
Po zainicjowaniu obiektu
IDownloaderService
możesz wysyłać polecenia do usługi pobierania, np. wstrzymania i wznowienia pobierania (requestPauseDownload()
irequestContinueDownload()
). onDownloadStateChanged(int newState)
- Usługa pobierania wywołuje to polecenie, gdy nastąpi zmiana stanu pobierania, na przykład
rozpocznie się lub zakończy pobieranie.
Wartość
newState
będzie jedną z kilku możliwych wartości określonych w parametrze jedną ze stałychSTATE_*
klasyIDownloaderClient
.Aby przekazać użytkownikom przydatną wiadomość, możesz poprosić o odpowiedni ciąg znaków. dla każdego stanu, wywołując
Helpers.getDownloaderStringResourceIDFromState()
. Ten zwraca identyfikator zasobu jednego z ciągów połączonych z narzędziem do pobierania Biblioteka. Na przykład tekst „Pobieranie wstrzymane z powodu roamingu” odpowiada wartościSTATE_PAUSED_ROAMING
. onDownloadProgress(DownloadProgressInfo progress)
- Usługa pobierania wywołuje to, aby przesłać obiekt
DownloadProgressInfo
, który zawiera różne informacje o postępie pobierania, w tym szacowany czas do jego zakończenia, aktualna szybkość, ogólny postęp i suma, które pozwalają aktualizować UI postępu pobierania.
Wskazówka: przykłady tych wywołań zwrotnych, które aktualizują pobierane pliki
interfejsu postępu, patrz SampleDownloaderActivity
w przykładowej aplikacji z
Pakiet rozszerzenia pliku APK.
Niektóre publiczne metody korzystania z interfejsu IDownloaderService
, które mogą Ci się przydać:
requestPauseDownload()
- Wstrzymuje pobieranie.
requestContinueDownload()
- Wznawia wstrzymane pobieranie.
setDownloadFlags(int flags)
- Określa typy sieci, w których użytkownik może pobierać pliki.
bieżąca implementacja obsługuje 1 flagę,
FLAGS_DOWNLOAD_OVER_CELLULAR
, ale możesz dodać reszta. Domyślnie ta flaga nie jest włączona, więc aby pobrać, użytkownik musi mieć połączenie z Wi-Fi plików rozszerzeń. Możesz określić preferencje użytkownika, aby umożliwić pobieranie przez do sieci komórkowej. W takim przypadku możesz zadzwonić pod numer:Kotlin
remoteService = DownloaderServiceMarshaller.CreateProxy(m).apply { ... setDownloadFlags(IDownloaderService.FLAGS_DOWNLOAD_OVER_CELLULAR) }
Java
remoteService .setDownloadFlags(IDownloaderService.FLAGS_DOWNLOAD_OVER_CELLULAR);
Przy użyciu APKExpansionPolicy
Jeśli zamiast korzystać z Google Play, wolisz stworzyć własną usługę pobierania
biblioteki narzędzia do pobierania, nadal należy korzystać z biblioteki APKExpansionPolicy
dostępnej w bibliotece weryfikacji licencji. Klasa APKExpansionPolicy
jest prawie taka sama jak ServerManagedPolicy
(dostępna w
biblioteki weryfikacji licencji Google Play), ale obejmuje dodatkową obsługę rozszerzania pliku APK.
w pliku.
Uwaga: jeśli używasz Biblioteki pobierania zgodnie z opisem w poprzedniej sekcji,
Biblioteka wykonuje wszystkie działania z tagiem APKExpansionPolicy
, więc nie musisz używać
bezpośrednio na tych zajęciach.
Zajęcia te obejmują metody, które pomagają zdobyć niezbędne informacje o dostępnych opcjach pliki rozszerzeń:
getExpansionURLCount()
getExpansionURL(int index)
getExpansionFileName(int index)
getExpansionFileSize(int index)
Aby uzyskać więcej informacji o tym, jak korzystać z funkcji APKExpansionPolicy
, gdy nie
przy użyciu biblioteki narzędzia do pobierania, zapoznaj się z dokumentacją dotyczącą dodawania licencji do aplikacji,
który wyjaśnia, jak wdrożyć taką zasadę dotyczącą licencji.
Odczytywanie pliku rozszerzenia
Po zapisaniu plików rozszerzeń APK na urządzeniu możesz sprawdzić sposób odczytywania plików
zależy od typu użytego pliku. Jak wspomnieliśmy w omówieniu, funkcje
pliki rozszerzające mogą być dowolnymi plikami
ale są zmieniane przy użyciu określonego formatu nazwy pliku i są zapisywane
<shared-storage>/Android/obb/<package-name>/
.
Niezależnie od sposobu odczytywania plików, zawsze najpierw sprawdź, czy zewnętrzny dostępna jest pamięć masowa do odczytu. Możliwe, że użytkownik ma pamięć podręczną przez USB lub wyjął(a) kartę SD.
Uwaga: przy uruchamianiu aplikacji zawsze sprawdzaj, czy
pamięć zewnętrzna jest dostępna i można ją odczytać, wywołując getExternalStorageState()
. Zwraca jeden z kilku możliwych ciągów
reprezentującą stan pamięci zewnętrznej. Aby był czytelny dla
app, zwrócona wartość musi wynosić MEDIA_MOUNTED
.
Pobieram nazwy plików
Zgodnie z opisem w omówieniu pliki rozszerzeń APK są zapisywane. w określonym formacie nazwy pliku:
[main|patch].<expansion-version>.<package-name>.obb
Aby uzyskać lokalizację i nazwy plików rozszerzeń, skorzystaj z funkcji
getExternalStorageDirectory()
i getPackageName()
do utworzenia ścieżki do plików.
Oto metoda, której możesz użyć w aplikacji, aby uzyskać tablicę zawierającą pełną ścieżkę do obu plików rozszerzeń:
Kotlin
fun getAPKExpansionFiles(ctx: Context, mainVersion: Int, patchVersion: Int): Array<String> { val packageName = ctx.packageName val ret = mutableListOf<String>() if (Environment.getExternalStorageState() == Environment.MEDIA_MOUNTED) { // Build the full path to the app's expansion files val root = Environment.getExternalStorageDirectory() val expPath = File(root.toString() + EXP_PATH + packageName) // Check that expansion file path exists if (expPath.exists()) { if (mainVersion > 0) { val strMainPath = "$expPath${File.separator}main.$mainVersion.$packageName.obb" val main = File(strMainPath) if (main.isFile) { ret += strMainPath } } if (patchVersion > 0) { val strPatchPath = "$expPath${File.separator}patch.$mainVersion.$packageName.obb" val main = File(strPatchPath) if (main.isFile) { ret += strPatchPath } } } } return ret.toTypedArray() }
Java
// The shared path to all app expansion files private final static String EXP_PATH = "/Android/obb/"; static String[] getAPKExpansionFiles(Context ctx, int mainVersion, int patchVersion) { String packageName = ctx.getPackageName(); Vector<String> ret = new Vector<String>(); if (Environment.getExternalStorageState() .equals(Environment.MEDIA_MOUNTED)) { // Build the full path to the app's expansion files File root = Environment.getExternalStorageDirectory(); File expPath = new File(root.toString() + EXP_PATH + packageName); // Check that expansion file path exists if (expPath.exists()) { if ( mainVersion > 0 ) { String strMainPath = expPath + File.separator + "main." + mainVersion + "." + packageName + ".obb"; File main = new File(strMainPath); if ( main.isFile() ) { ret.add(strMainPath); } } if ( patchVersion > 0 ) { String strPatchPath = expPath + File.separator + "patch." + mainVersion + "." + packageName + ".obb"; File main = new File(strPatchPath); if ( main.isFile() ) { ret.add(strPatchPath); } } } } String[] retArray = new String[ret.size()]; ret.toArray(retArray); return retArray; }
Możesz wywołać tę metodę, przekazując ją do aplikacji Context
oraz wersję żądanego pliku rozszerzenia.
Numer wersji pliku rozszerzenia można określić na wiele sposobów. Prostym sposobem jest
zapisz wersję w pliku SharedPreferences
po rozpoczęciu pobierania, przez
i wysyła zapytanie o nazwę pliku rozszerzenia za pomocą metody getExpansionFileName(int index)
klasy APKExpansionPolicy
. Kod wersji możesz uzyskać, odczytując plik SharedPreferences
, gdy chcesz uzyskać dostęp do rozszerzenia
.
Więcej informacji o odczytywaniu z pamięci współdzielonej znajdziesz w sekcji Magazyn danych. dokumentacji.
Używanie biblioteki ZIP rozszerzenia APK
Pakiet rozszerzenia Apk Google Market zawiera bibliotekę o nazwie APK
Rozszerzona biblioteka Zip (dostępna w: <sdk>/extras/google/google_market_apk_expansion/zip_file/
). To jest opcjonalna biblioteka, która
ułatwia odczytywanie rozszerzenia zasięgu,
gdy są zapisywane jako pliki ZIP. Korzystanie z tej biblioteki pozwala łatwo odczytywać zasoby z
ZIP jako wirtualny system plików.
Biblioteka ZIP rozszerzeń APK zawiera te klasy i interfejsy API:
APKExpansionSupport
- Udostępnia kilka metod dostępu do nazw plików rozszerzających i plików ZIP:
getAPKExpansionFiles()
- Ta sama metoda jak powyżej, która zwraca pełną ścieżkę pliku do obu rozwinięcia .
getAPKExpansionZipFile(Context ctx, int mainVersion, int patchVersion)
- Zwraca wartość
ZipResourceFile
reprezentującą sumę zarówno pliku głównego, jak i . Oznacza to, że jeśli podasz zarównomainVersion
, jak ipatchVersion
, zwraca wartośćZipResourceFile
, która zapewnia dostęp do odczytu funkcji wszystkie dane, z danymi z pliku poprawki scalonym nad plikiem głównym.
ZipResourceFile
- Reprezentuje plik ZIP w pamięci współdzielonej i wykonuje całą pracę, aby udostępnić
na podstawie plików ZIP. Możesz uzyskać instancję za pomocą
APKExpansionSupport.getAPKExpansionZipFile()
lubZipResourceFile
, przekazując ją w metodzie ścieżki do pliku rozszerzenia. Te zajęcia obejmują wiele przydatnych metod, ale zazwyczaj nie potrzebują dostępu do większości z nich. Kilka ważnych metod to:getInputStream(String assetPath)
- Udostępnia
InputStream
umożliwiający odczyt pliku w pliku ZIP.assetPath
musi być ścieżką do żądanego pliku podaną w odniesieniu do katalogu głównego zawartości pliku ZIP. getAssetFileDescriptor(String assetPath)
- Udostępnia
AssetFileDescriptor
dla pliku w zakresie ZIP.assetPath
musi być ścieżką do żądanego pliku podaną w odniesieniu do katalogu głównego zawartości pliku ZIP. Jest to przydatne w przypadku określonych interfejsów API Androida, które wymagająAssetFileDescriptor
, na przykład niektórych interfejsów APIMediaPlayer
.
APEZProvider
- Większość aplikacji nie musi używać tych zajęć. Ta klasa definiuje element
ContentProvider
, który grupuje dane z plików ZIP za pomocą treściUri
, aby umożliwić dostęp do plików określonym interfejsom API Androida, które oczekuje dostępuUri
do plików multimedialnych. Jest to przydatne, jeśli na przykład chcesz odtwórz film na urządzeniuVideoView.setVideoURI()
.
Pomijam kompresję ZIP z plikami multimedialnymi
Jeśli przechowujesz pliki multimedialne w plikach rozszerzeń, archiwum ZIP umożliwia
używać wywołań funkcji odtwarzania multimediów na Androidzie z elementami sterującymi przesunięciem i długością (np. MediaPlayer.setDataSource()
,
SoundPool.load()
). Aby
nie działa, nie należy wykonywać dodatkowej kompresji plików multimedialnych podczas tworzenia pliku ZIP.
przesyłek. Na przykład w narzędziu zip
należy użyć narzędzia -n
możesz określić sufiksy plików, które nie powinny być skompresowane:
zip -n .mp4;.ogg main_expansion media_files
Odczyt z pliku ZIP
Jeśli używasz biblioteki ZIP rozszerzenia APK, odczytanie pliku z pliku ZIP zwykle wymaga :
Kotlin
// Get a ZipResourceFile representing a merger of both the main and patch files val expansionFile = APKExpansionSupport.getAPKExpansionZipFile(appContext, mainVersion, patchVersion) // Get an input stream for a known file inside the expansion file ZIPs expansionFile.getInputStream(pathToFileInsideZip).use { ... }
Java
// Get a ZipResourceFile representing a merger of both the main and patch files ZipResourceFile expansionFile = APKExpansionSupport.getAPKExpansionZipFile(appContext, mainVersion, patchVersion); // Get an input stream for a known file inside the expansion file ZIPs InputStream fileStream = expansionFile.getInputStream(pathToFileInsideZip);
Powyższy kod umożliwia dostęp do każdego pliku istniejącego w głównym pliku rozszerzenia lub
pliku rozszerzenia poprawki, odczytując scaloną mapę wszystkich plików z obu plików. Ty
należy podać metodę getAPKExpansionFile()
, czyli aplikację android.content.Context
, a także numer wersji głównego pliku rozszerzenia i poprawki.
.
Jeśli wolisz odczytać dane z konkretnego pliku rozszerzenia, możesz użyć konstruktora ZipResourceFile
ze ścieżką do odpowiedniego pliku rozszerzenia:
Kotlin
// Get a ZipResourceFile representing a specific expansion file val expansionFile = ZipResourceFile(filePathToMyZip) // Get an input stream for a known file inside the expansion file ZIPs expansionFile.getInputStream(pathToFileInsideZip).use { ... }
Java
// Get a ZipResourceFile representing a specific expansion file ZipResourceFile expansionFile = new ZipResourceFile(filePathToMyZip); // Get an input stream for a known file inside the expansion file ZIPs InputStream fileStream = expansionFile.getInputStream(pathToFileInsideZip);
Więcej informacji o korzystaniu z tej biblioteki w przypadku plików rozszerzeń znajdziesz tutaj:
klasy SampleDownloaderActivity
w przykładowej aplikacji, która zawiera dodatkowy kod do
sprawdzić pobrane pliki za pomocą CRC. Pamiętaj, że jeśli wykorzystasz tę próbkę jako podstawę
Twojej implementacji wymaga zadeklarowania rozmiaru rozszerzenia w bajtach
w tablicy xAPKS
.
Testowanie plików rozszerzających
Zanim opublikujesz aplikację, warto przetestować 2 rzeczy: przeczytanie rozszerzeń i pobierania plików.
Testuję odczyty plików
Zanim prześlesz aplikację do Google Play, powinno przetestować możliwość odczytu plików z pamięci współdzielonej przez aplikację. Wszystko, co musisz zrobić to umieszczenie plików w odpowiedniej lokalizacji w pamięci współdzielonej urządzenia i uruchomienie aplikacja:
- Na urządzeniu utwórz w pamięci współdzielonej odpowiedni katalog, w którym Google
Google Play zapisze Twoje pliki.
Jeśli na przykład nazwa Twojego pakietu to
com.example.android
, musisz utworzyć kataloguAndroid/obb/com.example.android/
w pamięci współdzielonej. (Podłącz urządzenia testowego do komputera, aby podłączyć pamięć współdzieloną i ręcznie utworzyć ). - Dodaj ręcznie do tego katalogu pliki rozszerzeń. Pamiętaj, aby zmienić ich nazwy na
muszą być zgodne z formatem nazwy pliku, którego będzie używać Google Play.
Na przykład bez względu na typ pliku główny plik rozszerzenia aplikacji
com.example.android
powinien mieć formatmain.0300110.com.example.android.obb
. Kod wersji może mieć dowolną wartość. Pamiętaj:- Główny plik rozszerzający zaczyna się zawsze od
main
, a plik poprawki – odpatch
- Nazwa pakietu zawsze odpowiada nazwie pliku APK, do którego jest dołączony plik. Google Play.
- Główny plik rozszerzający zaczyna się zawsze od
- Po zapisaniu plików rozszerzenia na urządzeniu możesz zainstalować i uruchomić aplikację przetestować pliki rozszerzające.
Oto kilka przypomnień o obsłudze plików rozszerzeń:
- Nie usuwaj plików rozszerzeń
.obb
ani nie zmieniaj ich nazw (nawet po rozpakowaniu dane w innej lokalizacji). Spowoduje to, że Google Play (lub sama aplikacja) pobrać plik rozszerzający. - Nie zapisuj innych danych na koncie
obb/
Katalog. Jeśli musisz rozpakować niektóre dane, zapisz je w lokalizacji podanej w zasadziegetExternalFilesDir()
.
Testuję pobieranie plików
Ponieważ aplikacja po raz pierwszy musi czasami ręcznie pobrać pliki rozszerzeń warto przetestować ten proces, by mieć pewność, że aplikacja prawidłowo pod kątem adresów URL, pobierz pliki i zapisz je na urządzeniu.
Aby sprawdzić wdrożenie procedury pobierania ręcznego w aplikacji: możesz opublikować na ścieżce testu wewnętrznego, by był dostępny tylko autoryzowanych testerów. Jeśli wszystko działa zgodnie z oczekiwaniami, aplikacja powinna pobieranie plików rozszerzeń rozpocznie się natychmiast po rozpoczęciu głównej aktywności.
Uwaga: wcześniej można było testować aplikację przez przesłanie nieopublikowanej wersji roboczej, wersji. Ta funkcja nie jest już dostępna obsługiwane. Zamiast tego musisz ją opublikować na ścieżce testów wewnętrznych, zamkniętych lub otwartych. śledzić. Więcej informacji: Wersje robocze aplikacji nie Dłużej obsługiwane.
Aktualizowanie aplikacji
Jedną z największych zalet korzystania z plików rozszerzeń w Google Play jest możliwość zaktualizować aplikację bez ponownego pobierania wszystkich oryginalnych zasobów. Ponieważ Google Play pozwala dostarczyć dwa pliki rozszerzające z każdym pakietem APK, drugi może służyć jako „poprawka” który zawiera aktualizacje i nowe zasoby. Pozwoli to uniknąć musisz ponownie pobrać główny plik rozszerzenia, bo może to być duży i kosztowny dla użytkowników.
Plik rozszerzenia poprawki jest technicznie taki sam jak główny plik rozszerzenia, ale żaden z nich system Android lub Google Play instaluje poprawki między rozszerzeniem głównym i poprawką. . Kod aplikacji musi samodzielnie instalować wszystkie niezbędne poprawki.
Jeśli używasz plików ZIP jako plików rozszerzających, plik APK Expansion Zip Biblioteka dołączona do pakietu rozszerzeń Apk obejmuje możliwość scalania Twój z głównym plikiem rozszerzenia.
Uwaga: nawet jeśli musisz wprowadzić tylko zmiany w poprawce.
pliku rozszerzenia, musisz mimo to zaktualizować pakiet APK, by umożliwić Google Play przeprowadzenie aktualizacji.
Jeśli nie potrzebujesz zmian w kodzie aplikacji, zaktualizuj versionCode
w
pliku manifestu.
O ile nie zmienisz głównego pliku rozszerzenia powiązanego z pakietem APK. użytkownicy, którzy wcześniej zainstalowali Twoją aplikację, pobierz główny plik rozszerzenia. Dotychczasowi użytkownicy otrzymają tylko zaktualizowany plik APK z nową poprawką (z zachowaniem poprzedniego głównego pliku rozszerzenia).
Oto kilka kwestii, o których warto pamiętać przy aktualizowaniu plików rozszerzeń:
- W przypadku aplikacji mogą być dostępne tylko 2 pliki rozszerzeń. 1 główne rozwinięcie i jednym plikiem rozszerzenia poprawki. Podczas aktualizowania pliku Google Play usuwa w poprzedniej wersji (podobnie jak w przypadku ręcznych aktualizacji).
- Przy dodawaniu pliku rozszerzenia z poprawką system Android nie instaluje poprawek aplikacji ani głównego pliku rozszerzenia. Musisz zaprojektować aplikację tak, aby obsługiwała dane poprawek. Pakiet rozszerzenia Apk zawiera bibliotekę do używania plików ZIP. jako pliki rozszerzające, które scalają dane z pliku poprawki z głównym plikiem rozszerzenia, możesz łatwo odczytać wszystkie dane w pliku rozszerzenia.