Omówienie zasobów aplikacji

Zasoby to dodatkowe pliki i treści statyczne używane w kodzie, np. mapy bitowe, definicje układu, ciągi znaków interfejsu użytkownika, instrukcje animacji itp.

Zawsze udostępniaj na zewnątrz zasoby aplikacji, takie jak obrazy czy ciągi znaków z kodu, aby móc je utrzymywać niezależnie. Udostępnij też zasoby alternatywne dla konkretnych konfiguracji urządzeń, grupując je w specjalnie nazywanych katalogach zasobów. W czasie działania Android używa odpowiedniego zasobu na podstawie bieżącej konfiguracji. Możesz na przykład określić różne układy interfejsu w zależności od rozmiaru ekranu lub różne ciągi znaków w zależności od ustawień językowych.

Gdy udostępnisz zasoby aplikacji na zewnątrz, możesz uzyskać do nich dostęp za pomocą identyfikatorów zasobów generowanych w klasie R projektu. W tym dokumencie opisujemy, jak grupować zasoby w projekcie Androida. Pokazuje też, jak udostępnić alternatywne zasoby na potrzeby konkretnych konfiguracji urządzeń, a następnie uzyskać do nich dostęp z poziomu kodu aplikacji lub innych plików XML.

Typy zasobów grupy

Umieść każdy typ zasobów w określonym podkatalogu katalogu res/ projektu. Na przykład oto hierarchia plików prostego projektu:

MyProject/
    src/
        MyActivity.java
    res/
        drawable/
            graphic.png
        layout/
            main.xml
            info.xml
        mipmap/
            icon.png
        values/
            strings.xml

Katalog res/ zawiera wszystkie zasoby w jego podkatalogach: zasób graficzny, dwa zasoby układu, katalog mipmap/ dla ikon programu uruchamiającego oraz plik zasobów w postaci ciągu znaków. Nazwy katalogów zasobów są ważne i zostały opisane w tabeli 1.

Uwaga: więcej informacji na temat korzystania z folderów mipmap znajdziesz w artykule na temat umieszczania ikon aplikacji w katalogach mipmap.

Tabela 1. Katalogi zasobów obsługiwane w katalogu projektu res/.

Katalog Typ zasobu
animator/ Pliki XML definiujące animacje właściwości.
anim/ Pliki XML definiujące Tweenanimations. W tym katalogu można też zapisywać animacje właściwości, ale w przypadku animacji właściwości preferowany jest katalog animator/, który pozwala odróżnić te 2 typy.
color/ Pliki XML definiujące listę stanów kolorów. Więcej informacji znajdziesz w sekcji Zasób listy stanów kolorów.
drawable/

Pliki bitmapy (PNG, .9.png, JPG lub GIF) lub pliki XML, które są skompilowane do tych rysowalnych podtypów zasobów:

  • Pliki bitmapy
  • 9 poprawek (mapy bitowe z możliwością zmiany rozmiaru)
  • Listy stanów
  • Kształty
  • Elementy rysowalne animacji
  • Inne elementy rysowalne

Więcej informacji znajdziesz w artykule Materiały rysowalne.

mipmap/ Pliki rysowalne dla różnych gęstości ikon programu uruchamiającego. Więcej informacji o zarządzaniu ikonami programu uruchamiającego w folderach mipmap/ znajdziesz w artykule o umieszczaniu ikon aplikacji w katalogach mipmap.
layout/ Pliki XML, które definiują układ interfejsu użytkownika. Więcej informacji znajdziesz w artykule Zasób Układ.
menu/ Pliki XML, które definiują menu aplikacji, takie jak menu opcji, menu kontekstowe lub menu podrzędne. Więcej informacji znajdziesz w sekcji Zasób menu.
raw/

Dowolnych plików do zapisania w nieprzetworzonej postaci. Aby otworzyć te zasoby za pomocą nieprzetworzonego zasobu InputStream, wywołaj metodę Resources.openRawResource() z identyfikatorem zasobu, który jest wartością R.raw.filename.

Jeśli jednak potrzebujesz dostępu do oryginalnych nazw plików i hierarchii plików, rozważ zapisanie zasobów w katalogu assets/ zamiast w res/raw/. Pliki w domenie assets/ nie mają identyfikatora zasobu, więc możesz je odczytać tylko za pomocą AssetManager.

values/

Pliki XML zawierające proste wartości, takie jak ciągi znaków, liczby całkowite i kolory.

Pliki zasobów XML w innych podkatalogach res/ definiują 1 zasób na podstawie nazwy pliku XML, pliki w katalogu values/ opisują wiele zasobów. W przypadku pliku znajdującego się w tym katalogu każdy element podrzędny elementu <resources> definiuje jeden zasób. Na przykład element <string> tworzy zasób R.string, a element <color> tworzy zasób R.color.

Ponieważ każdy zasób jest definiowany przez własny element XML, możesz nadać plikowi dowolną nazwę, a różne typy zasobów umieścić w jednym pliku. Warto jednak umieścić unikalne typy zasobów w różnych plikach. Oto przykładowe konwencje nazw plików zasobów, które można utworzyć w tym katalogu:

Więcej informacji znajdziesz w sekcjach Zasoby tekstowe, Zasób stylu i Więcej typów zasobów.

xml/ Dowolne pliki XML, które można odczytać w czasie działania, wywołując Resources.getXML(). W tym miejscu trzeba zapisać różne pliki konfiguracji XML, np. konfigurację wyszukiwania.
font/ Pliki czcionek z rozszerzeniami takimi jak TTF, OTF lub TTC albo pliki XML, które zawierają element <font-family>. Więcej informacji o czcionkach jako zasobach znajdziesz w artykule o dodawaniu czcionki jako zasobu XML.

Uwaga: nigdy nie zapisuj plików zasobów bezpośrednio w katalogu res/. Powoduje to błąd kompilatora.

Więcej informacji o poszczególnych typach zasobów znajdziesz w artykule Omówienie typów zasobów.

Zasoby zapisywane w podkatalogach zdefiniowanych w tabeli 1 są zasobami domyślnymi. Oznacza to, że określają one domyślny wygląd i zawartość aplikacji. Jednak różne typy urządzeń z Androidem mogą wymagać różnych typów zasobów.

Możesz na przykład udostępnić różne zasoby układu dla urządzeń z większymi niż zwykle ekranami, aby wykorzystać dodatkową przestrzeń. Możesz też udostępnić różne zasoby tekstowe, które tłumaczą tekst w interfejsie w zależności od ustawienia języka na urządzeniu. Aby zapewnić różne zasoby na potrzeby różnych konfiguracji urządzeń, oprócz zasobów domyślnych musisz podać też zasoby alternatywne.

Udostępnianie alternatywnych zasobów

Większość aplikacji udostępnia alternatywne zasoby do obsługi określonych konfiguracji urządzeń. Na przykład możesz uwzględnić alternatywne, możliwe do rysowania zasoby o różnej gęstości ekranu i alternatywne zasoby tekstowe dla różnych języków. W czasie działania Android wykrywa bieżącą konfigurację urządzenia i wczytuje odpowiednie zasoby aplikacji.

Rysunek 1. 2 urządzenia korzystające z różnych zasobów układu w zależności od rozmiaru ekranu.

