Tổng quan về tài nguyên ứng dụng

Tài nguyên là các tệp bổ sung và nội dung tĩnh mà mã của bạn sử dụng, chẳng hạn như bitmap, chuỗi giao diện người dùng, hướng dẫn về ảnh động, v.v.

Hãy luôn tách riêng các tài nguyên ứng dụng (chẳng hạn như hình ảnh và chuỗi) khỏi đoạn mã để có thể duy trì chúng một cách độc lập. Ngoài ra, hãy cung cấp tài nguyên thay thế cho các cấu hình thiết bị cụ thể bằng cách nhóm những tài nguyên đó trong các thư mục tài nguyên có tên riêng. Trong thời gian chạy, Android sử dụng tài nguyên phù hợp dựa trên cấu hình hiện tại. Ví dụ: bạn nên cung cấp các chuỗi khác nhau, tuỳ thuộc vào chế độ cài đặt ngôn ngữ.

Sau khi tách tài nguyên ứng dụng, bạn có thể truy cập vào các tài nguyên này bằng cách sử dụng mã nhận dạng tài nguyên được tạo trong lớp R của dự án. Tài liệu này cho bạn biết cách nhóm các tài nguyên trong dự án Android. Tài liệu này cũng chỉ cho bạn cách cung cấp tài nguyên thay thế cho cấu hình thiết bị cụ thể, sau đó truy cập vào những tài nguyên đó từ đoạn mã ứng dụng hoặc các tệp XML khác.

Nhóm các loại tài nguyên

Đặt mỗi loại tài nguyên vào một thư mục con cụ thể thuộc thư mục res/ của dự án. Ví dụ: sau đây là hệ phân cấp tệp của một dự án đơn giản:

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

Thư mục res/ chứa mọi tài nguyên trong các thư mục con: 1 tài nguyên hình ảnh, 1 thư mục mipmap/ cho các biểu tượng trình chạy và 1 tệp tài nguyên chuỗi. Tên thư mục tài nguyên rất quan trọng và được mô tả trong Bảng 1.

Lưu ý: Để biết thêm thông tin về cách sử dụng thư mục mipmap, hãy xem phần Đặt biểu tượng ứng dụng trong thư mục mipmap.

Bảng 1. Các thư mục tài nguyên được hỗ trợ bên trong thư mục res/ của dự án.

Thư mục Loại tài nguyên
drawable/

Tệp bitmap (PNG, .9.png, JPG hoặc GIF) hoặc tệp XML được biên dịch thành các loại tài nguyên phụ có thể vẽ sau:

  • Tệp bitmap
  • 9-patch (bitmap có thể thay đổi kích thước)
  • Danh sách trạng thái
  • Hình dạng
  • Ảnh động có thể vẽ
  • Đối tượng có thể vẽ khác

Để biết thêm thông tin, hãy xem bài viết Tài nguyên có thể vẽ.

mipmap/ Các tệp có thể vẽ cho những mật độ biểu tượng trình chạy khác nhau. Để biết thêm thông tin về cách quản lý biểu tượng trình chạy bằng các thư mục mipmap/, vui lòng xem phần Đặt biểu tượng ứng dụng trong thư mục mipmap.
raw/

Các tệp tuỳ ý để lưu ở dạng thô của các tệp này. Để mở các tài nguyên này bằng InputStream thô, hãy gọi Resources.openRawResource bằng mã nhận dạng tài nguyên là R.raw.filename.

Tuy nhiên, nếu bạn cần quyền truy cập vào tên tệp gốc và hệ phân cấp tệp, hãy cân nhắc việc lưu tài nguyên trong thư mục assets/ thay vì res/raw/. Các tệp trong assets/ không được cung cấp mã nhận dạng tài nguyên nên bạn chỉ có thể đọc các tệp này bằng AssetManager.

values/

Tệp XML chứa các giá trị đơn giản, chẳng hạn như chuỗi, số nguyên và màu.

Trong khi các tệp tài nguyên XML ở các thư mục con res/ khác xác định một tài nguyên duy nhất dựa trên tên tệp XML, thì các tệp trong thư mục values/ sẽ mô tả nhiều tài nguyên. Đối với một tệp trong thư mục này, mỗi thành phần con của phần tử <resources> đều xác định một tài nguyên duy nhất. Ví dụ: phần tử <string> tạo tài nguyên R.string và phần tử <color> tạo tài nguyên R.color.

Vì mỗi tài nguyên được xác định bằng phần tử XML riêng, nên bạn có thể tuỳ ý đặt tên cho tệp và đặt nhiều loại tài nguyên trong một tệp. Tuy nhiên, để cho rõ ràng, bạn nên đặt những loại tài nguyên duy nhất trong các tệp khác nhau. Ví dụ: sau đây là một số quy ước về tên tệp cho những tài nguyên mà bạn có thể tạo trong thư mục này:

Để biết thêm thông tin, hãy xem bài viết Tài nguyên chuỗi, Tài nguyên kiểuCác loại tài nguyên khác.

xml/ Các tệp XML tuỳ ý có thể được đọc trong thời gian chạy bằng cách gọi Resources.getXML. Bạn phải lưu các tệp cấu hình XML khác nhau vào đây.
font/ Các tệp phông chữ có đuôi như TTF, OTF hoặc TTC, hoặc các tệp XML có chứa phần tử <font-family>. Để biết thêm thông tin về phông chữ ở dạng tài nguyên, hãy xem bài viết Thêm phông chữ ở dạng tài nguyên XML.

