Thông tin cơ bản về NFC

Tài liệu này mô tả các tác vụ NFC cơ bản mà bạn thực hiện trong Android. Hướng dẫn 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 và mô tả các API khung Android hỗ trợ các tính năng này. Để biết thêm 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.

Có hai trường hợp sử dụng chính khi làm việc với dữ liệu NDEF và Android:

  • Đọc dữ liệu NDEF từ thẻ NFC
  • Chiếu thông báo NDEF từ thiết bị này sang thiết bị khác bằng Android BeamTM

Việc đọc dữ liệu NDEF từ thẻ NFC được xử lý bằng hệ thống gửi thẻ. Hệ thống này sẽ phân tích các thẻ NFC đã phát hiện, phân loại dữ liệu một cách phù hợp và khởi động một ứng dụng quan tâm đến dữ liệu đã phân loại. Một ứng dụng muốn xử lý thẻ NFC đã quét có thể khai báo bộ lọc ý định và yêu cầu xử lý dữ liệu.

Tính năng Android BeamTM cho phép một thiết bị đẩy thông báo NDEF sang một thiết bị khác bằng cách nhấn vật lý các thiết bị đó lại với nhau. Hoạt động tương tác này giúp gửi dữ liệu dễ dàng hơn so với các công nghệ không dây khác như Bluetooth, vì với NFC, bạn không cần phải tự khám phá hoặc ghép nối thiết bị theo cách thủ công. Kết nối tự động bắt đầu khi hai thiết bị trong phạm vi phủ sóng. Android Beam được cung cấp thông qua một bộ API NFC, vì vậy, mọi ứng dụng đều có thể truyền thông tin giữa các thiết bị. Ví dụ: các ứng dụng Danh bạ, Trình duyệt và YouTube sử dụng tính năng Truyền tia Android để chia sẻ danh bạ, trang web và video với các thiết bị khác.

Hệ thống điều phối 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 thích hợp nhất xử lý ý định mà không hỏi người dùng sẽ 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 nhiều khả năng việc người dùng chọn một hoạt động theo cách thủ công sẽ buộc họ phải di chuyển thiết bị ra khỏi thẻ và ngắt kết nối. Bạn nên phát triển hoạt động của mình để chỉ xử lý các thẻ NFC mà hoạt động của bạn 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 phân phối thẻ đặc biệt giúp 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ủa các ứng dụng quan tâm đến dữ liệu đã quét. Trình quản lý thẻ của Google thực hiện việc này bằng cách:

  1. Phân tích cú pháp thẻ NFC và xác định loại MIME hoặc URI xác định tải trọng dữ liệu trong thẻ.
  2. Đó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 thẻ NFC được ánh xạ với loại MIME và URI.
  3. 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 thẻ NFC được điều phối đến các ứng dụng.

Cách thẻ NFC được ánh xạ với loại MIME và URI

Trước khi bắt đầu viết ứng dụng NFC, điều quan trọng là bạn phải hiểu nhiều 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ông báo NDEF. Thẻ NFC có rất 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 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 định dạng đúng theo thông số kỹ thuật 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 mà bạn có thể xử lý 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. Khi xử lý các loại thẻ khác này, bạn cần viết ngăn xếp giao thức của riêng mình để giao tiếp với các 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 thiết bị chạy Android.

Lưu ý: Để tải thông số kỹ thuật NDEF hoàn chỉnh xuống, hãy truy cập trang web Tài liệu về ứng dụng và thông số của diễn đàn NFC và xem bài viết Tạo các loại bản ghi NDEF phổ biến để xem ví dụ về cách tạo bản ghi NDEF.

Giờ đây, khi bạn đã có một số thông tin 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 thiết bị chạy Android quét một thẻ NFC có chứa dữ liệu theo đị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 của dữ liệu hoặc URI nhận dạng. Để thực hiện 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 một thông báo NDEF được định dạng đúng cách, NdefRecord đầu tiên sẽ chứa các trường sau:

