Tworzenie wielu plików APK o kilku wymiarach

Jeśli publikujesz aplikację w Google Play, musisz utworzyć i przesłać pakiet Android App Bundle. Gdy to zrobisz, Google Play będzie automatycznie generować i udostępniać zoptymalizowane pliki APK dla każdej konfiguracji urządzenia. Dzięki temu użytkownicy pobierają tylko kod i zasoby niezbędne do uruchomienia Twojej aplikacji. Publikowanie wielu plików APK jest przydatne, jeśli nie publikujesz w Google Play, ale musisz samodzielnie stworzyć i podpisać każdy plik APK oraz nim zarządzać.

Przy tworzeniu aplikacji na Androida, która ma korzystać z wielu pakietów APK dostępnych w Google Play, warto stosować sprawdzone metody od samego początku i uniknąć niepotrzebnych problemów w trakcie procesu programowania. Z tej lekcji dowiesz się, jak utworzyć wiele plików APK swojej aplikacji, z których każdy obejmuje inny rozmiar ekranu. Zyskasz też dostęp do narzędzi, dzięki którym obsługa bazy kodu z wieloma plikami APK będzie jak najbardziej prosta.

Potwierdzanie, że potrzebujesz wielu plików APK

Gdy próbujesz utworzyć aplikację, która działa na wielu różnych urządzeniach z Androidem, z pewnością zależy Ci na tym, aby wyglądała dobrze na każdym urządzeniu. Chcesz wykorzystać przestrzeń dużych ekranów, ale nadal pracować na małych, aby korzystać z nowych funkcji Android API lub tekstur wizualnych dostępnych na najnowocześniejszych urządzeniach, ale nie rezygnować ze starszych. Na początku może się wydawać, że obsługa wielu plików APK to najlepsze rozwiązanie, ale często jest to inaczej. W sekcji Jak używać pojedynczego pliku APK w przewodniku dla programistów korzystających z wielu plików APK znajdziesz przydatne informacje o tym, jak można to osiągnąć dzięki jednemu plikowi APK, m.in. skorzystać z naszej biblioteki pomocy. Znajdziesz tam też linki do materiałów dostępnych w przewodniku dla programistów aplikacji na Androida.

Jeśli możesz nim zarządzać, ograniczenie aplikacji do jednego pliku APK ma kilka zalet, w tym:

  • Publikowanie i testowanie jest łatwiejsze
  • Trzeba zarządzać tylko jedną bazą kodu.
  • Aplikacja może dostosowywać się do zmian konfiguracji urządzenia.
  • Przywracanie aplikacji z różnych urządzeń po prostu działa
  • Nie musisz martwić się o preferencje rynkowe, zachowanie użytkowników od momentu przejścia z jednego pakietu APK na kolejny ani który plik APK pasuje do danej klasy urządzeń.

W pozostałej części tej lekcji zakładamy, że znasz już temat, dokładnie wiesz, co znajduje się w powiązanych z nimi zasobach, i że stwierdzisz, że wiele plików APK to odpowiednia ścieżka dla Twojej aplikacji.

Pokaż swoje wymagania

Zacznij od utworzenia prostego wykresu, aby szybko określić, ile plików APK potrzebujesz i jakie rozmiary ekranów obejmuje każdy z nich. Na szczęście możesz szybko i łatwo przygotować listę swoich wymagań i mieć pod ręką potrzebne informacje. Załóżmy, że chcesz podzielić pliki APK na 2 wymiary: interfejs API oraz rozmiar ekranu. Utwórz tabelę z wierszem i kolumną dla każdej możliwej pary wartości i kolorem niektórych „obiektów blob”, każdy kolor oznacza 1 plik APK.

3 4 5 6 7 8 9 10 11 12 +
mały
normalny
duży
bardzo duża

Powyżej znajdziesz przykład z 4 plikami APK. Niebieski jest przeznaczony dla urządzeń z małymi i normalnymi ekranami, zielony – dla urządzeń z dużymi ekranami, a czerwony – do bardzo dużych ekranów. Wszystkie mają zakres API od 3 do 10. Szczególnym przypadkiem jest fioletowy, ponieważ dotyczy on wszystkich rozmiarów ekranu, ale tylko interfejsu API 11 i nowszych. Co ważniejsze, patrząc na ten wykres, od razu wiesz, który plik APK obejmuje dane połączenie interfejsu API i rozmiaru ekranu. Do każdego z nich masz dopracowane kryptonimy, ponieważ pytanie „Czy przetestowaliśmy czerwony kod na komputerze?” jest znacznie łatwiejsze, Wydrukuj ten wykres i przekaż go każdej osobie pracującej nad Twoją bazą kodu. Życie stało się znacznie prostsze.

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

