Interakcja z urządzeniami NFC w Chrome na Androida

Możesz teraz odczytywać i zapisywać tagi NFC.

François Beaufort
François Beaufort

Czym jest Web NFC?

NFC to komunikacja Near Field Communication, czyli technologia bezprzewodowa krótkiego zasięgu działająca na częstotliwości 13,56 MHz, która umożliwia komunikację między urządzeniami w odległości mniejszej niż 10 cm i prędkości transmisji do 424 kbit/s.

Interfejs Web NFC umożliwia stronom odczytywanie i zapisywanie tagów NFC, gdy znajdują się one w pobliżu urządzenia użytkownika (zwykle w odległości 5–10 cm). Obecny zakres jest ograniczony do formatu wymiany danych NFC (NDEF), który jest lekkim binarnym formatem wiadomości działającym w różnych formatach tagów.

Telefon zasilający tag NFC w celu wymiany danych
Diagram działania NFC

Sugerowane przypadki użycia

Web NFC jest ograniczona do NDEF, ponieważ właściwości zabezpieczeń związane z odczytywaniem i zapisywaniem danych NDEF są łatwiejsze do określenia. Operacje wejścia/wyjścia niskiego poziomu (np. ISO-DEP, NFC-A/B, NFC-F), tryb komunikacji peer-to-peer i emulacja karty na hoście (HCE) nie są obsługiwane.

Przykłady witryn, które mogą korzystać z Web NFC:

  • Muzea i galerie sztuki mogą wyświetlać dodatkowe informacje o ekspozycji, gdy użytkownik przyłoży urządzenie do karty NFC w pobliżu eksponatu.
  • Witryny do zarządzania asortymentem mogą odczytywać lub zapisywać dane na tagu NFC na pojemniku, aby aktualizować informacje o jego zawartości.
  • Organizatorzy konferencji mogą używać tej funkcji do skanowania identyfikatorów NFC podczas wydarzenia i blokowania ich, aby zapobiec dalszym zmianom informacji na nich zapisanych.
  • Witryny mogą używać go do udostępniania początkowych informacji tajnych potrzebnych w scenariuszach udostępniania urządzeń lub usług, a także do wdrażania danych konfiguracyjnych w trybie operacyjnym.
Telefon skanujący kilka tagów NFC
Ilustracja zarządzania asortymentem za pomocą NFC

Obecny stan,

Krok Stan
1. Tworzenie wyjaśnienia Zakończono
2. Tworzenie wstępnej wersji specyfikacji Zakończono
3. Zbieranie opinii i ulepszanie projektu Zakończono
4. Wersja próbna origin Zakończono
5. Uruchom Zakończono

Korzystanie z Web NFC

Wykrywanie cech

Wykrywanie funkcji sprzętu różni się od tego, do czego prawdopodobnie jesteś przyzwyczajony(-a). Obecność ikony NDEFReader oznacza, że przeglądarka obsługuje Web NFC, ale nie informuje, czy wymagany sprzęt jest dostępny. W szczególności, jeśli sprzęt jest niedostępny, obietnica zwrócona przez niektóre wywołania zostanie odrzucona. Szczegóły podam, gdy będę opisywać NDEFReader.

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

Terminologia

Tag NFC to pasywne urządzenie NFC, co oznacza, że jest zasilane przez indukcję magnetyczną, gdy w pobliżu znajduje się aktywne urządzenie NFC (np. telefon). Tagi NFC mają różne formy, np. naklejki, karty kredytowe, opaski na rękę i inne.

Zdjęcie przezroczystego tagu NFC
Przezroczysty tag NFC

Obiekt NDEFReader to punkt wejścia w Web NFC, który udostępnia funkcje przygotowywania działań związanych z odczytywaniem lub zapisywaniem, które są wykonywane, gdy w pobliżu znajdzie się tag NDEF. Symbol NDEFNDEFReader oznacza NFC Data Exchange Format, czyli lekki binarny format wiadomości standaryzowany przez NFC Forum.

Obiekt NDEFReader służy do obsługi przychodzących wiadomości NDEF z tagów NFC i do zapisywania wiadomości NDEF na tagach NFC w zasięgu.