Thận trọng: Đừng bao giờ lưu tệp tài nguyên ngay trong thư mục res/ vì việc này sẽ gây ra lỗi trình biên dịch.

Tài nguyên mà bạn lưu trong các thư mục con được xác định trong Bảng 1 là tài nguyên mặc định. Tức là những tài nguyên này xác định thiết kế và nội dung mặc định cho ứng dụng của bạn. Tuy nhiên, mỗi loại thiết bị chạy Android có thể yêu cầu các loại tài nguyên khác nhau.

Ví dụ: bạn có thể cung cấp nhiều tài nguyên chuỗi để dịch văn bản trong giao diện người dùng dựa trên chế độ cài đặt ngôn ngữ của thiết bị.

Lưu ý: Trong Compose, giao diện người dùng, ảnh động và màu sắc dựa trên trạng thái được khai báo trong Kotlin, vì vậy, các thư mục layout/, menu/, anim/, animator/color/ không còn được dùng cho các ứng dụng hiện đại. Để biết thêm thông tin, hãy xem phần Ảnh động trong ComposeKết cấu của một giao diện trong Compose.

Cung cấp tài nguyên thay thế

Hầu hết ứng dụng đều cung cấp tài nguyên thay thế để hỗ trợ các cấu hình thiết bị cụ thể. Ví dụ: thêm các tài nguyên có thể vẽ thay thế cho nhiều mật độ màn hình và tài nguyên chuỗi thay thế cho nhiều ngôn ngữ. Trong thời gian chạy, Android sẽ phát hiện cấu hình thiết bị hiện tại và tải các tài nguyên thích hợp cho ứng dụng của bạn.

Để chỉ định các tài nguyên thay thế theo cấu hình cụ thể cho một nhóm tài nguyên, hãy làm như sau:

  1. Tạo một thư mục mới trong res/ có tên trong biểu mẫu <resources_name>-<qualifier>.
    • <resources_name> là tên thư mục của các tài nguyên mặc định tương ứng (được xác định trong Bảng 1).
    • <qualifier> là tên chỉ định một cấu hình riêng lẻ để sử dụng những tài nguyên này (được xác định trong Bảng 2).

    Bạn có thể thêm nhiều <qualifier>. Phân tách từng mã bằng dấu gạch ngang.

    Chú ý: Khi thêm nhiều bộ hạn định, bạn phải đặt các bộ hạn định đó theo thứ tự được liệt kê trong Bảng 2. Nếu bạn sắp xếp các bộ hạn định không chính xác, thì các tài nguyên sẽ bị bỏ qua.

  2. Lưu các tài nguyên thay thế thích hợp trong thư mục mới này. Các tệp tài nguyên phải được đặt tên giống hệt với tệp tài nguyên mặc định.

Ví dụ: dưới đây là một số tài nguyên mặc định và tài nguyên thay thế:

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

Bộ hạn định hdpi cho biết các tài nguyên trong thư mục đó dành cho các thiết bị có màn hình với độ phân giải cao. Hình ảnh trong các thư mục có thể vẽ này được định kích thước cho mật độ màn hình cụ thể, nhưng tên tệp thì giống hệt nhau. Bằng cách này, mã nhận dạng tài nguyên mà bạn dùng để tham chiếu hình ảnh icon.png hoặc background.png luôn giống nhau. Android chọn phiên bản của từng tài nguyên phù hợp nhất với thiết bị hiện tại bằng cách so sánh thông tin cấu hình thiết bị với bộ hạn định trong tên thư mục tài nguyên.

Thận trọng: Khi xác định tài nguyên thay thế, hãy đảm bảo bạn cũng xác định tài nguyên trong cấu hình mặc định. Nếu không, ứng dụng của bạn có thể gặp phải trường hợp ngoại lệ về thời gian chạy khi thiết bị thay đổi cấu hình. Ví dụ: nếu bạn chỉ thêm một chuỗi vào values-en chứ không phải values, ứng dụng của bạn có thể gặp phải trường hợp ngoại lệ Resource Not Found khi người dùng thay đổi ngôn ngữ hệ thống mặc định.

Bảng 2 liệt kê các bộ hạn định cấu hình theo thứ tự ưu tiên. Bạn có thể thêm nhiều bộ hạn định vào một tên thư mục bằng cách dùng dấu gạch ngang phân tách từng bộ hạn định. Nếu sử dụng nhiều bộ hạn định cho một thư mục tài nguyên, bạn phải thêm các bộ hạn định đó vào tên thư mục theo thứ tự liệt kê trong bảng.

Bảng 2. Tên bộ hạn định cấu hình.

Cấu hình Giá trị bộ hạn định Nội dung mô tả
MCC và MNC Ví dụ:
mcc310
mcc310-mnc004
mcc208-mnc00

Mã di động quốc gia (MCC), theo sau là mã mạng di động (MNC) (không bắt buộc) có trên thẻ SIM trong thiết bị. Ví dụ: mcc310 là Hoa Kỳ trên bất kỳ nhà mạng nào, mcc310-mnc004 là Hoa Kỳ trên nhà mạng Verizon và mcc208-mnc00 là Pháp trên nhà mạng Orange.

Nếu thiết bị sử dụng kết nối vô tuyến (tức là điện thoại GSM), thì giá trị MCC và MNC sẽ có trên thẻ SIM.

Bạn cũng có thể sử dụng riêng MCC, ví dụ: để đưa các tài nguyên pháp lý ở từng quốc gia vào ứng dụng của bạn. Nếu bạn chỉ cần chỉ định dựa trên ngôn ngữ, hãy dùng bộ hạn định ngôn ngữ, tập lệnh (không bắt buộc) và khu vực (không bắt buộc). Nếu bạn dùng bộ hạn định MCC và MNC, hãy cẩn thận khi làm vậy và kiểm thử để chắc chắn chúng hoạt động như dự kiến.