Aby określić alternatywy specyficzne dla konfiguracji dla zbioru zasobów, wykonaj te czynności:

  1. W usłudze res/ utwórz nowy katalog o nazwie w formacie <resources_name>-<qualifier>.
    • <resources_name> to nazwa katalogu odpowiednich zasobów domyślnych (zdefiniowanych w tabeli 1).
    • <qualifier> to nazwa określająca pojedynczą konfigurację, w której mają być używane te zasoby (zdefiniowaną w tabeli 2).

    Możesz dołączyć więcej niż 1 element <qualifier>. Oddziel je łącznikiem.

    Uwaga: gdy dodajesz wiele kwalifikatorów, musisz je umieścić w tej samej kolejności co w tabeli 2. Jeśli kwalifikatory są ułożone w nieprawidłowej kolejności, zasoby są ignorowane.

  2. Zapisz odpowiednie zasoby alternatywne w tym nowym katalogu. Pliki zasobów muszą mieć taką samą nazwę jak domyślne pliki zasobów.

Oto na przykład zasoby domyślne i alternatywne:

res/
    drawable/
        icon.png
        background.png
    drawable-hdpi/
        icon.png
        background.png

Kwalifikator hdpi wskazuje, że zasoby w tym katalogu są przeznaczone dla urządzeń z ekranem o dużej gęstości. Rozmiar obrazów w tych katalogach rysowalnych jest dostosowywany do konkretnej gęstości ekranu, ale nazwy plików są dokładnie takie same. Dzięki temu identyfikator zasobu, którego używasz do odwoływania się do obrazu icon.png lub background.png, będzie zawsze taki sam. Android wybiera wersję każdego zasobu, która najlepiej pasuje do bieżącego urządzenia, porównując informacje o konfiguracji urządzenia z kwalifikatorami w nazwie katalogu zasobów.

Uwaga: określając zasób alternatywny, musisz też zdefiniować go w konfiguracji domyślnej. W przeciwnym razie, gdy urządzenie zmieni konfigurację, aplikacja może napotkać wyjątki związane ze środowiskiem wykonawczym. Jeśli na przykład dodasz ciąg znaków tylko do values-en, a nie do values, Twoja aplikacja może napotkać wyjątek Resource Not Found, gdy użytkownik zmieni domyślny język systemu.

W tabeli 2 znajdziesz prawidłowe kwalifikatory konfiguracji uporządkowane w kolejności ich obowiązywania. Do nazwy katalogu można dodać wiele kwalifikatorów, rozdzielając je łącznikiem. Jeśli używasz wielu kwalifikatorów dla katalogu zasobów, musisz je dodać do nazwy katalogu w kolejności, w jakiej są wymienione w tabeli.

Tabela 2. Nazwy kwalifikatorów konfiguracji.

Konfiguracja Wartości kwalifikatora Opis
MCK i MNC Przykłady:
mcc310
mcc310-mnc004
mcc208-mnc00

Kod kraju sieci komórkowej (MCK), opcjonalnie wraz z kodem sieci komórkowej (MNC) z karty SIM w urządzeniu. Na przykład mcc310 to USA w przypadku dowolnego operatora, mcc310-mnc004 to Stany Zjednoczone w sieci Verizon, a mcc208-mnc00 to Francja w Orange.

Jeśli urządzenie korzysta z połączenia radiowego (czyli jest to telefon GSM), wartości MCK i MNC pochodzą z karty SIM.

Możesz też użyć samego konta MCK, np. dodać do aplikacji materiały prawne obowiązujące w poszczególnych krajach. Jeśli musisz określić coś tylko na podstawie języka, użyj kwalifikatora języka, skryptu (opcjonalnie) i regionu (opcjonalnie). Jeśli używasz kwalifikatora MCK i MNC, rób to ostrożnie i sprawdź, czy działa zgodnie z oczekiwaniami.

Zapoznaj się też z polami konfiguracji mcc i mnc, które wskazują odpowiednio aktualny kod kraju komórkowego i kod sieci komórkowej.

Język, skrypt (opcjonalnie) i region (opcjonalnie) Przykłady:
en
fr
en-rUS
fr-rFR
fr-rCA
b+en
b+en+US
b+es+419
b+zh+Hant
b+sr+Latn+RS

Język jest określany za pomocą dwuliterowego kodu języka w formacie ISO 639-1, po którym następuje opcjonalnie dwuliterowy kod regionu ISO 3166-1-alpha-2 (z przedrostkiem „r”).

Wielkość liter w kodach nie jest rozróżniana. Prefiks r służy do rozróżniania części regionu. Nie możesz wskazać samego regionu.

W Androidzie 7.0 (poziom interfejsu API 24) wprowadzono obsługę tagów języka BCP 47, których możesz używać do kwalifikowania zasobów w zależności od języka i regionu. Tag języka składa się z sekwencji co najmniej 1 tagu podrzędnego, z których każdy zawęża lub zawęża zakres języka zidentyfikowanego przez tag. Więcej informacji o tagach języka znajdziesz w artykule Tagi do identyfikowania języków.

Aby użyć tagu języka BCP 47, połącz b+ i dwuliterowy kod języka w formacie ISO 639-1, a po nich opcjonalnie dodaj dodatkowe podtagi oddzielone atrybutem +.

Tag języka może się zmienić w trakcie działania aplikacji, jeśli użytkownik zmieni swój język w ustawieniach systemu. Informacje o tym, jak może to wpływać na aplikację w trakcie działania, znajdziesz w sekcji Obsługa zmian konfiguracji.

Pełny przewodnik po lokalizowaniu aplikacji na potrzeby innych języków znajdziesz w artykule Lokalizowanie aplikacji.

Zapoznaj się też z metodą getLocales(), która udostępnia zdefiniowaną listę języków. Ta lista zawiera język główny.

Kierunek układu ldrtl
ldltr

Kierunek układu aplikacji. ldrtl oznacza „układ-kierunku-od prawej do lewej”. ldltr oznacza „układ-kierunku-od lewej do prawej” i jest domyślną wartością domyślną.

Możesz to zrobić w przypadku dowolnych zasobów, takich jak układy, obiekty rysowane i wartości.

Jeśli na przykład chcesz określić konkretny układ dla języka arabskiego i ogólny układ dla innych języków pisanych od prawej do lewej, np. perskiego lub hebrajskiego, użyj katalogów w ten sposób:

res/
  layout/
    main.xml (układ domyślny)
  layout-ar/
    main.xml (określony układ dla języka arabskiego)
  layout-ldrtl/
    main.xml (dowolny język pisany od prawej do lewej oprócz arabskiego, ponieważ kwalifikator języka „ar” ma wyższy priorytet)

Uwaga: aby włączyć w aplikacji funkcje układu od prawej do lewej, ustaw SupportsRtl na "true" i ustaw TargetSdkVersion na 17 lub więcej.

Dodano w interfejsie API na poziomie 17.

Najmniejsza szerokość sw<N>dp

Przykłady:
sw320dp
sw600dp
sw720dp
itp.

Najkrótszy obszar ekranu dostępny dla aplikacji. smallestWidth okna aplikacji to najkrótsza dostępna wysokość i szerokość okna. Możesz też określić ją jako „najmniejszą szerokość okna”. Możesz użyć tego kwalifikatora, aby interfejs aplikacji miał szerokość co najmniej <N> dps.

Jeśli np. Twój układ wymaga, aby najmniejszy obszar ekranu zawsze miał wielkość co najmniej 600 dp, możesz użyć tego kwalifikatora, aby utworzyć zasoby układu w katalogu res/layout-sw600dp/. System korzysta z tych zasobów tylko wtedy, gdy najmniejszy dostępny ekran ma co najmniej 600 dp, niezależnie od tego, czy bok 600 dp jest wysokością czy szerokością widoczną dla użytkowników. Najmniejsza szerokość może się zmienić w przypadku zmiany rozmiaru okna lub dostępnej szerokości lub wysokości albo przesunięcia ekranu. Może to spowodować zmianę ustawień systemowych.

