Chrome for Android で NFC デバイスを操作する

NFC タグの読み取りと書き込みが可能になりました。

François Beaufort
François Beaufort

Web NFC とは

NFC は Near Field Communications(近距離無線通信)の略称です。13.56 MHz で動作する短距離無線技術で、10 cm 未満の距離でデバイス間の通信を可能にし、最大 424 kbit/s の伝送速度を実現します。

Web NFC を使用すると、サイトはユーザーのデバイスの近く(通常は 5 ~ 10 cm、2 ~ 4 インチ)にある NFC タグの読み取りと書き込みを行うことができます。現在のスコープは、さまざまなタグ形式で動作する軽量バイナリ メッセージ形式である NFC データ交換フォーマット(NDEF)に限定されています。

NFC タグに電力を供給してデータを交換するスマートフォン
NFC 動作の図

おすすめのユースケース

Web NFC が NDEF に限定されているのは、NDEF データの読み取りと書き込みのセキュリティ プロパティをより簡単に定量化できるためです。低レベルの I/O オペレーション(ISO-DEP、NFC-A/B、NFC-F など)、ピアツーピア通信モード、ホストベースのカード エミュレーション(HCE)はサポートされていません。

Web NFC を使用する可能性のあるサイトの例:

  • 美術館や美術館では、ユーザーがデバイスを展示物の近くにある NFC カードにタッチすると、展示に関する追加情報を表示できます。
  • 在庫管理サイトは、コンテナの NFC タグからデータを読み取ったり、データを書き込んだりして、コンテナの内容に関する情報を更新できます。
  • 会議の主催者は、イベント中に NFC バッジをスキャンして、バッジに書き込まれた情報がロックされ、それ以降の変更が防止されていることを確認できます。
  • サイトは、デバイスやサービスのプロビジョニング シナリオに必要な初期シークレットの共有や、運用モードでの構成データのデプロイに使用できます。
複数の NFC タグをスキャンしているスマートフォン
NFC インベントリ管理の図

現在のステータス

ステップ ステータス
1. 説明を作成する 完了
2. 仕様の最初のドラフトを作成する 完了
3. フィードバックを収集してデザインを反復 完了
4. オリジン トライアル 完了
5. リリース 完了

Web NFC を使用する

特徴検出

ハードウェアの機能検出は、おそらくこれまで使用してきたものとは異なります。NDEFReader が存在する場合、ブラウザが Web NFC をサポートしていることはわかりますが、必要なハードウェアが存在するかどうかはわかりません。特に、ハードウェアがない場合、特定の呼び出しによって返される Promise は拒否されます。NDEFReader の説明で詳細を説明します。

if ('NDEFReader' in window) { /* Scan and write NFC tags */ }

用語

NFC タグはパッシブ NFC デバイスです。つまり、アクティブ NFC デバイス(スマートフォンなど)が近くにあるときに磁気誘導によって電力が供給されます。NFC タグには、ステッカー、クレジット カード、腕輪など、さまざまな形状があります。

透明な NFC タグの写真
透明な NFC タグ

NDEFReader オブジェクトは、Web NFC のエントリ ポイントです。NDEF タグが近づいたときに実行される読み取り/書き込みアクションを準備するための機能を公開します。NDEFReaderNDEF は、NFC フォーラムによって標準化された軽量のバイナリ メッセージ形式である NFC データ交換フォーマットを表します。

NDEFReader オブジェクトは、NFC タグから受信した NDEF メッセージを処理し、範囲内の NFC タグに NDEF メッセージを書き込むためのものです。

NDEF をサポートする NFC タグは付箋のようなものです。誰でも読み取ることができ、読み取り専用でない限り、誰でも書き込むことができます。これには、1 つ以上の NDEF レコードをカプセル化する単一の NDEF メッセージが含まれます。各 NDEF レコードは、データ ペイロードと関連する型情報を含むバイナリ構造です。Web NFC は、NFC フォーラムの標準化された次のレコード タイプをサポートしています。empty、text、URL、smart poster、MIME type、absolute URL、external type、unknown、local type。

