NFCチップ搭載のPVCカードを買った

Amazonを見ていたらamiibo(アミーボ)等で使われている NFCチップ搭載の硬質塩化ビニールカード(PVCカード) が100円以下で手に入るようだったので、試しに買ってみた。

f:id:misyobun:20180506131458j:plainf:id:misyobun:20180426002804j:plain
NFCチップ搭載のPVCカード

ちなみにNFCは、13.56 MHzの周波数を利用する通信距離10cm程度の近距離無線通信技術 Near Field Communication の略称だ。

NFCには幾つか種類(規格)が存在していて、日本だとお財布携帯などで使われているFeliCa(フェリカ) type-Fが有名だろう。 ちなみに今回購入したチップはamiibo(アミーボ)やTaspoで使われている type-Aという規格のものだ。

f:id:misyobun:20180506131604j:plain

AndroidにはNFCによる特定の無線通信を認識するとIntentをシステム内に発送する仕組みがあるので、各アプリでそのIntentを検出できるようにManifestファイルを設定することにより、NFCのタッチアクションをトリガーにActivityやServiceといった各種コンポーネントを起動することができる。

NFC関連のIntentアクションには、NFCチップのレコード(NDEFレコード)内に書き込まれたデータ(例:URI URL)や特定の規格(Type-A Type-B Type-F)に対応するといった合致アクションがあり、そういった条件をManifestファイル内の<intent-filter>で絞り込むことによって起動コンポーネント(特定のアプリの特定のActivity/Service etc)を可能な限り一意に絞り込むことが可能だ。

NDEFレコードにURIスキーマがある場合に起動 android.nfc.action.NDEF_DISCOVERED

<intent-filter>
   <category android:name="android.intent.category.DEFAULT"/>
   <action android:name="android.nfc.action.NDEF_DISCOVERED" />
   <data android:scheme="○○○○" android:host="XXX" />
</intent-filter>

XMLに指定した企画のNFCチップとの通信だったら起動 android.nfc.action.TECH_DISCOVERED

<intent-filter>
   <category android:name="android.intent.category.DEFAULT" />
   <action android:name="android.nfc.action.TECH_DISCOVERED" />
   </intent-filter>
      <meta-data
         android:name="android.nfc.action.TECH_DISCOVERED"
         android:resource="@xml/nfc_tech" />

規格リスト

<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
    <tech-list>
        <tech>android.nfc.tech.NfcA</tech>
    </tech-list>
 </resources>

起動時Intentの情報を確認

試しに<intent-filter>によって絞り込まれてIntentを受け取るコンポーネントでNFCチップの個体識別番号を取得してみる

class NFCActivity: AppCompatActivity() {
    private val HEX_CHARS = "0123456789ABCDEF".toCharArray()
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        val intent = getIntent()
        val action = intent.action
        if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action) || NfcAdapter.ACTION_TECH_DISCOVERED.equals(action)) {
            val idm = getIdm(intent)
            Log.i("TAG","個体識別番号 ${idm}")
        }
    }

    private fun getIdm(intent : Intent): String {
        val idmBuffer = StringBuffer()
        val rawIdm:ByteArray = intent.getByteArrayExtra(NfcAdapter.EXTRA_ID)

        rawIdm.forEach {
            val octet = it.toInt()
            val firstIndex = (octet and 0xF0).ushr(4)
            val secondIndex = octet and 0x0F
            idmBuffer.append(HEX_CHARS[firstIndex])
            idmBuffer.append(HEX_CHARS[secondIndex])
        }

        return idmBuffer.toString()
    }
}

いまのところNFCは何かのアクションのトリガー要素でしかユースケースが想像できないが、そこら辺を軸に何か面白げなアイディアを考えたい。