LoginSignup
11
4

More than 3 years have passed since last update.

FeliCa が遅いしフルスキャンも不可能 後編【iOS 13 Core NFC】

Last updated at Posted at 2019-12-21

iOS 13 Core NFC での FeliCa に関する制限を紹介した前編、今回はそれの続きです。

iOS での FeliCa の制限

  • FeliCa の読み取りで得られる最初の currentSystemCode は Info.plist での FeliCa システムコードの記述する順番に依存する → 前編で紹介
  • FeliCa の読み取り速度は Info.plist での FeliCa システムコードの記述する順番に依存する → 前編で紹介
  • FeliCa のフルスキャンを iOS で行いたい場合、「じゃあ Info.plist に存在する全ての FeliCa システムコードを記載すればいいのでは…?」と考えつくが、それは現実的な解決策ではない

対応する FeliCa システムコードを増やすと最悪どれくらい遅くなるのか

前編では

iOS 13 の Core NFC の場合は検出された FeliCa カードにあるシステムのうち、Info.plist に記載され 最も順番が前にある FeliCa システムコードに一致するシステム が検出、currentSystemCode および currentIDm にはそれが入ることになります。

そのため、多数の FeliCa システムコードに対応しようとした場合、Info.plist に記載する順番が非常に重要になります。

と記事の最後に述べました。では具体的にどれくらい速度に変化があるのでしょうか。実際に測定してみます。

ここでの "読み取り速度" の定義

そもそも FeliCa は NFC の中で読み取り速度がめちゃ速いです。NFC-B の運転免許証の読み取りに比べても速度が段違いです。

しかし、iOS での Core NFC で私が述べたい "速度" はこのことではありません。

事例紹介をスキップして早く本題に行きたい方はこちらからジャンプ

各 App での読み取り時間に関する表示

iOS 13 のリリース以降、多くの電子マネーカードリーダー系の App が登場しましたが、各 App のスキャン画面等にこんな記載がありませんか?

Japan NFC Reader ICリーダー CardPort
IMG_6487.jpg IMG_6486.jpg IMG_6485.jpg
読み取りに時間がかかる場合があります。 読み込みまで少し時間がかかることがあります。 読み取りには時間がかかることがあります。

(個人的)ド定番 iOS カードリーダー 御三家のどれもに 読み取りに時間がかかる という記載があります。
本記事を読んでいただくと、なぜわざわざこのように表示しているのかがわかり、また文脈としては ICリーダー さんの 読み込みまで少し時間がかかることがある が最も正しい表現であることがわかると思います。

Japan NFC Reader の場合、このあと次のような表示になります。

読み取り中…
…ここで思うことはありませんか?別に「読み取り中…」の文言が表示されるなら、読み取り開始前の画面にわざわざ「読み取りに時間がかかる」ことを表示しなくてもいいんじゃないでしょうか。これは各 App 開発者の親切心で……?

……(少なからず親切心もあるでしょうが)それは違います。

コードを見てみる

ここで少しコードを見てみることにしましょう。

var session: NFCTagReaderSession?

// …

func scan() {
    // …
    self.session = NFCTagReaderSession(pollingOption: .iso18092, delegate: self)
    self.session?.alertMessage = "カードの上に iPhone の上部を載せてください。読み取りまでに時間がかかることがあります。"
    self.session?.begin()
}

// …

func tagReaderSession(_ session: NFCTagReaderSession, didDetect tags: [NFCTag]) {
    let tag = tags.first!
    session.connect(to: tag) { (error) in
        // …
        session.alertMessage = "カードを読み取っています…"
        // …
    }
}

App がカードのスキャンを行えるようになった後に表示されるメッセージは、scan() の中にある session.alertMessage です。そして、実際にカードを検出し、プログラム側にその情報がやってくるのが tagReaderSession(_:didDetect:) の中の session.alertMessage です。

ここで大きな問題になるのが、FeliCa カードに iPhone を載せてから tagReaderSession(_:didDetect:) が呼ばれるまでに、ものすごく時間がかかる場合があるということです。その条件が 検出された FeliCa カードに存在するシステムが、Info.plist に記載されている FeliCa システムコードの順番の後ろの方にあるとき です。

ここでの読み取り速度とは、tagReaderSession(_:didDetect:) が呼ばれるまでの時間のことを示します。

検証 ~ FeliCa システムコードを増やすとどれだけ遅くなるか ~

今回は以下のコードを使って、Dateの差がどれだけ増えるかを見ていきます。

func scan() {
    // …
    self.session = NFCTagReaderSession(pollingOption: .iso18092, delegate: self)
    self.session?.alertMessage = "カードの上に iPhone の上部を載せてください。読み取りまでに時間がかかることがあります。"
    self.session?.begin()
}

