Mit NFC-Geräten in Chrome für Android interagieren

Das Lesen und Schreiben in NFC-Tags ist jetzt möglich.

François Beaufort
François Beaufort

Was ist Web NFC?

NFC steht für Near Field Communication, eine drahtlose Nahfeldtechnologie, die mit 13,56 MHz betrieben wird und die Kommunikation zwischen Geräten auf einer Entfernung von weniger als 10 cm und mit einer Übertragungsrate von bis zu 424 kbit/s ermöglicht.

Mit Web NFC können Websites NFC-Tags lesen und darauf schreiben, wenn sie sich in unmittelbarer Nähe des Geräts des Nutzers befinden (in der Regel 5–10 cm). Der aktuelle Bereich beschränkt sich auf das NFC Data Exchange Format (NDEF), ein einfaches Binärnachrichtenformat, das für verschiedene Tag-Formate funktioniert.

Smartphone schaltet NFC-Tag zum Datenaustausch ein
Diagramm eines NFC-Vorgangs

Empfohlene Anwendungsfälle

Web-NFC ist auf NDEF beschränkt, da die Sicherheitseigenschaften beim Lesen und Schreiben von NDEF-Daten leichter quantifizierbar sind. Low-Level-I/O-Vorgänge (z.B. ISO-DEP, NFC-A/B, NFC-F), der Peer-to-Peer-Kommunikationsmodus und die hostbasierte Kartenemulation (HCE) werden nicht unterstützt.

Beispiele für Websites, auf denen Web-NFC verwendet werden kann, sind:

  • Museen und Kunstgalerien können zusätzliche Informationen zu einem Ausstellungsstück anzeigen, wenn der Nutzer sein Gerät an eine NFC-Karte in der Nähe des Ausstellungsstücks hält.
  • Websites für die Inventarverwaltung können Daten auf dem NFC-Tag eines Containers lesen oder darauf schreiben, um Informationen zu seinem Inhalt zu aktualisieren.
  • Konferenzstätten können damit NFC-Badges während der Veranstaltung scannen und dafür sorgen, dass sie gesperrt sind, um weitere Änderungen an den darauf geschriebenen Informationen zu verhindern.
  • Websites können damit anfängliche Secrets freigeben, die für Bereitstellungsszenarien von Geräten oder Diensten erforderlich sind, und Konfigurationsdaten im Betriebsmodus bereitstellen.
Smartphone scannt mehrere NFC-Tags
NFC-Inventarverwaltung – Abbildung

Aktueller Status

Schritt Status
1. Erklärende Mitteilung erstellen Abschließen
2. Ersten Entwurf der Spezifikation erstellen Abschließen
3. Feedback einholen und Design iterieren Abschließen
4. Ursprungstest Abschließen
5. Starten Abschließen

Web-NFC verwenden

Funktionserkennung

Die Funktionserkennung für Hardware unterscheidet sich von der, die Sie wahrscheinlich kennen. Wenn NDEFReader angezeigt wird, unterstützt der Browser Web-NFC, aber nicht, ob die erforderliche Hardware vorhanden ist. Insbesondere wenn die Hardware fehlt, wird das von bestimmten Aufrufen zurückgegebene Promise abgelehnt. Ich erläutere das genauer, wenn ich NDEFReader beschreibe.

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

Terminologie

Ein NFC-Tag ist ein passives NFC-Gerät. Das bedeutet, dass es durch magnetische Induktion betrieben wird, wenn sich ein aktives NFC-Gerät (z. B. ein Smartphone) in der Nähe befindet. NFC-Tags gibt es in vielen Formen und Arten, z. B. auf Aufklebern, Kreditkarten, Armhandbüchern und mehr.

Foto eines transparenten NFC-Tags
Ein transparentes NFC-Tag

Das NDEFReader-Objekt ist der Einstiegspunkt in Web NFC. Es bietet Funktionen zum Vorbereiten von Lese- und/oder Schreibaktionen, die ausgeführt werden, wenn sich ein NDEF-Tag in der Nähe befindet. Das NDEF in NDEFReader steht für NFC Data Exchange Format, ein schlankes Binärnachrichtenformat, das vom NFC Forum standardisiert wurde.