TNF 3 bit (Định dạng tên loại)
Cho biết cách diễn giải trường loại độ dài biến. Các giá trị hợp lệ được mô tả trong Bảng 1.
Loại độ dài biến
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ã độ dài biến
Giá trị nhận dạng duy nhất của bản ghi. Trường này không được sử 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ó chiều 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 giả định 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 loại và TNF để cố gắng liên kết một loại MIME hoặc URI với thông báo NDEF. Nếu thành công, mô-đun này sẽ đóng gói thông tin đó bên trong ý đị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 điều phối thẻ không thể xác định loại dữ liệu dựa trên bản ghi NDEF đầu tiên. Điều này xảy ra khi không thể ánh xạ dữ liệu NDEF tới một loại MIME hoặc URI, hoặc khi thẻ NFC không chứa dữ liệu NDEF để bắt đầu. Trong những trường hợp như vậy, đố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 ý đị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à trường kiểu với các loại MIME hoặc URI. Hướng dẫn này cũng mô tả những TNF không thể ánh xạ tới một URI hoặc loại MIME. Trong những trường hợp này, hệ thống điều phối thẻ sẽ quay lại dùng ACTION_TECH_DISCOVERED.

Ví dụ: nếu hệ thống điều phối thẻ gặp một bản ghi thuộc loại TNF_ABSOLUTE_URI, thì hệ thống sẽ ánh xạ trường loại độ dài biến số của bản ghi đó vào một URI. Hệ thống điều phối thẻ sẽ đóng gói URI đó trong trường dữ liệu của ý đị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 bản ghi thuộc loại TNF_UNKNOWN, thì mô-đun này sẽ tạo một ý định đóng gói công nghệ của thẻ.

Bảng 1. 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á thành trường loại NDEF ở dạng rút gọn: <domain_name>:<service_name>. Android ánh xạ mã này đến 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, vì vậy hãy quay lại dùng ACTION_TECH_DISCOVERED.
TNF_UNKNOWN Quay lại ACTION_TECH_DISCOVERED.
TNF_WELL_KNOWN Loại MIME hoặc URI phụ thuộc vào Định nghĩa loại bản ghi (RTD) mà bạn đặt trong trường loại. Vui lòng 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 các RTD đó.

Bảng 2. Các RTD được hỗ trợ cho TNF_WELL_KNOWN và các mục ánh xạ 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 tải trọng.
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 tạo xong một ý định đóng gói thẻ NFC và thông tin nhận dạng thẻ, hệ thống điều phối thẻ sẽ gửi ý định đến một ứng dụng quan tâm để lọc ý định. Nếu nhiều ứng dụng có thể xử lý ý định, thì Trình chọn hoạt động sẽ hiển thị để người dùng có thể chọn Hoạt động. Hệ thống điều phối thẻ xác định 3 ý định, được liệt kê theo thứ tự ưu tiên cao nhất đến thấp nhất:

  1. 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 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 bắt đầu 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ể.
  2. ACTION_TECH_DISCOVERED: Nếu không có hoạt động nào đăng ký để xử lý ý định ACTION_NDEF_DISCOVERED, thì hệ thống điều phối thẻ sẽ cố gắng khởi động ứng dụng bằng ý định này. Ý định này cũng được bắt đầu trực tiếp (không bắt đầu ACTION_NDEF_DISCOVERED trước) nếu thẻ được quét chứa dữ liệu NDEF không thể ánh xạ được tới loại MIME hay URI, hoặc nếu thẻ không chứa dữ liệu NDEF nhưng là công nghệ thẻ đã biết.
  3. ACTION_TAG_DISCOVERED: Ý định này được bắt đầu nếu không có hoạt động nào xử lý ý định ACTION_NDEF_DISCOVERED hoặc ACTION_TECH_DISCOVERED.

Cách hoạt động cơ bản của hệ thống điều phối thẻ như sau:

  1. Hãy thử 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_DISCOVERED hoặc ACTION_TECH_DISCOVERED).
  2. Nếu không có hoạt động nào lọc 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_DISCOVERED hoặc ACTION_TAG_DISCOVERED) cho đến khi ứng dụng lọc ý định hoặc cho đến khi hệ thống điều phối thẻ thử tất cả ý định có thể có.
  3. Nếu không có ứng dụng nào lọc cho bất kỳ ý định nào, thì không cần làm gì cả.
