Omówienie zasobów aplikacji

Zasoby to dodatkowe pliki i treści statyczne używane przez kod, takie jak mapy bitowe, ciągi tekstowe interfejsu użytkownika, instrukcje animacji i inne.

Zawsze wyodrębniaj z kodu zasoby aplikacji, takie jak obrazy i ciągi tekstowe, aby można było nimi zarządzać niezależnie. Możesz też udostępniać alternatywne zasoby dla konkretnych konfiguracji urządzeń, grupując je w specjalnie nazwanych katalogach zasobów. W czasie działania Android używa odpowiedniego zasobu na podstawie bieżącej konfiguracji. Możesz na przykład podawać różne ciągi znaków w zależności od ustawień języka.

Po wyodrębnieniu zasobów aplikacji możesz uzyskać do nich dostęp za pomocą identyfikatorów zasobów wygenerowanych w klasie R w projekcie. Z tego dokumentu dowiesz się, jak grupować zasoby w projekcie aplikacji na Androida. Pokazuje też, jak udostępniać alternatywne zasoby dla określonych konfiguracji urządzeń, a następnie uzyskiwać do nich dostęp z kodu aplikacji lub innych plików XML.

Typy zasobów grupy

Umieść każdy typ zasobu w określonym podkatalogu katalogu res/ projektu. Oto na przykład hierarchia plików w prostym projekcie:

MyProject/
    src/
        MyActivity.kt
    res/
        drawable/
            graphic.png
        mipmap/
            icon.png
        values/
            strings.xml

Katalog res/ zawiera wszystkie zasoby w podkatalogach: zasób obrazu, katalog mipmap/ z ikonami programu uruchamiającego i plik zasobu tekstowego. Nazwy katalogów zasobów są ważne i zostały opisane w tabeli 1.

Uwaga: więcej informacji o korzystaniu z folderów mipmap znajdziesz w artykule Umieszczanie ikon aplikacji w katalogach mipmap.

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

Katalog Typ zasobu
drawable/

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

  • Pliki bitmapowe
  • Pliki Nine-Patch (mapy bitowe o zmienianym rozmiarze)
  • Listy stanowe
  • Kształty
  • Rysunki animacji
  • Inne elementy rysowalne

Więcej informacji znajdziesz w artykule Zasoby rysowalne.

mipmap/ Pliki rysowalne dla różnych gęstości ikon programu uruchamiającego. Więcej informacji o zarządzaniu ikonami programu uruchamiającego za pomocą folderów mipmap/ znajdziesz w artykule Umieszczanie ikon aplikacji w katalogach mipmap.
raw/

dowolne pliki, które mają być zapisane w formie nieprzetworzonej; Aby otworzyć te zasoby za pomocą funkcji raw InputStream, wywołaj funkcję call Resources.openRawResource z identyfikatorem zasobu, czyli 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 assets/ nie mają identyfikatora zasobu, więc można je odczytywać 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ą pojedynczy zasób na podstawie nazwy pliku XML, natomiast pliki w katalogu values/ opisują wiele zasobów. W przypadku pliku w tym katalogu każdy element podrzędny elementu <resources> definiuje pojedynczy zasób. Na przykład element <string> tworzy zasób R.string, a element <color> tworzy zasób R.color.

Każdy zasób jest zdefiniowany za pomocą własnego elementu XML, więc możesz nazwać plik dowolnie i umieścić w nim różne typy zasobów. Jednak w celu uniknięcia wątpliwości możesz umieścić unikalne typy zasobów w różnych plikach. Oto na przykład konwencje nazewnictwa plików zasobów, które możesz utworzyć w tym katalogu:

Więcej informacji znajdziesz w sekcjach Zasoby tekstowe, Zasoby styluWięcej typów zasobów.

xml/ Dowolne pliki XML, które można odczytać w czasie działania programu, wywołując Resources.getXML. Musisz tu zapisać różne pliki konfiguracji XML.
font/ Pliki czcionek z rozszerzeniami TTF, OTF lub TTC albo pliki XML zawierające element <font-family>. Więcej informacji o czcionkach jako zasobach znajdziesz w artykule Dodawanie czcionki jako zasobu XML.

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

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