NDEF メッセージの図
NDEF メッセージの図

NFC タグをスキャンする

NFC タグをスキャンするには、まず新しい NDEFReader オブジェクトをインスタンス化します。scan() を呼び出すと、Promise が返されます。以前にアクセス権が付与されていない場合は、ユーザーに確認メッセージが表示されることがあります。次の条件がすべて満たされると、Promise は解決されます。

  • タッチ操作やマウスのクリックなどのユーザー操作に応じてのみ呼び出されました。
  • ユーザーがウェブサイトに NFC デバイスとのやり取りを許可している。
  • ユーザーのスマートフォンが NFC に対応している。
  • スマートフォンで NFC が有効になっている。

Promise が解決されると、イベント リスナーを介して reading イベントをサブスクライブすることで、受信した NDEF メッセージを利用できるようになります。また、互換性のない NFC タグが近くにあるときに通知されるように、readingerror イベントをサブスクライブする必要があります。

const ndef = new NDEFReader();
ndef.scan().then(() => {
  console.log("Scan started successfully.");
  ndef.onreadingerror = () => {
    console.log("Cannot read data from the NFC tag. Try another one?");
  };
  ndef.onreading = event => {
    console.log("NDEF message read.");
  };
}).catch(error => {
  console.log(`Error! Scan failed to start: ${error}.`);
});

NFC タグが近づくと、NDEFReadingEvent イベントがトリガーされます。このクラスには、固有のプロパティが 2 つ含まれています。

  • serialNumber はデバイスのシリアル番号(例: 00-11-22-33-44-55-66)を表します。シリアル番号がない場合は空の文字列になります。
  • message は、NFC タグに保存されている NDEF メッセージを表します。

NDEF メッセージのコンテンツを読み取るには、message.records をループ処理し、recordType に基づいて data メンバーを適切に処理します。data メンバーは DataView として公開されます。これにより、データが UTF-16 でエンコードされているケースを処理できます。

ndef.onreading = event => {
  const message = event.message;
  for (const record of message.records) {
    console.log("Record type:  " + record.recordType);
    console.log("MIME type:    " + record.mediaType);
    console.log("Record id:    " + record.id);
    switch (record.recordType) {
      case "text":
        // TODO: Read text record with record data, lang, and encoding.
        break;
      case "url":
        // TODO: Read URL record with record data.
        break;
      default:
        // TODO: Handle other records with record data.
    }
  }
};

NFC タグに書き込む

NFC タグに書き込むには、まず新しい NDEFReader オブジェクトをインスタンス化します。write() を呼び出すと、Promise が返されます。アクセスが以前に許可されていない場合、ユーザーにプロンプトが表示されることがあります。この時点で NDEF メッセージが「準備」され、次の条件がすべて満たされている場合、Promise が解決されます。

  • タッチ操作やマウスのクリックなどのユーザー操作に応じてのみ呼び出されました。
  • ユーザーがウェブサイトに NFC デバイスとのやり取りを許可している。
  • ユーザーのスマートフォンが NFC に対応している。
  • スマートフォンで NFC が有効になっている。
  • ユーザーが NFC タグをタップし、NDEF メッセージが正常に書き込まれました。

NFC タグにテキストを書き込むには、write() メソッドに文字列を渡します。

const ndef = new NDEFReader();
ndef.write(
  "Hello World"
).then(() => {
  console.log("Message written.");
}).catch(error => {
  console.log(`Write failed :-( try again: ${error}.`);
});

URL レコードを NFC タグに書き込むには、NDEF メッセージを表すディクショナリを write() に渡します。次の例では、NDEF メッセージは records キーを含む辞書です。値はレコードの配列です。この場合、recordType キーが "url" に設定され、data キーが URL 文字列に設定されたオブジェクトとして定義された URL レコードです。

const ndef = new NDEFReader();
ndef.write({
  records: [{ recordType: "url", data: "https://w3c.github.io/web-nfc/" }]
}).then(() => {
  console.log("Message written.");
}).catch(error => {
  console.log(`Write failed :-( try again: ${error}.`);
});