Użycie najmniejszej szerokości do określenia ogólnego rozmiaru ekranu jest przydatne, bo jest ona często czynnikiem wpływającym na projekt układu. Interfejs często przewija się w pionie, ale ma dość rygorystyczne ograniczenia dotyczące minimalnej ilości miejsca potrzebnego w poziomie.

Dostępna szerokość ma też decydujące znaczenie przy wyborze układu z 1 panelem w przypadku telefonów lub z wieloma panelami w przypadku tabletów. Dlatego też pewnie zależy Ci na najmniejszej możliwej szerokości na każdym z urządzeń.

Najmniejsza szerokość urządzenia uwzględnia dekoracje ekranu i interfejs systemu. Jeśli na przykład na ekranie urządzenia znajdują się stałe elementy interfejsu, które zajmują przestrzeń wzdłuż osi o najmniejszej szerokości, system deklaruje najmniejszą szerokość niż rzeczywisty rozmiar ekranu, ponieważ są to piksele ekranu niedostępne w Twoim interfejsie.

Niektóre wartości, których możesz użyć w przypadku typowych rozmiarów ekranu:

  • w wersji 320 w przypadku urządzeń z konfiguracją ekranu taką jak:
    • 240 x 320 ldpi (słuchawka QVGA)
    • 320 x 480 mdpi (słuchawka)
    • 480 x 800 hdpi (słuchawka o wysokiej gęstości)
  • 480, dla ekranów, np. 480 x 800 mdpi (tablet/słuchawka)
  • 600, dla ekranów, takich jak 600 x 1024 mdpi (7 cali)
  • 720, dla ekranów, takich jak 720 x 1280 mdpi (tablet 10")

Gdy aplikacja udostępnia wiele katalogów zasobów z różnymi wartościami kwalifikatora smallestWidth, system użyje katalogu znajdującego się najbliżej smallestWidth urządzenia (nie przekraczając go).

Dodano w interfejsie API na poziomie 13.

Zapoznaj się też z atrybutem android:requiresSmallestWidthDp, który deklaruje minimalną wartość smallestWidth, z którą Twoja aplikacja jest zgodna, oraz pole konfiguracji smallestScreenWidthDp, które zawiera wartość smallestWidth urządzenia.

Więcej informacji o projektowaniu na różne ekrany z użyciem tego kwalifikatora znajdziesz w artykule Obsługa różnych rozmiarów ekranu.

Dostępna szerokość i wysokość w<N>dp
h<N>dp

Przykłady:
w720dp
w1024dp
h720dp
h1024dp
itp.

Określa minimalną dostępną szerokość lub wysokość ekranu (w jednostkach dp zdefiniowanych przez wartość <N>), przy których jest używany zasób. Te wartości konfiguracyjne są porównywane z bieżącą szerokością i wysokością wyświetlacza, gdy orientacja urządzenia zmienia się między pionową a poziomą, składa się lub rozwija albo system włącza lub wyłącza tryb wielu okien. W trybie wielu okien wartości odpowiadają szerokości i wysokości okna zawierającego aplikację, a nie szerokości i wysokości ekranu urządzenia. Podobnie w przypadku umieszczonych aktywności wartości dotyczą szerokości i wysokości poszczególnych aktywności, a nie szerokości i wysokości ekranu. Więcej informacji znajdziesz w artykule o umieszczaniu aktywności.

Dostępne szerokości i wysokości są często przydatne przy ustalaniu, czy zastosować układ z wieloma panelami. Nawet na tablecie często nie chcesz mieć tego samego układu wielu paneli w orientacji pionowej, jak w orientacji poziomej. Dzięki temu możesz określić minimalną szerokość lub wysokość wymaganą w układzie, zamiast używać jednocześnie kwalifikatorów rozmiaru i orientacji ekranu.

Gdy aplikacja udostępnia wiele katalogów zasobów z różnymi wartościami na potrzeby tych konfiguracji, system użyje katalogu znajdującego się najbliżej bieżącej szerokości ekranu urządzenia (bez przekraczania). Wartość Najbliższa do jest określana przez dodanie różnic między rzeczywistą i podaną szerokością ekranu do różnicy między rzeczywistą wysokością ekranu a określoną wysokością. Przy nieokreślonych wysokościach i szerokościach wartość wynosi 0.

Wartości nie obejmują obszaru zajmowanego przez ustawienia okien. Jeśli więc urządzenie ma stałe elementy interfejsu na krawędziach wyświetlacza, wartości szerokości i wysokości są mniejsze niż rzeczywiste wymiary ekranu, nawet jeśli aplikacja jest wyświetlana od krawędzi do krawędzi za pomocą funkcji Window.setDecorFitsSystemWindows lub WindowCompat.setDecorFitsSystemWindows.

Niektóre nieutrwalone pionowe dekoracje ekranu (np. pasek stanu telefonu, który można ukryć na pełnym ekranie) nie są tu uwzględniane. Nie dotyczy to też dekoracji okien, takich jak pasek tytułu czy pasek działań. Aplikacje muszą być więc przygotowane na użycie miejsca nieco mniejszego niż określona przez użytkownika.

Uwaga: system wybiera zasób, który pasuje zarówno pod względem szerokości, jak i wysokości. Dlatego zasób, który określa oba, jest zdecydowanie preferowany w stosunku do zasobu, który określa tylko jeden z nich. Jeśli na przykład rzeczywisty ekran ma szerokość 720 dp i wysokość 1280 dp, a jeden zasób jest zakwalifikowanych jako w720dp, a inny jako w700dp-h1200dp, ten drugi zostanie wybrany, mimo że pierwszy zasób dokładnie odpowiada jego wskazaniom.

Dodano w interfejsie API na poziomie 13.

Zapoznaj się też z polami konfiguracji screenWidthDp i screenHeightDp, które zawierają bieżącą szerokość i wysokość ekranu.

Więcej informacji o projektowaniu na różne ekrany z użyciem tego kwalifikatora znajdziesz w artykule Obsługa różnych rozmiarów ekranu.

Rozmiar ekranu small
normal
large
xlarge
  • small: ekrany o rozmiarze podobnym do ekranu o niskiej gęstości QVGA. Minimalny rozmiar układu w przypadku małego ekranu to około 320 x 426 dp. Przykładami są QVGA o małej gęstości i VGA o dużej gęstości.
  • normal: ekrany o rozmiarze podobnym do ekranów o średniej gęstości ekranu HVGA. Minimalny rozmiar układu dla normalnego ekranu to około 320 x 470 dp. Przykłady takich ekranów to: WQVGA o małej gęstości, HVGA o średniej gęstości i WVGA o dużej gęstości.
  • large: ekrany o rozmiarze podobnej do ekranu VGA o średniej gęstości. Minimalny rozmiar układu w przypadku dużego ekranu to około 480 x 640 dp. Przykładami są ekrany VGA i WVGA o średniej gęstości.
  • xlarge: ekrany, które są znacznie większe niż tradycyjny ekran HVGA o średniej gęstości. Minimalny rozmiar układu bardzo dużego ekranu to około 720 x 960 dp. W większości przypadków urządzenia z bardzo dużymi ekranami są za duże, aby nosić je w kieszeni. Najprawdopodobniej są to tablety. Dodano w interfejsie API poziomu 9.

Uwaga: użycie kwalifikatora rozmiaru nie oznacza, że zasoby są przeznaczone tylko na ekrany o tej wielkości. Jeśli nie podasz alternatywnych zasobów z kwalifikatorami, które lepiej pasują do bieżącej konfiguracji urządzenia, system będzie mógł korzystać z zasobów, które są najlepsze.

Uwaga: jeśli wszystkie zasoby korzystają z kwalifikatora rozmiaru, który jest większy niż bieżący ekran, system nie będzie ich używać, a aplikacja ulegnie awarii w czasie działania. Dzieje się tak na przykład wtedy, gdy wszystkie zasoby układu są oznaczone kwalifikatorem xlarge, ale urządzenie ma ekran normalnej wielkości.

Dodano w interfejsie API na poziomie 4.

Zapoznaj się też z polem konfiguracji screenLayout, które wskazuje, czy ekran jest mały, normalny czy duży.

Więcej informacji znajdziesz w artykule Omówienie zgodności ekranu.

Proporcje ekranu long
notlong
  • long: długie ekrany, np. WQVGA, WVGA, FWVGA
  • notlong: nie długie ekrany, takie jak QVGA, HVGA i VGA.

Dodano w interfejsie API na poziomie 4.

Zależy to wyłącznie od proporcji ekranu (ekran long jest szerszy). Nie jest to związane z orientacją ekranu.

Zapoznaj się też z polem konfiguracji screenLayout, które wskazuje, czy ekran jest długi.

Okrągły ekran round
notround
  • round: okrągłe ekrany, np. okrągłe urządzenie do noszenia;
  • notround: prostokątne ekrany, np. telefony czy tablety

Dodano w interfejsie API na poziomie 23.

Zapoznaj się też z metodą konfiguracji isScreenRound(), która wskazuje, czy ekran jest okrągły.

Szeroki gama kolorów widecg
nowidecg
  • widecg: wyświetla o szerokiej gamie kolorów, np. Display P3 lub AdobeRGB.
  • nowidecg: wyświetla wąską gamę kolorów, np. sRGB

Dodano w interfejsie API na poziomie 26.

Zapoznaj się też z metodą konfiguracji isScreenWideColorGamut(), która wskazuje, czy ekran ma szeroki zakres kolorów.

HDR (High Dynamic Range) highdr
lowdr
  • highdr: wyświetla się o wysokim zakresie dynamicznym
  • lowdr: wyświetla się z niskim/standardowym zakresem dynamicznym

Dodano w interfejsie API na poziomie 26.

Zapoznaj się też z metodą konfiguracji isScreenHdr(), która wskazuje, czy ekran ma funkcje HDR.

Orientacja ekranu port
land
  • port: urządzenie jest w orientacji pionowej (pionowej).
  • land: urządzenie jest w orientacji poziomej.

Może się to zmienić w okresie życia aplikacji, jeśli użytkownik obróci ekran. Informacje o tym, jak wpłynie to na aplikację w trakcie działania, znajdziesz w sekcji Obsługa zmian konfiguracji.

Zapoznaj się też z polem konfiguracji orientation, które wskazuje aktualną orientację urządzenia.

Tryb UI car
desk
television
appliance
watch
vrheadset
  • car: urządzenie jest wyświetlane w samochodowej stacji dokującej
  • desk: urządzenie wyświetla się w stacji dokującej na biurku
  • television: urządzenie wyświetla się na telewizorze w trybie „z 3 metrów”, gdy interfejs użytkownika znajduje się na dużym ekranie, od którego użytkownik jest oddalony o daleko. Obsługa głównie za pomocą pada kierunkowego lub innych interakcji niezwiązanych ze wskaźnikiem
  • appliance: urządzenie działa jako urządzenie, ale nie wyświetla się
  • watch: urządzenie ma wyświetlacz i jest założone na nadgarstku
  • vrheadset: urządzenie jest wyświetlane w goglach rzeczywistości wirtualnej

Dodano w interfejsie API na poziomie 8; telewizor dodany w interfejsie API 13; oglądanie zostało dodane w interfejsie API 20.

Informacje o reagowaniu aplikacji po umieszczeniu urządzenia w stacji dokującej lub jego usunięciu ze stacji dokującej znajdziesz w artykule Określanie i monitorowanie stanu i typu dokowania.

Może się to zmienić w trakcie życia aplikacji, jeśli użytkownik umieści urządzenie w stacji dokującej. Niektóre z tych trybów możesz włączyć lub wyłączyć za pomocą UiModeManager. Informacje o tym, jak wpłynie to na aplikację w trakcie działania, znajdziesz w sekcji Obsługa zmian konfiguracji.

Tryb nocny night
notnight
  • night: noc
  • notnight: czas w ciągu dnia

Dodano w interfejsie API na poziomie 8.

Może się to zmieniać w trakcie działania aplikacji, jeśli tryb nocny jest pozostawiony w trybie automatycznym (domyślnym). W takim przypadku tryb zmienia się w zależności od pory dnia. Ten tryb możesz włączyć lub wyłączyć za pomocą UiModeManager. Informacje o tym, jak wpłynie to na aplikację w trakcie działania, znajdziesz w sekcji Obsługa zmian konfiguracji.

Gęstość pikseli ekranu (dpi) ldpi
mdpi
hdpi
xhdpi
xxhdpi
xxxhdpi
nodpi
tvdpi
anydpi
nnndpi
  • ldpi: ekrany o małej gęstości, około 120 dpi.
  • mdpi: średnia gęstość (na tradycyjnych urządzeniach HVGA), około 160 dpi.
  • hdpi: ekrany o dużej gęstości; około 240 dpi.
  • xhdpi: ekrany o bardzo dużej gęstości, około 320 dpi. Dodano w interfejsie API poziomu 8.
  • xxhdpi: ekrany o bardzo dużej gęstości; około 480 dpi. Dodano w interfejsie API poziomu 16.
  • xxxhdpi: zastosowania o bardzo dużej gęstości (tylko ikona programu uruchamiającego – patrz Obsługa różnych gęstości pikseli); około 640 dpi. Dodano w interfejsie API na poziomie 18.
  • nodpi: używana w przypadku zasobów map bitowych, których nie chcesz skalować w celu dopasowania do gęstości urządzenia.
  • tvdpi: ekrany o rozdzielczości od mdpi do hdpi – około 213 dpi. Nie jest to „główna” grupa gęstości. Obsługuje ona głównie telewizory z rozdzielczością 720p i większość aplikacji jej nie potrzebuje. W przypadku paneli telewizyjnych 1080p użyj xhdpi, a w przypadku paneli 4K – xxxhdpi. Dodano w interfejsie API na poziomie 13.
  • anydpi: odpowiada wszystkim gęstościom ekranu i ma pierwszeństwo przed innymi kwalifikatorami. Jest to przydatne w przypadku elementów rysowalnych w formacie wektorowym. Dodano w interfejsie API na poziomie 21.
  • nnndpi: służy do reprezentowania niestandardowych gęstości, gdzie nnn to dodatnia liczba całkowita. W większości przypadków ta opcja nie jest używana. Użycie zasobników o standardowej gęstości znacznie zmniejsza koszty związane z obsługą różnych gęstości ekranu urządzeń dostępnych na rynku.

Między 6 gęstościami podstawowymi występuje współczynnik skalowania 3:4:6:8:12:16 (z pominięciem gęstości tvdpi). Oznacza to, że mapa bitowa 9 x 9 w ldpi ma rozmiar 12 x 12 w mdpi, 18 x 18 w hdpi, 24 x 24 w xhdpi itd.

Uwaga: użycie kwalifikatora gęstości nie oznacza, że zasoby są przeznaczone tylko dla ekranów o takiej gęstości. Jeśli nie udostępnisz alternatywnych zasobów z kwalifikatorami, które lepiej pasują do bieżącej konfiguracji urządzenia, system użyje tych, które najlepiej pasują.

Więcej informacji o obsłudze różnych gęstości ekranu oraz o możliwości skalowania map bitowych przez Androida w celu dopasowania do bieżącej gęstości znajdziesz w artykule Omówienie zgodności ekranu.

Typ ekranu dotykowego notouch
finger
  • notouch: urządzenie nie ma ekranu dotykowego.
  • finger: urządzenie ma ekran dotykowy, który służy do sterowania ruchem palca użytkownika.

Zapoznaj się też z polem konfiguracji touchscreen, które wskazuje typ ekranu dotykowego urządzenia.

Dostępność klawiatury keysexposed
keyshidden
keyssoft
  • keysexposed: urządzenie ma dostępną klawiaturę. Jeśli urządzenie ma włączoną klawiaturę programową (prawdopodobnie), będzie ona używana nawet wtedy, gdy klawiatura sprzętowa nie jest widoczna dla użytkownika lub urządzenie nie ma klawiatury sprzętowej. Jeśli klawiatura programowa nie jest dostępna lub jest wyłączona, będzie ona używana tylko wtedy, gdy klawiatura sprzętowa jest odkryta.
  • keyshidden: urządzenie ma dostępną klawiaturę sprzętową, ale jest ukryte oraz nie ma włączonej klawiatury programowej.
  • keyssoft: urządzenie ma włączoną klawiaturę programową, niezależnie od tego, czy jest widoczna czy nie.

Jeśli udostępnisz zasoby keysexposed, ale nie zasoby keyssoft, system będzie używać zasobów keysexposed niezależnie od tego, czy klawiatura jest widoczna, o ile system ma włączoną klawiaturę programową.

Może się to zmienić w okresie życia aplikacji, jeśli użytkownik otworzy klawiaturę sprzętową. Informacje o tym, jak wpłynie to na aplikację w trakcie działania, znajdziesz w sekcji Obsługa zmian konfiguracji.

Zapoznaj się też z polami konfiguracji hardKeyboardHidden i keyboardHidden, które wskazują widoczność klawiatury sprzętowej i dowolnego rodzaju klawiatury (w tym oprogramowania).

Podstawowa metoda wprowadzania tekstu nokeys
qwerty
12key
  • nokeys: urządzenie nie ma klawiszy sprzętowych do wprowadzania tekstu.
  • qwerty: urządzenie ma sprzętową klawiaturę QWERTY, niezależnie od tego, czy jest widoczna dla użytkownika, czy nie.
  • 12key: urządzenie ma sprzętową klawiaturę 12-klawiszową, niezależnie od tego, czy jest widoczna dla użytkownika.

Zapoznaj się też z polem konfiguracji keyboard, które wskazuje podstawową dostępną metodę wprowadzania tekstu.

Wersja platformy (poziom interfejsu API) Przykłady:
v3
v4
v7
itp.

Poziom interfejsu API obsługiwany przez urządzenie. Na przykład v1 dla interfejsu API poziomu 1 (urządzenia z Androidem 1.0 lub nowszym) i v4 dla interfejsu API poziomu 4 (urządzenia z Androidem 1.6 lub nowszym). Więcej informacji o tych wartościach znajdziesz w artykule Poziomy interfejsu API Androida.

Uwaga: nie wszystkie wersje Androida obsługują wszystkie kwalifikatory. Użycie nowego kwalifikatora powoduje domyślnie dodanie kwalifikatora wersji platformy, aby starsze urządzenia mogły go ignorować. Na przykład użycie kwalifikatora w600dp automatycznie uwzględnia kwalifikator v13, ponieważ jest on nowy na poziomie 13 interfejsu API. Aby uniknąć problemów, zawsze dodawaj zbiór zasobów domyślnych (zbiór zasobów bez kwalifikatorów). Więcej informacji znajdziesz w sekcji na temat zapewniania najlepszej zgodności urządzeń z zasobami.

Reguły nazwy kwalifikatora

Oto kilka reguł dotyczących nazw kwalifikatorów konfiguracji:

  • Możesz określić wiele kwalifikatorów dla jednego zbioru zasobów rozdzielonych myślnikami. Na przykład właściwość drawable-en-rUS-land odnosi się do urządzeń w orientacji poziomej (USA i język angielski).
  • Kwalifikatory muszą być wymienione w tabeli 2.
    • Błąd: drawable-hdpi-port/
    • Poprawnie: drawable-port-hdpi/
  • Alternatywne katalogi zasobów nie mogą być zagnieżdżone. Na przykład nie możesz użyć res/drawable/drawable-en/.
  • Wielkość liter w wartościach nie jest rozróżniana. Kompilator zasobów konwertuje nazwy katalogów na małe litery przed przetwarzaniem, aby uniknąć problemów w systemach plików, w których wielkość liter nie jest rozróżniana. Używanie wielkich liter w nazwie ma jedynie zwiększyć czytelność.
  • Obsługiwana jest tylko jedna wartość dla każdego typu kwalifikatora. Jeśli na przykład chcesz użyć tych samych plików rysowalnych dla Hiszpanii i Francji, nie możesz mieć katalogu o nazwie drawable-es-fr/. Zamiast tego potrzebujesz 2 katalogów zasobów, np. drawable-es/ i drawable-fr/, które zawierają odpowiednie pliki. Nie musisz jednak duplikować plików w obu lokalizacjach. Zamiast tego możesz utworzyć alias zasobu zgodnie z opisem w sekcji Tworzenie zasobów aliasów.

Gdy zapiszesz zasoby alternatywne w katalogach z tymi kwalifikatorami, Android automatycznie zastosuje je w aplikacji na podstawie bieżącej konfiguracji urządzenia. Przy każdym żądaniu zasobu Android sprawdza alternatywne katalogi zasobów zawierające żądany plik zasobów, a następnie wyszukuje zasób, który najlepiej pasuje.

Jeśli nie ma zasobów alternatywnych, które pasowałyby do określonej konfiguracji urządzenia, Android używa odpowiednich zasobów domyślnych, czyli zbioru zasobów określonego typu, który nie zawiera kwalifikatora konfiguracji.

Tworzenie zasobów aliasów

Jeśli masz zasób, którego chcesz używać na potrzeby więcej niż jednej konfiguracji urządzenia, ale nie chcesz udostępniać go jako zasobu domyślnego, nie musisz umieszczać tego samego zasobu w więcej niż jednym alternatywnym katalogu zasobów. Zamiast tego możesz utworzyć alternatywny zasób działający jako alias dla zasobu zapisanego w domyślnym katalogu zasobów.

Uwaga: nie wszystkie zasoby oferują mechanizm umożliwiający utworzenie aliasu innego zasobu. W szczególności nie są one dostępne w przypadku animacji, menu, nieprzetworzonych danych i innych nieokreślonych zasobów w katalogu xml/.

Załóżmy, że masz ikonę aplikacji icon.png i potrzebujesz jej unikalnej wersji dla różnych języków. Jednak w dwóch językach: angielskim i kanadyjskim oraz francusko-kanadyjskim – muszą korzystać z tej samej wersji. Nie musisz kopiować do katalogu zasobów tego samego obrazu zarówno w języku angielskim-kanadyjskim, jak i francuskim. Zamiast tego możesz zapisać obraz używany w obu usługach, używając dowolnej nazwy innej niż icon.png, takiej jak icon_ca.png, i umieścić go w domyślnym katalogu res/drawable/. Następnie w res/drawable-en-rCA/ i res/drawable-fr-rCA/ utwórz plik icon.xml odwołujący się do zasobu icon_ca.png za pomocą elementu <bitmap>. Dzięki temu możesz zapisać tylko jedną wersję pliku PNG i 2 małe pliki XML, które do niego prowadzą. Szczegółowe przykłady znajdziesz w sekcjach poniżej.

Rysowa

Aby utworzyć alias istniejącego elementu, który można przeciągnąć, użyj elementu <drawable>:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <drawable name="icon">@drawable/icon_ca</drawable>
</resources>

Jeśli zapiszesz ten plik jako icon.xml w alternatywnym katalogu zasobów, takim jak res/values-en-rCA/, zostanie on skompilowany do zasobu, do którego możesz się odwołać jako R.drawable.icon, ale w rzeczywistości będzie to alias zasobu R.drawable.icon_ca, który jest zapisany w res/drawable/.

Układ

Aby utworzyć alias dla istniejącego układu, użyj elementu <include> umieszczonego w elemencie <merge>:

<?xml version="1.0" encoding="utf-8"?>
<merge>
    <include layout="@layout/main_ltr"/>
</merge>

Jeśli zapiszesz ten plik jako main.xml, zostanie on skompilowany do zasobu, do którego można się odwołać jako R.layout.main, ale w rzeczywistości będzie on aliasem zasobu R.layout.main_ltr.

Ciągi znaków i inne proste wartości

Aby utworzyć alias istniejącego ciągu znaków, jako wartości nowego ciągu użyj identyfikatora zasobu żądanego ciągu:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="hello">Hello</string>
    <string name="hi">@string/hello</string>
</resources>

Zasób R.string.hi jest teraz aliasem usługi R.string.hello.

Inne proste wartości działają w ten sam sposób, na przykład kolory:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="red">#f00</color>
    <color name="highlight">@color/red</color>
</resources>

Uzyskiwanie dostępu do zasobów aplikacji

Po podaniu zasobu w aplikacji możesz go zastosować, podając jego identyfikator. Wszystkie identyfikatory zasobów są zdefiniowane w klasie R projektu, którą narzędzie aapt generuje automatycznie.

Po skompilowaniu aplikacji aapt generuje klasę R, która zawiera identyfikatory zasobów wszystkich zasobów w katalogu res/. Dla każdego typu zasobu istnieje podklasa R, np. R.drawable, obejmująca wszystkie rysowalne zasoby. Dla każdego zasobu tego typu istnieje statyczna liczba całkowita, np. R.drawable.icon. Ta liczba całkowita to identyfikator zasobu, którego możesz użyć do jego pobrania.

Chociaż klasa R określa identyfikatory zasobów, nie trzeba jej szukać, aby znaleźć identyfikator zasobu. Identyfikator zasobu zawsze składa się z tych elementów:

  • Typ zasobu: każdy zasób jest pogrupowany według „typu”, np. string, drawable i layout. Więcej informacji o różnych typach zasobów znajdziesz w artykule Omówienie typów zasobów.
  • Nazwa zasobu, czyli nazwa pliku z wyłączeniem rozszerzenia lub wartość w atrybucie XML android:name w przypadku zasobów o prostej wartości, np. ciągu znaków.

Dostęp do zasobu możesz uzyskać na 2 sposoby:

  • W kodzie: przy użyciu statycznej liczby całkowitej z podklasy klasy R, np.
    R.string.hello

    string to typ zasobu, a hello to nazwa zasobu. Gdy podasz identyfikator zasobów w tym formacie, wiele interfejsów API na Androida ma dostęp do Twoich zasobów. Więcej informacji znajdziesz w sekcji Uzyskiwanie dostępu do zasobów w kodzie.

  • W formacie XML: użyj specjalnej składni XML, która odpowiada identyfikatorowi zasobu zdefiniowanemu w klasie R, np.
    @string/hello

    string to typ zasobu, a hello to nazwa zasobu. Tej składni możesz użyć w zasobie XML w dowolnym miejscu, w którym oczekiwana jest wartość podana w zasobie. Więcej informacji znajdziesz w sekcji Uzyskiwanie dostępu do zasobów z pliku XML.

Dostęp do zasobów w kodzie

Aby użyć zasobu w kodzie, przekaż jego identyfikator jako parametr metody. Możesz na przykład ustawić ImageView tak, aby używał zasobu res/drawable/myimage.png za pomocą setImageResource():

Kotlin

val imageView = findViewById(R.id.myimageview) as ImageView
imageView.setImageResource(R.drawable.myimage)

Java

ImageView imageView = (ImageView) findViewById(R.id.myimageview);
imageView.setImageResource(R.drawable.myimage);

Możesz też pobierać poszczególne zasoby za pomocą metod w Resources, które można pobrać za pomocą metody getResources().

Składnia

Składnia, która pozwala odwoływać się do zasobu w kodzie:

[<package_name>.]R.<resource_type>.<resource_name>
  • <package_name> to nazwa pakietu, w którym znajduje się zasób (nie jest wymagana, gdy odwołujesz się do zasobów z Twojego pakietu).
  • <resource_type> jest podklasą R typu zasobu.
  • <resource_name> to nazwa pliku zasobu bez rozszerzenia lub wartość atrybutu android:name w elemencie XML w przypadku prostych wartości.

Więcej informacji o poszczególnych typach zasobów i o tym, jak się do nich odwołać, znajdziesz w artykule Omówienie typów zasobów.

Przykłady zastosowań

Jest wiele metod, które akceptują parametr identyfikatora zasobu. Możesz pobierać zasoby za pomocą metod w interfejsie Resources. Możesz pobrać instancję Resources za pomocą Context.getResources().

Oto kilka przykładów uzyskiwania dostępu do zasobów w kodzie:

Kotlin

// Load a background for the current screen from a drawable resource.
window.setBackgroundDrawableResource(R.drawable.my_background_image)

// Set the Activity title by getting a string from the Resources object, because
//  this method requires a CharSequence rather than a resource ID.
window.setTitle(resources.getText(R.string.main_title))

// Load a custom layout for the current screen.
setContentView(R.layout.main_screen)

// Set a slide in animation by getting an Animation from the Resources object.
flipper.setInAnimation(AnimationUtils.loadAnimation(this,
        R.anim.hyperspace_in))

// Set the text on a TextView object using a resource ID.
val msgTextView = findViewById(R.id.msg) as TextView
msgTextView.setText(R.string.hello_message)

Java

// Load a background for the current screen from a drawable resource.
getWindow().setBackgroundDrawableResource(R.drawable.my_background_image) ;

// Set the Activity title by getting a string from the Resources object, because
//  this method requires a CharSequence rather than a resource ID.
getWindow().setTitle(getResources().getText(R.string.main_title));

// Load a custom layout for the current screen.
setContentView(R.layout.main_screen);

// Set a slide in animation by getting an Animation from the Resources object.
flipper.setInAnimation(AnimationUtils.loadAnimation(this,
        R.anim.hyperspace_in));

// Set the text on a TextView object using a resource ID.
TextView msgTextView = (TextView) findViewById(R.id.msg);
msgTextView.setText(R.string.hello_message);

Uwaga: nie modyfikuj pliku R.java ręcznie. Jest generowany przez narzędzie aapt podczas kompilowania projektu. Wszystkie zmiany zostaną zastąpione podczas następnej kompilacji.

Dostęp do zasobów z pliku XML

Wartości niektórych atrybutów i elementów XML można definiować, korzystając z odwołania do istniejącego zasobu. Często robi się tak przy tworzeniu plików układu, aby dobierać ciągi i obrazy do widżetów.

Jeśli na przykład dodasz do układu element Button, użyj zasobu w postaci ciągu dla tekstu przycisku:

<Button
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:text="@string/submit" />

Składnia

Oto składnia pozwalająca odwoływać się do zasobu w zasobie XML:

@[<package_name>:]<resource_type>/<resource_name>
  • <package_name> to nazwa pakietu, w którym znajduje się zasób (nie jest to wymagane, gdy odwołujesz się do zasobów z tego samego pakietu).
  • <resource_type> to podklasa typu zasobu R.
  • <resource_name> to nazwa pliku zasobu bez rozszerzenia lub wartość atrybutu android:name w elemencie XML w przypadku prostych wartości.

Więcej informacji o poszczególnych typach zasobów i o tym, jak się do nich odwołać, znajdziesz w artykule Omówienie typów zasobów.

Przykłady zastosowań

W niektórych przypadkach musisz użyć zasobu dla wartości w pliku XML, na przykład aby zastosować rysowalny obraz do widżetu, ale zasobu w formacie XML możesz też użyć w dowolnym miejscu, które akceptuje prostą wartość. Załóżmy na przykład, że masz plik zasobów zawierający zasób koloru i zasób w postaci ciągu znaków:

<?xml version="1.0" encoding="utf-8"?>
<resources>
   <color name="opaque_red">#f00</color>
   <string name="hello">Hello!</string>
</resources>

Możesz użyć tych zasobów w tym pliku układu, aby ustawić kolor tekstu i ciąg tekstowy:

<?xml version="1.0" encoding="utf-8"?>
<EditText xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:textColor="@color/opaque_red"
    android:text="@string/hello" />

W tym przypadku nie musisz określać nazwy pakietu w informacjach o zasobach, bo zasoby pochodzą z Twojego pakietu. Aby odwołać się do zasobu systemowego, musisz podać nazwę pakietu, jak pokazano w tym przykładzie:

<?xml version="1.0" encoding="utf-8"?>
<EditText xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:textColor="@android:color/secondary_text_dark"
    android:text="@string/hello" />

Uwaga: zawsze używaj zasobów w postaci ciągów znaków, aby umożliwić zlokalizowanie aplikacji na inne języki. Informacje o tworzeniu zasobów alternatywnych (takich jak zlokalizowane ciągi znaków) znajdziesz w sekcji Udostępnianie zasobów alternatywnych. Pełny przewodnik po lokalizowaniu aplikacji na potrzeby innych języków znajdziesz w artykule Lokalizowanie aplikacji.

Do tworzenia aliasów możesz nawet używać zasobów w języku XML. Możesz na przykład utworzyć rysowalny zasób będący aliasem innego rysowalnego zasobu:

<?xml version="1.0" encoding="utf-8"?>
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
    android:src="@drawable/other_drawable" />

Wygląda to nadmiernie, ale może być bardzo przydatne, gdy korzystasz z alternatywnych zasobów. Więcej informacji znajdziesz w sekcji dotyczącej tworzenia zasobów aliasów.

Atrybuty stylu odwołania

Zasób atrybutu stylu pozwala odwołać się do wartości atrybutu w aktualnie stosowanym motywie. Odwoływanie się do atrybutu stylu pozwala dostosować wygląd elementów interfejsu przez dostosowywanie ich stylu do standardowych odmian dostarczanych przez bieżący motyw, zamiast podawania wartości zakodowanej na stałe. Odwołanie do atrybutu stylu brzmi w zasadzie: „Użyj stylu zdefiniowanego przez ten atrybut w bieżącym motywie”.

Aby odwołać się do atrybutu stylu, składnia nazwy jest prawie identyczna jak zwykły format zasobów, ale zamiast symbolu „at” (@) użyj znaku zapytania (?). Część typu zasobu jest opcjonalna. Składnia referencji będzie więc wyglądać tak:

?[<package_name>:][<resource_type>/]<resource_name>

Oto przykład odwołania do atrybutu, który pozwala ustawić kolor tekstu tak, aby pasował do dodatkowego koloru tekstu w motywie systemowym:

<EditText id="text"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:textColor="?android:textColorSecondary"
    android:text="@string/hello_world" />

W tym przypadku atrybut android:textColor określa nazwę atrybutu stylu w bieżącym motywie. Android używa teraz wartości atrybutu stylu android:textColorSecondary jako wartości atrybutu android:textColor w tym widżecie. Narzędzie do zasobów systemowych wie, że zasób atrybutu jest oczekiwany w tym kontekście, dlatego nie musisz wyraźnie określać jego typu, którym jest ?android:attr/textColorSecondary. Możesz wykluczyć typ attr.

Dostęp do oryginalnych plików

Nie jest to regułą, ale może być konieczne uzyskanie dostępu do oryginalnych plików i katalogów. Jeśli to zrobisz, zapisanie plików w usłudze res/ nie zadziała, ponieważ jedyny sposób odczytania zasobu z res/ to użycie identyfikatora zasobu. Zamiast tego możesz zapisywać zasoby w katalogu assets/.

Pliki zapisane w katalogu assets/ nie mają identyfikatora zasobu, więc nie można odwoływać się do nich za pomocą klasy R ani zasobów XML. Zamiast tego możesz tworzyć zapytania dotyczące plików w katalogu assets/ jak w przypadku zwykłego systemu plików i odczytywać nieprzetworzone dane za pomocą narzędzia AssetManager.

Jeśli jednak potrzebujesz jedynie możliwości odczytu nieprzetworzonych danych (np. pliku wideo lub audio), zapisz plik w katalogu res/raw/ i odczytaj strumień bajtów za pomocą narzędzia openRawResource().

Dostęp do zasobów platformy

Android zawiera wiele standardowych zasobów, takich jak style, motywy i układy. Aby uzyskać dostęp do tych zasobów, musisz zakwalifikować odwołanie do zasobu za pomocą nazwy pakietu android. Na przykład Android zapewnia zasób układu, którego można użyć na potrzeby elementów listy w elemencie ListAdapter:

Kotlin

listAdapter = ArrayAdapter(this, android.R.layout.simple_list_item_1, myarray)

Java

setListAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, myarray));