Możesz na przykład udostępniać różne zasoby ciągów znaków, które tłumaczą tekst w interfejsie użytkownika na podstawie ustawienia języka na urządzeniu.

Uwaga: w Compose interfejsy, animacje i kolory zależne od stanu są deklarowane w Kotlinie, więc katalogi layout/, menu/, anim/, animator/color/ są w przypadku nowoczesnych aplikacji przestarzałe. Więcej informacji znajdziesz w artykułach Animacje w ComposeAnatomia motywu w Compose.

Podawanie zasobów alternatywnych

Większość aplikacji udostępnia alternatywne zasoby, które obsługują określone konfiguracje urządzeń. Na przykład dodaj alternatywne zasoby rysowalne dla różnych gęstości ekranu i alternatywne zasoby ciągów tekstowych dla różnych języków. W czasie działania Android wykrywa bieżącą konfigurację urządzenia i wczytuje odpowiednie zasoby dla aplikacji.

Aby określić alternatywne wersje zasobów dla konkretnej konfiguracji:

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

    Możesz dołączyć więcej niż jeden <qualifier>. Oddzielaj je od siebie myślnikami.

    Ostrzeżenie: podczas dołączania wielu kwalifikatorów musisz umieścić je w tej samej kolejności, w jakiej są wymienione w tabeli 2. Jeśli kwalifikatory są uporządkowane nieprawidłowo, zasoby są ignorowane.

  2. Zapisz odpowiednie zasoby alternatywne w tym nowym katalogu. Pliki zasobów muszą mieć dokładnie takie same nazwy jak domyślne pliki zasobów.

Oto przykłady domyślnych i alternatywnych zasobów:

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

Kwalifikator hdpi oznacza, że zasoby w tym katalogu są przeznaczone dla urządzeń z ekranem o wysokiej gęstości pikseli. Obrazy w tych katalogach zasobów są dostosowane do konkretnych 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, jest 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.

Ostrzeżenie: podczas definiowania zasobu alternatywnego upewnij się, że zdefiniowano go również w konfiguracji domyślnej. W przeciwnym razie, gdy urządzenie zmieni konfigurację, w aplikacji mogą wystąpić wyjątki w czasie działania. Jeśli na przykład dodasz ciąg znaków tylko do values-en, a nie do values, aplikacja może napotkać wyjątek Resource Not Found, gdy użytkownik zmieni domyślny język systemu.

W tabeli 2 podano kwalifikatory konfiguracji w kolejności ich ważności. Do nazwy katalogu możesz dodać kilka kwalifikatorów, rozdzielając je myślnikami. Jeśli używasz wielu kwalifikatorów w przypadku katalogu zasobów, musisz dodać je do nazwy katalogu w kolejności, w jakiej są wymienione w tabeli.

Tabela 2. Nazwy kwalifikatorów konfiguracji.

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

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

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

Możesz też użyć samego kodu MCC, np. aby uwzględnić w aplikacji zasoby prawne dotyczące danego kraju. Jeśli chcesz określić tylko język, użyj kwalifikatora język, pismo (opcjonalnie) i region (opcjonalnie). Jeśli używasz kwalifikatora MCC i MNC, rób to ostrożnie i sprawdź, czy działa on zgodnie z oczekiwaniami.

Zobacz też pola konfiguracji mccmnc, które wskazują odpowiednio bieżący kod kraju komórki i kod sieci komórkowej.