Niezależnie od tego, czy modyfikujesz istniejącą aplikację na Androida, czy tworzysz ją od podstaw, jest to pierwsza i najważniejsza rzecz, którą należy zrobić w kodzie bazy kodu. Wszystko, co wchodzi w projekt biblioteki, trzeba zaktualizować tylko raz (np. tłumaczone teksty, motywy kolorystyczne, poprawki błędów we wspólnym kodzie), co skraca czas tworzenia aplikacji i zmniejsza ryzyko popełnienia pomyłek, których można było łatwo uniknąć.

Uwaga: chociaż szczegóły implementacji tworzenia i dołączania projektów bibliotecznych wykraczają poza zakres tej lekcji, aby dowiedzieć się więcej, przeczytaj artykuł Tworzenie biblioteki na Androida.

Jeśli konwertujesz istniejącą aplikację do obsługi wielu plików APK, przeszukaj bazę kodu w poszukiwaniu każdego zlokalizowanego pliku ciągu znaków, listy wartości, kolorów motywów, ikon menu i układu, które nie będą się zmieniać w różnych plikach APK, i umieść wszystko w projekcie biblioteki. Kod, który się nie zmieni, powinien trafić również do projektu bibliotecznego. Prawdopodobnie rozszerzysz te klasy, aby dodać metodę lub dwie metody z pliku APK do pliku APK.

Jeśli jednak tworzysz aplikację od podstaw, najpierw spróbuj napisać jak najwięcej kodu w projekcie bibliotecznym, a potem w razie potrzeby przenieś ją do pojedynczego pliku APK. W dłuższej perspektywie łatwiej jest zarządzać tym obiektem niż dodawać go do jednego, potem kolejnego, a potem kolejnego, a potem wielu miesięcy, próbując ustalić, czy ten obiekt blob można przenieść do sekcji biblioteki bez pomyłki.

Tworzenie nowych projektów APK

Każdy plik APK, który zamierzasz opublikować, powinien istnieć oddzielny projekt na Androida. Aby ułatwić porządkowanie, 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 niekoniecznie musi to być nazwa, która musi dzielić się z biblioteką. Jeśli masz 3 pliki APK zgodne 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-purple
foo-red

Po utworzeniu projektów dodaj projekt biblioteki jako odwołanie do każdego projektu APK. Jeśli to możliwe, zdefiniuj początkową aktywność w projekcie biblioteki i rozszerz ją w projekcie APK. Dzięki zdefiniowaniu działania początkowego w projekcie biblioteki możesz umieścić wszystkie inicjowanie aplikacji w jednym miejscu, dzięki czemu nie musisz ponownie wdrażać „uniwersalnych” zadań, takich jak inicjowanie Analytics, sprawdzanie licencji czy inne procedury inicjowania, które nie zmieniają się znacznie z pakietu APK na plik APK.

Dostosowywanie plików manifestu

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

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

Weźmy na przykład zbiór wielu plików APK opisanych wcześniej i załóżmy, że każdy z nich jest skonfigurowany do obsługi wszystkich rozmiarów ekranu większych niż „docelowy” rozmiar ekranu. Spójrzmy na przykładowy wykres z wcześniejszego okresu:

3 4 5 6 7 8 9 10 11 12 +
mały
normalny
duży
bardzo duża

Zakres pokrycia może się pokrywać, więc możemy opisać obszar objęty każdym plikiem APK w ten sposób:

  • Niebieskie pokrywa się ze wszystkimi ekranami, minSDK 3.
  • Zielony kolor obejmuje duże ekrany i nowsze wersje (minSDK 3).
  • Czerwony obejmuje bardzo duże ekrany (zwykle tablety), minSDK w wersji 9.
  • Fioletowy zakrywa wszystkie ekrany, minSDK w wersji 11.

