Android 4.0のAndroidビームは、CreateNdefMessageCallbackを実装して送信します。
@Override public NdefMessage createNdefMessage(NfcEvent event) { Log.d(TAG, "createNdefMessage"); NdefMessage msg = null; int checkedId = mRadioGroup.getCheckedRadioButtonId(); if (checkedId == R.id.radio0) { Time time = new Time(); time.setToNow(); String text = ("Beam me up!\n\n" + "Beam Time: " + time.format("%H:%M:%S")); msg = new NdefMessage(NdefRecord.createMime( "application/com.example.android.beam", text.getBytes()) //,NdefRecord.createApplicationRecord("com.example.android.beam") ); } else if (checkedId == R.id.radio1) { msg = new NdefMessage( NdefRecord.createUri("http://www.atmarkit.co.jp/")); } return msg; }
どのラジオボタンが選択されているかで、送信するメッセージの生成を作り分けています。何も送信しない場合は、このメソッドはnullを返します。
ラジオボタンで「Text message」が選択されている際に送信するメッセージ生成で、コメントアウトされている行があります。NdefMessageのコンストラクタは、1つ以上のNdefRecordを引数に取ります。
11〜13行目では、「Android Application Record」(以下、AAR)をコンストラクタに渡すのを省略しています。AARを省略する場合、前述したAndroidManifest.xmlにIntentFilterが必要で、AARを渡す場合、指定したアプリケーションにのみメッセージが送信されるため、IntentFilterが必要なくなります。
URLを送信する場合、Webブラウザやそれに準じるアプリが起動されることを期待して、AARは付与しない方がユーザーは使いやすいでしょう。
Android 4.1のAndroidビームは、CreateBeamUrisCallbackを実装して送信します。
@Override public Uri[] createBeamUris(NfcEvent event) { Log.d(TAG, "createBeamUris"); Uri[] uri = null; if (mRadioGroup.getCheckedRadioButtonId() == R.id.radio2) { uri = new Uri[] { Uri.fromFile(mPng) }; } return uri; }
ラジオボタンで「PNG file」が選択されている場合にのみ、Uriのリストを返します。複数のコンテンツを一気に送る場合に便利なインターフェイスになっています。送信するものがない場合、nullを返します。
メッセージ送信が完了したことを通知するコールバックを実装します。
@Override public void onNdefPushComplete(NfcEvent arg0) { Log.d(TAG, "onNdefPushComplete"); mHandler.obtainMessage(MESSAGE_SENT).sendToTarget(); }
上記実装は、Handler経由でToastを表示しています。このコールバックが呼び出されたら、端末を離しても大丈夫です。Android 4.1のAndroidビームの場合、Bluetooth通信が開始しています。
今回のサンプルでは、ラジオボタンでどのようなデータを送信するかを選択し、データによって2つのAndroidビームのどちらを使用するかを決めています。
@Override public void onCheckedChanged(RadioGroup group, int checkedId) { if (checkedId == R.id.radio0 || checkedId == R.id.radio1) { mNfcAdapter.setBeamPushUrisCallback(null, this); mNfcAdapter.setNdefPushMessageCallback(this, this); } else { mNfcAdapter.setNdefPushMessageCallback(null, this); mNfcAdapter.setBeamPushUrisCallback(this, this); } }
上記はRadioGroupのリスナの定義です。
テキストメッセージとURLアドレスの場合は、NfcAdapter#setNdefPushMessageCallback()を有効にし、NfcAdapter#setBeamPushMessageCallback()を無効にしています。
PNGファイルの場合はその逆で、NfcAdapter#setBeamPushMessageCallback()を有効にし、NfcAdapter#setNdefPushMessageCallback()を無効にしています。このようにすることで、2つのAndroidビームを排他的に使用しつつ共存させることが可能です。
どのようなデータをどちらのAndroidビームで送信するかの判断材料の大きな要素は、送信するデータのサイズです。「テキストメッセージだから、Android 4.0のAndroidビームで送る」という判断ではなく、テキストメッセージのサイズで判断した方が賢明です。NFCの通信は最大424kbpsですが、体感では想像以上に遅いです。
NFCはAndroid 2.3(API Level 9)から利用可能で、Android 2.3.3(API Level 10)からフォアグラウンドNDEFメッセージプッシュが利用可能です。
これはAndroidビームと似た仕組みなのですが、Androidビームと異なりOSレベルでNDEFメッセージをハンドリングせず、アプリが協調してメッセージの取得優先順位を制御しなければならず、実際には協調することはできないため、使い勝手があまり良くない仕組みでした。
Androidビームは、このNDEFプッシュを置き換える新しい仕組みで、現在ではNDEFプッシュは非推奨になっています。ただし、古い機種との互換性を維持するために使うことは可能です。詳細は、NfcAdapter#enableForegroundNdefPush()とNfcAdapter#disableForegroundNdefPush()を参照してください。
Androidビームの魅力は、複雑な手続きなしで相手にデータを送信可能な点です。端末の背面を合わせることで「タッチしてビーム」という画面が表示され、その画面ではタッチ以外の操作ができないのもシンプルさの表れです。
シンプルさを追究しているAndroidビームですが、シンプルさ故の弊害もあります。背中合わせにした端末がどちらもアプリを起動していた場合、先にタッチしてビームした方のデータが送信されます。1度で双方向にデータを送り合うことはできないので、名刺交換のようなユースケースでは、再度背中合わせにして、もう一方から送信しなければなりません。
筆者は「Samsung Galaxy Nexus」「ASUS Nexus 7」で本記事の検証を行ったのですが、この際困ったのは、NFCが背面のどこにあるのか分からず、なかなかAndroidビームが起動しないことでした。どちらの端末にも背面にNFCの位置が刻印されていないためです。
特に、Nexus 7は大きいので、1cmずつずらして位置を探さなければならず、しかも早く動かし過ぎると通信に失敗するため、せっかくのシンプルな仕組みが刻印がないことで台無しになってしまっています。
国内のメーカーは、「おさいふケータイ」の経験があるので、実装されていればFeliCaのマークは付いていることがほとんどだと思います。
ただ、国内に限ってFaliCaはあってもNFCがない端末が多く見受けられます。Androidビームで目の前の友人とURLを共有しようとして、NFCの位置を探し回った挙句、実は友人の端末はNFCをサポートしていないことが分かった、というシチュエーションは残念過ぎます。メーカーには、背面にNFCの位置を示す刻印を付けるように努力してほしいところです。
従来のフィーチャーフォンの赤外線通信によるデータ交換のような普及はもう少しかかりそうだと感じました。
Copyright © ITmedia, Inc. All Rights Reserved.