Język, pismo (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 przez dwuliterowy kod języka ISO 639-1, po którym opcjonalnie może występować dwuliterowy kod regionu ISO 3166-1-alpha-2 (poprzedzony małą literą r).

W kodach nie jest rozróżniana wielkość liter. Prefiks r służy do odróżnienia części regionu. Nie możesz określić samego regionu.

W Androidzie 7.0 (interfejs API na poziomie 24) wprowadzono obsługę tagów języka zgodnych ze standardem BCP 47, których możesz używać do kwalifikowania zasobów specyficznych dla danego języka i regionu. Tag języka składa się z ciągu co najmniej 1 podtagu, z których każdy doprecyzowuje lub zawęża zakres języka identyfikowanego przez cały tag. Więcej informacji o tagach językowych znajdziesz w artykule Tagi do identyfikowania języków.

Aby użyć tagu języka BCP 47, połącz znak b+ z dwuliterowym kodem języka ISO 639-1. Opcjonalnie możesz dodać kolejne tagi podrzędne rozdzielone znakiem +.

Tag języka może się zmieniać w trakcie działania aplikacji, jeśli użytkownicy zmienią język w ustawieniach systemu. Więcej informacji o tym, jak może to wpłynąć na aplikację w czasie działania, znajdziesz w artykule Obsługa zmian konfiguracji.

Pełny przewodnik po lokalizowaniu aplikacji na inne języki znajdziesz w artykule Lokalizowanie aplikacji.

Zobacz też metodę getLocales, która zawiera zdefiniowaną listę ustawień regionalnych. Lista zawiera język podstawowy.

Rodzaj gramatyczny masculine
feminine
neuter

Płeć gramatyczna użytkownika. Używane w przypadku języków, w których występuje rodzaj gramatyczny.

Jeśli na przykład musisz udostępnić różne zasoby użytkownikom posługującym się językiem francuskim, możesz użyć katalogów takich jak te:

res/
  values-fr/
    strings.xml (domyślne ciągi znaków z nieokreśloną płcią)
  values-fr-masculine/
    strings.xml (ciągi znaków z rodzajem męskim)
  values-fr-feminine/
    strings.xml (ciągi znaków z rodzajem żeńskim)
  values-fr-neuter/
    strings.xml (ciągi znaków z rodzajem nijakim)

Zobacz Personalizowanie interfejsu aplikacji za pomocą rodzaju gramatycznego.

Zobacz też metodę konfiguracji getGrammaticalGender, która wskazuje rodzaj gramatyczny.

Dodano na poziomie API 34.

Szeroka gama kolorów widecg
nowidecg
  • widecg: wyświetlacze z szeroką gamą kolorów, np. Display P3 lub AdobeRGB.
  • nowidecg: wyświetlacze z wąską gamą kolorów, np. sRGB;

Dodano na poziomie interfejsu API 26.

Zobacz też metodę isScreenWideColorGamut konfiguracji, która wskazuje, czy ekran ma szeroką gamę kolorów.

High Dynamic Range (HDR) highdr
lowdr
  • highdr: wyświetlacze o wysokim zakresie dynamiki,
  • lowdr: wyświetlacze o niskim lub standardowym zakresie dynamicznym;

Dodano na poziomie interfejsu API 26.

Zobacz też metodę isScreenHdr konfiguracji, która wskazuje, czy ekran obsługuje HDR.

Tryb interfejsu car
desk
television
appliance
watch
vrheadset
  • car: urządzenie jest umieszczone w samochodowej stacji dokującej.
  • desk: urządzenie jest umieszczone w stacji dokującej na biurko;
  • television: urządzenie wyświetla obraz na telewizorze, zapewniając „10-stopową” wygodę, w której interfejs użytkownika jest wyświetlany na dużym ekranie, od którego użytkownik jest oddalony, a korzystanie z urządzenia odbywa się głównie za pomocą pada kierunkowego lub innych elementów sterujących niewymagających wskaźnika.
  • appliance: urządzenie pełni funkcję sprzętu AGD bez wyświetlacza.
  • watch: urządzenie ma wyświetlacz i jest noszone na nadgarstku.
  • vrheadset: urządzenie wyświetla obraz w goglach do rzeczywistości wirtualnej

Dodano na poziomie API 8; telewizor dodano na poziomie API 13; urządzenie dodano na poziomie API 16; zegarek dodano na poziomie API 20; gogle VR dodano na poziomie API 26.

Informacje o tym, jak aplikacja może reagować na włożenie urządzenia do stacji dokującej lub wyjęcie go z niej, znajdziesz w artykule Określanie i monitorowanie stanu i typu stacji dokującej.

Może się to zmienić w trakcie działania aplikacji, jeśli użytkownik umieści urządzenie w stacji dokującej. Niektóre z tych trybów możesz włączać i wyłączać za pomocą pola UiModeManager. Więcej informacji o tym, jak to wpływa na aplikację w czasie działania, znajdziesz w artykule Obsługa zmian konfiguracji.

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

Dodano na poziomie API 8.

Może się to zmienić w trakcie korzystania z aplikacji, jeśli tryb nocny pozostanie w trybie automatycznym (domyślnym), w którym to przypadku tryb zmienia się w zależności od pory dnia. Możesz włączyć lub wyłączyć ten tryb za pomocą ikony UiModeManager. Więcej informacji o tym, jak wpływa to na aplikację w czasie działania, znajdziesz w artykule Obsługa zmian konfiguracji.

Gęstość pikseli ekranu (dpi) ldpi
mdpi
hdpi
xhdpi
xxhdpi
xxxhdpi
nodpi
tvdpi
anydpi
nnndpi
  • ldpi: ekrany o niskiej gęstości, ok. 120 dpi.
  • mdpi: ekrany o średniej gęstości (tradycyjne ekrany HVGA); około 160 dpi.
  • hdpi: ekrany o wysokiej gęstości pikseli, ok. 240 dpi.
  • xhdpi: ekrany o bardzo wysokiej gęstości, ok. 320 dpi. Dodano w API na poziomie 8.
  • xxhdpi: ekrany o bardzo wysokiej gęstości pikseli, około 480 dpi. Dodano w interfejsie API na poziomie 16.
  • xxxhdpi: bardzo wysoka gęstość pikseli (tylko ikona programu uruchamiającego – patrz Obsługa różnych gęstości pikseli); około 640 dpi. Dodano na poziomie API 18.
  • nodpi: używany w przypadku zasobów bitmapowych, które nie mają być skalowane w celu dopasowania do gęstości urządzenia.
  • tvdpi: ekrany o rozdzielczości między mdpi a hdpi, czyli około 213 dpi. Nie jest to „podstawowa” grupa gęstości. Jest on przeznaczony głównie dla telewizorów o rozdzielczości 720p i nie jest potrzebny w większości aplikacji. W przypadku paneli telewizyjnych o rozdzielczości 1080p użyj xhdpi, a w przypadku paneli telewizyjnych o rozdzielczości 4K użyj xxxhdpi. Dodano na poziomie API 13.
  • anydpi: pasuje do wszystkich gęstości ekranu i ma pierwszeństwo przed innymi kwalifikatorami. Jest to przydatne w przypadku grafiki wektorowej. Dodano na poziomie API 21.
  • nnndpi: używany do reprezentowania niestandardowych gęstości, gdzie nnn to dodatnia liczba całkowita określająca gęstość ekranu. W większości przypadków nie jest to używane. Korzystanie ze standardowych zakresów gęstości znacznie zmniejsza nakład pracy związany z obsługą różnych gęstości ekranów urządzeń dostępnych na rynku.

Między 6 głównymi gęstościami występuje współczynnik skalowania 3:4:6:8:12:16 (z pominięciem gęstości tvdpi). Bitmapa 9x9 w rozdzielczości ldpi ma wymiary 12x12 w rozdzielczości mdpi, 18x18 w rozdzielczości hdpi, 24x24 w rozdzielczości xhdpi itd.

Uwaga: użycie kwalifikatora gęstości nie oznacza, że zasoby są przeznaczone tylko na ekrany o tej gęstości. Jeśli nie podasz alternatywnych zasobów z kwalifikatorami, które lepiej pasują do bieżącej konfiguracji urządzenia, system użyje zasobów, które są najlepiej dopasowane.

Więcej informacji o obsłudze różnych gęstości ekranu i o tym, jak Android może skalować mapy bitowe, aby dopasować je do bieżącej gęstości, znajdziesz w artykule Omówienie zgodności z ekranami.

Typ ekranu dotykowego notouch
finger
  • notouch: urządzenie nie ma ekranu dotykowego.
  • finger: urządzenie ma ekran dotykowy, który jest przeznaczony do bezpośredniej interakcji z użyciem palca.

Zobacz też pole konfiguracji touchscreen, które wskazuje typ ekranu dotykowego na urządzeniu.

Dostępność klawiatury keysexposed
keyshidden
keyssoft
  • keysexposed: urządzenie ma dostępną klawiaturę. Jeśli na urządzeniu jest włączona klawiatura programowa (co jest prawdopodobne), jest ona używana nawet wtedy, gdy klawiatura sprzętowa nie jest dostępna dla użytkownika lub gdy urządzenie nie ma klawiatury sprzętowej. Jeśli klawiatura programowa nie jest dostępna lub jest wyłączona, ta opcja jest używana tylko wtedy, gdy jest dostępna klawiatura sprzętowa.
  • keyshidden: urządzenie ma dostępną klawiaturę sprzętową, ale jest ona ukryta i na urządzeniu nie jest włączona klawiatura programowa.
  • keyssoft: na urządzeniu jest włączona klawiatura programowa, niezależnie od tego, czy jest widoczna.

Jeśli podasz zasoby keysexposed, ale nie zasoby keyssoft, system użyje zasobów keysexposed niezależnie od tego, czy klawiatura jest widoczna, o ile w systemie jest włączona klawiatura programowa.

Może się to zmienić w trakcie korzystania z aplikacji, jeśli użytkownik otworzy klawiaturę sprzętową. Więcej informacji o tym, jak wpływa to na aplikację w czasie działania, znajdziesz w artykule Obsługa zmian konfiguracji.

Zobacz też pola konfiguracji hardKeyboardHidden i keyboardHidden, które wskazują odpowiednio widoczność klawiatury sprzętowej i widoczność dowolnego rodzaju klawiatury (w tym programowej).

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

Zobacz też pole konfiguracji keyboard, które wskazuje dostępną podstawową metodę wpisywania tekstu.

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

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

Uwaga: nie wszystkie wersje Androida obsługują wszystkie kwalifikatory. Użycie nowego kwalifikatora powoduje niejawne dodanie kwalifikatora wersji platformy, dzięki czemu starsze urządzenia mogą go ignorować. Aby uniknąć problemów, zawsze uwzględniaj zestaw zasobów domyślnych (zestaw zasobów bez kwalifikatorów). Więcej informacji znajdziesz w sekcji Zapewnianie najlepszej zgodności urządzeń z zasobami.

W aplikacjach napisanych w Compose kwalifikatory konfiguracji związane z układem i wymiarami nie są potrzebne. Chociaż nadal istnieją, są wykluczone z tabeli 2. Są to: kierunek układu, najmniejsza szerokość, dostępna szerokość, dostępna wysokość, rozmiar ekranu, format ekranu, okrągły ekran i orientacja ekranu. Pełną tabelę kwalifikatorów konfiguracji w kolejności pierwszeństwa znajdziesz w artykule Omówienie zasobów aplikacji (widoki).

Reguły nazw kwalifikatorów

Oto kilka zasad dotyczących używania nazw kwalifikatorów konfiguracji:

  • Możesz określić wiele kwalifikatorów dla jednego zestawu zasobów, rozdzielając je myślnikami. Na przykład drawable-en-rUS-night dotyczy urządzeń z ustawionym językiem angielskim (Stany Zjednoczone) w trybie nocnym.
  • Kwalifikatory muszą być podane w kolejności wymienionej w tabeli 2.
    • Nieprawidłowo: drawable-hdpi-night/
    • Prawidłowo: drawable-night-hdpi/
  • Alternatywne katalogi zasobów nie mogą być zagnieżdżone. Nie możesz na przykład używać znaku res/drawable/drawable-en/.
  • W wartościach nie jest rozróżniana wielkość liter. Kompilator zasobów konwertuje nazwy katalogów na małe litery przed przetworzeniem, aby uniknąć problemów w systemach plików, w których wielkość liter nie ma znaczenia. Wielkie litery w nazwach służą tylko poprawie czytelności.
  • Obsługiwana jest tylko jedna wartość dla każdego typu kwalifikatora. Jeśli na przykład chcesz używać tych samych plików rysowalnych w Hiszpanii i Francji, nie możesz mieć katalogu o nazwie drawable-es-fr/. Zamiast tego potrzebujesz 2 katalogów zasobów, np. drawable-es/drawable-fr/, które zawierają odpowiednie pliki.

Po zapisaniu alternatywnych zasobów w katalogach oznaczonych tymi kwalifikatorami Android automatycznie stosuje zasoby w aplikacji na podstawie bieżącej konfiguracji urządzenia. Za każdym razem, gdy zasób jest wymagany, Android sprawdza alternatywne katalogi zasobów, które zawierają żądany plik zasobu, a następnie znajduje najlepiej pasujący zasób.

Jeśli nie ma alternatywnych zasobów pasujących do konkretnej konfiguracji urządzenia, Android używa odpowiednich zasobów domyślnych, czyli zestawu 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ć w przypadku 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 katalogu zasobów alternatywnych. Zamiast tego możesz utworzyć zasób alternatywny, który będzie działać jako alias zasobu zapisanego w domyślnym katalogu zasobów.

Obiekty rysowalne

Załóżmy na przykład, że masz ikonę aplikacji icon.png i potrzebujesz jej unikalnej wersji dla różnych regionów. Jednak 2 ustawienia regionalne, angielski – Kanada i francuski – Kanada, muszą korzystać z tej samej wersji. Nie musisz kopiować tego samego obrazu do katalogu zasobów zarówno w przypadku języka angielskiego (kanadyjskiego), jak i francuskiego (kanadyjskiego). Zamiast tego możesz zapisać obraz używany w obu przypadkach pod dowolną nazwą inną niż icon.png, np. icon_ca.png, i umieścić go w domyślnym katalogu res/drawable/. Następnie utwórz plik icon.xmlres/drawable-en-rCA/res/drawable-fr-rCA/, który odwołuje się do zasobu icon_ca.png za pomocą elementu <bitmap>.

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

Dzięki temu możesz przechowywać tylko jedną wersję pliku PNG i 2 małe pliki XML, które do niej odsyłają. Następnie możesz użyć painterResource(R.drawable.icon), a system wybierze odpowiedni plik po wykryciu ustawień regionalnych.

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

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

<?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 zasobu R.string.hello.

Inne proste wartości działają w ten sam sposób, np. kolory:

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

Dostęp do zasobów aplikacji

Po udostępnieniu zasobu w aplikacji możesz go zastosować, odwołując się do jego identyfikatora. Wszystkie identyfikatory zasobów są zdefiniowane w klasie R projektu, którą narzędzie aapt generuje automatycznie.

Podczas kompilacji aplikacji aapt generuje klasę R, która zawiera identyfikatory zasobów wszystkich zasobów w katalogu res/. Dla każdego typu zasobu istnieje R podklasa, np. R.drawable dla wszystkich zasobów rysowalnych. Każdy zasób tego typu ma statyczną liczbę całkowitą, np. R.drawable.icon. Ta liczba całkowita to identyfikator zasobu, którego możesz użyć do pobrania zasobu.

Chociaż identyfikatory zasobów są określane w klasie R, nie musisz tam szukać, aby znaleźć identyfikator zasobu. Identyfikator zasobu zawsze składa się z tych elementów:

  • Typ zasobu: każdy zasób jest zgrupowany w „typ”, np. string lub drawable.
  • Nazwa zasobu, czyli nazwa pliku bez rozszerzenia.

Dostęp do zasobów w Compose

Jetpack Compose udostępnia wbudowane funkcje, które są zgodne z kompozycjami i umożliwiają bezpieczny dostęp do zasobów.

  • Ciągi:
    stringResource(id = R.string.hello)
  • Obiekty do rysowania:
    painterResource(id = R.drawable.my_icon)

Dostęp do zasobów w kodzie interfejsu innego niż UI

Jeśli musisz uzyskać dostęp do zasobów spoza hierarchii interfejsu, np. w ViewModel, Repository lub w Service systemu, możesz je rozpoznać za pomocą Context.

// Retrieve a localized string resource
val greeting = context.getString(R.string.hello_world)

Możesz też pobierać poszczególne zasoby za pomocą metod w Resources, których instancję możesz uzyskać za pomocą getResources.

Składnia

Oto składnia odwoływania 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 w przypadku odwoływania się do zasobów z własnego pakietu).
  • <resource_type> to podklasa R dla 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 sposobach odwoływania się do nich znajdziesz w artykule Zasoby w Compose.

