[Flutter]NFC読み取りで遊ぶ
ぽちぽちのつどいGW Advent(?) Calendar6日目の記事です!
今日は前から気になっていたNFC読み取りをやってみます。
ios,androidそれぞれの設定方法は参考記事を読んでください。
使用パッケージ
実行環境
Galaxy Z Fold3 5G SC55B
Android 14,OneUI 6.1.1
とりあえず読み取り
とりあえず参考のコードを動かしてみたのですが動いたけどなんだかよくわからないデータが出てきたのですがとりあえずnfc_manager
で読み取りが可能であることがわかりました。
このコードの一部を借りて実装していくことにしました。
AI(GPT-4o)にも生成させたのですが精度が悪いのとFlutter_nfc_kit
を使いたがることがわかりました。
AIの出したコードでやってみたのですが、タイムアウトするだけで使い物になりませんでした。
やはりさっきのコードが良さそうとなったのでさっきのコードを使いつつAIに修正を手伝ってもらって実装しました。
発生した問題
一番多かった問題は読み取りを完了する前に読み取れていないと言う理由でエラーになってしまって強制的に読み取りが終了してしまうということです。
これのバグの対処に時間がかかりました。
結果として原因はよく話からなかったですが別の方の記事では履歴を読み取っており履歴や交通系ICの仕様について詳しく書かれているのでこれを参考に一から再生成し直しました。
ついに・・・
読み取れた!
一応おサイフケータイでも確認してみると...!!!
あれ???残高が全然違う
FelicaはISO規格(iso18092←今回知った)で全国統一されているはずなので変わることはないはず...16進数の参照箇所が違うのは明確なので探してみる。
final balanceBytes = response.sublist(13, 15);
final balance = balanceBytes[0] + (balanceBytes[1] << 8);
result.value = '残高: ¥$balance';
うーんこれ違うところを参照してね???となったので修正してみる。
GPTに投げてみると...
GPT:
Read Without Encryption コマンドで読み取った利用履歴のデータ構造は以下のようになっています(1ブロック = 16バイト):
0〜15バイト目 が1件目の履歴(1ブロック)
この中の 11バイト目と12バイト目(= インデックス[10], [11])に残高が入っていることが一般的です(ただし、カード種類による)
// 残高は1ブロック内の [10], [11] に格納(リトルエンディアン)
final blockData = response.sublist(13, 29); // 最初のブロック(16バイト)
final balance = blockData[10] + (blockData[11] << 8);
result.value = '残高: ¥$balance';
これに修正して挑戦してみる。
おおおお!!!できた!
しっかりと残高が読み取れています。
コード
おまけ
先日沖縄に行ってきた時に沖縄だけで使える交通系ICがあることを帰りの飛行機に乗る直前の路線バスの中の広告で知りました。その名もOKICAおお〜いい名前ですね😆。
結果は....
うーん何となく察してはいましたがやはり読み取ることはできませんでした。
色々調査してみると12バイトの長さしかないことが原因みたいです。今回のコードは残高に直接アクセスしているのではなく利用履歴の一番新しい部分の残高を参照していることが原因みたいです。
一回でも沖縄でゆいれーるで使っておけば...と今更後悔してます。全国共通交通系ICではないので本州では使えないです。なのでもし利用履歴があっても読み取れるとは限りません。誰か検証してくれ!
まとめ
利用履歴で読み取っているのと未検証な部分(iOS含む)が多いので正常に動作する可能性は低いです。
しかしFlutterでもNFC読み取りができること、交通系ICの読み取りができること、がわかっただけでも収穫があったと言えます。これを活用すれば色々なアプリに応用できると感じる結果となりました。
悔しかったのはOKICA読み取ることができなかったことですかね😅😅😅
このアプリでは読み取れたのでおそらく読み取り方を正しくすれば読み取れるようになりそう。
履歴が読み取れるということはいつ何駅から何駅まで移動したかもしくはいつ買い物に何円使ったかがわかるのでListViewと併用すればいい感じのアプリが作れるようになりそうですね(笑)
というわけで、ぽちぽちのつどいGW Advent(?) Calendar 6日目はNFCを使って遊んだ話でした!
参考
Discussion