Tag NFC obsługujący format NDEF jest jak karteczka samoprzylepna. Każdy może go odczytać, a jeśli nie jest on tylko do odczytu, każdy może w nim zapisywać. Zawiera pojedynczą wiadomość NDEF, która obejmuje co najmniej 1 rekord NDEF. Każdy rekord NDEF to struktura binarna zawierająca ładunek danych i powiązane informacje o typie. Web NFC obsługuje te standardowe typy rekordów NFC Forum: empty, text, URL, smart poster, MIME type, absolute URL, external type, unknown i local type.

Diagram wiadomości NDEF
Diagram wiadomości NDEF

Skanowanie tagów NFC

Aby skanować tagi NFC, najpierw utwórz nowy obiekt NDEFReader. Wywołanie funkcji scan() zwraca obietnicę. Użytkownik może zostać poproszony o zgodę, jeśli nie została ona wcześniej udzielona. Obietnica zostanie spełniona, jeśli zostaną spełnione wszystkie te warunki:

  • Było ono wywoływane tylko w odpowiedzi na gest użytkownika, np. dotknięcie lub kliknięcie myszą.
  • Użytkownik zezwolił witrynie na korzystanie z urządzeń NFC.
  • Telefon użytkownika obsługuje komunikację NFC.
  • Użytkownik włączył komunikację NFC na telefonie.

Gdy obietnica zostanie spełniona, przychodzące wiadomości NDEF będą dostępne po zasubskrybowaniu zdarzeń reading za pomocą detektora zdarzeń. Aby otrzymywać powiadomienia o niezgodnych tagach NFC w pobliżu, musisz też subskrybować zdarzenia 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}.`);
});

Gdy tag NFC znajduje się w pobliżu, wywoływane jest zdarzenie NDEFReadingEvent. Zawiera 2 unikalne właściwości:

  • serialNumber to numer seryjny urządzenia (np. 00-11-22-33-44-55-66) lub pusty ciąg znaków, jeśli nie jest dostępny.
  • message reprezentuje wiadomość NDEF zapisaną w tagu NFC.

Aby odczytać treść wiadomości NDEF, przejdź w pętli przez elementy message.records i przetwórz ich elementy data w odpowiedni sposób na podstawie ich wartości recordType. Element data jest udostępniany jako DataView, ponieważ umożliwia obsługę przypadków, w których dane są zakodowane w formacie 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.
    }
  }
};

Zapisywanie tagów NFC

Aby zapisać tagi NFC, najpierw utwórz instancję nowego obiektu NDEFReader. Wywołanie write() zwraca obietnicę. Użytkownik może otrzymać prośbę, jeśli dostęp nie został wcześniej przyznany. W tym momencie wiadomość NDEF jest „przygotowywana”, a obietnica zostanie spełniona, jeśli zostaną spełnione wszystkie te warunki:

  • Było ono wywoływane tylko w odpowiedzi na gest użytkownika, np. dotknięcie lub kliknięcie myszą.
  • Użytkownik zezwolił witrynie na korzystanie z urządzeń NFC.
  • Telefon użytkownika obsługuje komunikację NFC.
  • Użytkownik włączył komunikację NFC na telefonie.
  • Użytkownik dotknął tagu NFC i wiadomość NDEF została zapisana.

Aby zapisać tekst na tagu NFC, przekaż ciąg znaków do metody write().

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

Aby zapisać rekord adresu URL w tagu NFC, przekaż do funkcji write() słownik reprezentujący wiadomość NDEF. W przykładzie poniżej wiadomość NDEF jest słownikiem z kluczem records. Jego wartością jest tablica rekordów – w tym przypadku rekord adresu URL zdefiniowany jako obiekt z kluczem recordType ustawionym na "url" i kluczem data ustawionym na ciąg adresu 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}.`);
});

Na tagu NFC można też zapisać wiele rekordów.

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

Jeśli tag NFC zawiera wiadomość NDEF, która nie ma być zastąpiona, ustaw właściwość overwrite na false w opcjach przekazywanych do metody write(). W takim przypadku zwrócony obiekt Promise zostanie odrzucony, jeśli w tagu NFC jest już zapisana wiadomość NDEF.

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

Ustawianie tagów NFC jako tylko do odczytu

Aby uniemożliwić hakerom nadpisywanie zawartości tagu NFC, można ustawić tagi NFC jako trwale tylko do odczytu. Jest to proces jednokierunkowy, którego nie można cofnąć. Gdy tag NFC zostanie ustawiony jako tylko do odczytu, nie będzie można już na nim zapisywać danych.