Hình 1. Hệ thống điều phối thẻ

Bất cứ khi nào có thể, hãy xử lý thông báo NDEF và ý định ACTION_NDEF_DISCOVERED, vì ý định này là cụ thể nhất trong ba phương thức. Ý định này cho phép bạn khởi động ứng dụng tại 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 các mục sau 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 qua ACTION_TAG_DISCOVERED và chỉ cấp quyền truy cập vào các thông báo NDEF thông qua phần bổ sung EXTRA_NDEF_MESSAGES. Bạn 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 cung cấp tính năng hỗ trợ toàn diện cho trình đọc/người ghi cũng như tính năng đẩy NDEF trên nền trước. API cấp 14 cung cấp một cách dễ dàng hơn để đẩy thông báo NDEF đến các thiết bị khác bằng Android Beam và các phương thức bổ sung tiện lợi để 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 các thiết bị có phần cứng NFC:
    <uses-feature android:name="android.hardware.nfc" android:required="true" />
    

    Nếu ứng dụng dùng chức năng NFC nhưng chức năng đó không quan trọng với ứng dụng, thì bạn có thể bỏ qua phần tử uses-feature và kiểm tra xem getDefaultAdapter() có phải là null hay không trong thời gian chạy.

Lọc theo ý định NFC

Để khởi động ứng dụng khi thẻ NFC mà bạn muốn xử lý được quét được quét, ứng dụng của bạn có thể lọc cho một, hai hoặc cả ba ý định NFC trong tệp kê khai Android. Tuy nhiên, thường thì bạn sẽ muốn lọc ý định ACTION_NDEF_DISCOVERED để kiểm soát chặt chẽ nhất thời điểm ứng dụng khởi động. Ý định ACTION_TECH_DISCOVERED là phương án dự phòng cho ACTION_NDEF_DISCOVERED khi không có ứng dụng nào lọc cho ACTION_NDEF_DISCOVERED hoặc khi tải trọng không phải là NDEF. Bộ lọc cho ACTION_TAG_DISCOVERED thường là quá chung chung của một danh mục nên không thể lọc được. Nhiều ứng dụng sẽ lọc tìm ACTION_NDEF_DISCOVERED hoặc ACTION_TECH_DISCOVERED trước ACTION_TAG_DISCOVERED, vì vậy, ứng dụng của bạn có ít khả năng bắt đầu. ACTION_TAG_DISCOVERED chỉ dành cho các ứng dụng như phương án cuối cùng cần 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ì cách triển khai thẻ NFC khác nhau và nhiều lần không thuộc quyền kiểm soát của bạn, nên điều này không phải lúc nào cũng có thể xảy ra. Đó là lý do bạn có thể dự phòng cho 2 ý định còn lại khi cần. 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 theo từng loại ý định.

ACTION_NDEF_discoveryED

Để lọ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. Ví dụ sau đây lọc các ý đị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>

Sau đây là ví dụ về các bộ lọc cho 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_KHÁM PHÁ

