Tài liệu này mô tả các thao tác cơ bản với NFC mà bạn thực hiện trong Android. Tài liệu này giải thích cách gửi và nhận dữ liệu NFC dưới dạng thông báo NDEF, đồng thời mô tả các API khung Android hỗ trợ những tính năng này. Để biết thêm về các chủ đề nâng cao, bao gồm cả nội dung thảo luận về cách làm việc với dữ liệu không phải NDEF, hãy xem phần NFC nâng cao.
Việc đọc dữ liệu NDEF từ thẻ NFC được xử lý bằng hệ thống điều phối thẻ. Hệ thống này phân tích các thẻ NFC được phát hiện, phân loại dữ liệu một cách thích hợp và khởi động một ứng dụng quan tâm đến dữ liệu được phân loại. Một ứng dụng muốn xử lý thẻ NFC được quét có thể khai báo một bộ lọc ý định và yêu cầu xử lý dữ liệu.
Hệ thống truyền thẻ
Các thiết bị chạy Android thường tìm thẻ NFC khi màn hình được mở khoá, trừ phi NFC bị tắt trong trình đơn Cài đặt của thiết bị. Khi một thiết bị chạy Android phát hiện thấy thẻ NFC, hành vi mong muốn là hoạt động phù hợp nhất sẽ xử lý ý định mà không cần hỏi người dùng nên sử dụng ứng dụng nào. Vì các thiết bị quét thẻ NFC ở phạm vi rất ngắn, nên có khả năng việc yêu cầu người dùng chọn hoạt động theo cách thủ công sẽ buộc họ di chuyển thiết bị ra khỏi thẻ và làm gián đoạn kết nối. Bạn chỉ nên phát triển hoạt động của mình để xử lý các thẻ NFC mà hoạt động đó quan tâm nhằm ngăn Trình chọn hoạt động xuất hiện.
Để giúp bạn đạt được mục tiêu này, Android cung cấp một hệ thống gửi thẻ đặc biệt để phân tích các thẻ NFC đã quét, phân tích cú pháp các thẻ đó và cố gắng xác định vị trí các ứng dụng quan tâm đến dữ liệu đã quét. Thao tác này được thực hiện bằng cách:
- Phân tích cú pháp thẻ NFC và tìm ra loại MIME hoặc URI xác định tải trọng dữ liệu trong thẻ.
- Đóng gói loại MIME hoặc URI và tải trọng vào một ý định. Hai bước đầu tiên này được mô tả trong phần Cách ánh xạ thẻ NFC với các loại MIME và URI.
- Bắt đầu một hoạt động dựa trên ý định. Điều này được mô tả trong phần Cách gửi thẻ NFC đến các ứng dụng.
Cách ánh xạ thẻ NFC với các loại MIME và URI
Trước khi bắt đầu viết các ứng dụng NFC, bạn cần hiểu rõ các loại thẻ NFC, cách hệ thống điều phối thẻ phân tích cú pháp thẻ NFC và công việc đặc biệt mà hệ thống điều phối thẻ thực hiện khi phát hiện thấy một thông báo NDEF. Thẻ NFC có nhiều công nghệ và cũng có thể ghi dữ liệu vào thẻ theo nhiều cách. Android hỗ trợ nhiều nhất cho tiêu chuẩn NDEF do Diễn đàn NFC xác định.
Dữ liệu NDEF được đóng gói bên trong một thông báo (NdefMessage) chứa một hoặc nhiều bản ghi (NdefRecord). Mỗi bản ghi NDEF phải có cấu trúc phù hợp theo quy cách của loại bản ghi mà bạn muốn tạo. Android cũng hỗ trợ các loại thẻ khác không chứa dữ liệu NDEF. Bạn có thể làm việc với các loại thẻ này bằng cách sử dụng các lớp trong gói android.nfc.tech. Để tìm hiểu thêm về các công nghệ này, hãy xem chủ đề NFC nâng cao. Việc sử dụng các loại thẻ khác này liên quan đến việc viết ngăn xếp giao thức của riêng bạn để giao tiếp với thẻ. Vì vậy, bạn nên sử dụng NDEF khi có thể để dễ dàng phát triển và hỗ trợ tối đa cho các thiết bị chạy Android.
Lưu ý: Để tải thông số kỹ thuật NDEF đầy đủ xuống, hãy truy cập vào trang web NFC Forum Specifications & Application Documents (Thông số kỹ thuật và tài liệu ứng dụng của Diễn đàn NFC) rồi xem phần Tạo các loại bản ghi NDEF phổ biến để biết ví dụ về cách tạo bản ghi NDEF.
Giờ đây, khi bạn đã có một số kiến thức cơ bản về thẻ NFC, các phần sau đây sẽ mô tả chi tiết hơn về cách Android xử lý các thẻ được định dạng NDEF. Khi một thiết bị chạy Android quét thẻ NFC chứa dữ liệu được định dạng NDEF, thiết bị sẽ phân tích cú pháp thông báo và cố gắng tìm ra loại MIME hoặc URI nhận dạng của dữ liệu. Để làm việc này, hệ thống sẽ đọc NdefRecord đầu tiên bên trong NdefMessage để xác định cách diễn giải toàn bộ thông báo NDEF (một thông báo NDEF có thể có nhiều bản ghi NDEF). Trong thông báo NDEF có cấu trúc hợp lệ, NdefRecord đầu tiên chứa các trường sau:
- TNF (Định dạng tên loại) 3 bit
- Cho biết cách diễn giải trường loại có độ dài thay đổi. Các giá trị hợp lệ được mô tả trong Bảng 1.
- Loại có độ dài thay đổi
- Mô tả loại bản ghi. Nếu sử dụng
TNF_WELL_KNOWN, hãy dùng trường này để chỉ định Định nghĩa loại bản ghi (RTD). Các giá trị RTD hợp lệ được mô tả trong Bảng 2. - Mã nhận dạng có độ dài thay đổi
- Giá trị nhận dạng riêng biệt của bản ghi. Trường này không được dùng thường xuyên, nhưng nếu cần xác định duy nhất một thẻ, bạn có thể tạo mã nhận dạng cho thẻ đó.
- Tải trọng có độ dài thay đổi
- Tải trọng dữ liệu thực tế mà bạn muốn đọc hoặc ghi. Một thông báo NDEF có thể chứa nhiều bản ghi NDEF, vì vậy, đừng cho rằng toàn bộ tải trọng nằm trong bản ghi NDEF đầu tiên của thông báo NDEF.
Hệ thống điều phối thẻ sử dụng các trường TNF và loại để cố gắng ánh xạ một loại MIME hoặc URI đến thông báo NDEF. Nếu thành công, thông tin đó sẽ được đóng gói bên trong một ý định ACTION_NDEF_DISCOVERED cùng với tải trọng thực tế. Tuy nhiên, có những trường hợp hệ thống gửi thẻ không xác định được loại dữ liệu dựa trên bản ghi NDEF đầu tiên. Điều này xảy ra khi dữ liệu NDEF không thể được liên kết với một loại MIME hoặc URI, hoặc khi thẻ NFC không chứa dữ liệu NDEF ngay từ đầu. Trong những trường hợp như vậy, một đối tượng Tag có thông tin về các công nghệ của thẻ và tải trọng sẽ được đóng gói bên trong một ý định ACTION_TECH_DISCOVERED.
Bảng 1 mô tả cách hệ thống điều phối thẻ ánh xạ các trường TNF và loại sang các loại MIME hoặc URI. Nó cũng mô tả những TNF không thể được liên kết với một loại MIME hoặc URI.
Trong những trường hợp này, hệ thống gửi thẻ sẽ quay lại ACTION_TECH_DISCOVERED.
Ví dụ: nếu hệ thống phân phối thẻ gặp một bản ghi thuộc loại TNF_ABSOLUTE_URI, hệ thống sẽ ánh xạ trường loại có độ dài thay đổi của bản ghi đó thành một URI. Hệ thống điều phối thẻ sẽ đóng gói URI đó trong trường dữ liệu của một ý định ACTION_NDEF_DISCOVERED cùng với các thông tin khác về thẻ, chẳng hạn như tải trọng. Mặt khác, nếu gặp một bản ghi thuộc loại TNF_UNKNOWN, thì hệ thống sẽ tạo một ý định bao bọc các công nghệ của thẻ thay vì tạo một bản ghi.
Bảng 1. Các TNF được hỗ trợ và mối liên kết của chúng
| Định dạng tên loại (TNF) | Liên kết |
|---|---|
TNF_ABSOLUTE_URI |
URI dựa trên trường loại. |
TNF_EMPTY |
Quay lại ACTION_TECH_DISCOVERED. |
TNF_EXTERNAL_TYPE |
URI dựa trên URN trong trường loại. URN được mã hoá vào trường loại NDEF ở dạng rút gọn: <domain_name>:<service_name>.
Android ánh xạ URI này thành một URI có dạng: vnd.android.nfc://ext/<domain_name>:<service_name>. |
TNF_MIME_MEDIA |
Loại MIME dựa trên trường loại. |
TNF_UNCHANGED |
Không hợp lệ trong bản ghi đầu tiên, nên sẽ quay lại ACTION_TECH_DISCOVERED. |
TNF_UNKNOWN |
Quay lại ACTION_TECH_DISCOVERED. |
TNF_WELL_KNOWN |
Loại MIME hoặc URI, tuỳ thuộc vào Định nghĩa loại bản ghi (RTD) mà bạn thiết lập trong trường loại. Hãy xem Bảng 2 để biết thêm thông tin về các RTD hiện có và mối liên kết của chúng. |
Bảng 2. Các RTD được hỗ trợ cho TNF_WELL_KNOWN và các mối liên kết của chúng
| Định nghĩa loại bản ghi (RTD) | Liên kết |
|---|---|
RTD_ALTERNATIVE_CARRIER |
Quay lại ACTION_TECH_DISCOVERED. |
RTD_HANDOVER_CARRIER |
Quay lại ACTION_TECH_DISCOVERED. |
RTD_HANDOVER_REQUEST |
Quay lại ACTION_TECH_DISCOVERED. |
RTD_HANDOVER_SELECT |
Quay lại ACTION_TECH_DISCOVERED. |
RTD_SMART_POSTER |
URI dựa trên việc phân tích cú pháp trọng tải. |
RTD_TEXT |
Loại MIME của text/plain. |
RTD_URI |
URI dựa trên tải trọng. |
Cách thẻ NFC được gửi đến các ứng dụng
Khi hệ thống điều phối thẻ hoàn tất việc tạo một ý định bao bọc thẻ NFC và thông tin nhận dạng của thẻ, hệ thống sẽ gửi ý định đó đến một ứng dụng quan tâm có bộ lọc cho ý định. Nếu có nhiều ứng dụng có thể xử lý ý định này, thì Trình chọn hoạt động sẽ xuất hiện để người dùng có thể chọn Hoạt động. Hệ thống gửi thẻ xác định 3 ý định, được liệt kê theo thứ tự từ mức độ ưu tiên cao nhất đến thấp nhất:
-
ACTION_NDEF_DISCOVERED: Ý định này dùng để bắt đầu một Hoạt động khi một thẻ chứa tải trọng NDEF được quét và thuộc một loại được nhận dạng. Đây là ý định có mức độ ưu tiên cao nhất và hệ thống điều phối thẻ sẽ cố gắng khởi động một Hoạt động bằng ý định này trước bất kỳ ý định nào khác, bất cứ khi nào có thể.Lưu ý: Kể từ Android 16, việc quét các thẻ NFC lưu trữ đường liên kết URL (tức là lược đồ URI là "https://" hoặc "http://") sẽ kích hoạt ý định
ACTION_VIEWthay vì ý địnhACTION_NDEF_DISCOVERED. ACTION_TECH_DISCOVERED: Nếu không có hoạt động nào đăng ký xử lý ý địnhACTION_NDEF_DISCOVERED, thì hệ thống điều phối thẻ sẽ cố gắng khởi động một ứng dụng bằng ý định này. Ý định này cũng được bắt đầu trực tiếp (mà không cần bắt đầuACTION_NDEF_DISCOVEREDtrước) nếu thẻ được quét chứa dữ liệu NDEF không thể được liên kết với một kiểu MIME hoặc URI, hoặc nếu thẻ không chứa dữ liệu NDEF nhưng thuộc một công nghệ thẻ đã biết.ACTION_TAG_DISCOVERED: Ý định này được bắt đầu nếu không có hoạt động nào xử lý ý địnhACTION_NDEF_DISCOVEREDhoặcACTION_TECH_DISCOVERED.
Sau đây là cách hoạt động cơ bản của hệ thống điều phối thẻ:
- Cố gắng bắt đầu một Hoạt động bằng ý định do hệ thống điều phối thẻ tạo khi phân tích cú pháp thẻ NFC (
ACTION_NDEF_DISCOVEREDhoặcACTION_TECH_DISCOVERED). - Nếu không có bộ lọc hoạt động nào cho ý định đó, hãy thử bắt đầu một Hoạt động bằng ý định có mức độ ưu tiên thấp nhất tiếp theo (
ACTION_TECH_DISCOVEREDhoặcACTION_TAG_DISCOVERED) cho đến khi một ứng dụng lọc ý định hoặc cho đến khi hệ thống điều phối thẻ thử tất cả các ý định có thể. - Nếu không có ứng dụng nào lọc cho bất kỳ ý định nào, thì không làm gì cả.
Bất cứ khi nào có thể, hãy sử dụng thông báo NDEF và ý định ACTION_NDEF_DISCOVERED, vì đây là ý định cụ thể nhất trong số 3 ý định. Ý định này cho phép bạn khởi động ứng dụng vào thời điểm thích hợp hơn so với 2 ý định còn lại, mang lại trải nghiệm tốt hơn cho người dùng.
Yêu cầu quyền truy cập NFC trong tệp kê khai Android
Trước khi bạn có thể truy cập vào phần cứng NFC của thiết bị và xử lý đúng cách các ý định NFC, hãy khai báo những mục này trong tệp AndroidManifest.xml:
- Phần tử NFC
<uses-permission>để truy cập vào phần cứng NFC:<uses-permission android:name="android.permission.NFC" />
- Phiên bản SDK tối thiểu mà ứng dụng của bạn có thể hỗ trợ. API cấp 9 chỉ hỗ trợ việc gửi thẻ có giới hạn thông qua
ACTION_TAG_DISCOVEREDvà chỉ cho phép truy cập vào thông báo NDEF thông qua phần bổ sungEXTRA_NDEF_MESSAGES. Không thể truy cập vào các thuộc tính thẻ hoặc thao tác I/O khác. API cấp 10 có khả năng hỗ trợ toàn diện cho trình đọc/ghi cũng như tính năng đẩy NDEF ở nền trước, còn API cấp 14 cung cấp các phương thức tiện lợi bổ sung để tạo bản ghi NDEF.<uses-sdk android:minSdkVersion="10"/> - Phần tử
uses-featuređể ứng dụng của bạn chỉ xuất hiện trong Google Play đối với những thiết bị có phần cứng NFC:<uses-feature android:name="android.hardware.nfc" android:required="true" />
Nếu ứng dụng của bạn sử dụng chức năng NFC nhưng chức năng đó không quan trọng đối với ứng dụng, bạn có thể bỏ qua phần tử
uses-featurevà kiểm tra xem có NFC hay không trong thời gian chạy bằng cách kiểm tra xemgetDefaultAdapter()có phải lànullhay không.
Lọc các ý định NFC
Để khởi động ứng dụng khi một thẻ NFC mà bạn muốn xử lý được quét, ứng dụng của bạn có thể lọc một, hai hoặc cả ba ý định NFC trong tệp kê khai Android. Tuy nhiên, bạn thường muốn lọc ý định ACTION_NDEF_DISCOVERED để có quyền kiểm soát cao nhất đối với thời điểm ứng dụng của bạn bắt đầu. Ý định ACTION_TECH_DISCOVERED là một phương án dự phòng cho ACTION_NDEF_DISCOVERED khi không có bộ lọc ứng dụng cho ACTION_NDEF_DISCOVERED hoặc khi tải trọng không phải là NDEF. Việc lọc theo ACTION_TAG_DISCOVERED thường là một danh mục quá chung chung để lọc. Nhiều ứng dụng sẽ lọc ACTION_NDEF_DISCOVERED hoặc ACTION_TECH_DISCOVERED trước ACTION_TAG_DISCOVERED, vì vậy, ứng dụng của bạn có khả năng khởi động thấp. ACTION_TAG_DISCOVERED chỉ có sẵn dưới dạng phương án cuối cùng để các ứng dụng lọc trong trường hợp không có ứng dụng nào khác được cài đặt để xử lý ý định ACTION_NDEF_DISCOVERED hoặc ACTION_TECH_DISCOVERED.
Vì việc triển khai thẻ NFC rất đa dạng và nhiều lần nằm ngoài tầm kiểm soát của bạn, nên không phải lúc nào bạn cũng có thể thực hiện được việc này. Đó là lý do bạn có thể quay lại hai ý định còn lại khi cần thiết. Khi có quyền kiểm soát các loại thẻ và dữ liệu được ghi, bạn nên sử dụng NDEF để định dạng thẻ. Các phần sau đây mô tả cách lọc cho từng loại ý định.
ACTION_NDEF_DISCOVERED
Để lọc các ý định ACTION_NDEF_DISCOVERED, hãy khai báo bộ lọc ý định cùng với loại dữ liệu mà bạn muốn lọc. Sau đây là các bộ lọc ví dụ cho ý định ACTION_NDEF_DISCOVERED có loại MIME là text/plain:
<intent-filter> <action android:name="android.nfc.action.NDEF_DISCOVERED"/> <category android:name="android.intent.category.DEFAULT"/> <data android:mimeType="text/plain" /> </intent-filter>
Ví dụ sau đây lọc theo một URI ở dạng https://developer.android.com/index.html.
<intent-filter> <action android:name="android.nfc.action.NDEF_DISCOVERED"/> <category android:name="android.intent.category.DEFAULT"/> <data android:scheme="https" android:host="developer.android.com" android:pathPrefix="/index.html" /> </intent-filter>
ACTION_TECH_DISCOVERED
Nếu hoạt động của bạn lọc theo ý định ACTION_TECH_DISCOVERED, thì bạn phải tạo một tệp tài nguyên XML chỉ định những công nghệ mà hoạt động của bạn hỗ trợ trong một tập hợp tech-list. Hoạt động của bạn được coi là trùng khớp nếu một tập hợp tech-list là một tập hợp con của các công nghệ mà thẻ hỗ trợ. Bạn có thể lấy tập hợp này bằng cách gọi getTechList().
Ví dụ: nếu thẻ được quét hỗ trợ MifareClassic, NdefFormatable và NfcA, thì tập hợp tech-list của bạn phải chỉ định cả 3, 2 hoặc 1 trong số các công nghệ này (và không có công nghệ nào khác) để hoạt động của bạn được so khớp.
Mẫu sau đây xác định tất cả các công nghệ. Bạn phải xoá những thẻ không được thẻ NFC hỗ trợ. Lưu tệp này (bạn có thể đặt tên tuỳ ý) vào thư mục <project-root>/res/xml.
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <tech-list> <tech>android.nfc.tech.IsoDep</tech> <tech>android.nfc.tech.NfcA</tech> <tech>android.nfc.tech.NfcB</tech> <tech>android.nfc.tech.NfcF</tech> <tech>android.nfc.tech.NfcV</tech> <tech>android.nfc.tech.Ndef</tech> <tech>android.nfc.tech.NdefFormatable</tech> <tech>android.nfc.tech.MifareClassic</tech> <tech>android.nfc.tech.MifareUltralight</tech> </tech-list> </resources>
Bạn cũng có thể chỉ định nhiều bộ tech-list. Mỗi tập hợp tech-list được xem xét độc lập và hoạt động của bạn được coi là trùng khớp nếu bất kỳ tập hợp tech-list nào là một tập hợp con của các công nghệ mà getTechList() trả về. Điều này cung cấp ngữ nghĩa AND và OR cho các công nghệ so khớp. Ví dụ sau đây khớp với những thẻ có thể hỗ trợ công nghệ NfcA và Ndef hoặc có thể hỗ trợ công nghệ NfcB và Ndef:
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <tech-list> <tech>android.nfc.tech.NfcA</tech> <tech>android.nfc.tech.Ndef</tech> </tech-list> <tech-list> <tech>android.nfc.tech.NfcB</tech> <tech>android.nfc.tech.Ndef</tech> </tech-list> </resources>
Trong tệp AndroidManifest.xml, hãy chỉ định tệp tài nguyên mà bạn vừa tạo trong phần tử <meta-data> bên trong phần tử <activity> như trong ví dụ sau:
<activity> ... <intent-filter> <action android:name="android.nfc.action.TECH_DISCOVERED"/> </intent-filter> <meta-data android:name="android.nfc.action.TECH_DISCOVERED" android:resource="@xml/nfc_tech_filter" /> ... </activity>
Để biết thêm thông tin về cách sử dụng các công nghệ thẻ và ý định ACTION_TECH_DISCOVERED, hãy xem phần Làm việc với các công nghệ thẻ được hỗ trợ trong tài liệu NFC nâng cao.
ACTION_TAG_DISCOVERED
Để lọc ACTION_TAG_DISCOVERED, hãy sử dụng bộ lọc ý định sau:
<intent-filter> <action android:name="android.nfc.action.TAG_DISCOVERED"/> </intent-filter>
ACTION_VIEW
Kể từ Android 16, việc quét thẻ NFC lưu trữ đường liên kết URL sẽ kích hoạt ý định ACTION_VIEW. Để lọc theo ACTION_VIEW, hãy tham khảo this. Sử dụng Android app links để mở ứng dụng cho URL.
Lấy thông tin từ ý định
Nếu một hoạt động bắt đầu do ý định NFC, bạn có thể lấy thông tin về thẻ NFC đã quét từ ý định đó. Ý định có thể chứa các phần bổ sung sau đây, tuỳ thuộc vào thẻ đã được quét:
EXTRA_TAG(bắt buộc): Một đối tượngTagđại diện cho thẻ được quét.EXTRA_NDEF_MESSAGES(không bắt buộc): Một mảng gồm các thông báo NDEF được phân tích cú pháp từ thẻ. Thông tin bổ sung này là bắt buộc đối với các ý địnhACTION_NDEF_DISCOVERED.EXTRA_ID(không bắt buộc): Mã nhận dạng cấp thấp của thẻ.
Để lấy các phần bổ sung này, hãy kiểm tra xem hoạt động của bạn có được khởi chạy bằng một trong các ý định NFC hay không để đảm bảo rằng một thẻ đã được quét, sau đó lấy các phần bổ sung ra khỏi ý định. Ví dụ sau đây sẽ kiểm tra ý định ACTION_NDEF_DISCOVERED và nhận thông báo NDEF từ một ý định bổ sung.
Kotlin
override fun onNewIntent(intent: Intent) { super.onNewIntent(intent) ... if (NfcAdapter.ACTION_NDEF_DISCOVERED == intent.action) { intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES)?.also { rawMessages -> val messages: List<NdefMessage> = rawMessages.map { it as NdefMessage } // Process the messages array. ... } } }
Java
@Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); ... if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction())) { Parcelable[] rawMessages = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES); if (rawMessages != null) { NdefMessage[] messages = new NdefMessage[rawMessages.length]; for (int i = 0; i < rawMessages.length; i++) { messages[i] = (NdefMessage) rawMessages[i]; } // Process the messages array. ... } } }
Ngoài ra, bạn có thể lấy một đối tượng Tag từ ý định. Đối tượng này sẽ chứa tải trọng và cho phép bạn liệt kê các công nghệ của thẻ:
Kotlin
val tag: Tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG)
Java
Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
Tạo các loại bản ghi NDEF phổ biến
Phần này mô tả cách tạo các loại bản ghi NDEF phổ biến để hỗ trợ bạn khi ghi vào thẻ NFC. Kể từ Android 4.0 (API cấp 14), phương thức createUri() có sẵn để giúp bạn tự động tạo các bản ghi URI. Kể từ Android 4.1 (API cấp 16), createExternal() và createMime() có sẵn để giúp bạn tạo bản ghi NDEF loại bên ngoài và MIME. Hãy sử dụng các phương thức trợ giúp này bất cứ khi nào có thể để tránh mắc lỗi khi tạo bản ghi NDEF theo cách thủ công.
Phần này cũng mô tả cách tạo bộ lọc ý định tương ứng cho bản ghi. Tất cả các ví dụ về bản ghi NDEF này phải nằm trong bản ghi NDEF đầu tiên của thông báo NDEF mà bạn đang ghi vào thẻ.
TNF_ABSOLUTE_URI
Lưu ý: Bạn nên sử dụng loại RTD_URI thay vì TNF_ABSOLUTE_URI vì loại này hiệu quả hơn.
Bạn có thể tạo bản ghi NDEF TNF_ABSOLUTE_URI theo cách sau
:
Kotlin
val uriRecord = ByteArray(0).let { emptyByteArray -> NdefRecord( TNF_ABSOLUTE_URI, "https://developer.android.com/index.html".toByteArray(Charset.forName("US-ASCII")), emptyByteArray, emptyByteArray ) }
Java
NdefRecord uriRecord = new NdefRecord( NdefRecord.TNF_ABSOLUTE_URI , "https://developer.android.com/index.html".getBytes(Charset.forName("US-ASCII")), new byte[0], new byte[0]);
Bộ lọc ý định cho bản ghi NDEF trước đó sẽ có dạng như sau:
<intent-filter> <action android:name="android.nfc.action.NDEF_DISCOVERED" /> <category android:name="android.intent.category.DEFAULT" /> <data android:scheme="https" android:host="developer.android.com" android:pathPrefix="/index.html" /> </intent-filter>
TNF_MIME_MEDIA
Bạn có thể tạo bản ghi NDEF TNF_MIME_MEDIA theo những cách sau:
Sử dụng phương thức createMime():
Kotlin
val mimeRecord = NdefRecord.createMime( "application/vnd.com.example.android.beam", "Beam me up, Android".toByteArray(Charset.forName("US-ASCII")) )
Java
NdefRecord mimeRecord = NdefRecord.createMime("application/vnd.com.example.android.beam", "Beam me up, Android".getBytes(Charset.forName("US-ASCII")));
Tạo NdefRecord theo cách thủ công:
Kotlin
val mimeRecord = Charset.forName("US-ASCII").let { usAscii -> NdefRecord( NdefRecord.TNF_MIME_MEDIA, "application/vnd.com.example.android.beam".toByteArray(usAscii), ByteArray(0), "Beam me up, Android!".toByteArray(usAscii) ) }
Java
NdefRecord mimeRecord = new NdefRecord( NdefRecord.TNF_MIME_MEDIA , "application/vnd.com.example.android.beam".getBytes(Charset.forName("US-ASCII")), new byte[0], "Beam me up, Android!".getBytes(Charset.forName("US-ASCII")));
Bộ lọc ý định cho bản ghi NDEF trước đó sẽ có dạng như sau:
<intent-filter> <action android:name="android.nfc.action.NDEF_DISCOVERED" /> <category android:name="android.intent.category.DEFAULT" /> <data android:mimeType="application/vnd.com.example.android.beam" /> </intent-filter>
TNF_WELL_KNOWN có RTD_TEXT
Bạn có thể tạo bản ghi NDEF TNF_WELL_KNOWN theo cách sau:
Kotlin
fun createTextRecord(payload: String, locale: Locale, encodeInUtf8: Boolean): NdefRecord { val langBytes = locale.language.toByteArray(Charset.forName("US-ASCII")) val utfEncoding = if (encodeInUtf8) Charset.forName("UTF-8") else Charset.forName("UTF-16") val textBytes = payload.toByteArray(utfEncoding) val utfBit: Int = if (encodeInUtf8) 0 else 1 shl 7 val status = (utfBit + langBytes.size).toChar() val data = ByteArray(1 + langBytes.size + textBytes.size) data[0] = status.toByte() System.arraycopy(langBytes, 0, data, 1, langBytes.size) System.arraycopy(textBytes, 0, data, 1 + langBytes.size, textBytes.size) return NdefRecord(NdefRecord.TNF_WELL_KNOWN, NdefRecord.RTD_TEXT, ByteArray(0), data) }
Java
public NdefRecord createTextRecord(String payload, Locale locale, boolean encodeInUtf8) { byte[] langBytes = locale.getLanguage().getBytes(Charset.forName("US-ASCII")); Charset utfEncoding = encodeInUtf8 ? Charset.forName("UTF-8") : Charset.forName("UTF-16"); byte[] textBytes = payload.getBytes(utfEncoding); int utfBit = encodeInUtf8 ? 0 : (1 << 7); char status = (char) (utfBit + langBytes.length); byte[] data = new byte[1 + langBytes.length + textBytes.length]; data[0] = (byte) status; System.arraycopy(langBytes, 0, data, 1, langBytes.length); System.arraycopy(textBytes, 0, data, 1 + langBytes.length, textBytes.length); NdefRecord record = new NdefRecord(NdefRecord.TNF_WELL_KNOWN, NdefRecord.RTD_TEXT, new byte[0], data); return record; }
Bộ lọc ý định cho bản ghi NDEF trước đó sẽ có dạng như sau:
<intent-filter> <action android:name="android.nfc.action.NDEF_DISCOVERED" /> <category android:name="android.intent.category.DEFAULT" /> <data android:mimeType="text/plain" /> </intent-filter>
TNF_WELL_KNOWN có RTD_URI
Bạn có thể tạo bản ghi NDEF TNF_WELL_KNOWN theo những cách sau:
Sử dụng phương thức createUri(String):
Kotlin
val rtdUriRecord1 = NdefRecord.createUri("https://example.com")
Java
NdefRecord rtdUriRecord1 = NdefRecord.createUri("https://example.com");
Sử dụng phương thức createUri(Uri):
Kotlin
val rtdUriRecord2 = Uri.parse("https://example.com").let { uri -> NdefRecord.createUri(uri) }
Java
Uri uri = Uri.parse("https://example.com"); NdefRecord rtdUriRecord2 = NdefRecord.createUri(uri);
Tạo NdefRecord theo cách thủ công:
Kotlin
val uriField = "example.com".toByteArray(Charset.forName("US-ASCII")) val payload = ByteArray(uriField.size + 1) //add 1 for the URI Prefix payload [0] = 0x01 //prefixes https://www. to the URI System.arraycopy(uriField, 0, payload, 1, uriField.size) //appends URI to payload val rtdUriRecord = NdefRecord(NdefRecord.TNF_WELL_KNOWN, NdefRecord.RTD_URI, ByteArray(0), payload)
Java
byte[] uriField = "example.com".getBytes(Charset.forName("US-ASCII")); byte[] payload = new byte[uriField.length + 1]; //add 1 for the URI Prefix payload[0] = 0x01; //prefixes https://www. to the URI System.arraycopy(uriField, 0, payload, 1, uriField.length); //appends URI to payload NdefRecord rtdUriRecord = new NdefRecord( NdefRecord.TNF_WELL_KNOWN, NdefRecord.RTD_URI, new byte[0], payload);
Bộ lọc ý định cho bản ghi NDEF trước đó sẽ có dạng như sau:
<intent-filter> <action android:name="android.nfc.action.NDEF_DISCOVERED" /> <category android:name="android.intent.category.DEFAULT" /> <data android:scheme="https" android:host="example.com" android:pathPrefix="" /> </intent-filter>
TNF_EXTERNAL_TYPE
Bạn có thể tạo bản ghi NDEF TNF_EXTERNAL_TYPE theo những cách sau:
Sử dụng phương thức createExternal():
Kotlin
var payload: ByteArray //assign to your data val domain = "com.example" //usually your app's package name val type = "externalType" val extRecord = NdefRecord.createExternal(domain, type, payload)
Java
byte[] payload; //assign to your data String domain = "com.example"; //usually your app's package name String type = "externalType"; NdefRecord extRecord = NdefRecord.createExternal(domain, type, payload);
Tạo NdefRecord theo cách thủ công:
Kotlin
var payload: ByteArray ... val extRecord = NdefRecord( NdefRecord.TNF_EXTERNAL_TYPE, "com.example:externalType".toByteArray(Charset.forName("US-ASCII")), ByteArray(0), payload )
Java
byte[] payload; ... NdefRecord extRecord = new NdefRecord( NdefRecord.TNF_EXTERNAL_TYPE, "com.example:externalType".getBytes(Charset.forName("US-ASCII")), new byte[0], payload);
Bộ lọc ý định cho bản ghi NDEF trước đó sẽ có dạng như sau:
<intent-filter> <action android:name="android.nfc.action.NDEF_DISCOVERED" /> <category android:name="android.intent.category.DEFAULT" /> <data android:scheme="vnd.android.nfc" android:host="ext" android:pathPrefix="/com.example:externalType"/> </intent-filter>
Sử dụng TNF_EXTERNAL_TYPE cho các hoạt động triển khai thẻ NFC chung hơn để hỗ trợ tốt hơn cả thiết bị chạy Android và thiết bị không chạy Android.
Lưu ý: URN cho TNF_EXTERNAL_TYPE có định dạng chuẩn là: urn:nfc:ext:example.com:externalType, tuy nhiên, quy cách RTD của Diễn đàn NFC tuyên bố rằng phần urn:nfc:ext: của URN phải bị loại bỏ khỏi bản ghi NDEF. Vì vậy, bạn chỉ cần cung cấp miền (example.com trong ví dụ) và loại (externalType trong ví dụ) được phân tách bằng dấu hai chấm.
Khi gửi TNF_EXTERNAL_TYPE, Android sẽ chuyển đổi URN urn:nfc:ext:example.com:externalType
thành URI vnd.android.nfc://ext/example.com:externalType. Đây là những gì bộ lọc ý định trong ví dụ khai báo.
Bản ghi ứng dụng Android
Được giới thiệu trong Android 4.0 (API cấp 14), Bản ghi ứng dụng Android (AAR) mang lại sự chắc chắn hơn rằng ứng dụng của bạn sẽ được khởi động khi một thẻ NFC được quét. AAR có tên gói của một ứng dụng được nhúng bên trong bản ghi NDEF. Bạn có thể thêm một AAR vào bất kỳ bản ghi NDEF nào trong thông báo NDEF, vì Android sẽ tìm kiếm toàn bộ thông báo NDEF để tìm AAR. Nếu tìm thấy một AAR, thì ứng dụng sẽ khởi động dựa trên tên gói bên trong AAR. Nếu ứng dụng không có trên thiết bị, Google Play sẽ khởi chạy để tải ứng dụng xuống.
AAR rất hữu ích nếu bạn muốn ngăn các ứng dụng khác lọc cùng một ý định và có khả năng xử lý các thẻ cụ thể mà bạn đã triển khai. AAR chỉ được hỗ trợ ở cấp ứng dụng, do hạn chế về tên gói, chứ không được hỗ trợ ở cấp Hoạt động như khi lọc ý định. Nếu bạn muốn xử lý một ý định ở cấp Hoạt động, hãy sử dụng bộ lọc ý định.
Nếu một thẻ chứa AAR, hệ thống điều phối thẻ sẽ điều phối theo cách sau:
- Thử bắt đầu một Hoạt động bằng bộ lọc ý định như bình thường. Nếu Hoạt động khớp với ý định cũng khớp với AAR, hãy bắt đầu Hoạt động.
- Nếu Hoạt động lọc ý định không khớp với AAR, nếu nhiều Hoạt động có thể xử lý ý định hoặc nếu không có Hoạt động nào xử lý ý định, hãy khởi động ứng dụng do AAR chỉ định.
- Nếu không có ứng dụng nào có thể khởi động bằng AAR, hãy chuyển đến Google Play để tải ứng dụng xuống dựa trên AAR.
Lưu ý: Bạn có thể ghi đè AAR và hệ thống gửi ý định bằng hệ thống gửi ở nền trước. Hệ thống này cho phép một hoạt động ở nền trước có quyền ưu tiên khi phát hiện thấy thẻ NFC. Với phương thức này, hoạt động phải ở nền trước để ghi đè AAR và hệ thống gửi ý định.
Nếu vẫn muốn lọc các thẻ được quét không chứa AAR, bạn có thể khai báo bộ lọc ý định như bình thường. Điều này hữu ích nếu ứng dụng của bạn quan tâm đến các thẻ khác không chứa AAR. Ví dụ: có thể bạn muốn đảm bảo rằng ứng dụng của mình xử lý các thẻ độc quyền mà bạn triển khai cũng như các thẻ chung do bên thứ ba triển khai. Xin lưu ý rằng AAR dành riêng cho các thiết bị Android 4.0 trở lên, vì vậy, khi triển khai thẻ, bạn nên sử dụng kết hợp AAR và loại MIME/URI để hỗ trợ nhiều thiết bị nhất có thể. Ngoài ra, khi triển khai thẻ NFC, hãy nghĩ về cách bạn muốn ghi thẻ NFC để hỗ trợ hầu hết các thiết bị (thiết bị chạy Android và các thiết bị khác). Bạn có thể thực hiện việc này bằng cách xác định một loại MIME hoặc URI tương đối duy nhất để giúp các ứng dụng dễ dàng phân biệt.
Android cung cấp một API đơn giản để tạo AAR, createApplicationRecord(). Bạn chỉ cần nhúng AAR vào bất cứ đâu trong NdefMessage. Bạn không muốn sử dụng bản ghi đầu tiên của NdefMessage, trừ phi AAR là bản ghi duy nhất trong NdefMessage. Điều này là do hệ thống Android kiểm tra bản ghi đầu tiên của một NdefMessage để xác định loại MIME hoặc URI của thẻ. Loại MIME hoặc URI này được dùng để tạo một ý định cho các ứng dụng lọc. Đoạn mã sau đây cho biết cách tạo AAR:
Kotlin
val msg = NdefMessage( arrayOf( ..., NdefRecord.createApplicationRecord("com.example.android.beam") ) )
Java
NdefMessage msg = new NdefMessage( new NdefRecord[] { ..., NdefRecord.createApplicationRecord("com.example.android.beam")} ); )
Danh sách cho phép ứng dụng để quét thẻ NFC
Kể từ Android 16, người dùng sẽ nhận được thông báo khi một ứng dụng nhận được ý định NFC đầu tiên để quét thẻ NFC. Người dùng có thể chọn không cho phép ứng dụng quét thẻ NFC nữa trong thông báo.
- Các ứng dụng có thể kiểm tra xem người dùng đã cho phép ứng dụng quét thẻ NFC hay chưa bằng cách sử dụng
NfcAdapter.isTagIntentAllowed(). - Các ứng dụng có thể nhắc người dùng cho phép quét thẻ NFC một lần nữa bằng cách gửi ý định
ACTION_CHANGE_TAG_INTENT_PREFERENCE.
Lưu ý: Bạn có thể truy cập vào danh sách cho phép ứng dụng quét thẻ NFC trong phần Settings > Apps > Special app access > Launch via NFC.