このドキュメントでは、Android で行う基本的な NFC タスクについて説明します。NDEF メッセージの形式で NFC データを送受信する方法と、これらの機能をサポートする Android フレームワーク API について説明します。NDEF 以外のデータの処理方法など、詳細なトピックについては、高度な NFC をご覧ください。
NFC タグからの NDEF データの読み取りは、タグ ディスパッチ システムで処理されます。このシステムは、検出された NFC タグを分析し、データを適切に分類して、分類されたデータに関連したアプリケーションを起動します。スキャンされた NFC タグを処理するアプリケーションでインテント フィルタを宣言して、データの処理をリクエストできます。
タグ ディスパッチ システム
Android デバイスは通常、デバイスの設定メニューで NFC が無効になっていない限り、画面のロックが解除されたときに NFC タグを探します。Android デバイスが NFC タグを検出した場合、ユーザーに使用するアプリケーションを確認せずに、最も適切なアクティビティにインテントを処理させることが、期待される動作です。デバイスは NFC タグを非常に短い範囲でスキャンするため、ユーザーが手動でアクティビティを選択しようとすると、デバイスをタグから遠ざけ、接続が切断される可能性があります。 選択ダイアログが表示されないようにするには、アクティビティで重要な NFC タグのみを処理するようにアクティビティを開発する必要があります。
この目的を達成できるように、Android には特別なタグ ディスパッチ システムが用意されています。このシステムは、スキャンされた NFC タグを分析して解析し、スキャンしたデータを必要とするアプリを探します。これは次の方法で行います。
- NFC タグを解析して、タグ内のデータ ペイロードを識別する MIME タイプまたは URI を特定します。
- MIME タイプまたは URI、およびペイロードをインテントにカプセル化します。これらの最初 2 つの手順は、NFC タグが MIME タイプと URI にマッピングされる仕組みで説明します。
- インテントに基づいてアクティビティを開始します。これについては、NFC タグがアプリケーションにディスパッチされる仕組みをご覧ください。
NFC タグが MIME タイプと URI にマッピングされる仕組み
NFC アプリの作成を開始する前に、さまざまな種類の NFC タグ、タグ ディスパッチ システムが NFC タグを解析する方法、NDEF メッセージを検出したときにタグ ディスパッチ システムが行う特別な処理について理解しておくことが重要です。NFC タグは幅広いテクノロジーに対応しており、さまざまな方法でデータを書き込むことができます。Android は NFC フォーラムで定義されている NDEF 標準規格を最大限にサポートしています。
NDEF データは、1 つまたは複数のレコード(NdefRecord
)を含むメッセージ(NdefMessage
)内にカプセル化されます。各 NDEF レコードは、作成するレコードタイプの仕様に従って適切な形式にする必要があります。Android では、NDEF データを含まない他のタイプのタグもサポートしています。これらのタグは、android.nfc.tech
パッケージ内のクラスを使用して操作できます。これらの技術の詳細については、高度な NFC のトピックをご覧ください。このような他の種類のタグを処理する場合は、独自のプロトコル スタックを作成してタグと通信する必要があります。そのため、可能な限り NDEF を使用して、開発を容易にし、Android デバイスを最大限にサポートすることをおすすめします。
注: 完全な NDEF 仕様をダウンロードするには、NFC フォーラムの仕様とアプリケーション ドキュメントのサイトをご覧ください。NDEF レコードの作成例については、一般的な NDEF レコードタイプの作成をご覧ください。
NFC タグの技術的背景について説明したので、次のセクションでは、Android が NDEF 形式のタグを処理する方法について詳しく説明します。Android デバイスが NDEF 形式のデータを含む NFC タグをスキャンすると、メッセージをパースし、データの MIME タイプを見つけ出すか、URI を識別しようとします。これを行うために、システムは NdefMessage
内の最初の NdefRecord
を読み取り、NDEF メッセージ全体(NDEF メッセージには複数の NDEF レコードが含まれる場合があります)の解釈方法を決定します。正しい形式の NDEF メッセージでは、最初の NdefRecord
に次のフィールドが含まれます。
- 3 ビットの TNF(Type Name Format)
- 可変長タイプのフィールドの解釈方法を示します。有効な値については、表 1 をご覧ください。
- 可変長タイプ
- レコードのタイプを記述します。
TNF_WELL_KNOWN
を使用している場合、このフィールドを使用してレコードタイプ定義(RTD)を指定します。有効な RTD 値は表 2 に記載されています。 - 可変長 ID
- 当該レコードの一意の識別子。このフィールドはあまり使用されませんが、タグを一意に識別する必要がある場合は、その ID を作成できます。
- 可変長ペイロード
- 読み書きする実際のデータ ペイロード。NDEF メッセージに複数の NDEF レコードを含めることができるため、NDEF メッセージの最初の NDEF レコードに完全なペイロードがあるとは限りません。
タグ ディスパッチ システムは TNF とタイプ フィールドを使用して、MIME タイプまたは URI を NDEF メッセージにマッピングしようと試みます。成功した場合は、その情報を実際のペイロードとともに ACTION_NDEF_DISCOVERED
インテント内にカプセル化します。ただし、タグ ディスパッチ システムが、最初の NDEF レコードに基づいてデータの種類を判別できない場合もあります。これは、NDEF データを MIME タイプや URI にマッピングできない場合や、初めから NFC タグに NDEF データが含まれていない場合に発生します。このような場合、タグのテクノロジーとペイロードに関する情報が含まれる Tag
オブジェクトが代わりに ACTION_TECH_DISCOVERED
インテント内にカプセル化されます。
表 1 は、タグ ディスパッチ システムが TNF とタイプ フィールドを MIME タイプまたは URI にマッピングする方法を示します。また、MIME タイプまたは URI にマッピングできない TNF についても説明します。このような場合、タグ ディスパッチ システムは ACTION_TECH_DISCOVERED
にフォールバックします。
たとえば、タグ ディスパッチ システムが TNF_ABSOLUTE_URI
タイプのレコードを検出した場合、そのレコードの可変長タイプ フィールドを URI にマッピングします。タグ ディスパッチ システムは、その URI をペイロードなどのタグに関する他の情報とともに、ACTION_NDEF_DISCOVERED
インテントのデータ フィールドにカプセル化します。一方、TNF_UNKNOWN
タイプのレコードが見つかった場合は、代わりにタグのテクノロジーをカプセル化するインテントを作成します。
Type Name Format(TNF) | マッピング |
---|---|
TNF_ABSOLUTE_URI |
タイプ フィールドに基づく URI。 |
TNF_EMPTY |
ACTION_TECH_DISCOVERED にフォールバックします。 |
TNF_EXTERNAL_TYPE |
タイプ フィールドの URN に基づく URI。URN は NDEF タイプ フィールドに短縮形式(<domain_name>:<service_name> )でエンコードされます。Android はこれを vnd.android.nfc://ext/<domain_name>:<service_name> の形式の URI にマッピングします。 |
TNF_MIME_MEDIA |
タイプ フィールドに基づく MIME タイプ。 |
TNF_UNCHANGED |
最初のレコードが無効なため、ACTION_TECH_DISCOVERED にフォールバックします。 |
TNF_UNKNOWN |
ACTION_TECH_DISCOVERED にフォールバックします。 |
TNF_WELL_KNOWN |
[タイプ] フィールドで設定したレコードタイプ定義(RTD)に応じた MIME タイプまたは URI。利用可能な RTD とそのマッピングについて詳しくは、表 2 をご覧ください。 |
レコードタイプ定義(RTD) | マッピング |
---|---|
RTD_ALTERNATIVE_CARRIER |
ACTION_TECH_DISCOVERED にフォールバックします。 |
RTD_HANDOVER_CARRIER |
ACTION_TECH_DISCOVERED にフォールバックします。 |
RTD_HANDOVER_REQUEST |
ACTION_TECH_DISCOVERED にフォールバックします。 |
RTD_HANDOVER_SELECT |
ACTION_TECH_DISCOVERED にフォールバックします。 |
RTD_SMART_POSTER |
ペイロードのパースに基づく URI。 |
RTD_TEXT |
text/plain の MIME タイプ。 |
RTD_URI |
ペイロードに基づく URI。 |
NFC タグがアプリケーションにディスパッチされる仕組み
タグ ディスパッチ システムが、NFC タグとその識別情報をカプセル化するインテントの作成を完了すると、インテントをフィルタする関連アプリケーションにインテントを送信します。複数のアプリケーションがインテントを処理できる場合は、選択ダイアログが表示されるため、ユーザーがアクティビティを選択できます。タグ ディスパッチ システムは、3 つのインテントを定義します。このインテントは、優先度の高い順にリストされます。
-
ACTION_NDEF_DISCOVERED
: NDEF ペイロードを含むタグがスキャンされ、タイプが認識済みのものである場合は、このインテントを使用してアクティビティを開始します。これは最も優先度の高いインテントであり、タグ ディスパッチ システムは、可能な限り他のインテントよりも先にこのインテントでアクティビティを開始しようとします。 ACTION_TECH_DISCOVERED
:ACTION_NDEF_DISCOVERED
インテントを処理するアクティビティが登録されていない場合、タグ ディスパッチ システムはこのインテントでアプリケーションを起動しようとします。スキャンされるタグに MIME タイプまたは URI にマッピングできない NDEF データが含まれている場合、または NDEF データが含まれていなくても既知のテクノロジーのタグである場合、このインテントは(最初にACTION_NDEF_DISCOVERED
を開始せずに)直接開始されます。ACTION_TAG_DISCOVERED
: このインテントは、ACTION_NDEF_DISCOVERED
またはACTION_TECH_DISCOVERED
インテントを処理するアクティビティがない場合に開始されます。
タグ ディスパッチ システムの基本的な仕組みは次のとおりです。
- NFC タグのパース時にタグ ディスパッチ システムによって作成されたインテント(
ACTION_NDEF_DISCOVERED
またはACTION_TECH_DISCOVERED
)でアクティビティの開始を試みます。 - そのインテントにアクティビティ フィルタがない場合は、次に優先度の低いインテント(
ACTION_TECH_DISCOVERED
またはACTION_TAG_DISCOVERED
)でアクティビティを開始しようとします。これは、アプリケーションがインテントをフィルタするまで、またはタグ ディスパッチ システムが可能なすべてのインテントを試みるまで行います。 - アプリケーションがどのインテントもフィルタしない場合は、何もしません。
可能な限り、NDEF メッセージと ACTION_NDEF_DISCOVERED
インテントを処理します。これは、3 つの中で最も具体的であるためです。このインテントを使用すると、他の 2 つのインテントよりも適切なタイミングでアプリケーションを起動できるため、ユーザーのエクスペリエンスが向上します。
Android マニフェストで NFC アクセスをリクエストする
デバイスの NFC ハードウェアにアクセスし、NFC インテントを適切に処理する前に、AndroidManifest.xml
ファイルで次の項目を宣言します。
- NFC ハードウェアにアクセスするための NFC
<uses-permission>
要素:<uses-permission android:name="android.permission.NFC" />
- アプリケーションでサポート可能な SDK の最小バージョン。API レベル 9 では、
ACTION_TAG_DISCOVERED
による限定的なタグ ディスパッチのみがサポートされ、EXTRA_NDEF_MESSAGES
エクストラによる NDEF メッセージへのアクセスのみが許可されます。他のタグプロパティや I/O オペレーションにアクセスすることはできません。API レベル 10 には、リーダー/ライターの包括的サポートとフォアグラウンド NDEF プッシュ機能があります。API レベル 14 には、NDEF レコードを作成するための便利な追加メソッドがあります。<uses-sdk android:minSdkVersion="10"/>
uses-feature
要素: NFC ハードウェアを備えたデバイスでのみ、アプリが Google Play に表示されます。<uses-feature android:name="android.hardware.nfc" android:required="true" />
アプリで NFC 機能を使用しているが、その機能がアプリにとって重要でない場合は、
uses-feature
要素を省略し、実行時にgetDefaultAdapter()
がnull
かどうかを確認して NFC が利用可能かどうかを確認します。
NFC インテントのフィルタ
処理する NFC タグのスキャン時にアプリを起動するには、Android マニフェストで NFC インテントの 1 つ、2 つ、または 3 つすべてをフィルタします。ただし、通常は、アプリケーションの起動タイミングを最大限に制御するために、ACTION_NDEF_DISCOVERED
インテントをフィルタする必要があります。ACTION_TECH_DISCOVERED
インテントは、ACTION_NDEF_DISCOVERED
をフィルタしているアプリケーションがない場合、またはペイロードが NDEF でない場合の ACTION_NDEF_DISCOVERED
のフォールバックです。通常、ACTION_TAG_DISCOVERED
のフィルタは、カテゴリのフィルタとしては一般的すぎます。多くのアプリは、ACTION_TAG_DISCOVERED
の前に ACTION_NDEF_DISCOVERED
または ACTION_TECH_DISCOVERED
でフィルタするため、アプリが起動する可能性は低くなります。ACTION_TAG_DISCOVERED
は、ACTION_NDEF_DISCOVERED
または ACTION_TECH_DISCOVERED
インテントを処理する他のアプリケーションがインストールされていない場合の最後の手段としてのみ利用できます。
NFC タグのデプロイメントはさまざまであり、多くの場合制御できず、これが常に可能であるとは限らないため、必要に応じて他の 2 つのインテントにフォールバックできます。タグのタイプと書き込みデータを制御できる場合は、NDEF を使用してタグをフォーマットすることをおすすめします。次のセクションでは、インテントのタイプごとにフィルタを適用する方法について説明します。
ACTION_NDEF_DISCOVERED
ACTION_NDEF_DISCOVERED
インテントをフィルタするには、フィルタ対象のデータタイプとともにインテント フィルタを宣言します。MIME タイプが text/plain
の ACTION_NDEF_DISCOVERED
インテントをフィルタする例を以下に示します。
<intent-filter> <action android:name="android.nfc.action.NDEF_DISCOVERED"/> <category android:name="android.intent.category.DEFAULT"/> <data android:mimeType="text/plain" /> </intent-filter>
次の例では、URI を 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
アクティビティで ACTION_TECH_DISCOVERED
インテントをフィルタする場合、tech-list
セット内でアクティビティがサポートするテクノロジーを指定する XML リソース ファイルを作成する必要があります。tech-list
セットがタグでサポートされているテクノロジー(getTechList()
の呼び出しで取得可能)のサブセットである場合、アクティビティは一致すると見なされます。
たとえば、スキャンされるタグが MifareClassic、NdefFormatable、NfcA をサポートしている場合、アクティビティを一致させるには、1 つ、2 つ、または 3 つすべてのテクノロジー(他のものは含めない)を tech-list
セットで指定する必要があります。
次の例では、テクノロジーをすべて定義しています。NFC タグでサポートされていないものは削除する必要があります。このファイル(名前は自由に指定できます)を <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>
また、複数の tech-list
セットを指定できます。各 tech-list
セットは個別に扱われ、getTechList()
で返されるテクノロジーのサブセットに相当する tech-list
セットが 1 つでも存在する場合、アクティビティは一致すると見なされます。これにより、テクノロジーのマッチングに AND
と OR
のセマンティクスが提供されます。次の例は、NfcA と Ndef テクノロジー、または NfcB と 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>
次の例のように、AndroidManifest.xml
ファイルで、<activity>
要素内の <meta-data>
要素に、作成したばかりのリソース ファイルを指定します。
<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>
タグ技術と ACTION_TECH_DISCOVERED
インテントの使用方法について詳しくは、高度な NFC ドキュメントのサポートされているタグ テクノロジーの使用をご覧ください。
ACTION_TAG_DISCOVERED
ACTION_TAG_DISCOVERED
をフィルタするには、次のインテント フィルタを使用します。
<intent-filter> <action android:name="android.nfc.action.TAG_DISCOVERED"/> </intent-filter>
インテントから情報を取得する
NFC インテントが原因でアクティビティが開始した場合、スキャンされた NFC タグに関する情報をインテントから取得できます。インテントには、スキャンされたタグに応じて次の EXTRA 項目が含まれます。
EXTRA_TAG
(必須): スキャンされたタグを表すTag
オブジェクト。EXTRA_NDEF_MESSAGES
(省略可): タグからパースされた NDEF メッセージの配列。ACTION_NDEF_DISCOVERED
インテントでは、このエクストラは必須です。EXTRA_ID
(任意): タグの低レベル ID。
これらの EXTRA を取得するには、アクティビティが NFC インテントの 1 つで起動されたかどうかを確認し、タグがスキャンされたことを確認してから、インテントから EXTRA を取得します。ACTION_NDEF_DISCOVERED
インテントを確認し、インテントの EXTRA から NDEF メッセージを取得する例を次に示します。
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. ... } } }
または、インテントから Tag
オブジェクトを取得できます。これにはペイロードが含まれ、タグのテクノロジーを列挙することができます。
Kotlin
val tag: Tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG)
Java
Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
一般的なタイプの NDEF レコードを作成する
ここでは、NFC タグへの書き込みに役立つ、一般的なタイプの NDEF レコードを作成する方法について説明します。Android 4.0(API レベル 14)以降では、URI レコードの自動作成に createUri()
メソッドを使用できます。Android 4.1(API レベル 16)以降では、createExternal()
と createMime()
を使用して MIME タイプと外部タイプの NDEF レコードを作成できます。NDEF レコードを手動で作成する際の間違いを避けるため、可能な限りこれらのヘルパー メソッドを使用してください。
このセクションでは、レコードに対応するインテント フィルタの作成方法についても説明します。これらの NDEF レコードの例はすべて、タグに書き込む NDEF メッセージの最初の NDEF レコードに配置する必要があります。
TNF_ABSOLUTE_URI
注: TNF_ABSOLUTE_URI
ではなく RTD_URI
を使用する方が効率的であるため、おすすめします。
TNF_ABSOLUTE_URI
NDEF レコードは次の方法で作成できます。
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]);
前の NDEF レコードのインテント フィルタは次のようになります。
<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
TNF_MIME_MEDIA
NDEF レコードの作成方法を以下に示します。
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")));
手動で NdefRecord
を作成:
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")));
前の NDEF レコードのインテント フィルタは次のようになります。
<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(RTD_TEXT)
TNF_WELL_KNOWN
NDEF レコードの作成方法を以下に示します。
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; }
前の NDEF レコードのインテント フィルタは次のようになります。
<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(RTD_URI)
TNF_WELL_KNOWN
NDEF レコードは次の方法で作成できます。
createUri(String)
メソッドを使用:
Kotlin
val rtdUriRecord1 = NdefRecord.createUri("https://example.com")
Java
NdefRecord rtdUriRecord1 = NdefRecord.createUri("https://example.com");
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);
手動で NdefRecord
を作成:
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);
前の NDEF レコードのインテント フィルタは次のようになります。
<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
TNF_EXTERNAL_TYPE
NDEF レコードの作成方法を以下に示します。
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);
手動で NdefRecord
を作成:
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);
前の NDEF レコードのインテント フィルタは次のようになります。
<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>
TNF_EXTERNAL_TYPE
を使用すると、より一般的な NFC タグをデプロイし、Android デバイスと Android 以外のデバイスの両方をより適切にサポートできます。
注: TNF_EXTERNAL_TYPE
の URN の標準形式は urn:nfc:ext:example.com:externalType
ですが、NFC フォーラムの RTD 仕様では、URN の urn:nfc:ext:
部分を NDEF レコードから削除する必要があると宣言されています。したがって、必要となるのは、ドメイン(例では example.com
)とタイプ(例では externalType
)をコロンで区切って指定することだけです。TNF_EXTERNAL_TYPE
をディスパッチする際、Android は urn:nfc:ext:example.com:externalType
URN を vnd.android.nfc://ext/example.com:externalType
URI に変換します。これは、この例のインテント フィルタが宣言したものです。
Android アプリのレコード
Android 4.0(API レベル 14)で導入された Android Application Record(AAR)により、NFC タグのスキャン時にアプリケーションが起動される確実性が向上します。AAR には、NDEF レコードに埋め込まれたアプリのパッケージ名があります。Android は NDEF メッセージ全体で AAR を検索するため、NDEF メッセージの任意の NDEF レコードに AAR を追加できます。AAR が見つかると、AAR 内のパッケージ名に基づいてアプリケーションを起動します。アプリケーションがデバイスにない場合、Google Play を起動してアプリをダウンロードします。
AAR は、同じインテントをフィルタリングする他のアプリケーションにより、自分がデプロイした特定のタグが処理されるのを防ぐ場合に便利です。AAR は、パッケージ名の制約のため、アプリケーション レベルでのみサポートされ、インテント フィルタリングの場合のようにアクティビティ レベルではサポートされません。アクティビティ レベルでインテントを処理する場合は、インテント フィルタを使用します。
タグに AAR が含まれている場合、タグ ディスパッチ システムによるディスパッチ方法は以下のとおりです。
- 通常どおりに、インテント フィルタを使用したアクティビティの開始を試みます。インテントに一致するアクティビティが AAR にも一致する場合、アクティビティを開始します。
- インテントをフィルタするアクティビティが AAR と一致しない場合、複数のアクティビティがインテントを処理できる場合、インテントを処理するアクティビティがない場合は、AAR で指定されたアプリを起動します。
- AAR で開始できるアプリがない場合は、Google Play にアクセスして AAR ベースのアプリをダウンロードします。
注: AAR とインテント ディスパッチ システムを、フォアグラウンド ディスパッチ システムでオーバーライドできます。これにより、NFC タグが検出されたときにフォアグラウンド アクティビティを優先させることができます。このメソッドでは、AAR とインテント ディスパッチ システムをオーバーライドするために、アクティビティがフォアグラウンドにある必要があります。
AAR が含まれていない、スキャンされたタグをフィルタしたい場合は、通常どおりインテント フィルタを宣言できます。これは、アプリケーションが AAR を含まない他のタグと関連している場合に便利です。たとえば、デベロッパーがデプロイする独自のタグと、サードパーティによってデプロイされた一般的なタグをアプリケーションで処理できるようにしたい場合があります。AAR は Android 4.0 以降のデバイスに固有であるため、タグをデプロイする場合は AAR と、MIME タイプまたは URI を組み合わせて使用し、幅広いデバイスをサポートすることをおすすめします。さらに、NFC タグをデプロイする際は、NFC タグの書き込み方法を検討して、ほとんどのデバイス(Android デバイスやその他のデバイス)への対応を可能にしてください。これを行うには、重複が比較的生じにくい MIME タイプや URI を定義して、アプリケーションが識別しやすいようにします。
Android は AAR を作成するシンプルな API createApplicationRecord()
を提供します。AAR を NdefMessage
の任意の場所に埋め込むだけです。AAR が NdefMessage
内の唯一のレコードでない限り、NdefMessage
の最初のレコードを使用する必要はありません。これは、Android システムが NdefMessage
の最初のレコードをチェックして、タグの MIME タイプまたは URI(アプリケーションがフィルタするインテントの作成に使用されます)を決定するためです。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")} ); )