Ngoài ra, hãy xem các trường cấu hình mccmnc, cho biết mã di động quốc gia và mã mạng di động hiện tại tương ứng.

Ngôn ngữ, tập lệnh (không bắt buộc) và khu vực (không bắt buộc) Ví dụ:
en
fr
en-rUS
fr-rFR
fr-rCA
b+en
b+en+US
b+es+419
b+zh+Hant
b+sr+Latn+RS

Ngôn ngữ này được xác định bằng mã ngôn ngữ gồm 2 chữ cái theo tiêu chuẩn ISO 639-1, có thể theo sau là mã vùng gồm 2 chữ cái theo tiêu chuẩn ISO 3166-1-alpha-2 (đứng trước r viết thường).

Các mã này không phân biệt chữ hoa chữ thường. Tiền tố r được dùng để phân biệt phần khu vực. Bạn không thể chỉ định riêng một khu vực.

Android 7.0 (API cấp 24) đã ra mắt tính năng hỗ trợ thẻ ngôn ngữ BCP 47. Bạn có thể dùng các thẻ này để đáp ứng điều kiện về tài nguyên dành riêng cho từng ngôn ngữ và khu vực. Thẻ ngôn ngữ được tạo từ một trình tự gồm một hoặc nhiều thẻ phụ, mỗi thẻ trong số đó sẽ tinh chỉnh hoặc thu hẹp phạm vi ngôn ngữ mà thẻ tổng thể xác định. Để biết thêm thông tin về thẻ ngôn ngữ, hãy xem phần Thẻ để xác định ngôn ngữ.

Để sử dụng thẻ ngôn ngữ BCP 47, hãy nối b+ với một mã ngôn ngữ gồm 2 chữ cái theo tiêu chuẩn ISO 639-1, có thể theo sau là các thẻ phụ bổ sung được phân tách bằng +.

Thẻ ngôn ngữ có thể thay đổi trong suốt thời gian hoạt động của ứng dụng nếu người dùng thay đổi ngôn ngữ trong phần cài đặt hệ thống. Để biết thông tin về mức độ ảnh hưởng của thay đổi này đến ứng dụng của bạn trong thời gian chạy, hãy xem bài viết Xử lý các thay đổi về cấu hình.

Để xem hướng dẫn đầy đủ về cách bản địa hoá ứng dụng cho các ngôn ngữ khác, hãy xem bài viết Bản địa hoá ứng dụng.

Ngoài ra, hãy xem phương thức getLocales, phương thức này cung cấp danh sách các ngôn ngữ được xác định. Danh sách này bao gồm các ngôn ngữ chính.

Giống trong ngữ pháp masculine
feminine
neuter

Giống trong ngữ pháp của người dùng. Được dùng cho những ngôn ngữ có giống trong ngữ pháp.

Ví dụ: nếu cần cung cấp các tài nguyên khác nhau cho người dùng nói tiếng Pháp, thì bạn có thể sử dụng các thư mục như sau:

res/
  values-fr/
    strings.xml (chuỗi mặc định không xác định giới tính)
  values-fr-masculine/
    strings.xml (chuỗi có giới tính nam)
  values-fr-feminine/
    strings.xml (chuỗi có giới tính nữ)
  values-fr-neuter/
    strings.xml (chuỗi có giới tính trung tính)

Xem phần Dùng yếu tố giống trong ngữ pháp để cá nhân hoá giao diện người dùng của ứng dụng.

Ngoài ra, hãy xem phương thức cấu hình getGrammaticalGender để biết giống ngữ pháp.

Đã thêm vào cấp độ API 34.

Gam màu rộng widecg
nowidecg
  • widecg: các màn hình có gam màu rộng, chẳng hạn như Display P3 hoặc AdobeRGB
  • nowidecg: các màn hình có gam màu hẹp, chẳng hạn như sRGB

Đã thêm vào API cấp 26.

Ngoài ra, hãy xem phương thức cấu hình isScreenWideColorGamut để biết màn hình có gam màu rộng hay không.

Dải động cao (HDR) highdr
lowdr
  • highdr: các màn hình có dải động cao
  • lowdr: các màn hình có dải động thấp/chuẩn

Đã thêm vào API cấp 26.

Ngoài ra, hãy xem phương thức cấu hình isScreenHdr để biết màn hình có tính năng HDR hay không.

Chế độ giao diện người dùng car
desk
television
appliance
watch
vrheadset
  • car: thiết bị đang hiển thị trong đế trên ô tô
  • desk: thiết bị đang hiển thị trong một đế để bàn
  • television: thiết bị đang hiển thị trên TV, mang đến trải nghiệm "10 feet" mà trong đó giao diện người dùng của thiết bị này nằm trên một màn hình lớn mà người dùng ở xa. Trải nghiệm này chủ yếu được định hướng xung quanh D-pad hoặc chế độ tương tác khác không phải con trỏ
  • appliance: thiết bị đang hoạt động như một thiết bị không có màn hình
  • watch: thiết bị có màn hình và được đeo trên cổ tay
  • vrheadset: thiết bị đang hiển thị trong kính thực tế ảo

Đã thêm vào cấp độ API 8; TV được thêm vào API 13; thiết bị gia dụng được thêm vào API 16; đồng hồ được thêm vào API 20; vrheadset được thêm vào API 26.