Das NDEFReader-Objekt dient dazu, auf eingehende NDEF-Nachrichten von NFC-Tags zu reagieren und NDEF-Nachrichten in NFC-Tags in Reichweite zu schreiben.

Ein NFC-Tag, das NDEF unterstützt, ist wie ein Haftnotizen. Jeder kann sie lesen und, sofern sie nicht schreibgeschützt ist, auch darauf schreiben. Sie enthält eine einzelne NDEF-Nachricht, die einen oder mehrere NDEF-Einträge kapselt. Jeder NDEF-Eintrag ist eine binäre Struktur, die eine Datennutzlast und zugehörige Typinformationen enthält. Web NFC unterstützt die folgenden vom NFC Forum standardisierten Datensatztypen: leer, Text, URL, Smart Poster, MIME-Typ, absolute URL, externer Typ, unbekannt und lokaler Typ.

Diagramm einer NDEF-Nachricht
Diagramm einer NDEF-Nachricht

NFC-Tags scannen

Wenn Sie NFC-Tags scannen möchten, müssen Sie zuerst ein neues NDEFReader-Objekt erstellen. Der Aufruf von scan() gibt ein Versprechen zurück. Der Nutzer wird möglicherweise aufgefordert, wenn zuvor kein Zugriff gewährt wurde. Die Zusicherung wird erfüllt, wenn alle folgenden Bedingungen erfüllt sind:

  • Sie wurde nur als Reaktion auf eine Nutzergeste wie eine Touch-Geste oder einen Mausklick aufgerufen.
  • Der Nutzer hat der Website erlaubt, mit NFC-Geräten zu interagieren.
  • Das Smartphone des Nutzers unterstützt NFC.
  • Der Nutzer hat NFC auf seinem Smartphone aktiviert.

Sobald das Versprechen erfüllt ist, sind eingehende NDEF-Nachrichten verfügbar, wenn Sie reading-Ereignisse über einen Ereignis-Listener abonnieren. Sie sollten auch readingerror-Ereignisse abonnieren, um benachrichtigt zu werden, wenn sich in der Nähe inkompatible NFC-Tags befinden.

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

Wenn sich ein NFC-Tag in der Nähe befindet, wird ein NDEFReadingEvent-Ereignis ausgelöst. Es enthält zwei einzigartige Eigenschaften:

  • serialNumber steht für die Seriennummer des Geräts (z. B.00-11-22-33-44-55-66) oder einen leeren String, wenn keine verfügbar ist.
  • message steht für die im NFC-Tag gespeicherte NDEF-Nachricht.

Wenn Sie den Inhalt der NDEF-Nachricht lesen möchten, durchlaufen Sie message.records und verarbeiten Sie die data-Elemente entsprechend anhand ihrer recordType. Das data-Mitglied wird als DataView bereitgestellt, da es die Verarbeitung von Fällen ermöglicht, in denen Daten in UTF-16 codiert sind.

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-Tags beschreiben

Wenn Sie NFC-Tags schreiben möchten, müssen Sie zuerst ein neues NDEFReader-Objekt instanziieren. Beim Aufrufen von write() wird ein Promise zurückgegeben. Der Nutzer wird möglicherweise aufgefordert, wenn der Zugriff zuvor nicht gewährt wurde. An diesem Punkt wird eine NDEF-Nachricht „vorbereitet“ und die Zustellung wird garantiert, wenn alle folgenden Bedingungen erfüllt sind:

  • Sie wurde nur als Reaktion auf eine Nutzergeste wie eine Touch-Geste oder einen Mausklick aufgerufen.
  • Der Nutzer hat der Website erlaubt, mit NFC-Geräten zu interagieren.
  • Das Smartphone des Nutzers unterstützt NFC.
  • Der Nutzer hat NFC auf seinem Smartphone aktiviert.
  • Der Nutzer hat ein NFC-Tag getippt und eine NDEF-Nachricht wurde erfolgreich geschrieben.