Dostęp do oryginalnych plików

Chociaż jest to rzadkie, może się zdarzyć, że będziesz potrzebować dostępu do oryginalnych plików i katalogów. Jeśli tak jest, zapisywanie plików w res/ nie będzie działać, ponieważ jedynym sposobem odczytania zasobu z res/ jest użycie identyfikatora zasobu. Zamiast tego możesz zapisać zasoby w katalogu assets/.

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

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

Dostęp do zasobów platformy

Android zawiera wiele standardowych zasobów, takich jak style i motywy systemowe. Aby uzyskać do nich dostęp, zakwalifikuj odwołanie do zasobu za pomocą klasy pakietu android. Na przykład:painterResource(android.R.drawable.ic_menu_info_details).

Zapewnianie najlepszej zgodności urządzeń z zasobami

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

Jeśli na przykład Twoja aplikacja obsługuje kilka języków, zawsze uwzględniaj katalog values/ (w którym zapisane są ciągi znaków) bez kwalifikatora języka i regionu. Jeśli umieścisz wszystkie pliki ciągów znaków w katalogach, które mają kwalifikator języka i regionu, aplikacja ulegnie awarii, gdy zostanie uruchomiona na urządzeniu ustawionym na język, którego ciągi znaków nie obsługują.

Jeśli udostępnisz zasoby domyślnevalues/, aplikacja będzie działać prawidłowo, nawet jeśli użytkownik nie rozumie języka, w którym jest wyświetlana. To lepsze niż awaria.

