情報畑でつかまえてロゴ
本サイトは NTTテクノクロスが旬の IT をキーワードに
IT 部門が今知っておきたい最新テクノロジーに関する情報をお届けするサイトです

AndroidによるNFCスマートポスタータグの作成

「NFCケータイ」を使って、スマートポスター タグを作成する(書き込む)Androidアプリケーションの作り方についてご紹介します。

はじめに

AndroidにNFC機能が搭載されることが発表されてから、約2年半が経過しようとしています。この間に、国内で発売されているAndroid搭載スマートフォンの多くは非接触ICチップにアクセスするための機能を備えるようになりました。そのようなスマートフォンは、Androidアプリケーション開発者の観点から、以下のように分類することができます。

(1)フェリカネットワークス株式会社が提供しているライブラリを使って、
FeliCaチップにアクセスできるもの

(2)Android標準のNFC APIが利用できるもの

(1) の機能を備えたスマートフォンでは、FeliCaチップを使った国内の電子マネーサービスを利用できます。「おサイフケータイ」という商標で、広く知られていると思います。

(2) には特に定まった名称はないのですが、ここでは便宜的に「NFCケータイ」と呼ぶことにしたいと思います。もちろん、(1)と(2)の両方の機能を兼ね備えたスマートフォンも存在します。そのようなスマートフォンは「おサイフケータイ」でもあり「NFCケータイ」でもあることになります。

さて、このコラムのタイトルである「スマートポスタータグ」とはどういうものなのでしょうか。スマートポスタータグとは、市販のNFCタグ( 図.1-1 )に、「スマートポスター」と呼ばれる仕様 [1] に従った情報を書き込んだものです。たとえば「このURLをブラウザで表示せよ」と記録されたタグに、NFCケータイをかざすと、スマートフォンのブラウザが自動的に起動し、当該URLを表示しようとします( 図.1-2 )。

図.1-1 NFCタグの例

< 図.1-1 NFCタグの例 >

図.1-2 スマートポスター形式のNFCタグを、NFCケータイにかざした時の動作

< 図.1-2 スマートポスター形式のNFCタグを、NFCケータイにかざした時の動作 >

また「おサイフケータイ」であっても、株式会社NTTドコモがGoogle Playで無料配布している「 ICタグ・バーコードリーダー 」をインストールすることで、同様の動作を実現することができます。

この「ICタグ・バーコードリーダー」には、スマートポスタータグを作成する機能もあるため、その機能を使えば、独自にAndroidアプリケーションを開発せずとも、スマートポスタータグを作成することができます (*1) 。しかしながら、大量のタグに、それぞれ異なるURLを書き込みたい場合などでは、そのための専用アプリケーションを開発する方が良いでしょう。

今回のコラムでは、「NFCケータイ」を使って、スマートポスタータグを作成する(書き込む)Androidアプリケーションの作り方についてご紹介します。

【解 説】

*1:「ICタグ・バーコードリーダー」は、おサイフケータイにも、NFCケータイにもインストールして利用することができるようです。

前提知識

「NFCケータイ」と「おサイフケータイ」の両方で読み取ることのできるスマートポスタータグを作成するためには、それぞれの端末でできることの違いを理解しておく必要があります。アプリケーションの作り方の説明の前に、最低限理解しておいた方が良い知識について説明します。

1.NFCとは

NFCとは、Near Field Communicationの略で、日本語では「近距離無線通信」と訳されます。「近距離無線通信」にはいくつかの方式が並存しているため、互換性を確保するために、業界標準団体 「NFCフォーラム」 により、実装仕様が策定されています。

NFCケータイに採用されているAPIも、NFCフォーラムの仕様を元に設計されており、たとえば以下のタグと通信することができます。

(1)NFC-A: ISO/IEC 14443 Type A (MIFARE)

(2)NFC-B: ISO/IEC 14443 Type B (住基カードなど)