Nếu hoạt động của bạn lọc ý định ACTION_TECH_DISCOVERED, bạn phải tạo một tệp tài nguyên XML chỉ định các 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à khớp nếu tập hợp tech-list là một tập hợp con của các công nghệ được thẻ hỗ trợ. Bạn có thể lấy hoạt động 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ả ba, hai hoặc một trong các công nghệ (không chỉ định 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ông nghệ. Bạn phải xoá những mã không được thẻ NFC hỗ trợ. Lưu tệp này (bạn có thể đặt tên theo ý muốn) trong 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 tập hợp 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 sẽ được coi là 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ệ do getTechList() trả về. Việc này cung cấp ngữ nghĩa ANDOR cho các công nghệ so khớp. Ví dụ sau đây khớp với các 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 làm việc với các công nghệ thẻ và ý định ACTION_TECH_DISCOVERED, hãy xem bài viết 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_KHÁM PHÁ

Để 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>

Thu thập thông tin từ ý định

Nếu một hoạt động bắt đầu do ý định NFC, thì bạn có thể lấy thông tin về thẻ NFC đã quét qua ý định đó. Ý định có thể chứa các dữ liệu bổ sung sau tuỳ thuộc vào thẻ đã được quét:

  • EXTRA_TAG (bắt buộc): Đối tượng Tag đại diện cho thẻ đã quét.
  • EXTRA_NDEF_MESSAGES (không bắt buộc): Một mảng các thông báo NDEF được phân tích cú pháp từ thẻ. Dữ liệu bổ sung này là bắt buộc đối với các ý định ACTION_NDEF_DISCOVERED.
  • EXTRA_ID (không bắt buộc): Mã cấp thấp của thẻ.

Để có được các dữ liệu 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 thẻ đã được quét, sau đó lấy các dữ liệu bổ sung từ ý định đó. Ví dụ sau đây sẽ kiểm tra ý định ACTION_NDEF_DISCOVERED và lấy 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 đối tượng Tag qua ý đị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 để trợ giúp bạn khi ghi vào thẻ NFC hoặc gửi dữ liệu bằng tính năng Truyền tia Android. Kể từ Android 4.0 (API cấp 14), phương thức createUri() sẽ có sẵn để giúp bạn tự động tạo bản ghi URI. Kể từ Android 4.1 (API cấp 16), bạn có thể dùng createExternal()createMime() để tạo bản ghi MIME và bản ghi NDEF loại bên ngoài. 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 sai sót 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ả ví dụ về bản ghi NDEF phải có trong bản ghi NDEF đầu tiên của thông báo NDEF mà bạn đang ghi vào thẻ hoặc đang chiếu.

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 các 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 với 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 với RTD_URI

Bạn có thể tạo bản ghi NDEF TNF_WELL_KNOWN theo các 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 các 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 để triển khai thẻ NFC tổng quát hơn nhằm hỗ trợ tốt hơn cho cả thiết bị chạy Android và không chạy Android.

Lưu ý: URN cho TNF_EXTERNAL_TYPE có định dạng chính tắc: urn:nfc:ext:example.com:externalType. Tuy nhiên, thông số kỹ thuật RTD của Diễn đàn NFC khai báo rằng phần urn:nfc:ext: của URN phải được bỏ qua khỏi bản ghi NDEF. Vì vậy, bạn chỉ cần cung cấp miền (trong ví dụ này là example.com) và nhập (trong ví dụ là externalType) được phân tách bằng dấu hai chấm. Khi gửi TNF_EXTERNAL_TYPE, Android sẽ chuyển đổi urn:nfc:ext:example.com:externalType URN thành URI vnd.android.nfc://ext/example.com:externalType, đây là nội dung mà bộ lọc ý định trong ví dụ này khai báo.

Bản ghi ứng dụng Android

Ra mắt trong Android 4.0 (API cấp 14), Bản ghi ứng dụng Android (AAR) cung cấp độ chắc chắn mạnh mẽ hơn rằng ứng dụng của bạn được khởi động khi thẻ NFC được quét. AAR có tên gói của một ứng dụng được nhúng trong bản ghi NDEF. Bạn có thể thêm AAR vào bất kỳ bản ghi NDEF nào của thông báo NDEF, vì Android sẽ tìm kiếm toàn bộ thông báo NDEF cho các AAR. Nếu tìm thấy một AAR, thì nó sẽ khởi động ứng dụ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ị, thì Google Play sẽ được 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 cho cùng một ý định và có thể xử lý các thẻ cụ thể mà bạn đã triển khai. Các AAR chỉ được hỗ trợ ở cấp ứng dụng do ràng buộc về tên gói, chứ không phải ở cấp Hoạt động như với tính năng 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, thì hệ thống điều phối thẻ sẽ gửi đi theo cách sau:

  1. Thử bắt đầu một Hoạt động bằng cách sử dụng bộ lọc ý định như bình thường. Nếu Hoạt động khớp với ý định và cũng khớp với AAR, hãy bắt đầu Hoạt động.
  2. 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.
  3. Nếu không có ứng dụng nào có thể bắt đầu bằng AAR, hãy truy cập Google Play để tải ứng dụng dựa trên AAR đó xuống.

Lưu ý: Bạn có thể ghi đè AAR và hệ thống điều phối ý định bằng hệ thống điều phối trên nền trước. Hệ thống này cho phép hoạt động ở nền trước được ưu tiên khi phát hiện 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 điều phối ý định.

Nếu vẫn muốn lọc các thẻ đã quét không chứa AAR, thì bạn có thể khai báo các bộ lọc ý định như bình thường. Việc này sẽ 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 bạn 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 các tệp 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ẻ, rất có thể bạn muốn sử dụng kết hợp các loại/URI AAR và MIME để hỗ trợ nhiều loại thiết bị nhất. Ngoài ra, khi bạn triển khai thẻ NFC, hãy nghĩ về cách bạn muốn ghi thẻ NFC để có thể 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 ứng dụng dễ phân biệt hơn.

Android cung cấp một API đơn giản để tạo một AAR (đề xuất được tự động áp dụng) 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 NdefMessage để xác định loại MIME hoặc URI của thẻ, được dùng để tạo ý định cho các ứng dụng lọc. Đoạn mã sau đây cho bạn 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")}
        );
)