Dostarczanie zasobów domyślnych jest ważne nie tylko dlatego, że aplikacja może działać w nieprzewidzianej 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, aplikacja uruchomiona na starszej wersji Androida ulegnie awarii, jeśli nie udostępnisz zasobów domyślnych, ponieważ nie będzie mogła używać zasobów nazwanych z użyciem nowego kwalifikatora.

Jeśli na przykład wartość minSdkVersion wynosi 4, a wszystkie zasoby rysowalne kwalifikujesz za pomocą trybu nocnego (night lub notnight, które zostały dodane w interfejsie API na poziomie 8), urządzenie z interfejsem API na poziomie 4 nie będzie mieć dostępu do zasobów rysowalnych i ulegnie awarii. W tym przypadku prawdopodobnie chcesz, aby domyślnymi zasobami były zasoby notnight, więc wyklucz ten kwalifikator i umieść zasoby rysowalne w folderze drawable/ lub drawable-night/.

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

Istnieje jeden wyjątek od tej reguły: jeśli minSdkVersion aplikacji ma wartość 4 lub większą, nie musisz używać domyślnych zasobów rysowalnych, gdy udostępniasz alternatywne zasoby rysowalne z kwalifikatorem gęstości ekranu. Nawet bez domyślnych zasobów rysowalnych Android może znaleźć najlepsze dopasowanie wśród alternatywnych gęstości ekranu i w razie potrzeby skalować mapy bitowe. Aby jednak zapewnić jak najlepsze wrażenia na wszystkich typach urządzeń, podaj alternatywne elementy rysunkowe dla wszystkich 3 rodzajów gęstości.