(3)NFC-F: JIS X 6319-4 (FeliCa)

「通信」といっても、NFCケータイが、チップの全ての機能を使えるわけではありません。たとえば、FeliCaチップに格納されている電子マネー残額を書き換えるような、暗号化/復号が必要な機能は利用することはできません。

一方、(3)へのアクセスに特化しているおサイフケータイでは、FeliCaの機能全てが利用できるように実装されていますが、当然、(1)や(2)と通信することはできません。また、 日本Androidの会2012年2月の定例会発表資料 によると、おサイフケータイをリーダー/ライターとして利用して外部のFeliCaタグと通信するためのAPIを利用するには、フェリカネットワークス株式会社への申請が必要とされています。

2.書き込むタグを選ぶ

前節で説明したように、NFCケータイとおサイフケータイの両方からアクセスできるようにするためには、NFCフォーラムに準拠したFeliCa ICチップ搭載タグを用意する必要があります。

そのようなタグはいくつかありますが、このコラムでは、個人でも安価に入手可能な「FeliCa Lite シール (RC-S965)」にスマートポスター情報を書き込むことにします。インターネットによる通信販売でも購入できますので、気になる方は検索してみてください。

なお、NFCケータイのみからアクセスできれば良いのであれば、より安価なMIFAREタグが利用可能ですので、用途に応じて選択してみてください (*1)

3.NDEF

スマートポスター形式のデータは、NDEF (NFC Data Exchange Format)と呼ばれる形式に準拠しています。そのため、NDEFのうち、スマートポスターのデータ構造を理解するために必要最低限の部分を説明します。より詳細な内容については [2] を参照してください。

NDEFは、複数のNDEF Recordで構成されている、NDEF Messageと呼ばれる構造を持っています( 図.2-1 )。また、それぞれのNDEF Recordは、 図.2-2 のような構造を持っています。この中で、Androidアプリケーション開発者が知っておくべき内容(図中のオレンジ色の部分)は以下の通りです。

図.2-1 NDEF Messageの構造

< 図.2-1 NDEF Messageの構造 >

  • TNF: Type Name Format
    このNDEFレコード中のTYPEフィールドに、どのような値を書き込めるかを規定します。詳細は Androidの公式ドキュメント に譲りますが、スマートポスタータグの場合には0x01 ( TNF_WELL_KNOWN )を指定します。
  • TYPE:
    PAYLOADの型を表します。TNFがTNF_WELL_KNOWNの場合に指定できる文字列の例を、 表.2-1 に示します。
  • ID:
    NDEFレコードをさらに識別したい場合に用いますが、省略するケースが多いため、詳細は割愛します。
  • PAYLOAD:
    データ本体です。
図.2-2 NDEF Recordの構造

< 図.2-2 NDEF Recordの構造 >


(文字列)
Androidの定数名
(NdefRecordクラス)
意 味
   U    RTD_URI  URIレコード型
   T    RTD_TEXT  テキストレコード型
   Sp    RTD_SMART_POSTER  スマートポスターレコード型

< 表.2-1 TNFがTNF_WELL_KNOWNの場合のTYPEフィールドの代表例 >

NDEFに関連して、もうひとつ忘れてはならないのは、タグのフォーマットについてです。NDEF Messageをタグに書き込むためには、NDEF形式でフォーマット済みのタグでなければなりません。市販のNFCタグには、NDEF未フォーマットのものも流通しています。このコラムでは、NFCケータイを使ってNDEFフォーマットを実行する方法については触れません。別途、NDEFフォーマット済みのタグを用意してください。

NDEF未フォーマットのタグを購入した場合は、ソニー株式会社が公開している NDEF Writer を使って、一度適当なURLを書き込むと、同時にフォーマットも実行されるようです。NDEF Writerを実行するには、ソニー製非接触ICカード リーダー/ライターPaSoRiが必要となりますが、現状では一番手軽なフォーマット手段だと思われます。