Pamiętaj, że w dużym stopniu te reguły się nakładają. Na przykład bardzo duże urządzenie z interfejsem API 11 może obsługiwać dowolny z 4 podanych plików APK. Jednak dzięki regule „wygrane o najwyższym numerze wersji” możemy ustalić taką kolejność ustawień:

Fioletowy ≥ Czerwony ≥ zielony ≥ Niebieski

Dlaczego zezwalać na wszystkie nakładanie się? Załóżmy, że fioletowy plik APK ma pewne wymagania, a pozostałe nie mają. Pełną listę możliwych przyczyn problemu znajdziesz na stronie Filtry w Google Play w przewodniku dla programistów aplikacji na Androida. Załóżmy na przykład, że fioletowy wymaga aparatu z przodu. Podstawowym celem tej wersji jest korzystanie z rozrywki przy użyciu przedniej kamery. Okazuje się jednak, że nie wszystkie urządzenia z interfejsem API w wersji 11 lub nowszej mają aparaty przednie. Co za strach!

Na szczęście, jeśli użytkownik przegląda Google Play na takim urządzeniu, Google Play sprawdzi plik manifestu, zauważy, że fioletowy wskazuje przedni aparat jako wymagany, i zignoruje go, bo stwierdził, że fioletowy i to urządzenie nie stanowią dokładnie tego, co w cyfrowym niebie. Dzięki temu zauważy, że kolor czerwony jest nie tylko zgodny z bardzo dużymi urządzeniami, ale też nie ma znaczenia, czy jest przedni aparat. Użytkownik nadal może pobrać aplikację z Google Play, ponieważ pomimo całego błędu z przednim aparatem nadal istnieje plik APK obsługujący dany poziom interfejsu API.

Aby przechowywać wszystkie pliki APK na osobnych „ścieżkach”, musisz mieć dobry schemat kodu wersji. Zalecane kody znajdziesz w sekcji Kody wersji naszego przewodnika dla programistów. Warto zapoznać się z całą sekcją, ale w przypadku tego zestawu plików APK uwzględniliśmy 2 cyfry oznaczające min./maksymalny rozmiar ekranu, a 3 to numer kompilacji. Dzięki temu, gdy urządzenie zostanie uaktualnione do nowej wersji Androida (np. z 10 do 11), wszystkie pliki APK, które są teraz odpowiednie i preferowane względem obecnie zainstalowanego, będą widoczne dla urządzenia jako „uaktualnienie”. Schemat numeru wersji po zastosowaniu do przykładowego zestawu plików APK może wyglądać tak:

Niebieski: 0304001, 0304002, 0304003...
Zielony: 0334001, 0334002, 0334003
Czerwony: 0344001, 0344002, 0344003...
Fioletowy: 1104001, 1104002, 1104003...

Po połączeniu wszystkich tych elementów Twój plik manifestu Androida wyglądałby mniej więcej tak:

Niebieski:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    android:versionCode="0304001" android:versionName="1.0" package="com.example.foo">
    <uses-sdk android:minSdkVersion="3" />
    <supports-screens android:smallScreens="true"
        android:normalScreens="true"
        android:largeScreens="true"
        android:xlargeScreens="true" />
    ...

Zielony:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    android:versionCode="0334001" android:versionName="1.0" package="com.example.foo">
    <uses-sdk android:minSdkVersion="3" />
    <supports-screens android:smallScreens="false"
        android:normalScreens="false"
        android:largeScreens="true"
        android:xlargeScreens="true" />
    ...

Czerwony:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    android:versionCode="0344001" android:versionName="1.0" package="com.example.foo">
    <uses-sdk android:minSdkVersion="3" />
    <supports-screens android:smallScreens="false"
        android:normalScreens="false"
        android:largeScreens="false"
        android:xlargeScreens="true" />
    ...

Fioletowy:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    android:versionCode="1104001" android:versionName="1.0" package="com.example.foo">
    <uses-sdk android:minSdkVersion="11" />
    <supports-screens android:smallScreens="true"
        android:normalScreens="true"
        android:largeScreens="true"
        android:xlargeScreens="true" />
    ...

