2013年7月5日金曜日

AARメッセージをゲットする

NFCの便利なところは何と言ってもタッチだけでいろんな動作をさせることができるところではないでしょうか。これの肝となるAndroidの機能が、タグディスパッチシステムというものになります。
Androidデバイスは画面がロック状態でなければ常にNFCタグを探しています。そして見つかるとすばやく中身を見てNDEFかどうか判断したりして、それからそれを必要とするアプリケーションへ通知します。この部分がタグディスパッチシステムになります。

で、どのアプリが必要としているかはアプリのマニフェストファイルに記述した内容で判断されます。
「こういうタグがきたら俺を呼んでくれ」的なことをアプリのマニフェストファイルに書いておくわけですね。

マニフェストに指定する場合、まずは大きな分類として「NDEF_DISCOVERD」、「TECH_DISCOVERD」、「TAG_DISCOVERD」の3種類の指定方法があります。タグがNDEFだった場合、まずはNDEF_DISCOVERDをくれと設定してあるアプリから検索され、見つかればそのアプリを起動します。複数あった場合は、例の選択画面が出てきます。それが無かった場合、今度はTECH_DISCOVERDをくれと設定してあるアプリを探します。それでも無い場合はTAG_DISCOVERDをくれのアプリを探します。

また、NDEF_DISCOVERDとTECH_DISCOVERDはさらに細かい設定ができます。NDEFの場合はスマートポスターがきたらとか、特定のメッセージに反応するように指定できます。TECH_DISCOVERDの方は、反応したいタグの種類(タイプAとかBとかFeliCaとか)を指定できます。

例えば、

<intent-filter>  
    <action android:name="android.nfc.action.NDEF_DISCOVERED" />
    <category android:name="android.intent.category.DEFAULT" />
    <data android:mimetype="text/plain" />
</intent-filter>

のように記述しておくと、テキストのNDEFが書かれているタグがきたら教えてくれるようになるわけですね。で、アプリ側ではonCreateあたりでgetIntentをすれば、NDEF_DISCOVERDの情報を含んだインテントがゲットできるわけです。

話は変わってNDEFなんですが、Android4.0からAAR(あんどろいど あぷりけーしょん れこーど)というのが追加されています。これはアプリケーションを一意に選択できるアプリのパッケージ名をデータとするレコードで、これがNDEFメッセージに含まれているとそのアプリケーションを起動してくれるという便利な機能です。さらには端末にそのアプリケーションがインストールされてない場合はGoogle Playの該当アプリのダウンロードページに飛ばしてくれるという至れり尽くせりの機能です。

ということでここからこれらの話がつながってくるんですが、AARを書き込んで起動してくれるようにしておいて、さらに起動時にゲットしたインテントからタグのUIDを取ろうとしたんですが、これがうまく行きませんでした。

起動してくれるんやからマニフェストの指定はいらんやろ~ということでまずは記述しなかったんですが、それだと起動時に取得できるインテントにタグ情報が含まれていませんでした。よってUIDの取得ができません。

じゃあTECH_DISCOVERDでも入れるか~ということで入れてもダメ。まあ、AARといってもNDEFですから、タグディスパッチシステムはNDEFとして認識してるはず、よっしゃもうこうなったらNDEF_DISCOVERD入れたろ~ということで入れてもダメ。
NDEF_DISCOVERDの詳細設定が必要なのか?でもAARって何?NFCフォーラムで規定されてるもんじゃないよね?アンドロイドってネーミングに入ってるし。
困ったときのNFC TagInfoということでAARを書き込んだタグを見てみると、


おー、えくすたーなる?そういえばそういうのあったな。ということでドキュメントを見ると、エクスターナルの場合は

<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="/example.com:externalType"/>
</intent-filter>

こんな風に指定せいと書いてありました。じゃあ、この「example.com:externalType」の部分を「android.com:pkg」にすればいいのかな?ということでこんな風に変更してみると。

<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="/android.com:pkg"/>
</intent-filter>

うまく行きましたー。ちゃんと1回の読み取りで、AARから起動→アプリでUIDを取得までできるようになりましたー。だから何とかやめてー。