W tym przykładzie simple_list_item_1 jest zasobem układu zdefiniowanym przez platformę dla elementów w obiekcie ListView. Możesz go użyć zamiast tworzyć własny układ elementów listy.

Zapewnij największą zgodność urządzeń z zasobami

Aby aplikacja obsługiwała wiele konfiguracji urządzeń, ważne jest, aby dla każdego typu zasobów używanych przez aplikację zawsze udostępniać zasoby domyślne.

Jeśli na przykład aplikacja obsługuje kilka języków, zawsze dodawaj katalog values/ (w którym zapisywane są ciągi znaków) bez kwalifikatora języka i regionu. Jeśli zamiast tego umieścisz wszystkie pliki ciągu znaków w katalogach z kwalifikatorem języka i regionu, aplikacja ulegnie awarii, gdy zostanie uruchomiona na urządzeniu z językiem, którego ciągi nie obsługują.

Jeśli podasz domyślne zasoby values/, aplikacja będzie działać prawidłowo, nawet jeśli użytkownik nie rozumie przedstawianego języka. To lepsze niż awaria.

Podobnie, jeśli udostępniasz różne zasoby układu w zależności od orientacji ekranu, wybierz jedną z nich jako domyślną. Na przykład zamiast podawać zasoby układu w języku layout-land/ dla orientacji poziomej i layout-port/ dla orientacji pionowej, pozostaw wartość domyślną – np. layout/ dla orientacji poziomej i layout-port/ dla orientacji pionowej.