なお、難易度は高くなりますが、NFCケータイが備えるAndroid APIの NfcF.transceive() を使って、FeliCa Liteタグをフォーマットすることも可能です。興味がある方は、 [3] [4] に、フォーマットに成功された方による有用な情報がありますので、フォーマット機能の作成にチャレンジしてみてください (*2)

以上で前提知識の説明は終わりました。早速スマートポスタータグ書き込みアプリの実装を始めましょう。

【解 説】

*1:このコラムで紹介する方法でアプリケーションを作成すれば、MIFAREタグにも問題なく書き込むことができます。

*2:一見、NDEFフォーマットを実行する NdefFormatable.format() を呼び出せば簡単にフォーマットできそうです。しかし、筆者が確認した範囲では、NdefFormatable.format()を使ってFeliCa Liteタグをフォーマットすることはできないようです。

タグ書き込みアプリを実際に作ってみよう

以下のようなシンプルな仕様を持つ、スマートポスタータグを書き込むAndroidアプリケーションを作っていきましょう。

動作端末:
Android 4.0以降のNFCケータイ
スマートポスターを書き込むタグ:
NDEFフォーマット済みのNFCタグ
動作仕様:
(1)
NDEFフォーマット済みのNFCタグにスマートポスター情報を書き込みます。このアプリケーションの画面が表示されているときに限り、タグへの書き込みを行います。
(2)
スマートポスタータグのURLには、弊社のテクノロジーコラム一覧のページを設定します。

もちろん、このアプリケーションを使ってタグへの書き込みができてしまえば、あとはタグ単独でスマートポスターとして使うことができます。すなわち「タグにかざすと、自動的にブラウザが起動して、タグに設定されているURLのWebページを表示する」という動作には、本アプリケーションは必要ありません (*1)

以降では、本アプリケーションの作成方法を、以下の順序で紹介します。

1.マニフェストを準備する

本アプリケーションのマニフェストファイルを、 図.3-1 に示します。NFCを扱うアプリケーションで必ず必要となるのが、NFCを利用するためのパーミッション宣言( 図.3-1 【1】)です。

図.3-1 【2】は、Google Playにアプリケーションを公開するときに、NFCケータイ以外ではダウンロードできないようにするための設定です。必須というわけではありませんが、アプリケーションを公開する場合には記載しておくと良いでしょう。

マニフェストの準備において、NFCを扱う場合に注意すべき点は上記2点のみです。あとは通常のAndroidアプリケーション作成の流儀にしたがって作成してください。

なお、 図.3-1 では省略していますが、本アプリケーションはSmartPosterWritingActivityという名前の、1つのActivityのみで構成されています。

< 図. 3-1 AndroidManifest.xml >

2.タグがかざされたことを検知する

NFCケータイは、NFCタグがかざされたことを検知すると、タグの種類に応じた暗黙的インテント (*2) を配送します。具体的なインテントの種類を決定するルールは 多少複雑 ですが、たとえば、NDEF形式のタグがかざされた時には、ACTION_NDEF_DISCOVEREDインテントが配送されます。言い換えると、NDEF形式のタグがかざされた時に、自分が作成したアプリケーションを起動するようにしたい場合は、ACTION_NDEF_DISCOVEREDインテントを受け取るようなインテントフィルタを、マニフェストに宣言することになります (*3)

ただ、今回は、画面表示中(Activity起動中)にのみ、タグがかざされたことを検知できれば良いので、マニフェストにはインテントフィルタは定義していません。代わりに、 foreground dispatch system と呼ばれる機能を利用します。

foreground dispatch systemとは、あるActivityがフォアグラウンド(最前面)にある場合に限って、NFCタグがかざされたときに発行されるインテントを独り占めすることができる機能です。

