Signatur
Beschreibung
Der Konstruktor NDEFReader() ist der Einstieg in die Web NFC API. Das zurückgegebene Objekt stellt die Methoden scan(), write() und makeReadOnly() bereit und löst die Ereignisse reading und readingerror aus. So können Webanwendungen NFC-Tags im NDEF-Format (NFC Data Exchange Format) lesen und beschreiben, etwa für Inventarlisten, Eintrittskarten, Museumsführer oder zum Koppeln von Geräten.
Der Konstruktor hat keine Parameter und fragt selbst noch keine Berechtigung ab. Den Berechtigungsdialog zeigt der Browser erst beim ersten Aufruf von scan() oder write(), und dieser Aufruf muss durch eine Nutzeraktion ausgelöst werden, zum Beispiel durch einen Klick. In der Praxis erzeugt man den Reader deshalb meist in einem Klick-Handler oder hält eine Instanz bereit und startet den Scan erst nach einer Nutzereingabe.
NDEFReader erbt von EventTarget. Gelesene Nachrichten kommen als NDEFReadingEvent an, mit den Eigenschaften serialNumber und message (ein NDEFMessage mit einem Array aus NDEFRecord-Objekten). Einen laufenden Scan beendet man über ein AbortSignal, das man an scan() übergibt.
Rückgabewert
NDEFReader-Objekt. Es scannt noch nicht und hat noch keine Berechtigung angefragt.Beispiele
Feature-Erkennung und Instanziierung
if ('NDEFReader' in window) {
const reader = new NDEFReader();
console.log('Web NFC verfügbar:', reader instanceof EventTarget);
} else {
console.log('Web NFC wird von diesem Browser nicht unterstützt.');
}
Tags nach Klick scannen und Text-Records auslesen
const scanButton = document.querySelector('#scan');
scanButton.addEventListener('click', async () => {
const reader = new NDEFReader();
try {
await reader.scan(); // löst den Berechtigungsdialog aus
console.log('Scan gestartet – Tag an das Gerät halten.');
reader.addEventListener('reading', ({ serialNumber, message }) => {
console.log(`Tag erkannt: ${serialNumber}`);
for (const record of message.records) {
if (record.recordType === 'text') {
const decoder = new TextDecoder(record.encoding ?? 'utf-8');
console.log('Text:', decoder.decode(record.data));
} else {
console.log('Record-Typ:', record.recordType);
}
}
});
reader.addEventListener('readingerror', () => {
console.warn('Tag konnte nicht gelesen werden (kein NDEF?).');
});
} catch (error) {
console.error('Scan fehlgeschlagen:', error.name, error.message);
}
});
URL auf ein Tag schreiben
document.querySelector('#write').addEventListener('click', async () => {
const writer = new NDEFReader();
try {
await writer.write({
records: [{ recordType: 'url', data: 'https://programmierung.net' }]
});
console.log('URL erfolgreich auf das Tag geschrieben.');
} catch (error) {
console.error('Schreiben fehlgeschlagen:', error.message);
}
});
Scan mit AbortController zeitlich begrenzen
const startTimedScan = async (ms = 10000) => {
const reader = new NDEFReader();
const controller = new AbortController();
reader.onreading = (event) => {
console.log('Gelesen:', event.serialNumber);
controller.abort(); // nach dem ersten Tag aufhören
};
controller.signal.addEventListener('abort', () => console.log('Scan beendet.'));
setTimeout(() => controller.abort(), ms);
await reader.scan({ signal: controller.signal });
};
document.querySelector('#scan').addEventListener('click', () => startTimedScan());
// Wichtig · Fallstricke
- Browser-Kompatibilität: Web NFC ist experimentell und wird nur von Chrome für Android (ab Version 89) und darauf aufbauenden Browsern unterstützt. Desktop-Browser, Firefox und Safari/iOS kennen
NDEFReadernicht, daher immer vorher mit'NDEFReader' in windowprüfen. - Sicherer Kontext: Die API steht nur über HTTPS (oder
localhost) und nur im Top-Level-Dokument zur Verfügung, nicht in eingebetteten iframes über fremde Origins. - Nutzeraktion erforderlich: Der Konstruktor läuft auch ohne Nutzeraktion, aber
scan()undwrite()lehnen mit einemNotAllowedErrorab, wenn keine Nutzeraktion vorausging oder der Nutzer die Berechtigung verweigert hat. Ist NFC am Gerät ausgeschaltet oder nicht vorhanden, gibt es einenNotReadableErrorbzw.NotSupportedError. - Sichtbarkeit: Gelesen wird nur, solange die Seite sichtbar ist und den Fokus hat. Im Hintergrund kommen keine
reading-Ereignisse an. - Sicherheit: Tag-Inhalte sind nicht vertrauenswürdige Eingaben. Gelesene Texte oder URLs nie ungeprüft per
innerHTMLeinfügen oder automatisch aufrufen, sonst drohen XSS oder Phishing.makeReadOnly()macht ein Tag dauerhaft schreibgeschützt, und das lässt sich nicht rückgängig machen. - Den
reading-Listener am besten vor oder direkt nachawait scan()registrieren, damit keine Ereignisse verloren gehen.