Podanie zasobów domyślnych jest ważne nie tylko dlatego, że aplikacja może działać w nieoczekiwanej konfiguracji, ale także dlatego, że nowe wersje Androida czasami dodają kwalifikatory konfiguracji, których starsze wersje nie obsługują. Jeśli używasz nowego kwalifikatora zasobów, ale zachowujesz zgodność kodu ze starszymi wersjami Androida, to gdy starsza wersja Androida uruchomi Twoją aplikację, a jeśli nie podasz zasobów domyślnych, spowoduje to awarię, ponieważ nie będzie ona mogła korzystać z zasobów wymienionych na podstawie nowego kwalifikatora.

Jeśli na przykład wartość minSdkVersion ma wartość 4 i kwalifikujesz się do korzystania ze wszystkich rysowalnych zasobów w trybie nocnym (night lub notnight, które zostały dodane na poziomie 8 interfejsu API), urządzenie API poziomu 4 nie może uzyskać dostępu do tych zasobów i awarii. W takim przypadku Twoim domyślnym zasobem może być notnight, więc wyklucz ten kwalifikator i umieść rysowalne zasoby w polu drawable/ lub drawable-night/.

Krótko mówiąc, aby zapewnić jak największą zgodność z urządzeniami, zawsze udostępniaj domyślne zasoby zasobów, których aplikacja potrzebuje do prawidłowego działania. Następnie utwórz alternatywne zasoby dla konkretnych konfiguracji urządzeń za pomocą kwalifikatorów konfiguracji.