Wenn Sie Text in ein NFC-Tag schreiben möchten, übergeben Sie der Methode write() einen String.

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

Übergeben Sie ein Wörterbuch, das eine NDEF-Nachricht darstellt, an write(), um einen URL-Eintrag in ein NFC-Tag zu schreiben. Im folgenden Beispiel ist die NDEF-Nachricht ein Wörterbuch mit einem records-Schlüssel. Sein Wert ist ein Array von Einträgen. In diesem Fall ist es ein URL-Eintrag, der als Objekt mit einem recordType-Schlüssel ("url") und einem data-Schlüssel (URL-String) definiert ist.

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

Es ist auch möglich, mehrere Einträge in ein NFC-Tag zu schreiben.

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

Wenn das NFC-Tag eine NDEF-Nachricht enthält, die nicht überschrieben werden soll, legen Sie in den an die write()-Methode übergebenen Optionen die Eigenschaft overwrite auf false fest. In diesem Fall wird das zurückgegebene Promise abgelehnt, wenn bereits eine NDEF-Nachricht im NFC-Tag gespeichert ist.

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-Tags schreibgeschützt machen

Um zu verhindern, dass böswillige Nutzer den Inhalt eines NFC-Tags überschreiben, können Sie NFC-Tags dauerhaft schreibgeschützt machen. Dieser Vorgang ist nur in eine Richtung möglich und kann nicht rückgängig gemacht werden. Sobald ein NFC-Tag schreibgeschützt ist, kann nicht mehr in dieses Tag geschrieben werden.

Wenn Sie NFC-Tags schreibgeschützt machen möchten, müssen Sie zuerst ein neues NDEFReader-Objekt erstellen. Der Aufruf von makeReadOnly() gibt ein Versprechen zurück. Wenn zuvor noch kein Zugriff gewährt wurde, wird der Nutzer möglicherweise dazu aufgefordert. Die Zusicherung wird erfüllt, wenn alle folgenden Bedingungen erfüllt sind:

  • Sie wurde nur als Reaktion auf eine Nutzergeste wie eine Touch-Geste oder einen Mausklick aufgerufen.
  • Der Nutzer hat der Website erlaubt, mit NFC-Geräten zu interagieren.
  • Das Smartphone des Nutzers unterstützt NFC.
  • Der Nutzer hat NFC auf seinem Smartphone aktiviert.
  • Der Nutzer hat ein NFC-Tag getippt und das NFC-Tag wurde in den Lesezugriff geändert.
const ndef = new NDEFReader();
ndef.makeReadOnly()
.then(() => {
  console.log("NFC tag has been made permanently read-only.");
}).catch(error => {
  console.log(`Operation failed: ${error}`);
});

So legen Sie fest, dass ein NFC-Tag nach dem Schreiben dauerhaft schreibgeschützt ist:

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

Da makeReadOnly() unter Android in Chrome 100 oder höher verfügbar ist, prüfen Sie, ob diese Funktion mit den folgenden Elementen unterstützt wird:

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

Sicherheit und Berechtigungen

Das Chrome-Team hat Web-NFC gemäß den in Zugriff auf leistungsstarke Funktionen der Webplattform steuern definierten Grundprinzipien entwickelt und implementiert, einschließlich Nutzersteuerung, Transparenz und Ergonomie.

Da NFC die Domain der Informationen erweitert, die potenziell für schädliche Websites zur Verfügung stehen, wird die Verfügbarkeit von NFC eingeschränkt, um das Erkennen und die Kontrolle der Nutzer über die NFC-Nutzung zu maximieren.

Screenshot einer Web-NFC-Aufforderung auf einer Website
NFC-Aufforderung für Webnutzer

Web-NFC ist nur für Frames der obersten Ebene und sichere Browserkontexte (nur HTTPS) verfügbar. Ursprünge müssen zuerst die "nfc" Berechtigung anfordern, während sie eine Nutzergeste verarbeiten (z. B. einen Klick auf eine Schaltfläche). Die Methoden NDEFReader, scan(), write() und makeReadOnly() lösen eine Nutzeraufforderung aus, wenn der Zugriff nicht zuvor gewährt wurde.

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