NFC タグに複数のレコードを書き込むこともできます。

const ndef = new NDEFReader();
ndef.write({ records: [
    { recordType: "url", data: "https://w3c.github.io/web-nfc/" },
    { recordType: "url", data: "https://web.dev/nfc/" }
]}).then(() => {
  console.log("Message written.");
}).catch(error => {
  console.log(`Write failed :-( try again: ${error}.`);
});

NFC タグに上書きを意図しない NDEF メッセージが含まれている場合は、write() メソッドに渡されるオプションで overwrite プロパティを false に設定します。この場合、NFC タグに NDEF メッセージがすでに保存されていると、返された Promise は拒否されます。

const ndef = new NDEFReader();
ndef.write("Writing data on an empty NFC tag is fun!", { overwrite: false })
.then(() => {
  console.log("Message written.");
}).catch(error => {
  console.log(`Write failed :-( try again: ${error}.`);
});

NFC タグを読み取り専用にする

悪意のあるユーザーが NFC タグのコンテンツを上書きできないように、NFC タグを永続的に読み取り専用にすることができます。このオペレーションは一方向のプロセスであり、元に戻すことはできません。NFC タグを読み取り専用にすると、書き込みができなくなります。

NFC タグを読み取り専用にするには、まず新しい NDEFReader オブジェクトをインスタンス化します。makeReadOnly() を呼び出すと、Promise が返されます。アクセスが以前に許可されていない場合、ユーザーにプロンプトが表示されることがあります。次の条件がすべて満たされると、Promise は解決されます。

  • タッチ操作やマウスのクリックなどのユーザー操作に応じてのみ呼び出されました。
  • ユーザーがウェブサイトに NFC デバイスとのやり取りを許可している。
  • ユーザーのスマートフォンが NFC に対応している。
  • スマートフォンで NFC が有効になっている。
  • ユーザーが NFC タグをタップし、NFC タグが読み取り専用に正常に設定されました。
const ndef = new NDEFReader();
ndef.makeReadOnly()
.then(() => {
  console.log("NFC tag has been made permanently read-only.");
}).catch(error => {
  console.log(`Operation failed: ${error}`);
});

NFC タグに書き込んだ後、永続的に読み取り専用にする方法は次のとおりです。

const ndef = new NDEFReader();
try {
  await ndef.write("Hello world");
  console.log("Message written.");
  await ndef.makeReadOnly();
  console.log("NFC tag has been made permanently read-only after writing to it.");
} catch (error) {
  console.log(`Operation failed: ${error}`);
}

makeReadOnly() は Chrome 100 以降の Android で利用できるため、次の方法でこの機能がサポートされているかどうかを確認します。

if ("NDEFReader" in window && "makeReadOnly" in NDEFReader.prototype) {
  // makeReadOnly() is supported.
}

セキュリティと権限

Chrome チームは、強力なウェブ プラットフォーム機能へのアクセスを制御するで定義されているユーザー制御、透明性、人間工学などの基本原則を使用して、Web NFC を設計、実装しました。

NFC は悪意のあるウェブサイトが利用できる可能性のある情報のドメインを拡大するため、NFC の利用を制限して、NFC の使用に対するユーザーの認識と制御を最大限に高めています。

ウェブサイトの Web NFC プロンプトのスクリーンショット
Web NFC のユーザー プロンプト

Web NFC は、トップレベル フレームと安全なブラウジング コンテキスト(HTTPS のみ)でのみ使用できます。オリジンは、ユーザー操作(ボタンのクリックなど)を処理する際に、まず "nfc" 権限をリクエストする必要があります。NDEFReader scan()write()makeReadOnly() の各メソッドは、アクセスが以前に許可されていない場合、ユーザー プロンプトをトリガーします。

  document.querySelector("#scanButton").onclick = async () => {
    const ndef = new NDEFReader();
    // Prompt user to allow website to interact with NFC devices.
    await ndef.scan();
    ndef.onreading = event => {
      // TODO: Handle incoming NDEF messages.
    };
  };

