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

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

François Beaufort
François Beaufort

ウェブ NFC とは

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

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

データを交換するために NFC タグを起動しているスマートフォン
NFC 操作の図

推奨されるユースケース

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

ウェブ NFC を使用できるサイトの例:

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

現在のステータス

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

ウェブ NFC の使用

機能検出

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

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

用語

NFC タグはパッシブ NFC デバイスです。つまり、アクティブな NFC デバイス(スマートフォンなど)が近くにある場合、磁気誘導によって駆動されます。NFC タグには、ステッカー、クレジット カード、腕の手首など、さまざまな形態やファッションがあります。

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

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

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

NDEF をサポートする NFC タグは、ポストイット ノートのようなものです。誰でも読み取ることができ、読み取り専用でない限り、誰でも書き込むことができます。これには、1 つ以上の NDEF レコードをカプセル化する単一の NDEF メッセージが含まれます。各 NDEF レコードは、データ ペイロードと関連する型情報を含むバイナリ構造です。ウェブ NFC は、NFC フォーラムの標準化されたレコードタイプ(空、テキスト、URL、スマートポスター、MIME タイプ、絶対 URL、外部タイプ、不明、ローカルタイプ)をサポートしています。

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 メンバーは、データが UTF-16 でエンコードされるケースを処理できるため、DataView として公開されます。

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}.`);
});

1 つの 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 に設定します。この場合、NDEF メッセージがすでに NFC タグに格納されている場合、返される 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 チームは、ユーザー制御、透明性、エルゴノミクスなど、強力なウェブ プラットフォーム機能へのアクセスの制御で定義されている基本原則に基づいてウェブ NFC を設計、実装しています。

NFC は、悪意のあるウェブサイトで利用できる可能性のある情報の領域を拡張するため、NFC の使用に対するユーザーの認識と制御を最大化するために、NFC の利用が制限されます。

ウェブサイトに表示されたウェブ NFC プロンプトのスクリーンショット
ウェブ NFC のユーザー プロンプト

ウェブ 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 オペレーションを簡単に中止できます。以下の例は、AbortControllersignal を NDEFReader scan()makeReadOnly()write() メソッドのオプションを介して渡し、両方の 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 で、現在のドキュメントの言語が使用されますが、両方のプロパティ(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 テキストをデコードするには JSON.parse を使用し、画像データをデコードするには 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 タイプのレコードは、"mime" に設定された recordType キー、コンテンツの実際の MIME タイプに設定された mediaType キー、ArrayBuffer または ArrayBuffer に対するビューを提供するオブジェクト(Uint8ArrayDataView など)に設定された data キーを持つオブジェクトとして定義されます。

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 レコードのローカル コンテキスト内でのみ一意です。含まれるレコードのローカル コンテキストの外部で型の意味が重要でない場合や、ストレージ使用量が厳しい制約の場合は、これらを使用します。ウェブ 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 キーと、外部タイプレコードに含まれる NDEF メッセージを表すオブジェクトに設定された data キーを持つオブジェクトとして定義されます。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] });

ブラウザ サポート

ウェブ NFC は Chrome 89 で Android で利用可能になります。

開発のヒント

以下は、ウェブ NFC を使い始めたときに知っておきたかったことのリストです。

  • Android では、ウェブ NFC が動作する前に OS レベルで NFC タグを処理します。
  • NFC アイコンは material.io にあります。
  • NDEF レコード id を使用すると、必要に応じてレコードを簡単に識別できます。
  • NDEF をサポートするフォーマットされていない NFC タグには、空のタイプのレコードが 1 つ含まれます。
  • 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] });

デモ

公式サンプルと便利なウェブ NFC デモをご覧ください。

Chrome Dev Summit 2019 でのウェブ NFC カードのデモ

フィードバック

ウェブ NFC コミュニティ グループと Chrome チーム一同、ウェブ NFC に関するご意見やご感想をお待ちしております。

API の設計についてお聞かせください

API に想定外の動作はありますか?あるいは、アイデアを実装する必要があるメソッドやプロパティが不足しているのでしょうか。

Web NFC GitHub リポジトリで仕様の問題を提出するか、既存の問題にご意見をお寄せください。

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

Chrome の実装にバグが見つかりましたか?それとも 実装が仕様と異なっているか?

https://new.crbug.com でバグを報告します。できる限り詳細を記載し、バグを再現するための簡単な手順を記載して、[Components] を Blink>NFC に設定します。Glitch は、すばやく簡単に再現する場合に適しています。

応援する

ウェブ NFC を使用する予定はありますか?一般公開のサポートにより、Chrome チームが機能に優先順位を付け、他のブラウザ ベンダーをサポートすることがいかに重要であるかを示します。

ハッシュタグ #WebNFC を使用して @ChromiumDev 宛てにツイートを送信し、使用場所と使用方法をお知らせください。

関連情報

謝辞

ウェブ NFC を実装してくれた Intel の社員に深く感謝します。Google Chrome は、コミッターのコミュニティが協力して Chromium プロジェクトを推進しています。すべての Chromium コミッターが Google 社員であるわけではなく、こうした貢献者には特別な評価が求められます。