Die Kombination aus einer vom Nutzer initiierten Berechtigungsaufforderung und einer realen, physischen Bewegung, bei der das Gerät über ein Ziel-NFC-Tag gebracht wird, spiegelt das Auswahlmuster der anderen APIs für den Datei- und Gerätezugriff wider.

Damit ein Scan oder Schreibvorgang ausgeführt werden kann, muss die Webseite sichtbar sein, wenn der Nutzer sein Gerät an ein NFC-Tag hält. Der Browser verwendet haptisches Feedback, um ein Tippen anzuzeigen. Der Zugriff auf die NFC-Funkschnittstelle wird blockiert, wenn das Display ausgeschaltet oder das Gerät gesperrt ist. Bei nicht sichtbaren Webseiten wird der Empfang und die Übertragung von NFC-Inhalten angehalten und fortgesetzt, wenn eine Webseite wieder sichtbar wird.

Mit der Page Visibility API können Sie nachverfolgen, wann sich die Sichtbarkeit von Dokumenten ändert.

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

Kochbuch

Hier sind einige Codebeispiele für den Einstieg.

Berechtigung prüfen

Mit der Permissions API können Sie prüfen, ob die Berechtigung "nfc" gewährt wurde. In diesem Beispiel wird gezeigt, wie NFC-Tags ohne Nutzerinteraktion gescannt werden, wenn der Zugriff zuvor gewährt wurde, oder andernfalls eine Schaltfläche angezeigt wird. Derselbe Mechanismus funktioniert auch für das Schreiben von NFC-Tags, da dieselbe Berechtigung verwendet wird.

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-Vorgänge abbrechen

Mit der Primitive AbortController können Sie NFC-Vorgänge ganz einfach abbrechen. Im folgenden Beispiel wird gezeigt, wie Sie die signal eines AbortController durch die Optionen der NDEFReader-Methoden scan(), makeReadOnly() und write() übergeben und beide NFC-Vorgänge gleichzeitig abbrechen.

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();
};

Lesen nach Schreiben

Wenn Sie write() und dann scan() mit der AbortController-Primitiv verwenden, können Sie ein NFC-Tag lesen, nachdem Sie eine Nachricht darauf geschrieben haben. Im folgenden Beispiel wird gezeigt, wie Sie eine SMS auf ein NFC-Tag schreiben und die neue Nachricht im NFC-Tag lesen. Nach drei Sekunden wird der Scan beendet.

// 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.

Texteintrag lesen und schreiben

Der Textdatensatz data kann mit einer TextDecoder decodiert werden, die mit dem Attribut encoding instanziiert wird. Die Sprache des Texteintrags ist über das Attribut lang verfügbar.

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

Um einen einfachen Textdatensatz zu schreiben, übergeben Sie einen String an die NDEFReader-Methode write().

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

Texteinträge sind standardmäßig UTF-8-codiert und setzen die Sprache des aktuellen Dokuments voraus. Beide Attribute (encoding und lang) können jedoch mit der vollständigen Syntax zum Erstellen eines benutzerdefinierten NDEF-Eintrags angegeben werden.

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-Eintrag lesen und schreiben

Verwenden Sie TextDecoder, um die data des Eintrags zu decodieren.

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

Übergeben Sie ein NDEF-Nachrichtenwörterbuch an die NDEFReader-Methode write(), um einen URL-Eintrag zu schreiben. Der in der NDEF-Nachricht enthaltene URL-Eintrag wird als Objekt mit einem recordType-Schlüssel definiert, der auf "url" gesetzt ist, und einem data-Schlüssel, der auf den URL-String gesetzt ist.

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

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

MIME-Typ-Eintrag lesen und schreiben