Chiếu thông báo NDEF tới các thiết bị khác

Android Beam cho phép trao đổi dữ liệu ngang hàng đơn giản giữa hai thiết bị chạy Android. Ứng dụng muốn truyền dữ liệu tới một thiết bị khác phải ở nền trước và thiết bị nhận dữ liệu phải không bị khoá. Khi thiết bị phát tín hiệu tiếp xúc đủ gần với thiết bị thu, thiết bị phát tín hiệu sẽ hiển thị giao diện người dùng "Chạm để chiếu". Sau đó, người dùng có thể chọn có truyền thông báo tới thiết bị nhận hay không.

Lưu ý: Tính năng đẩy NDEF trên nền trước đã có ở API cấp 10, cung cấp chức năng tương tự như tính năng Truyền tia Android. Các API này kể từ đó đã ngừng hoạt động nhưng vẫn có sẵn để hỗ trợ các thiết bị cũ. Hãy xem enableForegroundNdefPush() để biết thêm thông tin.

Bạn có thể bật Android Beam cho ứng dụng của mình bằng cách gọi một trong hai phương thức:

  • setNdefPushMessage(): Chấp nhận NdefMessage để đặt làm thông báo cần truyền. Tự động phát thông báo khi 2 thiết bị ở đủ gần.
  • setNdefPushMessageCallback(): Chấp nhận lệnh gọi lại chứa createNdefMessage(). Lệnh này được gọi khi thiết bị nằm trong phạm vi để truyền dữ liệu đến. Lệnh gọi lại chỉ cho phép bạn tạo thông báo NDEF khi cần.

Một hoạt động chỉ có thể đẩy mỗi lần một thông báo NDEF, vì vậy, setNdefPushMessageCallback() sẽ được ưu tiên hơn setNdefPushMessage() nếu bạn đặt cả hai. Để sử dụng tính năng Truyền tia Android, bạn phải đáp ứng các nguyên tắc chung sau đây:

  • Hoạt động đang chiếu dữ liệu phải ở nền trước. Cả hai thiết bị đều phải mở khoá màn hình.
  • Bạn phải đóng gói dữ liệu mà bạn đang chiếu trong đối tượng NdefMessage.
  • Thiết bị NFC đang nhận dữ liệu được chiếu theo phải hỗ trợ giao thức đẩy NDEF com.android.npp hoặc SNEP (Giao thức trao đổi NDEF đơn giản) của Diễn đàn NFC. Giao thức com.android.npp là bắt buộc đối với các thiết bị ở API cấp 9 (Android 2.3) đến API cấp 13 (Android 3.2). com.android.npp và SNEP đều là bắt buộc trên API cấp 14 (Android 4.0) trở lên.

Lưu ý: Nếu hoạt động của bạn bật tính năng Truyền tia Android và chạy ở nền trước, thì hệ thống điều phối ý định chuẩn sẽ bị tắt. Tuy nhiên, nếu hoạt động của bạn cũng bật tính năng gửi dữ liệu trên nền trước, thì hoạt động đó vẫn có thể quét những thẻ khớp với bộ lọc ý định đã đặt trong chế độ gửi trên nền trước.