Od tej reguły jest 1 wyjątek: jeśli parametr minSdkVersion Twojej aplikacji ma wartość 4 lub większą, nie potrzebujesz domyślnych zasobów, które można przeciągać, gdy udostępniasz alternatywne zasoby rysowalne za pomocą kwalifikatora gęstości ekranu. Nawet bez domyślnych zasobów rysowanych Android może znaleźć najlepsze dopasowanie spośród alternatywnych gęstości ekranu i w razie potrzeby skalować mapy bitowe. Aby jednak uzyskać najlepsze wrażenia na wszystkich typach urządzeń, zapewnij alternatywne elementy rysowane na potrzeby wszystkich 3 typów gęstości.

Jak Android znajduje najlepszy zasób

Gdy prosisz o zasób, dla którego udostępniasz zasoby alternatywne, Android wybiera ten zasób w czasie działania w zależności od bieżącej konfiguracji urządzenia. Aby pokazać, jak Android wybiera alternatywny zasób, załóżmy, że każdy z nich zawiera różne wersje tych samych obrazów:

drawable/
drawable-en/
drawable-fr-rCA/
drawable-en-port/
drawable-en-notouch-12key/
drawable-port-ldpi/
drawable-port-notouch-12key/

Przyjmijmy też taką konfigurację urządzenia:

Język = en-GB
Orientacja ekranu = port
Gęstość pikseli ekranu = hdpi
Typ ekranu dotykowego = notouch
Podstawowa metoda wprowadzania tekstu = 12key

Porównując konfigurację urządzenia z dostępnymi zasobami alternatywnymi, Android wybiera elementy rysunkowe z drawable-en-port.

System podejmuje decyzję, których zasobów użyć, korzystając z następującej logiki:

Rysunek 2. Schemat blokowy pokazujący, jak Android znajduje najlepiej pasujący zasób.

  1. Usuń pliki zasobów, które są sprzeczne z konfiguracją urządzenia.

    Katalog drawable-fr-rCA/ został wyeliminowany, ponieważ jest sprzeczny z językiem en-GB.

    drawable/
    drawable-en/
    drawable-fr-rCA/
    drawable-en-port/
    drawable-en-notouch-12key/
    drawable-port-ldpi/
    drawable-port-notouch-12key/
    

    Wyjątek: jedyny kwalifikator, który nie jest eliminowany ze względu na sprzeczność, to gęstość pikseli na ekranie. Chociaż gęstość ekranu urządzenia jest hdpi, drawable-port-ldpi/ nie jest usuwana, ponieważ w tym momencie każda gęstość ekranu jest uznawana za pasującą. Więcej informacji znajdziesz w artykule Omówienie zgodności ekranu.

  2. Znajdź na liście kwalifikator o następnym najwyższym priorytecie (tabela 2). (Rozpocznij od MCK).
  3. Czy którykolwiek z katalogów zasobów zawiera ten kwalifikator?
    • Jeśli nie, wróć do kroku 2 i sprawdź kolejne kwalifikacje. W tym przykładzie odpowiedź brzmi „nie”, dopóki nie zostanie osiągnięty kwalifikator języka.
    • Jeśli tak, przejdź do kroku 4.
  4. Usuń katalogi zasobów, które nie zawierają tego kwalifikatora. W tym przykładzie funkcja Następne eliminuje wszystkie katalogi, które nie zawierają kwalifikatora języka:
    drawable/
    drawable-en/
    drawable-en-port/
    drawable-en-notouch-12key/
    drawable-port-ldpi/
    drawable-port-notouch-12key/
    

    Wyjątek: jeśli kwalifikator to gęstość pikseli ekranu, Android wybiera opcję, która najlepiej pasuje do gęstości ekranu urządzenia. Ogólnie rzecz biorąc, Android woli zmniejszać rozmiar oryginalnego obrazu, aby pomniejszać go w górę. Więcej informacji znajdziesz w artykule Omówienie zgodności ekranu.

  5. Powtórz kroki 2, 3 i 4, aż pozostanie tylko jeden katalog. W tym przykładzie kolejnym kwalifikatorem, w przypadku którego występują dopasowania, jest orientacja ekranu. Z tego powodu zasoby, które nie mają określonej orientacji ekranu, są eliminowane:
    drawable-en/
    drawable-en-port/
    drawable-en-notouch-12key/
    

    Pozostały katalog to drawable-en-port.

