🌈

Chrome 89で正式サポートしたWebNFCを試す

2021/06/13に公開

2021/03/02にChrome89がリリースされました。47件のバグフィックスがされた上で、「WebHID」「WebNFC」「Web Serial」などの機能が実装されました。今回は、WebNFCを試してみます。

WebNFCについて

まず、NFCはNear Field Communicationsの略であり、ICチップを用いて約10cm未満の距離でデバイス間の通信が出来ます。NFCは、ユニクロのタグで有名なRFID(Radio Frequency IDentification)と同じ個体認識技術の一種です。

WebNFCは、Chrome 81 betaで実験的に実装されたJavaScriptでNFCタグにデータを書き込んだり読み取ったりすることが出来るAPIです。対応しているのは、NFC搭載のAndroid Chromeのみです(2021年6月)。

必要なもの

最初は、ローカルサーバで試そうとしたのですが、ReferenceError: NDEFReader is not defined

というエラーがでます。MDN Web Docsを確認するとWebNFCは、サポートしているブラウザで、セキュアコンテキスト(HTTPS)でのみ使うことができるようです。

https://developer.mozilla.org/en-US/docs/Web/API/NDEFRecord

そうなのか〜と思い、試しにGitHub Pagesにホスティングしてみると正常に動くことを確認しました。しかし、いちいちgit pushして挙動を確認するのはすごく面倒なことで疲れてしまいます。
そこで今回は、Glitchというサービスを使ってコードを書いていきます。Glitchは、web上のエディタで爆速コーディングが可能でスマホでの確認もしやすいと思います。

Glitchで新規プロジェクトの作成

アカウントは取得済みとします。右上の"New Project"からプロジェクトの作成をします。Starter appsとしていくつかのサンプルがあるのでここでは、"glitch-hello-website"を選択します。

しばらくするとエディタが表示されて雛形が出来上がっています。すごい。

左上の"share"からURLの取得が出来ます。これをスマホに流して表示すれば実機で確認が出来ます。

Androidでデバッグする準備

コードを書く時、console.log()デバッグをすることがあります。しかし、スマホ単体では確認することが出来ません。そこでChromeのリモートデバッグを使います。PCとスマホをUSBケーブルで接続してデバッグが出来ます。Macの場合、ドライバ等が必要だと思っていましたが特に何もしていない状態でも使うことが出来ました。

作業内容は以下のサイトで紹介されています。USBデバッグを有効にしてchrome://inspect#devicesに移動すると端末が認識されます。

https://developer.chrome.com/docs/devtools/remote-debugging/

問題がなければ以下のように表示されます。

"inspect"を押すとdevtoolが表示されます。端末の画面をPCで確認することが出来ます。

conosleにてデバッグができるようになりました。便利機能ですね。PCから操作することも出来ます。これで準備は整いました。

Write

NFCタグにはデータが書き込まれていない状態なので最初にデータを書き込む処理を作ります。HTMLでボタンとログを表示する部分を作り、以下のようなコードを書きます。ユーザが入力した値をタグに書き込むようにしました。

script.js
let inputText = document.getElementById("writeText");
const writeButton = document.getElementById("writeButton");
const writeLog = document.getElementById("writeLog");

writeButton.addEventListener("click", async () => {
  console.log("write button clicked");
  writeLog.textContent = await "please touch the NFC tag!";
  try {
    let writeText = inputText.value
    console.log(writeText)
    if (!writeText) {
      writeLog.textContent = "empty";
      return;
    }
    const reader = new NDEFReader();
    await reader.write(writeText);
    writeLog.textContent = `write: ${writeText}`;
  } catch (error) {
    writeLog.textContent = error;
    console.log(error);
  }
});

write()メソッドで、テキストの書き込みをしています。今回は、テキストですが、JSON等の他のデータの場合はエンコードをする必要があります。画像の書き込みも可能ですが、NFCタグは保存できる容量が500バイトと小さく、SNSでやり取りしているような画像サイズ(数MB)は書き込みが出来ません。

Read

書き込んだデータを読み取ってみます。scan()メソッドでデータを取得しています。NFCタグをタッチする毎にイベントが発火しています。

script.js
const readButton = document.getElementById("readButton");
const readLog = document.getElementById("readLog");

readButton.addEventListener("click", async () => {
  readLog.textContent = await "clicked read button";
  try {
    const reader = new NDEFReader();
    await reader.scan();
    readLog.textContent = "scan started";

    reader.addEventListener("error", () => {
      console.log("Error");
    });

    reader.addEventListener("reading", ({ message, serialNumber }) => {
      console.log(`> Serial Number: ${serialNumber}`);
      console.log(message);
      const record = message.records[0];
      const { data, encoding, recordType } = record;
      if (recordType === "text") {
        const textDecoder = new TextDecoder(encoding);
        const text = textDecoder.decode(data);
        readLog.textContent = text;
      }
    });
  } catch (error) {
    readLog.textContent = error;
  }
});

最初にscanするときにNFCを許可する確認ダイアログが表示するようです。また、スキャン、書き込み時はヴァイブレーションによる感覚でタッチを示します。

取得するNDEFデータは以下のようにconsoleで確認することができます。データの内容はmessage.recordsで取得できます。

GitHub Pagesで動作確認

GitHubにソースコードをpushして動作の確認をします。任意のリポジトリを作成し、Glitch上で作成したコードをpushします。

私のリポジトリはこちら

https://github.com/ktpi2000/webnfc-playground

注意点としては、jsとcssの指定は絶対パスになります。

以下が動作確認ができるページです。

https://ktpi2000.github.io/webnfc-playground/

テキスト入力に好きな文字を入れてデータをwrite/readできることを確認しました。

最後に

簡単なコードでWebNFCに触れてみました。NFCは、SuicaやPasmo等交通系ICカードのイメージが強いですが、最近だとマイナンバーカードとスマホで確定申告をするのに使われたりしています。WebNFCでは、Suica等で使われるNFCフォーマットが未サポートなので今後の対応に期待です。

参考

https://github.com/googlechrome/samples/tree/gh-pages/web-nfc

Discussion