Để bật tính năng Truyền tia Android:

  1. Tạo một NdefMessage chứa các NdefRecord mà bạn muốn đẩy sang thiết bị khác.
  2. Gọi setNdefPushMessage() bằng NdefMessage hoặc gọi setNdefPushMessageCallback truyền vào đối tượng NfcAdapter.CreateNdefMessageCallback trong phương thức onCreate() của hoạt động. Các phương thức này đòi hỏi ít nhất một hoạt động mà bạn muốn bật bằng Android Beam, cùng với một danh sách không bắt buộc gồm các hoạt động khác cần kích hoạt.

    Nhìn chung, bạn thường sử dụng setNdefPushMessage() nếu Hoạt động của bạn chỉ cần đẩy cùng một thông báo NDEF vào mọi lúc, khi 2 thiết bị ở trong phạm vi giao tiếp. Bạn dùng setNdefPushMessageCallback khi ứng dụng quan tâm đến ngữ cảnh hiện tại của ứng dụng và muốn đẩy một thông báo NDEF tuỳ thuộc vào thao tác mà người dùng đang thực hiện trong ứng dụng.

Mẫu sau đây cho thấy cách một hoạt động đơn giản gọi NfcAdapter.CreateNdefMessageCallback trong phương thức onCreate() của một hoạt động (xem AndroidBeamdemo để biết mẫu đầy đủ). Ví dụ này cũng có các phương thức giúp bạn tạo bản ghi MIME:

Kotlin

package com.example.android.beam

import android.app.Activity
import android.content.Intent
import android.nfc.NdefMessage
import android.nfc.NdefRecord
import android.nfc.NfcAdapter
import android.nfc.NfcAdapter.CreateNdefMessageCallback
import android.nfc.NfcEvent
import android.os.Bundle
import android.os.Parcelable
import android.widget.TextView
import android.widget.Toast
import java.nio.charset.Charset

class Beam : Activity(), NfcAdapter.CreateNdefMessageCallback {
    
    private var nfcAdapter: NfcAdapter? = null
    private lateinit var textView: TextView

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.main)
        textView = findViewById(R.id.textView)
        // Check for available NFC Adapter
        nfcAdapter = NfcAdapter.getDefaultAdapter(this)
        if (nfcAdapter == null) {
            Toast.makeText(this, "NFC is not available", Toast.LENGTH_LONG).show()
            finish()
            return
        }
        // Register callback
        nfcAdapter?.setNdefPushMessageCallback(this, this)
    }

    override fun createNdefMessage(event: NfcEvent): NdefMessage {
        val text = "Beam me up, Android!\n\n" +
                "Beam Time: " + System.currentTimeMillis()
        return NdefMessage(
                arrayOf(
                        createMime("application/vnd.com.example.android.beam", text.toByteArray())
                )
                /**
                 * The Android Application Record (AAR) is commented out. When a device
                 * receives a push with an AAR in it, the application specified in the AAR
                 * is guaranteed to run. The AAR overrides the tag dispatch system.
                 * You can add it back in to guarantee that this
                 * activity starts when receiving a beamed message. For now, this code
                 * uses the tag dispatch system.
                 *///,NdefRecord.createApplicationRecord("com.example.android.beam")
        )
    }

    override fun onResume() {
        super.onResume()
        // Check to see that the Activity started due to an Android Beam
        if (NfcAdapter.ACTION_NDEF_DISCOVERED == intent.action) {
            processIntent(intent)
        }
    }

    override fun onNewIntent(intent: Intent) {
        // onResume gets called after this to handle the intent
        setIntent(intent)
    }

    /**
     * Parses the NDEF Message from the intent and prints to the TextView
     */
    private fun processIntent(intent: Intent) {
        textView = findViewById(R.id.textView)
        // only one message sent during the beam
        intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES)?.also { rawMsgs ->
            (rawMsgs[0] as NdefMessage).apply {
                // record 0 contains the MIME type, record 1 is the AAR, if present
                textView.text = String(records[0].payload)
            }
        }
    }
}

Java

package com.example.android.beam;

