本記事は、Android 4.4 KitKat 冬コミ原稿リレーというちょっと気の早いアドベントカレンダー的なものの11/8担当分となります。
Android 4.4にて導入された Host card emulation (以下、HCE)を試したいけど、まず何をすれば良いのかわからないという方向けの導入編となります。
本記事よりも少し踏み込んだ話については、TechBooster様から冬コミに発行されるAndroid 4.4本に寄稿する予定です。
そもそもホストカードエミュレーションとはなにものか?
これまでも、(交通系カードや電子マネーカードなどのように)Android端末が非接触ICカードとして振る舞うことができていましたが、Androidアプリとして独自のカード機能を追加するようなことができませんでした。
Android 4.4 (API Level 19)からは、Androidアプリとして非接触ICカードのふりをするアプリを作成することが可能になりました。NFC規格に含まれる通信方式のうちType A/Bに対応し、通信コマンドはISO 7816-4に規定されたAPDUコマンドを用います。
カードをエミュレートするAndroidアプリがあると何がうれしいのか?
たとえば、以下のような利用方法が考えられます。
- ICカードアプリ開発のプロトタイピング
- ICカードを利用した既存システムと、Andorid端末の連携システムの開発
高機能なデバッガを利用できる環境でカードアプリのプロトタイピングができるというのは、システム構築の一部としてカスタマイズしたICカードを開発されている現場では役立つのではないでしょうか。
また、HCEはISO7816-4という標準仕様ベースですので、その標準を用いた既存システムとAndroid端末の連携に利用するということも考えられます。
出来るとしても気軽に手を出してはいけないものはなにか?
この機能を用いて電子マネーシステムを新たに作ろうとするのは高いリスクを伴います。
既存の電子マネーは、Secure Element (以下、SE)と呼ばれる耐タンパ性の非常に高いチップによって、決済に必要となる情報の保護や暗号化の処理を行っています。これと同等レベルのことをソフトウェアで実現することは不可能です。ソフトウェア耐タンパ技術といったものもありますが、ハードウェアによる保護よりも破られるリスクは非常に高いものです。 ((そのリスクを負ってでもチャレンジしようとされる会社さんは出てくると思いますが。))
HCE (API Level 19)でやりやすいこと
いろいろありますが、「Type 4のNFC Forum Tag のエミュレーション」は比較的簡単にできることの一つです。
NFC Forum TagのType 4というのは、ISO7816-4をベースにしていますし、タッチすれば誰でも読めるタグということでセキュリティがかかっていないためです。
HCE (API Level 19)でできないこと
「Felicaを利用したカードのエミュレーション」はできません。FelicaはISO7816-4とは異なるコマンド体系を持っているためです。特に日本ではFelicaベースのシステムが普及しているため、残念な仕様かもしれませんが諦めてください。 ((最近の非接触ICカードR/WはTypeA/B/Felica全対応のものも多いのでハードウェアは使いまわせる場合が多いでしょう。))
NFC HCEアプリ開発のハマリポイント
実は、GoogleのHCEドキュメントですが、間違いがあります(11/8現在)。この通りに実装してもHCEは動作しません。
HCEはサービスとして実装しインストールします。AndroidMannifest.xmlに適切に宣言することで、AndroidシステムがそのHCEサービスを起動してくれます。 ((正しく実装されていれば、インストール後すぐにサービスが起動します。))
しかし、前述のドキュメントには以下のようなマニフェスト断片が提示されていますが、抜けがあるため、システムによるサービスの起動が行われません。自分でサービスを起動しても権限が適切ではないため動作しません。
<service android:name=".MyHostApduService" android:exported="true"
android:permission="android.permission.BIND_NFC_SERVICE">
<intent-filter>
<action android:name="android.nfc.cardemulation.action.HOST_APDU_SERVICE"/>
</intent-filter>
<meta-data android:name="android.nfc.cardemulation.host_apdu_service"
android:resource="@xml/apduservice"/>
</service>
何が間違っているかというと、intent-filter にてカテゴリが宣言されていないためです。以下のようにカテゴリを追加してください。
<service android:name=".MyHostApduService" android:exported="true"
android:permission="android.permission.BIND_NFC_SERVICE">
<intent-filter>
<action android:name="android.nfc.cardemulation.action.HOST_APDU_SERVICE"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<meta-data android:name="android.nfc.cardemulation.host_apdu_service"
android:resource="@xml/apduservice"/>
</service>
また、NFCを利用するため、以下のpermission宣言も必要です。忘れないようにしましょう。
<uses-permission android:name="android.permission.NFC" />
カードアプリを書くために必要な情報
さて、これでカードのふりをするサービスを起動するところまでは出来ました。ではここからどうやってカードアプリを書けばいいでしょうか?
カードアプリには、必ず対向するシステム(たとえばNFCタグリーダ、クーポン読み取り機など)があります。そのシステムが求める機能を実現してください。
え? それでは不親切すぎる? ではとりあえず何か試してみたいということであれば、Type 4 の NFC Forum Tag を試しに実装してみてはいかがでしょうか。仕様書はNFC Forumから入手可能です。 ((弊社でも現在お試し実装にチャレンジ中です。))
Type 4のNFC Forum Tagの仕様書だけあれば、ISO7816-4のAPDUの詳しい知識が無くても実装できます。
暗号化や認証の機能もカードアプリとそれを用いるシステムにて行いたいのであれば、ISOから7816の仕様書(もしくはそれに対応したJIS規格書)を購入する必要が出てくるでしょう。 ICカードに関するISOとJISの対応関係は、こちらのサイトが詳しいです。
実際にお試しいただく際にあると良いもの
- NFC HCEに対応したAndroid 4.4端末
- 非接触ICカードR/W側となるAndroid 4.4端末
1は11/8時点ではNexus5しか存在しないかもしれません。2はGalaxy NexusにAOSPのAndroid 4.4をビルドして焼いたGalaxy NexusでOKでした。
自分でビルドしても当然良いのですが、@androidsola さんがビルドしたイメージを以下のページにて公開していらっしゃいますので、そちらを利用させていただくのも良いでしょう。
なお、Galaxy Nexus + 前述のAOSP版4.4 ROMイメージでは、Host card emulation非対応のようです。 ((対応端末では、NFCをONにしていれば、設定画面の「アプリ」の下に「タップ&ペイ」というメニュー項目が表示されるのですが、それが表示されませんでした。))
もう一つのハマリポイント、カードリーダによる動作確認
Android端末は古いものでも、NFC対応であればNFC Forum Tagを読み取れるはずと思った方もいるでしょう。NFC Forumタグを実現したHCEアプリを確認するのに、なぜ4.4端末をもう一台用意しないといけないのかと。
実は、NFC Forum Tag を実現したHCEアプリを、API Level 18以下のNFC対応端末に近づけた場合、せっかく作ったHCEアプリが呼び出されません。
なぜそんなことになるかというと、NFCをオンにしたAndroid端末同士を近づけると、まずNFCで規定されたLLCPというプロトコルで接続をしてしまうのです。LLCPが先に解決されてしまい、TypeA/BによるNFC Forum TagのHCEアプリにまで辿り着かないのです。
これを回避するためには、API Level 19にて NfcAdapterに追加されたAPIを用いて、R/W側の端末アプリを作らなければなりません。このことはNfcAdapterのenableReaderMode()メソッドのリファレンスにも以下のように記載されています。
For interacting with tags that are emulated on another Android device using Android’s host-based card-emulation, the recommended flags are FLAG_READER_NFC_A and FLAG_READER_SKIP_NDEF_CHECK.
enableReaderMode()はAPI Level 19からしか使えませんので、どうしてももう一台Android 4.4端末が必要となるのです。
以下に、NFC Forum Tagを確認するR/Wアプリを作るために役立つコード断片を記しておきます。参考にしてください。
public class MainActivity extends Activity {
....
private NfcAdapter mNfcAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
......
mNfcAdapter = NfcAdapter.getDefaultAdapter(getApplicationContext());
}
@Override
protected void onResume() {
super.onResume();
mNfcAdapter.setNdefPushMessage(null, this);
mNfcAdapter.enableReaderMode(this, new NfcAdapter.ReaderCallback() {
@Override
public void onTagDiscovered(Tag tag) {
// TODO: ここに受け取ったタグに対しての処理を記載する
}
}, NfcAdapter.FLAG_READER_NFC_A, null);
// NDEFタグ (NFC Forum Tag)を対象にしているので、ここでは enableReaderMode()に
// 記載されたフラグ FLAG_READER_SKIP_NDEF_CHECK は使わないで、システムに
// NDEFタグのスキャンを任せる。
}
@Override
protected void onPause() {
super.onPause();
mNfcAdapter.disableReaderMode(this);
}
最後に
本記事の情報を用いることで、ホストカードエミュレーションを試す入り口までたどり着くことはできるのではないかと思いますが、実際にそれを用いてアプリを実装するにはICカード(特にISO7816系コマンド)の知識を必要とします。
また、NFC Forum Tagカードのような静的なものを除けば、カードアプリだけを作ることには意味がありません。システムと連携することが非常に重要です。非接触ICカードの特徴の一つは、近接距離、すなわちタッチ動作をユーザの意思表示として利用するというところにあります。この性質によってユーザ体験(UX)を改善できるシステムでなければ、Bluetoothなどの他の通信を利用したシステム構築も選択肢とすべきです。
と、少しハードルを上げてしまいましたが、何はともあれどんな技術についても言えることですが、まずは触れてみましょう。その上で、自分が作りたいものに向いているのかいないのかを考えましょう。
触れてみて理解してから導入可否を検討するのは大変だ? その場合、弊社にて相談に乗れるかもしれませんのでお気軽にご連絡ださい(とさりげなく宣伝)。