Jak Android znajduje najlepiej pasujący zasób

Gdy zażądasz zasobu, dla którego podasz alternatywy, Android wybierze w czasie działania, którego zasobu alternatywnego użyć, w zależności od bieżącej konfiguracji urządzenia. Aby pokazać, jak Android wybiera zasób alternatywny, załóżmy, że te katalogi obiektów rysowalnych zawierają różne wersje tych samych obrazów:

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

Załóżmy, że konfiguracja urządzenia jest taka:

Locale = en-GB
Night mode = night
Screen pixel density = hdpi
Touchscreen type = notouch
Primary text input method = 12key

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

System podejmuje decyzję o tym, z których zasobów skorzystać, na podstawie tej 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ł usunięty, ponieważ jest sprzeczny z ustawieniami regionalnymi en-GB.

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

    Wyjątek: gęstość pikseli na ekranie to jedyny kwalifikator, który nie jest eliminowany z powodu sprzeczności. Mimo że gęstość ekranu urządzenia to hdpi, element drawable-night-ldpi/ nie jest usuwany, ponieważ na tym etapie każda gęstość ekranu jest uznawana za pasującą. Więcej informacji znajdziesz w artykule Omówienie zgodności z ekranem.

  2. Na liście znajdź kwalifikator o kolejnym najwyższym priorytecie (tabela 2). (Zacznij od kodu kategorii sprzedawcy).
  3. Czy któryś z katalogów zasobów zawiera ten kwalifikator?
    • Jeśli nie, wróć do kroku 2 i sprawdź kolejny kwalifikator. W tym przykładzie odpowiedź to „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 system eliminuje wszystkie katalogi, które nie zawierają kwalifikatora języka:
    drawable/
    drawable-en/
    drawable-en-night/
    drawable-en-notouch-12key/
    drawable-night-ldpi/
    drawable-night-notouch-12key/
    

    Wyjątek: jeśli kwalifikator dotyczy gęstości pikseli na ekranie, Android wybiera opcję, która najbardziej odpowiada gęstości pikseli na ekranie urządzenia. Ogólnie rzecz biorąc, Android woli zmniejszać większy obraz oryginalny niż powiększać mniejszy obraz oryginalny. Więcej informacji znajdziesz w omówieniu zgodności ekranów.

  5. Powtarzaj kroki 2, 3 i 4, aż pozostanie tylko jeden katalog. W tym przykładzie tryb nocny jest kolejnym kwalifikatorem, dla którego istnieją dopasowania. Zatem zasoby, które nie określają trybu nocnego, są eliminowane:
    drawable-en/
    drawable-en-night/
    drawable-en-notouch-12key/
    

    Pozostały katalog to drawable-en-night.