import android.app.Activity;
import android.content.Intent;
import android.nfc.NdefMessage;
import android.nfc.NdefRecord;
import android.nfc.NfcAdapter;
import android.nfc.NfcAdapter.CreateNdefMessageCallback;
import android.nfc.NfcEvent;
import android.os.Bundle;
import android.os.Parcelable;
import android.widget.TextView;
import android.widget.Toast;
import java.nio.charset.Charset;


public class Beam extends Activity implements CreateNdefMessageCallback {
    NfcAdapter nfcAdapter;
    TextView textView;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        TextView textView = (TextView) findViewById(R.id.textView);
        // Check for available NFC Adapter
        nfcAdapter = NfcAdapter.getDefaultAdapter(this);
        if (nfcAdapter == null) {
            Toast.makeText(this, "NFC is not available", Toast.LENGTH_LONG).show();
            finish();
            return;
        }
        // Register callback
        nfcAdapter.setNdefPushMessageCallback(this, this);
    }

    @Override
    public NdefMessage createNdefMessage(NfcEvent event) {
        String text = ("Beam me up, Android!\n\n" +
                "Beam Time: " + System.currentTimeMillis());
        NdefMessage msg = new NdefMessage(
                new NdefRecord[] { createMime(
                        "application/vnd.com.example.android.beam", text.getBytes())
         /**
          * The Android Application Record (AAR) is commented out. When a device
          * receives a push with an AAR in it, the application specified in the AAR
          * is guaranteed to run. The AAR overrides the tag dispatch system.
          * You can add it back in to guarantee that this
          * activity starts when receiving a beamed message. For now, this code
          * uses the tag dispatch system.
          */
          //,NdefRecord.createApplicationRecord("com.example.android.beam")
        });
        return msg;
    }

    @Override
    public void onResume() {
        super.onResume();
        // Check to see that the Activity started due to an Android Beam
        if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(getIntent().getAction())) {
            processIntent(getIntent());
        }
    }

    @Override
    public void onNewIntent(Intent intent) {
        // onResume gets called after this to handle the intent
        setIntent(intent);
    }

    /**
     * Parses the NDEF Message from the intent and prints to the TextView
     */
    void processIntent(Intent intent) {
        textView = (TextView) findViewById(R.id.textView);
        Parcelable[] rawMsgs = intent.getParcelableArrayExtra(
                NfcAdapter.EXTRA_NDEF_MESSAGES);
        // only one message sent during the beam
        NdefMessage msg = (NdefMessage) rawMsgs[0];
        // record 0 contains the MIME type, record 1 is the AAR, if present
        textView.setText(new String(msg.getRecords()[0].getPayload()));
    }
}

Xin lưu ý rằng mã này có nhận xét một AAR (đề xuất được tự động áp dụng) mà bạn có thể xoá. Nếu bạn bật AAR, thì ứng dụng được chỉ định trong AAR sẽ luôn nhận được thông báo Android Beam. Nếu không có ứng dụng thì Google Play sẽ bắt đầu tải ứng dụng xuống. Do đó, bộ lọc ý định sau đây là không cần thiết về mặt kỹ thuật đối với các thiết bị Android 4.0 trở lên nếu sử dụng AAR:

<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>

Với bộ lọc ý định này, ứng dụng com.example.android.beam giờ đây có thể khởi động khi quét thẻ NFC hoặc nhận được Android Beam có AAR thuộc loại com.example.android.beam hoặc khi thông báo có định dạng NDEF chứa bản ghi MIME thuộc loại application/vnd.com.example.android.beam.

Mặc dù AAR đảm bảo một ứng dụng sẽ khởi động hoặc được tải xuống, nhưng bạn nên sử dụng các bộ lọc ý định vì các bộ lọc ý định này cho phép bạn bắt đầu một Hoạt động mà bạn chọn trong ứng dụng đó thay vì luôn bắt đầu Hoạt động chính trong gói do AAR chỉ định. AAR không có độ chi tiết cấp Hoạt động. Ngoài ra, vì một số thiết bị chạy Android không hỗ trợ AAR, bạn cũng nên nhúng thông tin nhận dạng vào bản ghi NDEF đầu tiên của thông báo NDEF và lọc cả thông báo đó để phòng trường hợp bị chặn. Xem phần Tạo các loại bản ghi NDEF phổ biến để biết thêm thông tin về cách tạo bản ghi.