NFCタグがかざされた時に発行されるインテントは、暗黙的インテントですから、複数のアプリケーションが同一インテントに反応した場合に、どのアプリケーションを起動するか選択するダイアログが表示されてしまい、とても使い勝手が悪くなってしまいます(片方の手でタグにスマートフォンをかざしながら、もう片方の手でダイアログを操作することを想像してみてください)。foreground dispatch systemを使うことで、タグがかざされたときに、自分以外のアプリケーションが反応するのを防ぐことができます。

図.3-2 に、foreground dispatch systemを有効にするためのコード例を示します(レイアウトファイル activity_main.xml の内容は省略していますが、正しい形式のものであればどのような内容でも構いません)。

< 図. 3-2 foreground dispatch systemを有効にするためのコード例 >

まず、onCreate時に、NfcAdapterインスタンスを入手し、インスタンス変数として保持しておきます( 図.3-2 【1】)。

onResume時(Activityがフォアグラウンドになるとき)に、入手したNfcAdapterインスタンスを使って、foreground dispatch systemを有効化するenableForegroundDispatchメソッドを呼び出します( 図.3-2 【3】)。

また、onPause時(Activityがバックグラウンドになるとき)に、foreground dispatch systemを無効化するdisableForegroundDispatchメソッドを呼び出します( 図.3-2 【4】)。

enableForegroundDispatchメソッドに指定する引数の意味について、 表.3-1 に示しました。第2引数に指定するためのPendingIntentは、createPendingIntentメソッド内で生成しており( 図.3-2 【2】)、自分自身(SmartPosterWritingActivity)を起動するためのインテントを指定しています。その時に、FLAG_ACTIVITY_SINGLE_TOPフラグを指定するのを忘れないようにしてください( 図.3-2 【5】)。この指定によって、NFCタグがかざされた時に、本Activityが再起動せずに、onNewIntent()が呼び出されるようになります。

第3引数と第4引数にはnullを指定し、全てのNFCタグに反応するようにしています。このようにすることで、目的以外のタグがかざされた場合に、別のアプリケーションが起動してしまうことを防ぐことができます。

-
意味
第1引数
Activity foreground dispatchを実行するActivity。典型的にはthisを指定する。
第2引数
PendingIntent 第3、4引数で指定した条件に合致したNFCタグがかざされた場合に、代わりに配送したいインテントを格納したPendingIntent。典型的には自Activityを起動する明示的インテントを格納する。
第3引数
IntentFilter[] 反応したいNFCタグの種別を絞り込む条件を指定する(詳細は割愛)。全てのNFCタグに反応したい場合には、両方の引数にnullを指定する。
第4引数
String[][]

< 表.3-1 enableForegroundDispatch()メソッドのAPI仕様 >

ここまでで、NFCタグがかざされた場合に、本ActivityのonNewIntent()メソッドが呼び出されるようになりました。あとは、onNewIntent()メソッド内で、タグへの書き込み処理を実行すれば完成です。

3.検知したタグに、スマートポスター情報を書き込む

では、SmartPosterWritingActivityのonNewIntent()メソッドの実装を見て、インテントを受信してから、実際に書き込むまでの流れを見てみましょう( 図.3-3 )。

< 図. 3-3 onNewInent()メソッドのコード例 >

NFCタグがかざされた場合、インテントが送出されることは既に述べましたが、そのインテントからTagオブジェクトを取得することができます( 図.3-3 【1】)。もし、このTagオブジェクトが取得できなかった場合は、NFCタグがかざされたことによるインテントではない、ということになりますので、処理を中断します(ここでは、見通しを良くするために、ログの出力のみにとどめています)。

次に、 図.3-3 【2】で、取得したTagインスタンスから、Ndefインスタンスを取得しようとしています。