Procedura ta jest wykonywana dla każdego żądanego zasobu, ale system optymalizuje niektóre aspekty. Jedną z takich optymalizacji jest to, że znana konfiguracja urządzenia może wyeliminować alternatywne zasoby, które nigdy nie będą do siebie pasować. Jeśli na przykład językiem konfiguracji jest język angielski, to każdy katalog zasobów z kwalifikatorem języka innym niż angielski nie będzie nigdy uwzględniany w puli sprawdzonych zasobów (chociaż katalog zasobów bez kwalifikatora języka jest nadal uwzględniany).

Podczas wybierania zasobów na podstawie kwalifikatorów rozmiaru ekranu system używa zasobów przeznaczonych dla ekranu mniejszego niż bieżący, jeśli nie ma zasobów, które lepiej pasowałyby do ekranu. Na przykład na dużym ekranie w razie potrzeby są używane zasoby ekranu o normalnej wielkości.

Jeśli jednak jedyne dostępne zasoby są większe niż bieżący ekran, system nie z nich korzysta, a aplikacja ulega awarii, gdy żadne inne zasoby nie pasują do konfiguracji urządzenia. Dzieje się tak na przykład wtedy, gdy wszystkie zasoby układu są oznaczone kwalifikatorem xlarge, ale urządzenie ma normalny rozmiar.

Uwaga: wcześniejsza kolejność kwalifikatora (w tabeli 2) jest ważniejsza niż liczba kwalifikatorów, które dokładnie odpowiadają urządzeniu. W poprzednim przykładzie w kroku 4 ostatnia opcja na liście zawiera 3 kwalifikatory dokładnie dopasowane do urządzenia (orientacja, typ ekranu dotykowego i metoda wprowadzania), a drawable-en ma tylko 1 pasujący parametr (język). Język ma jednak wyższy priorytet niż inne kwalifikatory, więc właściwość drawable-port-notouch-12key jest usuwana.