Để biết thông tin về cách ứng dụng của bạn có thể phản hồi khi thiết bị được cắm vào hoặc bị tháo khỏi đế, hãy đọc bài viết Xác định và theo dõi trạng thái cũng như loại đế sạc.

Các chế độ này có thể thay đổi trong quá trình hoạt động của ứng dụng nếu người dùng đặt thiết bị vào một đế. Bạn có thể bật hoặc tắt một số chế độ này bằng UiModeManager. Để biết thông tin về mức độ ảnh hưởng của thay đổi này đến ứng dụng của bạn trong thời gian chạy, hãy xem bài viết Xử lý các thay đổi về cấu hình.

Chế độ ban đêm night
notnight
  • night: ban đêm
  • notnight: ban ngày

Đã thêm vào API cấp 8.

Điều này có thể thay đổi trong quá trình hoạt động của ứng dụng nếu bạn để chế độ ban đêm ở chế độ tự động (mặc định). Trong trường hợp này, chế độ này thay đổi dựa vào thời gian trong ngày. Bạn có thể bật hoặc tắt chế độ này bằng UiModeManager. Để biết thông tin về mức độ ảnh hưởng của thay đổi này đến ứng dụng của bạn trong thời gian chạy, hãy xem bài viết Xử lý các thay đổi về cấu hình.

Mật độ pixel màn hình (dpi) ldpi
mdpi
hdpi
xhdpi
xxhdpi
xxxhdpi
nodpi
tvdpi
anydpi
nnndpi
  • ldpi: màn hình có độ phân giải thấp; khoảng 120 dpi.
  • mdpi: màn hình có độ phân giải trung bình (trên HVGA truyền thống); khoảng 160 dpi.
  • hdpi: màn hình có độ phân giải cao; khoảng 240 dpi.
  • xhdpi: màn hình có độ phân giải cực cao; khoảng 320 dpi. Đã thêm vào API cấp 8.
  • xxhdpi: màn hình có độ phân giải cực cực cao; khoảng 480 dpi. Đã thêm vào API cấp 16.
  • xxxhdpi: sử dụng mật độ cực cực cực cao (chỉ biểu tượng trình chạy – xem bài viết Hỗ trợ nhiều mật độ pixel); khoảng 640 dpi. Đã thêm vào API cấp 18.
  • nodpi: dùng cho các tài nguyên bitmap mà bạn không muốn điều chỉnh theo tỷ lệ cho phù hợp với độ phân giải màn hình của thiết bị.
  • tvdpi: màn hình ở đâu đó giữa mdpi và hdpi; khoảng 213 dpi. Đây không được coi là nhóm mật độ "chính". Màn hình này chủ yếu dành cho TV 720p mà hầu hết các ứng dụng không cần dùng đến. Đối với màn hình TV 1080p, hãy dùng xhdpi, còn đối với màn hình TV 4K, hãy dùng xxxhdpi. Đã thêm vào API cấp 13.
  • anydpi: khớp với mọi mật độ màn hình và được ưu tiên hơn các bộ hạn định khác. Mật độ này sẽ hữu ích cho vectơ vẽ được. Đã thêm vào API cấp 21.
  • nnndpi: dùng để biểu thị mật độ không chuẩn, trong đó nnn là mật độ màn hình có số nguyên dương. Mật độ này không được sử dụng trong hầu hết các trường hợp. Việc sử dụng nhóm mật độ chuẩn giúp giảm đáng kể chi phí khi phải hỗ trợ nhiều mật độ màn hình của thiết bị trên thị trường.

Có một tỷ lệ xích là 3:4:6:8:12:16 giữa 6 mật độ chính (bỏ qua mật độ tvdpi). Vì vậy, một bitmap 9x9 ở ldpi là 12x12 ở mdpi, 18x18 ở hdpi, 24x24 ở xhdpi, v.v.

Lưu ý: Việc sử dụng bộ hạn định mật độ không có nghĩa là tài nguyên chỉ dành cho màn hình có mật độ đó. Nếu bạn không cung cấp tài nguyên thay thế có bộ hạn định phù hợp hơn với cấu hình thiết bị hiện tại, thì hệ thống có thể sử dụng bất kỳ tài nguyên nào phù hợp nhất.

Để biết thêm thông tin về cách xử lý các mật độ màn hình khác nhau và cách Android có thể điều chỉnh bitmap theo tỷ lệ cho phù hợp với mật độ hiện tại, hãy xem bài viết Tổng quan về khả năng tương thích với màn hình.

Loại màn hình cảm ứng notouch
finger
  • notouch: thiết bị không có màn hình cảm ứng.
  • finger: thiết bị có màn hình cảm ứng dùng để tương tác trực tiếp bằng ngón tay của người dùng.

Ngoài ra, hãy xem trường cấu hình touchscreen để biết loại màn hình cảm ứng trên thiết bị.

Khả năng sử dụng bàn phím keysexposed
keyshidden
keyssoft
  • keysexposed: thiết bị có bàn phím. Nếu thiết bị (có thể) đã bật bàn phím phần mềm, thì bạn có thể sử dụng tính năng này ngay cả khi bàn phím phần cứng không hiển thị với người dùng hoặc thiết bị không có bàn phím phần cứng. Nếu bàn phím phần mềm không được cung cấp hoặc bị tắt, thì tính năng này chỉ được sử dụng khi bàn phím phần cứng hiển thị.
  • keyshidden: thiết bị có bàn phím phần cứng nhưng bị ẩn thiết bị không bật bàn phím phần mềm.
  • keyssoft: thiết bị đã bật bàn phím phần mềm, cho dù người dùng có nhìn thấy bàn phím đó hay không.

