Tworzenie wielu plików APK dla różnych poziomów interfejsu API

Jeśli publikujesz aplikację w Google Play, musisz utworzyć i przesłać pakiet Android App Bundle. Gdy to zrobisz, Google Play automatycznie wygeneruje i udostępni pliki APK zoptymalizowane pod kątem konfiguracji urządzenia każdego użytkownika. Pobiera więc tylko kod i zasoby, których potrzebują do uruchomienia aplikacji. Jeśli nie publikujesz w Google Play, możesz publikować wiele plików APK, ale każdy z nich musisz utworzyć i podpisać. Musisz też samodzielnie utworzyć i podpisać każdy z nich.

Przy programowaniu aplikacji na Androida, które będą korzystać z wielu pakietów APK w Google Play, warto od razu stosować pewne sprawdzone metody, by uniknąć niepotrzebnych problemów w trakcie programowania. W tej lekcji pokazujemy, jak utworzyć kilka plików APK aplikacji, z których każdy będzie obsługiwał nieco inny zakres poziomów interfejsu API. Zyskasz też dostęp do narzędzi niezbędnych do jak najszybszego utrzymywania bazy kodu z wieloma plikami APK.

Potwierdź, że potrzebujesz wielu plików APK

Jeśli chcesz utworzyć aplikację, która będzie działać na różnych generacjach platformy Android, z pewnością zależy Ci na tym, aby korzystała z nowych funkcji na nowych urządzeniach, nie tracąc przy tym zgodności wstecznej. Na pierwszy rzut oka może się wydawać, że obsługa wielu plików APK jest najlepszym rozwiązaniem, ale często tak nie jest. W sekcji Używanie pojedynczego pliku APK w przewodniku dla programistów obejmujących wiele plików APK znajdziesz przydatne informacje o tym, jak to zrobić, korzystając z jednego pliku APK. Znajdziesz tam m.in. naszą bibliotekę pomocy. Możesz też dowiedzieć się, jak pisać kod, który działa tylko na określonych poziomach interfejsu API w pojedynczym pliku APK, bez stosowania kosztownych pod względem obliczeniowym technik, takich jak odbicie lustrzane. Więcej informacji znajdziesz w tym artykule.

Jeśli możesz sobie z nim poradzić, ograniczenie aplikacji do jednego pliku APK ma kilka zalet, w tym:

  • Publikowanie i testowanie są łatwiejsze
  • Trzeba utrzymywać tylko jeden kod źródłowy.
  • Aplikacja może dostosowywać się do zmian w konfiguracji urządzenia
  • Przywracanie aplikacji na różnych urządzeniach po prostu działa
  • Nie musisz się martwić preferencjami rynkowymi, zachowaniem po „uaktualnieniu” z jednego pliku APK na inny ani tym, który plik APK pasuje do której klasy urządzeń.

W dalszej części tej lekcji zakładamy, że znasz już ten temat, przyswajasz materiał z powiązanych zasobów i stwierdzisz, że odpowiednią ścieżką do Twojej aplikacji może być kilka plików APK.

Przedstaw swoje wymagania

Najpierw utwórz prosty wykres, aby szybko określić, ile plików APK potrzebujesz i jaki zakres interfejsu API pokrywa każdy z nich. Na stronie Wersje platformy w witrynie dla deweloperów aplikacji na Androida znajdziesz dane o względnej liczbie aktywnych urządzeń, na których działa dana wersja platformy Androida. Poza tym, choć na początku może się to wydawać proste, śledzenie, do których poziomów interfejsu API kieruje się każdy plik APK, dość szybko staje się trudne, zwłaszcza jeśli występuje nakładanie się (a często tak się dzieje). Na szczęście można szybko i łatwo sporządzić schemat wymagań, aby później łatwo się do niego odnieść.

Aby utworzyć wykres z większą liczbą pakietów APK, zacznij od wiersza komórek reprezentujących różne poziomy interfejsu API platformy Android. Dodaj na końcu dodatkową komórkę, aby reprezentować przyszłe wersje Androida.

3 4 5 6 7 8 9 10 11 12 13 +