ユーザーが開始した権限プロンプトと、デバイスをターゲットの NFC タグにかざすという現実世界の物理的な動作の組み合わせは、他のファイル アクセス API やデバイス アクセス API に見られる選択ツール パターンを反映したものです。

スキャンまたは書き込みを行うには、ユーザーがデバイスで NFC タグにタッチしたときにウェブページが表示されている必要があります。ブラウザは、タップを示すために触覚フィードバックを使用します。ディスプレイがオフになっている場合やデバイスがロックされている場合、NFC 無線へのアクセスはブロックされます。表示されていないウェブページでは、NFC コンテンツの受信とプッシュが一時停止され、ウェブページが再び表示されると再開されます。

Page Visibility API を使用すると、ドキュメントの可視性が変更されたタイミングを追跡できます。

document.onvisibilitychange = event => {
  if (document.hidden) {
    // All NFC operations are automatically suspended when document is hidden.
  } else {
    // All NFC operations are resumed, if needed.
  }
};

レシピ

以下に、開始にあたって役立つコードサンプルを示します。

権限を確認する

Permissions API を使用すると、"nfc" 権限が付与されているかどうかを確認できます。この例は、アクセス権が以前に付与されている場合はユーザーの操作なしで NFC タグをスキャンし、それ以外の場合はボタンを表示する方法を示しています。NFC タグへの書き込みにも同じメカニズムが使用されます。これは、内部で同じ権限が使用されるためです。

const ndef = new NDEFReader();

async function startScanning() {
  await ndef.scan();
  ndef.onreading = event => {
    /* handle NDEF messages */
  };
}

const nfcPermissionStatus = await navigator.permissions.query({ name: "nfc" });
if (nfcPermissionStatus.state === "granted") {
  // NFC access was previously granted, so we can start NFC scanning now.
  startScanning();
} else {
  // Show a "scan" button.
  document.querySelector("#scanButton").style.display = "block";
  document.querySelector("#scanButton").onclick = event => {
    // Prompt user to allow UA to send and receive info when they tap NFC devices.
    startScanning();
  };
}

NFC オペレーションを中止する

AbortController プリミティブを使用すると、NFC オペレーションを簡単に中止できます。次の例は、NDEFReader の scan()makeReadOnly()write() メソッドのオプションを介して AbortControllersignal を渡し、両方の NFC オペレーションを同時に中止する方法を示しています。

const abortController = new AbortController();
abortController.signal.onabort = event => {
  // All NFC operations have been aborted.
};

const ndef = new NDEFReader();
await ndef.scan({ signal: abortController.signal });

await ndef.write("Hello world", { signal: abortController.signal });
await ndef.makeReadOnly({ signal: abortController.signal });

document.querySelector("#abortButton").onclick = event => {
  abortController.abort();
};

書き込み後の読み取り

AbortController プリミティブで write()scan() を使用すると、メッセージを書き込んだ後に NFC タグを読み取ることができます。次の例は、NFC タグにテキスト メッセージを書き込み、NFC タグ内の新しいメッセージを読み取る方法を示しています。3 秒後にスキャンを停止します。

// Waiting for user to tap NFC tag to write to it...
const ndef = new NDEFReader();
await ndef.write("Hello world");
// Success! Message has been written.

// Now scanning for 3 seconds...
const abortController = new AbortController();
await ndef.scan({ signal: abortController.signal });
const message = await new Promise((resolve) => {
  ndef.onreading = (event) => resolve(event.message);
});
// Success! Message has been read.

await new Promise((r) => setTimeout(r, 3000));
abortController.abort();
// Scanning is now stopped.

テキスト レコードの読み取りと書き込み

テキスト レコード data は、レコード encoding プロパティでインスタンス化された TextDecoder でデコードできます。テキスト レコードの言語は、lang プロパティから取得できます。

function readTextRecord(record) {
  console.assert(record.recordType === "text");
  const textDecoder = new TextDecoder(record.encoding);
  console.log(`Text: ${textDecoder.decode(record.data)} (${record.lang})`);
}