Die mediaType-Eigenschaft eines MIME-Typ-Eintrags entspricht dem MIME-Typ der NDEF-Eintragsnutzlast, damit data richtig decodiert werden kann. Verwenden Sie beispielsweise JSON.parse, um JSON-Text zu decodieren, und ein Bildelement zum Decodieren von Bilddaten.

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.
  }
}

Wenn Sie einen MIME-Typ-Eintrag schreiben möchten, übergeben Sie der Methode NDEFReaderwrite() ein NDEF-Nachrichten-Wörterbuch. Der MIME-Typ-Eintrag in der NDEF-Nachricht wird als Objekt mit einem recordType-Schlüssel definiert, der auf "mime" festgelegt ist, einem mediaType-Schlüssel, der auf den tatsächlichen MIME-Typ der Inhalte festgelegt ist, und einem data-Schlüssel, der auf ein Objekt festgelegt ist, das entweder ein ArrayBuffer ist oder eine Ansicht auf ein ArrayBuffer bietet (z.B. Uint8Array, DataView).

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] });

Eintrag mit absoluter URL lesen und schreiben

Der absolute-URL-Eintrag data kann mit einer einfachen TextDecoder decodiert werden.

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

Wenn Sie einen absoluten URL-Eintrag schreiben möchten, übergeben Sie der Methode write() des NDEFReader ein NDEF-Nachrichten-Dictionary. Der absolute-URL-Eintrag in der NDEF-Nachricht wird als Objekt mit einem recordType-Schlüssel definiert, der auf "absolute-url" gesetzt ist, und einem data-Schlüssel, der auf den URL-String gesetzt ist.

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

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

Smart Poster-Eintrag lesen und schreiben

Ein Smart-Poster-Eintrag (in Anzeigen in Zeitschriften, Flyern, Plakaten usw. verwendet) beschreibt einige Webinhalte als NDEF-Eintrag, der eine NDEF-Nachricht als Nutzlast enthält. Rufen Sie record.toRecords() auf, um data in eine Liste von Einträgen umzuwandeln, die im Smart-Poster-Eintrag enthalten sind. Er sollte einen URL-Eintrag, einen Texteintrag für den Titel, einen MIME-Typ-Eintrag für das Bild und einige benutzerdefinierte lokale Typeneinträge wie ":t", ":act" und ":s" für den Typ, die Aktion und die Größe des Smart-Poster-Eintrags enthalten.

Einträge vom Typ „local“ sind nur im lokalen Kontext des enthaltenden NDEF-Eintrags eindeutig. Verwenden Sie sie, wenn die Bedeutung der Typen außerhalb des lokalen Kontexts des enthaltenden Datensatzes keine Rolle spielt und die Speichernutzung eine strenge Einschränkung darstellt. Die Namen von Einträgen vom Typ „Lokales Element“ beginnen in Web NFC immer mit : (z.B. ":t", ":s", ":act"). So lässt sich beispielsweise ein Texteintrag von einem Texteintrag vom Typ „Lokales Element“ unterscheiden.

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;
  }
}

Wenn Sie einen Smart-Poster-Eintrag schreiben möchten, übergeben Sie eine NDEF-Nachricht an die Methode write() des NDEFReaders. Der Smart-Poster-Eintrag in der NDEF-Nachricht wird als Objekt mit einem recordType-Schlüssel definiert, der auf "smart-poster" gesetzt ist, und einem data-Schlüssel, der auf ein Objekt verweist, das wiederum eine NDEF-Nachricht im Smart-Poster-Eintrag darstellt.

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] });

Externen Typdatensatz lesen und schreiben

Verwenden Sie Datensätze vom Typ „Externer Typ“, um anwendungsdefinierte Datensätze zu erstellen. Diese können eine NDEF-Nachricht als Nutzlast enthalten, auf die mit toRecords() zugegriffen werden kann. Der Name enthält den Domainnamen der ausstellenden Organisation, einen Doppelpunkt und einen Typnamen, der mindestens ein Zeichen lang ist, z. B. "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.
    }
  }
}