Android NFC APIでは、android.nfc.techパッケージ配下に、 タグテクノロジー と呼ばれるクラス群が用意されており、それぞれがstaticメソッド get(Tag)を持ちます。get(Tag)メソッドは、そのクラスが提供している機能が使える場合に限って非nullを返し、そうでない場合はnullを返すように設計されています。たとえば、NDEFでフォーマットされたFeliCaタグがかざされた場合はNfcF.get(Tag)とNdef.get(Tag)の両方が非nullを返しますので、NfcFクラスが持つ機能と、Ndefクラスが持つ機能の両方を使うことができます。

今回は、NDEFの一種である、スマートポスター形式のデータを書き込もうとしているので、Ndefインスタンスを取得しようとしているわけです。ここでnullが返される場合は、NDEF形式ではないタグがかざされたことになりますので、処理を中断します。

その後、 図.3-3 【3】でスマートポスターの形式にのっとったNdefMessageを生成し、 図.3-3 【4】で、そのNdefMessageを書き込んでいます。以降では、 図.3-3 【3】と 図.3-3 【4】の処理の中身を、詳しく見ていきます。

3-2. スマートポスター形式のNdefMessageを生成する

スマートポスター形式にのっとったNdefMessageを作成するには、その構成を理解しなければなりません。詳細な構成は [1] に記載されているのですが、ブラウザを起動するために必要最低限の構成を 図.3-4 に示しました。

図.3-4 スマートポスターのNDEF Message構造

< 図.3-4 スマートポスターのNDEF Message構造 >

この図から分かるように、スマートポスター形式のNdefMessageは入れ子構造になっており、スマートポスターを表すNdefRecordのペイロードに、URIレコードとActionレコードで構成されるNdefMessageが格納された形になっています。

このような構造を持ったNdefMessageを生成する、具体的なソースコードを 図.3-5 に示します。

< 図. 3-5 スマートポスター形式のNDEF Messageを生成するコード例 >

URIレコード( 図.3-4 の② )をcreateUriRecord()で、Actionレコード( 図.3-4 の③ )をcreateActionRecord()で、それぞれ生成しています。URIレコードの生成は、専用のAPIがAndroid側に用意されているため、単純にNdefRecord.createUri()を呼び出すだけとなります( 図.3-5 【1】) (*4) 。Actionレコードは、専用のAPIは用意されていないため、NdefRecordコンストラクタを利用して自作する必要があります。NdefRecordコンストラクタの引数には、先頭から、TNF、TYPEフィールド、IDフィールド、PAYLOADの順に指定します。 図.3-5 【2】では、 図.3-4 の③ に合致するように指定しています

生成したURIレコードとActionレコードを元に、スマートポスター全体を表すNdefMessageを生成しているのがcreateSmartPosterメソッドです。

図.3-5 【3】で、スマートポスターレコードのペイロード部分を作成し、それを元にスマートポスターレコード( 図.3-4 の① )を作成します( 図.3-5 【4】)。最後に、スマートポスターレコード1つだけを含むNdefMessageを作成して、目的のNdefMessageが完成します。

3-3. NdefMessageをタグへ書き込む

以上で、タグに書き込むNdefMessageを構築することができました。実際に、NdefMessageをタグへ書き込むコードを 図.3-6 に示します。

< 図. 3-6 NDEFメッセージを実際にタグに書き込むコード例 >

メソッド前半では、作成したNdefMessageが本当にタグに書き込めるかを確認しています。まず、タグが書き込み可能かどうか確認し( 図.3-6 【1】)、次に、書き込み可能サイズが十分かどうかを確認しています( 図.3-6 【2】)。

メソッド後半で、実際に書き込みを行っています。Ndef.connect()にて、タグへのコネクション確立を行い( 図.3-6 【3】)、Ndef.writeNdefMessage()にて、書き込みます( 図.3-6 【4】)。書き込みに失敗すると例外が発生しますので、適切に処理を行い、最後にclose()します( 図.3-6 【5】)。