シンプルなテキスト レコードを書き込むには、NDEFReader の write() メソッドに文字列を渡します。

const ndef = new NDEFReader();
await ndef.write("Hello World");

テキスト レコードはデフォルトで UTF-8 であり、現在のドキュメントの言語を想定していますが、カスタム NDEF レコードを作成するための完全な構文を使用して両方のプロパティ(encodinglang)を指定できます。

function a2utf16(string) {
  let result = new Uint16Array(string.length);
  for (let i = 0; i < string.length; i++) {
    result[i] = string.codePointAt(i);
  }
  return result;
}

const textRecord = {
  recordType: "text",
  lang: "fr",
  encoding: "utf-16",
  data: a2utf16("Bonjour, François !")
};

const ndef = new NDEFReader();
await ndef.write({ records: [textRecord] });

URL レコードの読み取りと書き込み

TextDecoder を使用して、レコードの data をデコードします。

function readUrlRecord(record) {
  console.assert(record.recordType === "url");
  const textDecoder = new TextDecoder();
  console.log(`URL: ${textDecoder.decode(record.data)}`);
}

URL レコードを書き込むには、NDEF メッセージ ディクショナリを NDEFReader write() メソッドに渡します。NDEF メッセージに含まれる URL レコードは、recordType キーが "url" に設定され、data キーが URL 文字列に設定されたオブジェクトとして定義されます。

const urlRecord = {
  recordType: "url",
  data:"https://w3c.github.io/web-nfc/"
};

const ndef = new NDEFReader();
await ndef.write({ records: [urlRecord] });

MIME タイプのレコードを読み書きする

MIME タイプ レコードの mediaType プロパティは、data が適切にデコードされるように、NDEF レコード ペイロードの MIME タイプを表します。たとえば、JSON.parse を使用して JSON テキストをデコードし、Image 要素を使用して画像データをデコードします。

function readMimeRecord(record) {
  console.assert(record.recordType === "mime");
  if (record.mediaType === "application/json") {
    const textDecoder = new TextDecoder();
    console.log(`JSON: ${JSON.parse(decoder.decode(record.data))}`);
  }
  else if (record.mediaType.startsWith('image/')) {
    const blob = new Blob([record.data], { type: record.mediaType });
    const img = new Image();
    img.src = URL.createObjectURL(blob);
    document.body.appendChild(img);
  }
  else {
    // TODO: Handle other MIME types.
  }
}

MIME タイプのレコードを書き込むには、NDEF メッセージの辞書を NDEFReader の write() メソッドに渡します。NDEF メッセージに含まれる MIME タイプ レコードは、recordType キーが "mime" に設定され、mediaType キーがコンテンツの実際の MIME タイプに設定され、data キーが ArrayBuffer であるか ArrayBuffer のビューを提供する(Uint8ArrayDataView など)オブジェクトに設定されたオブジェクトとして定義されます。

const encoder = new TextEncoder();
const data = {
  firstname: "François",
  lastname: "Beaufort"
};
const jsonRecord = {
  recordType: "mime",
  mediaType: "application/json",
  data: encoder.encode(JSON.stringify(data))
};

const imageRecord = {
  recordType: "mime",
  mediaType: "image/png",
  data: await (await fetch("icon1.png")).arrayBuffer()
};

const ndef = new NDEFReader();
await ndef.write({ records: [jsonRecord, imageRecord] });

絶対 URL レコードの読み取りと書き込み

絶対 URL レコード data は、単純な TextDecoder でデコードできます。

function readAbsoluteUrlRecord(record) {
  console.assert(record.recordType === "absolute-url");
  const textDecoder = new TextDecoder();
  console.log(`Absolute URL: ${textDecoder.decode(record.data)}`);
}

絶対 URL レコードを書き込むには、NDEF メッセージ ディクショナリを NDEFReader write() メソッドに渡します。NDEF メッセージに含まれる絶対 URL レコードは、recordType キーが "absolute-url" に設定され、data キーが URL 文字列に設定されたオブジェクトとして定義されます。

const absoluteUrlRecord = {
  recordType: "absolute-url",
  data:"https://w3c.github.io/web-nfc/"
};