Teraz pokoloruj wykres tak, aby każdy kolor odpowiadał jednemu plikowi APK. Oto przykład zastosowania każdego pakietu APK na określonym zakresie poziomów API.

3 4 5 6 7 8 9 10 11 12 13 +

Gdy utworzysz ten wykres, przekaż go swojemu zespołowi. Komunikacja w zespole dotycząca projektu stała się łatwiejsza, ponieważ zamiast pytać „Jak wygląda APK dla poziomów interfejsu API 3–6, czyli Androida 1.x, Co słychać?” Wystarczy powiedzieć „Jak idzie z tworzeniem pliku APK Blue?”.

Umieść cały wspólny kod i zasoby w projekcie biblioteki

Niezależnie od tego, czy modyfikujesz już istniejącą aplikację na Androida, czy tworzysz ją od podstaw, to właśnie to powinno być pierwszą i najważniejszą rzeczą, którą należy zrobić z bazą kodu. Wszystko, co wchodzi w skład projektu bibliotecznego, trzeba zaktualizować tylko raz (np. zlokalizowane na różne języki ciągi, motywy kolorystyczne, naprawione błędy w wspólnym kodzie), co skraca czas programowania i zmniejsza prawdopodobieństwo pomyłek, których można łatwo uniknąć.

Uwaga: chociaż szczegóły implementacji tworzenia i dołączania projektów w bibliotece wykraczają poza zakres tej lekcji, możesz zapoznać się z artykułem Tworzenie biblioteki Androida.

Jeśli konwertujesz istniejącą aplikację na wersję obsługującą wiele plików APK, przeszukaj kod pod kątem każdego zlokalizowanego pliku z wierszami, listy wartości, kolorów motywu, ikon menu i układów, które nie będą się zmieniać w różnych plikach APK, i umieścić je w projekcie biblioteki. Kod, który nie ulegnie znacznym zmianom, powinien również znaleźć się w projekcie biblioteki. Prawdopodobnie będziesz musiał rozszerzyć te klasy, aby dodać jedną lub dwie metody z pliku APK.

Jeśli natomiast tworzysz aplikację od zera, najpierw postaraj się napisać kod w projekcie bibliotecznym biblioteki, a następnie w razie potrzeby przenieś go do konkretnego pliku APK. Długofalowo jest to znacznie łatwiejsze niż dodawanie do jednej, potem do drugiej, potem do kolejnej, a potem po kilku miesiącach próbowanie ustalić, czy ten blob można przenieść do sekcji biblioteki bez niszczenia czegokolwiek.

Tworzenie nowych projektów APK

Do każdego pakietu APK, który zamierzasz opublikować, powinien istnieć oddzielny projekt na Androida. Aby ułatwić organizację, umieść projekt biblioteki i wszystkie powiązane projekty APK w tym samym folderze nadrzędnym. Pamiętaj też, że każdy plik APK musi mieć tę samą nazwę pakietu, ale nie musi mieć tej samej nazwy co biblioteka. Jeśli masz 3 pliki APK zgodnie ze schematem opisanym wcześniej, katalog główny może wyglądać tak:

alexlucas:~/code/multi-apks-root$ ls
foo-blue
foo-green
foo-lib
foo-red

Po utworzeniu projektów dodaj projekt biblioteki jako odwołanie do każdego projektu APK. Jeśli to możliwe, zdefiniuj aktywność początkową w projekcie biblioteki i rozszerzaj ją w projekcie APK. Jeśli masz określone działanie początkowe w projekcie biblioteki, możesz umieścić wszystkie inicjalizacje aplikacji w jednym miejscu, dzięki czemu nie trzeba będzie ponownie wdrażać „uniwersalnych” zadań, takich jak inicjowanie Analytics, sprawdzanie licencji czy inne procedury inicjowania, które nie ulegną zmianie w znaczących stopniu w poszczególnych pakietach APK.

Dostosuj pliki manifestu