Wenn Sie einen externen Typ-Eintrag schreiben möchten, übergeben Sie der Methode NDEFReader write() ein NDEF-Nachrichten-Wörterbuch. Der in der NDEF-Nachricht enthaltene Eintrag vom Typ „Externer Typ“ wird als Objekt mit einem recordType-Schlüssel definiert, der auf den Namen des externen Typs festgelegt ist, und einem data-Schlüssel, der auf ein Objekt festgelegt ist, das eine NDEF-Nachricht im Eintrag vom Typ „Externer Typ“ darstellt. Der data-Schlüssel kann auch ein ArrayBuffer sein oder eine Ansicht auf einen ArrayBuffer bieten (z.B. Uint8Array oder DataView).

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] });

Leere Einträge lesen und schreiben

Ein leerer Eintrag hat keine Nutzlast.

Wenn Sie einen leeren Eintrag schreiben möchten, übergeben Sie der Methode NDEFReaderwrite() ein NDEF-Nachrichten-Wörterbuch. Der leere Eintrag in der NDEF-Nachricht wird als Objekt mit einem recordType-Schlüssel definiert, der auf "empty" gesetzt ist.

const emptyRecord = {
  recordType: "empty"
};

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

Unterstützte Browser

Web-NFC ist in Chrome 89 für Android verfügbar.

Entwicklertipps

Hier ist eine Liste mit Dingen, die ich gerne gewusst hätte, als ich mit Web NFC angefangen habe:

  • Android verarbeitet NFC-Tags auf Betriebssystemebene, bevor Web NFC aktiv ist.
  • Ein NFC-Symbol finden Sie auf material.io.
  • Mit dem NDEF-Eintrag id können Sie einen Eintrag bei Bedarf einfach identifizieren.
  • Ein nicht formatiertes NFC-Tag, das NDEF unterstützt, enthält einen einzelnen Eintrag vom Typ „leer“.
  • Das Erstellen eines Android App-Eintrags ist einfach, wie unten gezeigt.
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] });

Demos

Probieren Sie das offizielle Beispiel aus und sehen Sie sich einige coole Web-NFC-Demos an:

NFC-Karten-Demo für das Web auf dem Chrome Dev Summit 2019

Feedback

Die Web NFC Community Group und das Chrome-Team würden sich sehr über Ihre Meinung und Ihre Erfahrungen mit Web NFC freuen.

Informationen zum API-Design

Funktioniert die API nicht wie erwartet? Oder fehlen Methoden oder Eigenschaften, die Sie für die Implementierung Ihrer Idee benötigen?

Melden Sie ein Problem mit der Spezifikation im GitHub-Repository für Web NFC oder fügen Sie Ihre Gedanken zu einem vorhandenen Problem hinzu.

Problem mit der Implementierung melden

Haben Sie einen Fehler in der Chrome-Implementierung gefunden? Oder unterscheidet sich die Implementierung von der Spezifikation?

Melden Sie den Fehler unter https://new.crbug.com. Geben Sie so viele Details wie möglich an, machen Sie eine einfache Anleitung zum Nachstellen des Fehlers und setzen Sie Components auf Blink>NFC. Glitch eignet sich hervorragend, um schnell und einfach Reproduktionen zu teilen.

Unterstützung zeigen

Planen Sie die Verwendung von Web-NFC? Ihr öffentlicher Support hilft dem Chrome-Team dabei, Funktionen zu priorisieren, und zeigt anderen Browseranbietern, wie wichtig es ist, diese zu unterstützen.

Senden Sie einen Tweet an @ChromiumDev mit dem Hashtag #WebNFC und teilen Sie uns mit, wo und wie Sie ihn verwenden.

Nützliche Links

Danksagungen

Vielen Dank an das Intel-Team für die Implementierung von Web NFC. Google Chrome ist auf eine Community von Google Chrome-Mitgliedern angewiesen, die zusammenarbeiten, um das Chromium-Projekt voranzutreiben. Nicht jeder Chromium-Committer ist ein Google-Mitarbeiter. Diese Mitwirkenden verdienen eine besondere Anerkennung.