const ndef = new NDEFReader();
await ndef.write({ records: [absoluteUrlRecord] });

スマートポスター レコードの読み取りと書き込み

スマート ポスター レコード(雑誌広告、チラシ、看板などで使用)は、ペイロードとして NDEF メッセージを含む NDEF レコードとして、一部のウェブ コンテンツを記述します。record.toRecords() を呼び出して、data をスマート ポスター レコードに含まれるレコードのリストに変換します。スマートポスター レコードのタイプ、アクション、サイズに対応する URL レコード、タイトルのテキスト レコード、画像の MIME タイプ レコード、":t"":act"":s" などのカスタム ローカル タイプ レコードが必要です。

ローカル タイプ レコードは、それを含む NDEF レコードのローカル コンテキスト内でのみ一意です。これらの型は、包含レコードのローカル コンテキスト外で型の意味が重要でない場合や、ストレージ使用量が厳しい制約である場合に使用します。ローカル タイプのレコード名は、Web NFC では常に : で始まります(例: ":t"":s"":act")。これは、たとえばテキスト レコードとローカル タイプのテキスト レコードを区別するためです。

function readSmartPosterRecord(smartPosterRecord) {
  console.assert(record.recordType === "smart-poster");
  let action, text, url;

  for (const record of smartPosterRecord.toRecords()) {
    if (record.recordType == "text") {
      const decoder = new TextDecoder(record.encoding);
      text = decoder.decode(record.data);
    } else if (record.recordType == "url") {
      const decoder = new TextDecoder();
      url = decoder.decode(record.data);
    } else if (record.recordType == ":act") {
      action = record.data.getUint8(0);
    } else {
      // TODO: Handle other type of records such as `:t`, `:s`.
    }
  }

  switch (action) {
    case 0:
      // Do the action
      break;
    case 1:
      // Save for later
      break;
    case 2:
      // Open for editing
      break;
  }
}

スマート ポスター レコードを書き込むには、NDEF メッセージを NDEFReader の write() メソッドに渡します。NDEF メッセージに含まれるスマート ポスター レコードは、recordType キーが "smart-poster" に設定され、data キーがスマート ポスター レコードに含まれる NDEF メッセージを(再び)表すオブジェクトに設定されたオブジェクトとして定義されます。

const encoder = new TextEncoder();
const smartPosterRecord = {
  recordType: "smart-poster",
  data: {
    records: [
      {
        recordType: "url", // URL record for smart poster content
        data: "https://my.org/content/19911"
      },
      {
        recordType: "text", // title record for smart poster content
        data: "Funny dance"
      },
      {
        recordType: ":t", // type record, a local type to smart poster
        data: encoder.encode("image/gif") // MIME type of smart poster content
      },
      {
        recordType: ":s", // size record, a local type to smart poster
        data: new Uint32Array([4096]) // byte size of smart poster content
      },
      {
        recordType: ":act", // action record, a local type to smart poster
        // do the action, in this case open in the browser
        data: new Uint8Array([0])
      },
      {
        recordType: "mime", // icon record, a MIME type record
        mediaType: "image/png",
        data: await (await fetch("icon1.png")).arrayBuffer()
      },
      {
        recordType: "mime", // another icon record
        mediaType: "image/jpg",
        data: await (await fetch("icon2.jpg")).arrayBuffer()
      }
    ]
  }
};

const ndef = new NDEFReader();
await ndef.write({ records: [smartPosterRecord] });

外部タイプ レコードの読み取りと書き込み

アプリケーション定義レコードを作成するには、外部タイプ レコードを使用します。これらには、toRecords() でアクセス可能なペイロードとして NDEF メッセージが含まれている場合があります。名前には、発行組織のドメイン名、コロン、1 文字以上の型名が含まれます(例: "example.com:foo")。