Gdy użytkownik pobiera z Google Play aplikację, która korzysta z wielu plików APK, właściwy plik APK do wyboru jest wybierany na podstawie 2 prostych reguł:

  • Plik manifestu musi pokazywać, że dany plik APK spełnia wymagania
  • Spośród kwalifikujących się plików APK wygrywa największy numer wersji

Załóżmy na przykład, że w opisanym wcześniej zestawie z wieloma plikami APK zakładamy, że nie ustawiono maksymalnego poziomu interfejsu API dla żadnego z nich. W przypadku każdego pliku APK zakres możliwych wartości wyglądałby tak:

3 4 5 6 7 8 9 10 11 12 13 +
3 4 5 6 7 8 9 10 11 12 13 +
3 4 5 6 7 8 9 10 11 12 13 +

Ponieważ plik APK o większej wartości parametru minSdkVersion musi mieć również wyższy kod wersji, wiemy, że w przypadku wartości versionCode czerwony ≥ zielony ≥ niebieski. Dlatego możemy zwinąć wykres, aby wyglądał tak:

3 4 5 6 7 8 9 10 11 12 13 +

Przyjmijmy teraz, że w przypadku czerwonego pakietu APK wymagane są wymagania, których nie spełniają pozostałe 2 opcje. Na stronie Filtry w Google Play w przewodniku dla programistów aplikacji na Androida znajduje się pełna lista potencjalnych problemów. Załóżmy na przykład, że kolor czerwony wymaga użycia przedniego aparatu. Celem czerwonego pliku APK jest połączenie przedniej kamery z nowymi funkcjami dodanymi w interfejsie API 11. Okazuje się jednak, że nie wszystkie urządzenia, które obsługują interfejs API 11, mają nawet przednie kamery. horror!

Na szczęście, jeśli użytkownik przegląda Google Play na takim urządzeniu, Google Play sprawdzi plik i zobaczy, że przedni aparat jest wymagany, a potem dyskretnie go zignoruje, mając pewność, że czerwony i urządzenie nie pasuje do tego typu urządzeń. Następnie stwierdzi, że kolor zielony jest nie tylko kompatybilny z urządzeniami z interfejsem API 11 (ponieważ nie zdefiniowano parametru maxSdkVersion), ale nie ma znaczenia, czy jest wyposażony w przedni aparat. Użytkownik może pobrać aplikację z Google Play, ponieważ pomimo awarii przedniego aparatu dostępny był pakiet APK, który obsługiwał dany poziom interfejsu API.

Aby wszystkie pliki APK mieć oddzielne „ścieżki”, ważne jest stosowanie dobrego schematu kodu wersji. Zalecane ustawienia znajdziesz w sekcji Kody wersji w poradniku dla deweloperów. Ponieważ przykładowy zestaw plików APK dotyczy tylko 1 z 3 możliwych wymiarów, wystarczy rozdzielić każdy plik APK o 1000, ustawić pierwsze 2 cyfry na wartość minSdkVersion danego pliku APK i od niej zwiększać. Może to wyglądać tak:

Niebieski: 03001, 03002, 03003, 03004…
Zielone: 07001, 07002, 07003, 07004…
Czerwony:11001, 11002, 11003, 11004...

Po połączeniu wszystkich tych elementów pliki Android Manifest będą wyglądać mniej więcej tak:

Niebieski:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    android:versionCode="03001" android:versionName="1.0" package="com.example.foo">
    <uses-sdk android:minSdkVersion="3" />
    ...

Zielony:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    android:versionCode="07001" android:versionName="1.0" package="com.example.foo">
    <uses-sdk android:minSdkVersion="7" />
    ...

Czerwony:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    android:versionCode="11001" android:versionName="1.0" package="com.example.foo">
    <uses-sdk android:minSdkVersion="11" />
    ...

Przejrzyj listę kontrolną przed opublikowaniem