Aby tagi NFC były tylko do odczytu, najpierw utwórz instancję nowego obiektu NDEFReader. Wywołanie makeReadOnly() zwraca obietnicę. Użytkownik może otrzymać prośbę, jeśli dostęp nie został wcześniej przyznany. Obietnica zostanie spełniona, jeśli zostaną spełnione wszystkie te warunki:

  • Było ono wywoływane tylko w odpowiedzi na gest użytkownika, np. dotknięcie lub kliknięcie myszą.
  • Użytkownik zezwolił witrynie na korzystanie z urządzeń NFC.
  • Telefon użytkownika obsługuje komunikację NFC.
  • Użytkownik włączył komunikację NFC na telefonie.
  • Użytkownik dotknął tagu NFC i został on pomyślnie ustawiony jako tylko do odczytu.
const ndef = new NDEFReader();
ndef.makeReadOnly()
.then(() => {
  console.log("NFC tag has been made permanently read-only.");
}).catch(error => {
  console.log(`Operation failed: ${error}`);
});

Oto jak po zapisaniu danych na tagu NFC ustawić go na stałe jako tylko do odczytu.

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

Funkcja makeReadOnly() jest dostępna na Androidzie w Chrome w wersji 100 lub nowszej. Aby sprawdzić, czy jest ona obsługiwana, wykonaj te czynności:

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

Zabezpieczenia i uprawnienia

Zespół Chrome zaprojektował i wdrożył Web NFC zgodnie z głównymi zasadami określonymi w dokumencie Controlling Access to Powerful Web Platform Features, w tym kontrolą użytkownika, przejrzystością i ergonomią.

NFC rozszerza zakres informacji potencjalnie dostępnych dla złośliwych stron internetowych, dlatego dostępność NFC jest ograniczona, aby zwiększyć świadomość użytkowników i kontrolę nad korzystaniem z tej technologii.

Zrzut ekranu z prośbą o użycie technologii Web NFC w witrynie
Prośba o potwierdzenie użytkownika w przypadku Web NFC

Interfejs Web NFC jest dostępny tylko w ramkach najwyższego poziomu i bezpiecznych kontekstach przeglądania (tylko HTTPS). Pochodzenia muszą najpierw poprosić o "nfc" uprawnienia podczas obsługi gestu użytkownika (np.kliknięcia przycisku). Metody NDEFReader scan(), write()makeReadOnly() wywołują prośbę o zgodę użytkownika, jeśli dostęp nie został wcześniej przyznany.

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

Połączenie wywołanego przez użytkownika okna z prośbą o uprawnienia i rzeczywistego, fizycznego ruchu polegającego na zbliżeniu urządzenia do docelowego tagu NFC odzwierciedla wzorzec selektora występujący w innych interfejsach API dostępu do plików i urządzeń.

Aby przeprowadzić skanowanie lub zapis, strona internetowa musi być widoczna, gdy użytkownik dotknie tagu NFC urządzeniem. Przeglądarka używa reakcji haptycznej, aby wskazać kliknięcie. Dostęp do modułu NFC jest blokowany, gdy wyświetlacz jest wyłączony lub urządzenie jest zablokowane. W przypadku niewidocznych stron internetowych odbieranie i przesyłanie treści NFC jest wstrzymane i wznawiane, gdy strona internetowa ponownie staje się widoczna.

Dzięki interfejsowi Page Visibility API można śledzić zmiany widoczności dokumentu.

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

Książka kucharska

Oto kilka przykładowych kodów, które pomogą Ci zacząć.

Sprawdzanie uprawnień

Interfejs Permissions API umożliwia sprawdzanie, czy przyznano uprawnienie "nfc". Ten przykład pokazuje, jak skanować tagi NFC bez interakcji użytkownika, jeśli dostęp został wcześniej przyznany, lub w przeciwnym razie wyświetlić przycisk. Pamiętaj, że ten sam mechanizm działa w przypadku zapisywania tagów NFC, ponieważ wykorzystuje to samo uprawnienie.

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

Przerywanie operacji NFC