function readExternalTypeRecord(externalTypeRecord) {
  for (const record of externalTypeRecord.toRecords()) {
    if (record.recordType == "text") {
      const decoder = new TextDecoder(record.encoding);
      console.log(`Text: ${textDecoder.decode(record.data)} (${record.lang})`);
    } else if (record.recordType == "url") {
      const decoder = new TextDecoder();
      console.log(`URL: ${decoder.decode(record.data)}`);
    } else {
      // TODO: Handle other type of records.
    }
  }
}

外部タイプのレコードを書き込むには、NDEF メッセージ ディクショナリを NDEFReader write() メソッドに渡します。NDEF メッセージに含まれる外部型レコードは、recordType キーが外部型の名前に設定され、data キーが外部型レコードに含まれる NDEF メッセージを表すオブジェクトに設定されたオブジェクトとして定義されます。data キーは ArrayBuffer にすることも、ArrayBuffer のビューを提供することもできます(Uint8ArrayDataView など)。

const externalTypeRecord = {
  recordType: "example.game:a",
  data: {
    records: [
      {
        recordType: "url",
        data: "https://example.game/42"
      },
      {
        recordType: "text",
        data: "Game context given here"
      },
      {
        recordType: "mime",
        mediaType: "image/png",
        data: await (await fetch("image.png")).arrayBuffer()
      }
    ]
  }
};

const ndef = new NDEFReader();
ndef.write({ records: [externalTypeRecord] });

空のレコードの読み取りと書き込み

空のレコードにはペイロードがありません。

空のレコードを書き込むには、NDEF メッセージ ディクショナリを NDEFReader write() メソッドに渡します。NDEF メッセージに含まれる空のレコードは、recordType キーが "empty" に設定されたオブジェクトとして定義されます。

const emptyRecord = {
  recordType: "empty"
};

const ndef = new NDEFReader();
await ndef.write({ records: [emptyRecord] });

ブラウザ サポート

Web NFC は、Android 版 Chrome 89 で利用できます。

開発のヒント

Web NFC を使い始めたときに知っておきたかったことを以下にまとめました。

  • Android は、Web NFC が動作する前に OS レベルで NFC タグを処理します。
  • NFC アイコンは material.io で確認できます。
  • NDEF レコード id を使用して、必要に応じてレコードを簡単に識別します。
  • NDEF をサポートするフォーマットされていない NFC タグには、空のタイプの単一のレコードが含まれています。
  • 以下に示すように、Android アプリケーション レコードの作成は簡単です。
const encoder = new TextEncoder();
const aarRecord = {
  recordType: "android.com:pkg",
  data: encoder.encode("com.example.myapp")
};

const ndef = new NDEFReader();
await ndef.write({ records: [aarRecord] });

デモ

公式サンプルを試して、Web NFC のクールなデモをご覧ください。

Chrome Dev Summit 2019 での Web NFC カードのデモ

フィードバック

Web NFC コミュニティ グループと Chrome チームは、Web NFC についてのご意見やご経験をぜひお聞かせいただきたいと考えています。

API 設計について教えてください

API が想定どおりに動作しない点はありますか?それとも、アイデアを実装するために必要なメソッドやプロパティが不足していますか?

Web NFC GitHub リポジトリで仕様に関する問題を提出するか、既存の問題に意見を追加します。

実装に関する問題を報告する

Chrome の実装にバグが見つかりましたか?それとも、実装が仕様と異なるのでしょうか?

https://new.crbug.com でバグを報告します。できるだけ詳細な情報を記載し、バグを再現するための簡単な手順を記載し、[コンポーネント] を Blink>NFC に設定してください。

サポートを表示

Web NFC を使用する予定はありますか?公開サポートは、Chrome チームが機能の優先順位を付け、他のブラウザ ベンダーにサポートの重要性を示すのに役立ちます。

ハッシュタグ #WebNFC を使用して @ChromiumDev にツイートし、どこでどのように使用しているかをお知らせください。

関連情報

謝辞

Web NFC を実装してくれた Intel の皆さんに感謝します。Google Chrome は、Chromium プロジェクトを推進するために協力するコミッターのコミュニティに依存しています。Chromium のコミッターはすべてが Google 社員ではありません。これらの貢献者には特別な認識が必要です。