Przed przesłaniem aplikacji do Google Play dokładnie sprawdź te kwestie. Pamiętaj, że dotyczą one wielu plików APK i w żaden sposób nie stanowią pełnej listy kontrolnej dla wszystkich aplikacji przesyłanych do Google Play.

  • Wszystkie pliki APK muszą mieć tę samą nazwę pakietu
  • Wszystkie pliki APK muszą być podpisane tym samym certyfikatem.
  • Jeśli wersje plików APK nakładają się na siebie w wersji platformy, ten z większą wartością parametru minSdkVersion musi mieć wyższy kod wersji
  • Sprawdź, czy w plikach manifestu nie ma sprzecznych informacji (plik APK, który obsługuje tylko ekrany w formacie XLARGE, nie będzie widoczny dla nikogo).
  • Plik manifestu każdego pliku APK musi być unikalny co najmniej w przypadku jednej z tych cech: obsługiwanego ekranu, tekstury OpenGL lub wersji platformy.
  • Spróbuj przetestować każdy plik APK na co najmniej 1 urządzeniu. Jeśli nie, masz na swoim komputerze deweloperskim jeden z najbardziej konfigurowalnych emulatorów urządzeń na rynku. Do dzieła!

Warto też sprawdzić skompilowany pakiet APK przed udostępnieniem go na rynku, aby mieć pewność, że nie pojawią się żadne niespodzianki, które mogłyby spowodować ukrycie aplikacji w Google Play. Przy użyciu narzędzia „aapt” można to zrobić w prosty sposób. Aapt (narzędzie Android Asset Packaging) jest częścią procesu kompilacji, który służy do tworzenia i pakowania aplikacji na Androida. Jest też bardzo przydatnym narzędziem do ich sprawdzania.

>aapt dump badging
package: name='com.example.hello' versionCode='1' versionName='1.0'
sdkVersion:'11'
uses-permission:'android.permission.SEND_SMS'
application-label:'Hello'
application-icon-120:'res/drawable-ldpi/icon.png'
application-icon-160:'res/drawable-mdpi/icon.png'
application-icon-240:'res/drawable-hdpi/icon.png'
application: label='Hello' icon='res/drawable-mdpi/icon.png'
launchable-activity: name='com.example.hello.HelloActivity'  label='Hello' icon=''
uses-feature:'android.hardware.telephony'
uses-feature:'android.hardware.touchscreen'
main
supports-screens: 'small' 'normal' 'large' 'xlarge'
supports-any-density: 'true'
locales: '--_--'
densities: '120' '160' '240'

Analizując dane wyjściowe narzędzia aapt, upewnij się, że nie masz sprzecznych wartości opcji „supports-screen” i „zgodne ekrany” oraz czy nie masz niezamierzonych wartości „uses-feature” dodanych w wyniku uprawnień ustawionych w pliku manifestu. W powyższym przykładzie pakiet APK nie będzie widoczny dla wielu urządzeń.

Dlaczego? Dodanie wymaganego uprawnienia SEND_SMS spowodowało dodanie wymaganej funkcji android.hardware.telephony. Interfejs API 11 to Honeycomb (wersja Androida zoptymalizowana pod kątem tabletów), a żadne urządzenia z Honeycomb nie mają sprzętu telefonicznego, więc Google Play będzie odfiltrowywać ten plik APK we wszystkich przypadkach, dopóki nie pojawią się nowsze urządzenia z wyższym poziomem interfejsu API, które mają też sprzęt telefoniczny.

Na szczęście ten problem można łatwo rozwiązać, dodając ten kod do pliku manifestu:

<uses-feature android:name="android.hardware.telephony" android:required="false" />

Bezpośrednio dodaliśmy też wymaganie android.hardware.touchscreen. Jeśli chcesz, aby Twój pakiet APK był widoczny na telewizorach, które nie mają ekranu dotykowego, do pliku manifestu dodaj te elementy:

<uses-feature android:name="android.hardware.touchscreen" android:required="false" />

Po wypełnieniu listy kontrolnej przed opublikowaniem przesyłaj pliki APK do Google Play. Zanim aplikacja pojawi się w Google Play, może minąć trochę czasu, ale gdy już się pojawi, sprawdź jeszcze raz. Pobierz aplikację na wszystkie używane urządzenia testowe, aby upewnić się, że pliki APK są kierowane na odpowiednie urządzenia. Gratulacje, wszystko gotowe.