Użycie elementu AbortController ułatwia przerywanie operacji NFC. Poniższy przykład pokazuje, jak przekazać signal elementu AbortController przez opcje metod NDEFReader scan(), makeReadOnly()write() oraz jednocześnie przerwać obie operacje 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();
};

Odczyt po zapisie

Użycie write(), a następnie scan()AbortController umożliwia odczytanie tagu NFC po zapisaniu w nim wiadomości. Poniższy przykład pokazuje, jak zapisać wiadomość tekstową na tagu NFC i odczytać nową wiadomość z tagu NFC. Skanowanie zatrzymuje się po 3 sekundach.

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

Odczytywanie i zapisywanie rekordu tekstowego

Rekord tekstowy data można odszyfrować za pomocą obiektu TextDecoder utworzonego na podstawie rekordu encoding. Język rekordu tekstowego jest dostępny we właściwości lang.

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

Aby zapisać prosty rekord tekstowy, przekaż ciąg znaków do metody NDEFReader write().

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

Rekordy tekstowe są domyślnie kodowane w UTF-8 i zakładają język bieżącego dokumentu, ale obie właściwości (encodinglang) można określić za pomocą pełnej składni tworzenia niestandardowego rekordu NDEF.

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

Odczytywanie i zapisywanie rekordu adresu URL

Użyj kodu TextDecoder, aby zdekodować data rekordu.

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

Aby zapisać rekord URL, przekaż słownik wiadomości NDEF do metody NDEFReader write(). Rekord adresu URL zawarty w wiadomości NDEF jest zdefiniowany jako obiekt z kluczem recordType ustawionym na "url" i kluczem data ustawionym na ciąg adresu URL.

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

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

Odczytywanie i zapisywanie rekordu typu MIME

Właściwość mediaType rekordu typu MIME reprezentuje typ MIME ładunku rekordu NDEF, dzięki czemu data może zostać prawidłowo zdekodowany. Na przykład użyj funkcji JSON.parse do dekodowania tekstu JSON i elementu Image do dekodowania danych obrazu.

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

Aby zapisać rekord typu MIME, przekaż słownik wiadomości NDEF do metody NDEFReader write(). Rekord typu MIME zawarty w wiadomości NDEF jest zdefiniowany jako obiekt z kluczem recordType ustawionym na "mime", kluczem mediaType ustawionym na rzeczywisty typ MIME treści i kluczem data ustawionym na obiekt, który może być ArrayBuffer lub zapewniać widok na ArrayBuffer (np. 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] });

Odczytywanie i zapisywanie rekordu z adresem URL bezwzględnym

Rekord absolute-URL data można dekodować za pomocą prostego TextDecoder.

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

Aby zapisać rekord z adresem URL, przekaż słownik wiadomości NDEF do metody NDEFReader write(). Rekord adresu URL bezwzględnego zawarty w wiadomości NDEF jest zdefiniowany jako obiekt z kluczem recordType ustawionym na "absolute-url" i kluczem data ustawionym na ciąg adresu URL.

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

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

Odczytywanie i zapisywanie rekordu plakatu inteligentnego

Rekord inteligentnego plakatu (używany w reklamach w czasopismach, ulotkach, billboardach itp.) opisuje niektóre treści internetowe jako rekord NDEF, który zawiera wiadomość NDEF jako ładunek. Wywołaj funkcję record.toRecords(), aby przekształcić data w listę rekordów zawartych w rekordzie plakatu inteligentnego. Powinien on zawierać rekord URL, rekord tekstowy dla tytułu, rekord typu MIME dla obrazu i kilka niestandardowych rekordów typu lokalnego, takich jak ":t", ":act"":s", odpowiednio dla typu, działania i rozmiaru rekordu plakatu inteligentnego.

Rekordy typu lokalnego są unikalne tylko w kontekście lokalnym rekordu NDEF, który je zawiera. Używaj ich, gdy znaczenie typów nie ma znaczenia poza lokalnym kontekstem rekordu zawierającego te typy i gdy zużycie pamięci jest istotnym ograniczeniem. Nazwy rekordów typu lokalnego zawsze zaczynają się od znaku : w przypadku interfejsu Web NFC (np. ":t", ":s", ":act"). Ma to na celu odróżnienie rekordu tekstowego od rekordu tekstowego typu lokalnego.

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