func tagReaderSessionDidBecomeActive(_ session: NFCTagReaderSession) {
    self.start = Date()
    print("tagReaderSessionDidBecomeActive(_:)")
}

func tagReaderSession(_ session: NFCTagReaderSession, didDetect tags: [NFCTag]) {
    let elapsedTime = Date().timeIntervalSince(self.start)
    print("elapsed time:", elapsedTime)
    // …
    session.alertMessage = "完了"
    session.invalidate()
}

対象とするカード、今回は楽天Edyを用います。このようにカードを iPhone の NFC 読み取り部をピッタリと置いた状態で Scan ボタンをタップします。

tagReaderSession(_:didDetect:)print でコンソールに出力される elapsed time の値がどれだけ変化するか測定します。

楽天Edy カードが持っている FeliCa システムコードは 0x8B610xFE00 です。Info.plist に記述する 0xFE00 の順番を段々と後ろにしていきます。
スクリーンショット 2019-12-22 2.14.49.png
スクリーンショット 2019-12-22 2.38.40.png

結果


このグラフのもとになった表はページ下部に記載しました。
FeliCa システムコードの順番が1つ後ろにずれると約0.3秒、tagReaderSession(_:didDetect:) が呼ばれるまでの時間が延びることがわかりました。

また、NFCReaderSession には時間制限があるのですが、その45秒となる Item 148 = 149 個目よりも FeliCa システムコードを多くしてしまうと、そもそも tagReaderSession(_:didDetect:) が呼ばれないことがわかりました。

各カードが持っている FeliCa システムコードはそれぞれ異なる場合があるので、1つの App で多数のカードに対応させようとすると、それだけ Info.plist に記載しなければならない FeliCa システムコードの数も増え、順番によってカードが検出されるまでの時間が左右されるのは使う側としてとても不便です。
また、tagReaderSession(_:didDetect:) が呼ばれないとプログラム側からもカードが iPhone に載せられているのかすら分からないため、各 App では「読み込みまで時間がかかる」という記載がスキャン前の段階で表示されることにつながっています。

Info.plist に 存在する全ての FeliCa システムコードを記載するのは現実的な解決策ではない

もし、iOS で FeliCa のフルスキャンを行おうとしたときに、0x0001 から 0xFEFE までの全ての FeliCa システムコードをInfo.plist に載せれば…?と思いつきますが、そもそも検出のみで149個が限界なので、それはいい方法とは言えないという結論になりました。

そもそもなぜ iOS (Apple) は検出にこれほど時間をかけるのでしょうか。
「ショートカット」のオートメーションに「NFC タグ」が使えますが、これは Apple 製ということもあってか FeliCa も即検出、登録することができています。確実にサードパーティのみを締め出しているということになりますが……。FeliCa システムの IDm による切り替えができないのと合わせて、理由がわかりません。

iOS 14…ではさらなる Core NFC の機能開放を希望します…。

結果(表)

"Item x" の列は 0 は 0xFE00 を Item 0 に記述した場合、1 は Item 1 に記述した場合…というような感じです。Item 7 = 8個目で2秒を超え始めています。実用ではもっと早く検出されたほうがいいですよね。

Item x 1 2 3 Ave.
0 0.046976 0.045720 0.045037 0.045911
1 0.349753 0.346604 0.345791 0.347383
2 0.647677 0.649241 0.646586 0.647835
3 0.947898 0.950009 0.952775 0.950227
4 1.250441 1.250477 1.250740 1.250553
5 1.550706 1.551337 1.552101 1.551381
6 1.854309 1.857909 1.855477 1.855898
7 2.156484 2.155968 2.155585 2.156012
8 2.459123 2.457329 2.458836 2.458429
9 2.759697 2.762735 2.758815 2.760416
10 3.058142 3.060277 3.059271 3.059230
15 4.566140 4.568311 4.569674 4.568042
20 6.072544 6.079473 6.078423 6.076813
25 7.583499 7.585000 7.584232 7.584244
30 9.094974 9.094320 9.096275 9.095190
40 12.111050 12.109540 12.105498 12.108696
50 15.123403 15.119864 15.120571 15.121279
100 30.202593 30.200774 30.201501 30.201623
101 30.512402 30.505607 30.501605 30.506538
102 30.811206 30.814952 30.807862 30.811340
103 31.109441 31.106589 31.107631 31.107887
140 42.270938 42.267985 42.274794 42.271239
145 43.787478 43.777525 43.775778 43.780260
148 44.683454 44.679594 44.683043 44.682030
149 NaN
150 NaN
11
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
4