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

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

François Beaufort
François Beaufort

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

ウェブ NFC を使用すると、サイトはユーザーのデバイスに近づいた NFC タグの読み取りと書き込みを行うことができます(通常は 5 ~ 10 cm)。現在のスコープは、さまざまなタグ形式で動作する軽量なバイナリ メッセージ形式である 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. リリース 完了

ウェブ NFC を使用する

特徴検出

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

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

用語

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

透明な NFC タグの画像
透明な NFC タグ

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

NDEFReader オブジェクトは、NFC タグからの受信 NDEF メッセージに対してアクションを実行し、範囲内の NFC タグに NDEF メッセージを書き込むためのものです。

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

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

NFC タグをスキャンする

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

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

プロミスが解決されると、イベント リスナーを介して 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() は Android 版 Chrome 100 以降で利用できる機能であるため、この機能が次の環境でサポートされているかどうかを確認します。

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

セキュリティと権限

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

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

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

Web NFC は、トップレベルのフレームと安全なブラウジング コンテキスト(HTTPS のみ)でのみ使用できます。オリジンは、ユーザー ジェスチャー(ボタンのクリックなど)を処理する際に、まず "nfc"権限をリクエストする必要があります。NDEFReaderscan()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 にある選択ツール パターンをミラーリングできます。

スキャンまたは書き込みを行うには、ユーザーがデバイスで 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 タグには、空のタイプのレコードが 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 カードのデモ

フィードバック

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

API 設計について

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

Web NFC GitHub リポジトリで仕様に関する問題を報告するか、既存の問題にコメントを追加します。

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

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

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

クリエイターを応援する

ウェブ NFC を使用する予定はありますか?一般公開されている機能は、Chrome チームが機能の優先順位付けを行う際に役立ちます。また、他のブラウザ ベンダーに、その機能のサポートがどれほど重要であるかを示します。

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

関連情報

謝辞

Web NFC を実装していただいた Intel の皆様に感謝いたします。Google Chrome は、Chromium プロジェクトを前進させるために協力しているコントリビューターのコミュニティに依存しています。Chromium のコントリビューターは Google 社員とは限りません。こうしたコントリビューターは特別な評価に値します。