Aby zapisać rekord inteligentnego plakatu, przekaż wiadomość NDEF do metody NDEFReader write(). Rekord plakatu inteligentnego zawarty w wiadomości NDEF jest zdefiniowany jako obiekt z kluczem recordType ustawionym na "smart-poster" i kluczem data ustawionym na obiekt, który (ponownie) reprezentuje wiadomość NDEF zawartą w rekordzie plakatu inteligentnego.

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

Odczytywanie i zapisywanie rekordu typu zewnętrznego

Aby utworzyć rekordy zdefiniowane przez aplikację, użyj rekordów typu zewnętrznego. Mogą one zawierać wiadomość NDEF jako ładunek, do którego można uzyskać dostęp za pomocą toRecords(). Ich nazwa zawiera nazwę domeny organizacji wydającej, dwukropek i nazwę typu o długości co najmniej 1 znaku, np. "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.
    }
  }
}

Aby zapisać rekord typu zewnętrznego, przekaż słownik wiadomości NDEF do metody NDEFReader write(). Rekord typu zewnętrznego zawarty w wiadomości NDEF jest zdefiniowany jako obiekt z kluczem recordType ustawionym na nazwę typu zewnętrznego i kluczem data ustawionym na obiekt reprezentujący wiadomość NDEF zawartą w rekordzie typu zewnętrznego. Pamiętaj, że klucz data może być też ArrayBuffer lub zapewniać widok na ArrayBuffer (np. Uint8Array, 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] });

Odczytywanie i zapisywanie pustego rekordu

Pusty rekord nie zawiera ładunku.

Aby zapisać pusty rekord, przekaż słownik wiadomości NDEF do metody NDEFReader write(). Pusty rekord zawarty w wiadomości NDEF jest zdefiniowany jako obiekt z kluczem recordType ustawionym na "empty".

const emptyRecord = {
  recordType: "empty"
};

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

Obsługa przeglądarek

Technologia Web NFC jest dostępna na Androidzie w Chrome 89.

Wskazówki dla programistów

Oto lista rzeczy, które warto było wiedzieć, zanim zacząłem korzystać z Web NFC:

  • Android obsługuje tagi NFC na poziomie systemu operacyjnego, zanim zacznie działać Web NFC.
  • Ikonę NFC znajdziesz na stronie material.io.
  • Użyj rekordu NDEF id, aby w razie potrzeby łatwo zidentyfikować rekord.
  • Nieformatowany tag NFC obsługujący NDEF zawiera jeden rekord pustego typu.
  • Napisanie rekordu aplikacji na Androida jest proste, jak pokazano poniżej.
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] });

Przykłady

Wypróbuj oficjalny przykład i obejrzyj ciekawe demonstracje Web NFC:

Prezentacja kart Web NFC na konferencji Chrome Dev Summit 2019

Prześlij opinię

Grupa społecznościowa Web NFC i zespół Chrome chętnie poznają Twoje opinie i doświadczenia związane z Web NFC.

Opisz projekt interfejsu API

Czy w API jest coś, co nie działa zgodnie z oczekiwaniami? Czy brakuje metod lub właściwości, które są Ci potrzebne do realizacji pomysłu?

Zgłoś problem ze specyfikacją w repozytorium GitHub Web NFC lub dodaj swoje uwagi do istniejącego problemu.

Zgłaszanie problemu z implementacją

Czy w implementacji Chrome występuje błąd? Czy implementacja różni się od specyfikacji?

Zgłoś błąd na stronie https://new.crbug.com. Podaj jak najwięcej szczegółów, proste instrukcje odtwarzania błędu i ustaw Komponenty na Blink>NFC.

Okaż wsparcie

Czy planujesz używać Web NFC? Twoje publiczne wsparcie pomaga zespołowi Chrome ustalać priorytety funkcji i pokazuje innym dostawcom przeglądarek, jak ważne jest ich obsługiwanie.

Wyślij tweeta do @ChromiumDev z hasztagiem #WebNFC i napisz, gdzie i jak korzystasz z tej funkcji.

Przydatne linki

Podziękowania

Dziękujemy zespołowi firmy Intel za wdrożenie Web NFC. Google Chrome zależy od społeczności osób zatwierdzających zmiany, które wspólnie rozwijają projekt Chromium. Nie każdy programista Chromium jest pracownikiem Google, a ci współtwórcy zasługują na szczególne uznanie.