Nếu bạn cung cấp tài nguyên keysexposed nhưng không cung cấp tài nguyên keyssoft, hệ thống sẽ sử dụng tài nguyên keysexposed bất kể bàn phím có hiển thị hay không, miễn là hệ thống đã bật bàn phím phần mềm.

Điều này có thể thay đổi trong quá trình hoạt động của ứng dụng nếu người dùng mở bàn phím phần cứng. Để biết thông tin về mức độ ảnh hưởng của thay đổi này đến ứng dụng của bạn trong thời gian chạy, hãy xem bài viết Xử lý các thay đổi về cấu hình.

Ngoài ra, hãy xem các trường cấu hình hardKeyboardHiddenkeyboardHidden, tương ứng cho biết khả năng hiển thị của bàn phím phần cứng và khả năng hiển thị của bất kỳ loại bàn phím nào (bao gồm cả bàn phím phần mềm).

Phương thức nhập văn bản chính nokeys
qwerty
12key
  • nokeys: thiết bị không có khoá phần cứng để nhập văn bản.
  • qwerty: thiết bị có bàn phím phần cứng dạng QWERTY, cho dù người dùng có nhìn thấy bàn phím đó hay không.
  • 12key: thiết bị có bàn phím phần cứng dạng 12 phím, cho dù người dùng có nhìn thấy bàn phím đó hay không.

Ngoài ra, hãy xem trường cấu hình keyboard để biết phương thức nhập văn bản chính hiện có.

Phiên bản nền tảng (cấp độ API) Ví dụ:
v3
v4
v7
, v.v.

Cấp độ API mà thiết bị hỗ trợ. Ví dụ: v1 cho API cấp 1 (thiết bị chạy Android 1.0 trở lên) và v4 cho API cấp 4 (thiết bị chạy Android 1.6 trở lên). Để biết thêm thông tin về các giá trị này, hãy xem tài liệu về Cấp độ API Android.

Lưu ý: Không phải phiên bản Android nào cũng hỗ trợ mọi bộ hạn định. Việc sử dụng bộ hạn định mới sẽ ngầm thêm bộ hạn định phiên bản nền tảng để các thiết bị cũ có thể bỏ qua bộ hạn định đó. Để tránh mọi sự cố, hãy luôn thêm một nhóm tài nguyên mặc định (một nhóm tài nguyên không có bộ hạn định). Để biết thêm thông tin, hãy xem phần cung cấp khả năng tương thích tốt nhất với thiết bị bằng tài nguyên.

Trong các ứng dụng Compose, bạn không cần đến các bộ đủ tiêu chuẩn về cấu hình liên quan đến bố cục và kích thước. Mặc dù vẫn tồn tại, nhưng các mục này sẽ bị loại trừ khỏi Bảng 2. Các bộ hạn định này bao gồm: hướng bố cục, chiều rộng nhỏ nhất, chiều rộng có sẵn, chiều cao có sẵn, kích thước màn hình, tỷ lệ khung hình màn hình, màn hình tròn và hướng màn hình. Để xem toàn bộ bảng bộ hạn định cấu hình theo thứ tự ưu tiên, hãy xem phần Tổng quan về tài nguyên ứng dụng (Chế độ xem).

Quy tắc về tên bộ hạn định

Dưới đây là một số quy tắc về việc sử dụng tên bộ hạn định cấu hình:

  • Bạn có thể chỉ định nhiều bộ hạn định cho một nhóm tài nguyên, phân tách bằng dấu gạch ngang. Ví dụ: drawable-en-rUS-night áp dụng cho các thiết bị Tiếng Anh-Mỹ ở chế độ ban đêm.
  • Bộ hạn định phải theo thứ tự được liệt kê trong Bảng 2.
    • Sai: drawable-hdpi-night/
    • Đúng: drawable-night-hdpi/
  • Không thể lồng các thư mục tài nguyên thay thế. Ví dụ: bạn không thể có res/drawable/drawable-en/.
  • Các giá trị không phân biệt chữ hoa chữ thường. Trình biên dịch tài nguyên chuyển đổi tên thư mục thành chữ thường trước khi xử lý để tránh các sự cố trên hệ thống tệp không phân biệt chữ hoa chữ thường. Mọi cách viết hoa trong tên chỉ mang lại lợi ích dễ đọc.
  • Chỉ hỗ trợ một giá trị cho mỗi loại bộ hạn định. Ví dụ: nếu muốn sử dụng cùng một tệp có thể vẽ cho Tây Ban Nha và Pháp, bạn không thể tạo thư mục có tên là drawable-es-fr/. Thay vào đó, bạn cần có 2 thư mục tài nguyên, chẳng hạn như drawable-es/drawable-fr/ chứa các tệp thích hợp.

Sau khi bạn lưu tài nguyên thay thế vào các thư mục được đặt tên bằng bộ hạn định này, Android sẽ tự động áp dụng các tài nguyên trong ứng dụng của bạn dựa trên cấu hình hiện tại của thiết bị. Mỗi khi có tài nguyên được yêu cầu, Android sẽ kiểm tra các thư mục tài nguyên thay thế xem có chứa tệp tài nguyên được yêu cầu hay không, sau đó tìm tài nguyên phù hợp nhất.

Nếu không có tài nguyên thay thế nào phù hợp với một cấu hình thiết bị cụ thể, thì Android sẽ sử dụng các tài nguyên mặc định tương ứng – nhóm tài nguyên cho một loại tài nguyên cụ thể không bao gồm bộ hạn định cấu hình.