Pamiętaj, że technicznie wiele plików APK będzie działać z tagiem obsługiwanych ekranów lub tagu zgodnych ekranów. Ogólnie zalecamy stosowanie ekranów z obsługą ekranów, ale ich używanie jest bardzo złe. Sprawia, że cały proces staje się niepotrzebnie skomplikowany i zwiększa ryzyko popełnienia błędu. Pamiętaj też, że zamiast korzystać z wartości domyślnych (domyślnie „małe” i „normalne” mają one zawsze wartość „prawda”), pliki manifestu jawnie określają wartość dla każdego rozmiaru ekranu. Może to zmniejszyć ryzyko problemów. Na przykład w pliku manifestu z docelowym pakietem SDK o wartości < 9 będzie automatycznie ustawiona wartość false (fałsz), ponieważ taki rozmiar jeszcze nie istniał. Unikaj więc dokładności.

Przejrzyj listę kontrolną przed opublikowaniem

Zanim prześlesz pliki do Google Play, dokładnie sprawdź te elementy. Pamiętaj, że odnoszą się one do wielu plików APK i nie stanowią pełnej listy kontrolnej dla wszystkich aplikacji przesyłanych do Google Play.

  • Wszystkie pliki APK muszą mieć taką samą nazwę.
  • Wszystkie pliki APK muszą być podpisane za pomocą tego samego certyfikatu.
  • Jeśli pliki APK pokrywają się w wersjach platformy, pakiet o wyższej wartości minSdkVersion musi mieć wyższy kod wersji.
  • Każdy rozmiar ekranu, który ma obsługiwać pakiet APK, ustaw w pliku manifestu wartość „true”. Dla każdego rozmiaru ekranu, w którym nie chcesz go wyświetlać, wybierz „false” (fałsz).
  • Dokładnie sprawdź filtry pliku manifestu pod kątem sprzecznych informacji (plik APK, który obsługuje tylko babeczki na ekranach XLARGE, nikt nie zobaczy tego pliku).
  • Każdy plik manifestu pliku APK musi być unikalny na co najmniej 1 obsługiwanej wersji ekranu, tekstury OpenGL lub wersji platformy.
  • Przetestuj każdy plik APK na co najmniej jednym urządzeniu. Poza tym masz jeden z najbardziej dostępnych emulatorów urządzeń w branży, który jest dostępny na Twoim komputerze. Do szaleństwa!

Warto też sprawdzić skompilowany plik APK przed wprowadzeniem go na rynek, aby mieć pewność, że nie ma niespodzianek, które mogłyby ukryć aplikację w Google Play. To dość proste przy użyciu narzędzia „aapt”. Aapt (Android Asset Packaging Tool) jest częścią procesu 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: 'xlarge'
supports-any-density: 'true'
locales: '--_--'
densities: '120' '160' '240'

Podczas analizowania danych wyjściowych aapt sprawdź, czy nie ma sprzecznych wartości dla atrybutów „supports-screen” i „zgodności” oraz czy nie zostały dodane niezamierzone wartości „uses-feature” w wyniku uprawnień ustawionych w pliku manifestu. W przykładzie powyżej plik APK będzie niewidoczny dla większości lub na wszystkich urządzeniach.

Dlaczego? Dzięki dodaniu wymaganego uprawnienia SEND_SMS automatycznie dodaliśmy wymaganie funkcji android.hardware.telephony. Większość bardzo dużych urządzeń (o ile nie wszystkie) to tablety bez sprzętu telefonicznego, dlatego Google Play odfiltruje w takich przypadkach ten plik APK, dopóki nie pojawią się urządzenia, które będą na tyle duże, że mogą być traktowane jako duży ekran, i będą zawierać sprzęt telefoniczny.

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

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

Domyślnie dodawany jest też wymóg android.hardware.touchscreen. Jeśli chcesz, aby pakiet APK był widoczny na telewizorach nieobsługujących ekranu dotykowego, dodaj do pliku manifestu:

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

Gdy wykonasz czynności z listy kontrolnej przed opublikowaniem, prześlij swoje pakiety APK do Google Play. Może minąć trochę czasu, zanim aplikacja pojawi się podczas przeglądania Google Play, ale gdy już się pojawi, sprawdź jeszcze raz. Pobierz aplikację na ewentualne urządzenia testowe, aby upewnić się, że pliki APK są kierowane na konkretne urządzenia. Gratulacje, to już wszystko!