以上により、スマートポスタータグを書き込むアプリケーションを作成することができました。本アプリケーションをNFCケータイにインストールし、起動後の画面が表示されている状態で、タグをかざしてみてください。成功すると「書き込みに成功しました。」と表示されるはずです。

本アプリケーションを終了させたあとに、さきほど書き込んだタグをNFCケータイにかざしてみましょう。目的のURLがブラウザで表示されれば成功です。

なお、この方法で作成したタグは、同じ方法で、誰でも書き換え可能なことに注意してください。タグを書き込み禁止にする方法は、タグの種類により異なります。FeliCa Liteタグの場合は、 [6] に規定されているAttribute Information Block中のRWFlagを0x00に変更することで書き込み禁止となります。更に、ユーザブロックが全てリードオンリーになるように、 [7] に記載されている手順で「2次発行」することで、物理的にも書き換え不能にすることができます。これらの操作も、 NfcF.transceive() メソッドを使って実現可能ですので、興味のある方はチャレンジしてみてください。

【解 説】

*1:すでにご紹介したとおり、おサイフケータイでは「ICタグ・バーコードリーダー」をインストールし、読み取り設定をONにしておく必要があります。
*2:Androidの機能の一つで、アプリケーションソフトウェア間やソフトウェア内の機能間を繋ぎ合わせる仕組みのこと。
*3:正確には、NDEFのレコード種別(TNFやTypeフィールドの値など)によって、より細かい条件のインテントフィルタを記述することができます。具体的な記述例は 公式ドキュメント を参照してください。
*4:createUri()メソッドはAndroid 4.0から導入されています。それ以前のAndroidバージョンにも対応したい場合は、 公式ドキュメントのコード例 を参考にして自作する必要があります。書き込みたいURLの先頭がどのようなパターンの文字列から始まるかによって、ペイロードの先頭1バイトに格納すべき値(URI Identifier Code)が変わることに注意してください。URI Identifier Codeの一覧は [5] に掲載されています。

おわりに

Android NFC APIを使って、スマートポスタータグを作成する方法を説明しました。このようにして作成されたタグを、おサイフケータイ(「ICタグ・バーコードリーダー」起動中のもの)やNFCケータイにかざすと、自動的にブラウザが起動し、タグに書き込まれているURLが表示されます。

たとえば、URLのリストをSDカードから読み込んで、タグに1つ1つ連続して書き込みたい場合など、このテクニックが使える場面は多いのではないかと思います。みなさんのニーズに沿ったタグ書き込みアプリケーションを作成するときに、このコラムがお役に立てば幸いです。

関連コンテンツ

参考URL

[1]NFC Forum. (2006, July)
 NFC Smart Poster RTD Technical Specification
 http://www.nfc-forum.org/specs/spec_list/#rtds

[2]NFC Forum. (2006, July)
 NFC Data Exchange Format (NDEF) Technical Specification.
 http://www.nfc-forum.org/specs/spec_list/#ndefts

[3]@tomorrowkey. (2012, Dec.)
 0次発行FeliCa LiteにNDEFを書き込む
 http://d.hatena.ne.jp/tomorrowkey/20121207/1354894370

[4]@hiro99ma. (2013, Mar.)
 月刊NDEF 2013年 1、2、3月号
 http://www.slideshare.net/hiro99ma/ndef-2013-010203

[5]NFC Forum. (2006, July)
 NFC URI RTD Technical Specification.
 http://www.nfc-forum.org/specs/spec_list/#rtds

[6]NFC Forum. (2011, June)
 NFC Forum Type 3 Tag Operation Specification.
 http://www.nfc-forum.org/specs/spec_list/#tagtypes


[7]ソニー株式会社 FeliCa事業部. (2010, Oct.)
 FeliCa Lite ユーザーズマニュアル
 http://www.sony.co.jp/Products/felica/business/tech-support/index.html?j-short=tech-support#Lite01

連載シリーズ
テクノロジーコラム
著者プロフィール
NTT-TX
NTT-TX