Tạo tài nguyên đại diện

Khi có một tài nguyên mà bạn muốn sử dụng cho nhiều cấu hình thiết bị nhưng không muốn cung cấp ở dạng tài nguyên mặc định, bạn không cần phải đặt cùng một tài nguyên vào nhiều thư mục tài nguyên thay thế. Thay vào đó, bạn có thể tạo một tài nguyên thay thế đóng vai trò là đại diện cho một tài nguyên được lưu trong thư mục tài nguyên mặc định của bạn.

Đối tượng có thể vẽ

Ví dụ: giả sử bạn có biểu tượng ứng dụng icon.png và cần một phiên bản độc đáo cho các ngôn ngữ khác nhau. Tuy nhiên, 2 ngôn ngữ là Tiếng Anh-Canada và Tiếng Pháp-Canada cần sử dụng cùng một phiên bản. Bạn không cần sao chép cùng một hình ảnh vào thư mục tài nguyên cho cả tiếng Anh-Canada và tiếng Pháp-Canada. Thay vào đó, bạn có thể lưu hình ảnh dùng cho cả hai với bất kỳ tên nào không phải icon.png, chẳng hạn như icon_ca.png rồi đặt hình ảnh đó vào thư mục res/drawable/ mặc định. Sau đó, hãy tạo một tệp icon.xml trong res/drawable-en-rCA/res/drawable-fr-rCA/ tham chiếu đến tài nguyên icon_ca.png bằng cách sử dụng phần tử <bitmap>.

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

Việc này cho phép bạn chỉ lưu trữ 1 phiên bản của tệp PNG và 2 tệp XML nhỏ trỏ đến tệp đó. Sau đó, bạn có thể sử dụng painterResource(R.drawable.icon) và hệ thống sẽ chọn tệp thích hợp sau khi phát hiện ngôn ngữ.

Chuỗi và các giá trị đơn giản khác

Để tạo một đại diện cho một chuỗi hiện có, hãy sử dụng mã nhận dạng tài nguyên của chuỗi mong muốn làm giá trị cho chuỗi mới:

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

Tài nguyên R.string.hi hiện là đại diện của R.string.hello.

Các giá trị đơn giản khác cũng hoạt động theo cách tương tự, chẳng hạn như màu:

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

Truy cập vào tài nguyên ứng dụng của bạn

Sau khi cung cấp tài nguyên trong ứng dụng, bạn có thể áp dụng tài nguyên đó bằng cách tham chiếu mã nhận dạng tài nguyên của tài nguyên đó. Mọi mã nhận dạng tài nguyên đều được xác định trong lớp R của dự án mà công cụ aapt sẽ tự động tạo.

Khi ứng dụng của bạn được biên dịch, aapt sẽ tạo lớp R, chứa mã nhận dạng tài nguyên cho mọi tài nguyên trong thư mục res/. Đối với mỗi loại tài nguyên, có một lớp con R, chẳng hạn như R.drawable cho mọi tài nguyên có thể vẽ. Mỗi tài nguyên thuộc loại đó đều có một số nguyên tĩnh, ví dụ: R.drawable.icon. Số nguyên này là mã nhận dạng tài nguyên mà bạn có thể dùng để truy xuất tài nguyên của mình.

Mặc dù lớp R là nơi có mã nhận dạng tài nguyên được chỉ định, nhưng bạn không cần phải tìm đến đó để khám phá mã nhận dạng tài nguyên. Mã nhận dạng tài nguyên luôn bao gồm các thành phần sau:

  • Loại tài nguyên: mỗi tài nguyên được nhóm thành một "loại", chẳng hạn như string hoặc drawable.
  • Tên tài nguyên là tên tệp, không bao gồm đuôi tệp.

Truy cập vào tài nguyên trong Compose

Jetpack Compose cung cấp các hàm tích hợp, có khả năng kết hợp để truy cập vào tài nguyên một cách an toàn.

  • Chuỗi:
    stringResource(id = R.string.hello)
  • Drawable:
    painterResource(id = R.drawable.my_icon)

Truy cập vào tài nguyên trong mã không phải giao diện người dùng

Nếu cần truy cập vào các tài nguyên bên ngoài hệ phân cấp giao diện người dùng (chẳng hạn như trong ViewModel, Repository hoặc Service hệ thống), bạn có thể phân giải các tài nguyên đó bằng Context.

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

Bạn cũng có thể truy xuất từng tài nguyên riêng lẻ bằng các phương thức trong Resources. Bạn có thể lấy thực thể này của getResources.

Cú pháp

Dưới đây là cú pháp để tham chiếu một tài nguyên trong mã:

[<package_name>.]R.<resource_type>.<resource_name>
  • <package_name> là tên của gói chứa tài nguyên (không bắt buộc khi tham chiếu tài nguyên từ gói của bạn).
  • <resource_type> là lớp con R cho loại tài nguyên.
  • <resource_name> là tên tệp tài nguyên không có đuôi hoặc giá trị thuộc tính android:name trong phần tử XML, đối với các giá trị đơn giản.

Để biết thêm thông tin về từng loại tài nguyên và cách tham chiếu, hãy xem bài viết Tài nguyên trong Compose.

Truy cập vào tệp gốc

Mặc dù không phổ biến, nhưng bạn có thể cần phải truy cập vào các tệp và thư mục gốc. Nếu truy cập vào thì bạn sẽ không thể lưu tệp trong res/, vì cách duy nhất để đọc tài nguyên từ res/ là dùng mã nhận dạng tài nguyên. Thay vào đó, bạn có thể lưu tài nguyên trong thư mục assets/.