Chociaż ta procedura jest wykonywana w przypadku każdego żądanego zasobu, system optymalizuje niektóre jej aspekty. Jedną z takich optymalizacji jest to, że gdy znana jest konfiguracja urządzenia, można wyeliminować alternatywne zasoby, które nigdy nie będą pasować. Jeśli na przykład język konfiguracji to angielski, żaden katalog zasobów z kwalifikatorem języka ustawionym na inny język niż angielski nie jest uwzględniany w puli sprawdzanych zasobów (ale 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 na ekran mniejszy niż bieżący, jeśli nie ma zasobów, które lepiej pasują. Na przykład w razie potrzeby ekran o dużym rozmiarze korzysta z zasobów ekranu o normalnym rozmiarze.

Jeśli jednak jedyne dostępne zasoby są większe niż bieżący ekran, system nie ich używa, a aplikacja ulega awarii, jeśli żadne inne zasoby nie pasują do konfiguracji urządzenia. Dzieje się tak na przykład, gdy wszystkie zasoby układu są oznaczone kwalifikatorem xlarge, ale urządzenie ma ekran o normalnym rozmiarze.

Uwaga: pierwszeństwo kwalifikatora (w tabeli 2) jest ważniejsze niż liczba kwalifikatorów, które dokładnie pasują do urządzenia. W przykładzie powyżej w kroku 4 ostatni wybór na liście zawiera 3 kwalifikatory, które dokładnie pasują do urządzenia (tryb nocny, 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ż te inne kwalifikatory, więcdrawable-night-notouch-12key jest eliminowany.

Dodatkowe materiały

Więcej informacji o zasobach aplikacji znajdziesz w tych materiałach:

Dokumentacja

Wyświetla treści