Các tệp đã lưu trong thư mục assets/ không được cấp mã nhận dạng tài nguyên. Do đó, bạn không thể tham chiếu đến các tệp này thông qua lớp R hoặc từ tài nguyên XML. Thay vào đó, bạn có thể truy vấn các tệp trong thư mục assets/ như một hệ thống tệp thông thường và đọc dữ liệu thô bằng cách sử dụng AssetManager.

Tuy nhiên, nếu bạn chỉ cần đọc dữ liệu thô (chẳng hạn như tệp video hoặc tệp âm thanh), thì hãy lưu tệp đó vào thư mục res/raw/ và đọc một luồng byte bằng openRawResource.

Truy cập vào tài nguyên của nền tảng

Android chứa một số tài nguyên chuẩn, chẳng hạn như kiểu và giao diện hệ thống. Để truy cập vào các tài nguyên này, hãy xác định điều kiện tham chiếu tài nguyên bằng lớp gói android. Ví dụ: painterResource(android.R.drawable.ic_menu_info_details).

Cung cấp khả năng tương thích tốt nhất với thiết bị bằng các tài nguyên

Để ứng dụng của bạn hỗ trợ nhiều cấu hình thiết bị, bạn phải luôn cung cấp tài nguyên mặc định cho mỗi loại tài nguyên mà ứng dụng của bạn dùng.

Ví dụ: nếu ứng dụng của bạn hỗ trợ nhiều ngôn ngữ, hãy luôn thêm thư mục values/ (nơi các chuỗi được lưu) không có bộ hạn định ngôn ngữ và khu vực. Thay vào đó, nếu bạn đặt mọi tệp chuỗi của mình vào thư mục có bộ hạn định ngôn ngữ và khu vực, thì ứng dụng sẽ gặp sự cố khi chạy trên thiết bị được đặt thành ngôn ngữ mà các chuỗi đó không hỗ trợ.

Miễn là bạn cung cấp tài nguyên values/ mặc định, thì ứng dụng sẽ chạy đúng cách, ngay cả khi người dùng không hiểu ngôn ngữ được hiển thị. Dù sao thì vẫn tốt hơn là gặp sự cố.

Việc cung cấp tài nguyên mặc định không chỉ quan trọng vì ứng dụng của bạn có thể chạy trên một cấu hình ngoài dự kiến, mà còn vì các phiên bản Android mới đôi khi sẽ thêm những bộ hạn định cấu hình mà các phiên bản thấp hơn không hỗ trợ. Nếu bạn sử dụng một bộ hạn định tài nguyên mới, nhưng vẫn duy trì khả năng tương thích mã với các phiên bản Android thấp hơn, thì khi một phiên bản Android thấp hơn chạy ứng dụng của bạn, ứng dụng đó sẽ gặp sự cố nếu bạn không cung cấp tài nguyên mặc định, vì ứng dụng không thể sử dụng tài nguyên có tên bộ hạn định mới.

Ví dụ: nếu minSdkVersion của bạn được đặt thành 4 và bạn đủ điều kiện dùng mọi tài nguyên có thể vẽ của mình bằng cách sử dụng chế độ ban đêm (night hoặc notnight đã được thêm vào API cấp 8), thì thiết bị API cấp 4 không thể truy cập vào các tài nguyên có thể vẽ của bạn và sẽ gặp sự cố. Trong trường hợp này, bạn có thể muốn notnight trở thành tài nguyên mặc định. Vì vậy, bạn nên loại trừ bộ hạn định đó để các tài nguyên có thể vẽ sẽ ở dạng drawable/ hoặc drawable-night/.

Tóm lại, để cung cấp khả năng tương thích tốt nhất với thiết bị, hãy luôn cung cấp tài nguyên mặc định cho các tài nguyên mà ứng dụng của bạn cần để có thể hoạt động đúng cách. Sau đó, hãy tạo tài nguyên thay thế cho các cấu hình thiết bị cụ thể bằng cách sử dụng bộ hạn định cấu hình.

Có một ngoại lệ đối với quy tắc này: Nếu minSdkVersion của ứng dụng là 4 trở lên, bạn không cần tài nguyên có thể vẽ mặc định khi cung cấp tài nguyên có thể vẽ thay thế với bộ hạn định mật độ màn hình. Ngay cả khi không có tài nguyên có thể vẽ mặc định, Android vẫn có thể tìm thấy kết quả phù hợp nhất trong số các mật độ màn hình thay thế và điều chỉnh bitmap theo tỷ lệ nếu cần. Tuy nhiên, để có trải nghiệm tốt nhất trên mọi loại thiết bị, hãy cung cấp các tài nguyên có thể vẽ thay thế cho cả 3 loại mật độ.

Cách Android tìm ra tài nguyên phù hợp nhất

Khi bạn yêu cầu một tài nguyên mà bạn cung cấp các tài nguyên thay thế, Android sẽ dựa vào cấu hình thiết bị hiện tại để chọn tài nguyên thay thế nhằm sử dụng trong thời gian chạy. Để minh hoạ cách Android chọn một tài nguyên thay thế, hãy giả sử mỗi thư mục có thể vẽ sau đây chứa các phiên bản khác nhau của cùng hình ảnh:

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

Đồng thời giả sử sau đây là cấu hình thiết bị:

Ngôn ngữ = en-GB
Chế độ ban đêm = night
Mật độ pixel màn hình = hdpi
Loại màn hình cảm ứng = notouch
Phương thức nhập văn bản chính = 12key

Bằng cách so sánh cấu hình thiết bị với tài nguyên thay thế có sẵn, Android sẽ chọn các đối tượng có thể vẽ từ drawable-en-night.

Hệ thống đưa ra quyết định về tài nguyên sẽ sử dụng với logic sau:

Hình 2. Sơ đồ quy trình về cách Android tìm được tài nguyên phù hợp nhất.

  1. Loại bỏ những tệp tài nguyên xung đột với cấu hình thiết bị.

    Thư mục drawable-fr-rCA/ bị loại bỏ vì thư mục này xung đột với ngôn ngữ en-GB.

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

    Ngoại lệ: Mật độ pixel trên màn hình là một bộ hạn định không bị loại bỏ do xung đột. Mặc dù mật độ màn hình của thiết bị là hdpi, nhưng drawable-night-ldpi/ sẽ không bị loại bỏ vì mọi mật độ màn hình đều được coi là khớp tại thời điểm này. Để biết thông tin, hãy xem bài viết Tổng quan về khả năng tương thích với màn hình.

  2. Tìm bộ hạn định có mức độ ưu tiên cao nhất tiếp theo trong danh sách (Bảng 2). (Bắt đầu bằng MCC.)
  3. Có thư mục tài nguyên nào bao gồm bộ hạn định này không?
    • Nếu không, hãy quay lại bước 2 và xem bộ hạn định tiếp theo. Trong ví dụ này, câu trả lời là "không" cho đến khi câu trả lời là bộ hạn định ngôn ngữ.
    • Nếu có, hãy chuyển sang bước 4.
  4. Loại bỏ các thư mục tài nguyên không bao gồm bộ hạn định này. Trong ví dụ này, tiếp theo, hệ thống sẽ loại bỏ tất cả các thư mục không bao gồm bộ hạn định ngôn ngữ:
    drawable/
    drawable-en/
    drawable-en-night/
    drawable-en-notouch-12key/
    drawable-night-ldpi/
    drawable-night-notouch-12key/
    

    Ngoại lệ: Nếu bộ hạn định được đề cập trong câu hỏi là mật độ pixel trên màn hình, thì Android sẽ chọn lựa chọn phù hợp nhất với mật độ màn hình của thiết bị. Nhìn chung, Android muốn giảm kích thước hình ảnh gốc lớn hơn để mở rộng hình ảnh gốc nhỏ hơn. Để biết thêm thông tin, hãy xem bài viết Tổng quan về khả năng tương thích với màn hình.

  5. Lặp lại các bước 2, 3 và 4 cho đến khi chỉ còn một thư mục. Trong ví dụ này, chế độ ban đêm là bộ hạn định tiếp theo mà sẽ có bất kỳ kết quả trùng khớp nào. Do đó, những tài nguyên không chỉ định chế độ ban đêm sẽ bị loại bỏ:
    drawable-en/
    drawable-en-night/
    drawable-en-notouch-12key/
    

    Thư mục còn lại là drawable-en-night.

Mặc dù quy trình này được thực thi cho mỗi tài nguyên được yêu cầu, nhưng hệ thống sẽ tối ưu hoá một số khía cạnh của quy trình. Một trong những cách tối ưu hoá này là khi đã biết cấu hình của thiết bị, hệ thống có thể loại bỏ các tài nguyên thay thế không bao giờ khớp. Ví dụ: nếu ngôn ngữ cấu hình là tiếng Anh, thì mọi thư mục tài nguyên có bộ hạn định ngôn ngữ được đặt thành một ngôn ngữ khác tiếng Anh sẽ không bao giờ được đưa vào nhóm tài nguyên được đánh dấu (mặc dù thư mục tài nguyên không có bộ hạn định ngôn ngữ vẫn được bao gồm).

Khi chọn tài nguyên dựa trên bộ hạn định kích thước màn hình, hệ thống sẽ sử dụng tài nguyên được thiết kế cho một màn hình nhỏ hơn màn hình hiện tại nếu không có tài nguyên nào phù hợp hơn. Ví dụ: màn hình kích thước lớn sẽ sử dụng tài nguyên màn hình kích thước bình thường nếu cần.

Tuy nhiên, nếu tài nguyên duy nhất hiện có lớn hơn màn hình hiện tại, thì hệ thống sẽ không sử dụng các tài nguyên đó và ứng dụng của bạn sẽ gặp sự cố nếu không có tài nguyên nào khác khớp với cấu hình thiết bị. Ví dụ: sự cố này xảy ra nếu tất cả tài nguyên bố cục được gắn thẻ với bộ hạn định xlarge, nhưng thiết bị là màn hình có kích thước bình thường.

Lưu ý: Mức độ ưu tiên của bộ hạn định (trong Bảng 2) quan trọng hơn số lượng bộ hạn định khớp chính xác với thiết bị. Trong ví dụ trước, ở bước 4, lựa chọn cuối cùng trong danh sách có 3 bộ hạn định khớp chính xác với thiết bị (chế độ ban đêm, loại màn hình cảm ứng và phương thức nhập), trong khi drawable-en chỉ có một tham số phù hợp (ngôn ngữ). Tuy nhiên, ngôn ngữ có mức độ ưu tiên cao hơn so với các bộ hạn định này, vì vậy drawable-night-notouch-12key sẽ bị loại bỏ.

Tài nguyên khác

Để tìm hiểu thêm về tài nguyên ứng dụng, hãy xem thêm các tài nguyên sau:

Tài liệu

Xem nội dung