Interakcja z urządzeniami NFC w Chrome na Androida

Teraz możliwe jest odczytywanie i zapisywanie tagów NFC.

François Beaufort
François Beaufort

Co to jest internetowa komunikacja NFC?

NFC to skrót od Near Field Communications.Jest to technologia bezprzewodowa krótkiego zasięgu działającego w prędkości 13,56 MHz, która umożliwia komunikację między urządzeniami w odległości mniejszej niż 10 cm i z prędkością transmisji do 424 kb/s.

Internetowa komunikacja NFC umożliwia witrynom odczytywanie i zapisywanie tagów NFC, gdy znajdują się one w niewielkiej odległości od urządzenia użytkownika (zwykle w odległości 5–10 cm, 2–4 cali). Obecny zakres jest ograniczony do NFC Data Exchange Format (NDEF) – lekkiego formatu wiadomości binarnych, który działa z różnymi formatami tagów.

Telefon uruchamiający tag NFC do wymiany danych
Diagram operacji NFC

Sugerowane przypadki użycia

Internetowa komunikacja NFC ogranicza się do NDEF, ponieważ właściwości zabezpieczeń związane z odczytem i zapisem danych NDEF są łatwiejsze do zmierzenia. Operacje wejścia-wyjścia niskiego poziomu (np. ISO-DEP, NFC-A/B, NFC-F), tryb komunikacji peer-to-peer oraz operacje emulacji karty hosta (HCE) nie są obsługiwane.

Oto przykłady witryn, które mogą używać technologii NFC (Web NFC):

  • Muzea i galerie sztuki mogą wyświetlać dodatkowe informacje o wyświetlaczu, gdy użytkownik dotknie urządzenia NFC w pobliżu wystawy.
  • Witryny zarządzania asortymentem mogą odczytywać lub zapisywać dane w tagu NFC w kontenerze, aby aktualizować informacje o jego zawartości.
  • Lokale konferencyjne mogą używać tego urządzenia do skanowania plakietek NFC podczas wydarzenia i pilnować, aby były zablokowane, aby zapobiec dalszej zmianie zapisanych na nich informacji.
  • Witryny mogą używać jej do udostępniania początkowych obiektów tajnych wymaganych 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 z komunikacją NFC

Obecny stan,

Step Stan
1. Utwórz wyjaśnienie Zakończono
2. Utwórz wstępną wersję roboczą specyfikacji Zakończono
3. Zbieranie opinii i ulepszanie projektu Zakończono
4. Testowanie origin Zakończono
5. Uruchom Zakończono

Używaj Web NFC

Wykrywanie funkcji

Wykrywanie funkcji na sprzęcie różni się od tego, do którego należysz. Obecność NDEFReader informuje, że przeglądarka obsługuje komunikację NFC, ale nie informuje o tym, czy jest potrzebny wymagany sprzęt. Jeśli brakuje sprzętu, obietnica zwracana przez określone wywołania zostanie odrzucona. Więcej szczegółów podam NDEFReader.

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

Terminologia

Tag NFC to pasywne urządzenie NFC, które jest zasilane indukcją magnetyczną, gdy w pobliżu znajduje się aktywne urządzenie NFC. Tagi NFC występują na wiele sposobów, np. naklejki, karty kredytowe i nadgarstki.

Zdjęcie przezroczystego tagu NFC
Przezroczysty tag NFC

Obiekt NDEFReader to punkt wejścia w internetowej technologii NFC, który udostępnia funkcje przygotowywania działań odczytu lub zapisu, które są wykonywane, gdy tag NDEF znajduje się w pobliżu. NDEF w NDEFReader to skrót od NFC Data Exchange Format, czyli lekki format wiadomości binarnych ustandaryzowany przez NFC Forum.

Obiekt NDEFReader służy do obsługi wiadomości NDEF przychodzących z tagów NFC oraz do zapisywania komunikatów NDEF do tagów NFC znajdujących się w zasięgu.

Tag NFC, który obsługuje NDEF, jest jak kartka pocztowa. Każdy może go przeczytać, ale każdy może do niego pisać, chyba że jest w trybie tylko do odczytu. Zawiera on pojedynczą wiadomość NDEF zawierającą 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: puste, tekst, adres URL, inteligentny plakat, typ MIME, bezwzględny URL, typ zewnętrzny, nieznany i typ lokalny.

Schemat wiadomości NDEF
Diagram wiadomości NDEF

Skanuj tagi NFC

Aby zeskanować tagi NFC, najpierw utwórz nowy obiekt NDEFReader. Wywołanie scan() zwraca obietnicę. Jeśli dostęp nie został wcześniej przyznany, użytkownik może zobaczyć prośbę. Obietnica wygaśnie, jeśli zostaną spełnione te warunki:

  • Jest ona wywoływana tylko w odpowiedzi na gest użytkownika, np. gest dotyku lub kliknięcie myszą.
  • Użytkownik zezwolił stronie na interakcję z urządzeniami z NFC.
  • Telefon użytkownika obsługuje komunikację NFC.
  • użytkownik włączył komunikację NFC na telefonie;

Po rozwiązaniu obietnicy przychodzące wiadomości NDEF będą dostępne po zarejestrowaniu zdarzeń reading za pomocą detektora zdarzeń. Musisz też zasubskrybować zdarzenia readingerror, aby otrzymywać powiadomienia, gdy w pobliżu będą się znajdować niezgodne tagi NFC.

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, przejrzyj message.records i przetwórz ich członków data odpowiednio na podstawie ich recordType. Element data jest widoczny 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 nowy obiekt NDEFReader. Wywołanie write() zwraca obietnicę. Jeśli dostęp nie został wcześniej przyznany, użytkownik może zobaczyć prośbę. Na tym etapie komunikat NDEF jest „gotowy” i obietnica zniknie, jeśli zostaną spełnione te warunki:

  • Jest ona wywoływana tylko w odpowiedzi na gest użytkownika, np. gest dotyku lub kliknięcie myszą.
  • Użytkownik zezwolił stronie na interakcję z urządzeniami z NFC.
  • Telefon użytkownika obsługuje komunikację NFC.
  • użytkownik włączył komunikację NFC na telefonie;
  • Użytkownik dotknął tagu NFC, a wiadomość NDEF została napisana.

Aby zapisać tekst do 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 do tagu NFC, przekaż do write() słownik reprezentujący wiadomość NDEF. W poniższym przykładzie komunikat NDEF to słownik 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", a 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}.`);
});

W tagu NFC możesz 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 komunikat NDEF, którego nie należy zastąpić, ustaw właściwość overwrite na false w opcjach przekazywanych do metody write(). W takim przypadku zwrócona obietnica zostanie odrzucona, jeśli wiadomość NDEF jest już zapisana w tagu NFC.

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

Ustaw tagi NFC w trybie tylko do odczytu

Aby zapobiec zastępowaniu zawartości tagu NFC przez złośliwych użytkowników, można skonfigurować tagi NFC w sposób trwały tylko do odczytu. Jest to proces jednokierunkowy i nie można go cofnąć. Po zmianie tagu NFC w tryb tylko do odczytu nie można już w nim zapisywać danych.

Aby tagi NFC były dostępne tylko do odczytu, najpierw utwórz nowy obiekt NDEFReader. Wywołanie makeReadOnly() zwraca obietnicę. Jeśli dostęp nie został wcześniej przyznany, użytkownik może zobaczyć prośbę. Obietnica wygaśnie, jeśli zostaną spełnione te warunki:

  • Jest ona wywoływana tylko w odpowiedzi na gest użytkownika, np. gest dotyku lub kliknięcie myszą.
  • Użytkownik zezwolił stronie na interakcję z urządzeniami z NFC.
  • Telefon użytkownika obsługuje komunikację NFC.
  • użytkownik włączył komunikację NFC na telefonie;
  • Użytkownik dotknął tagu NFC, a tag NFC został oznaczony 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}`);
});

Jak zmienić tag NFC na stałe w tryb tylko do odczytu po zapisaniu do niego.

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

Usługa makeReadOnly() jest dostępna na urządzeniach z Androidem w Chrome 100 i nowszych, dlatego sprawdź, czy obsługuje ją:

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

Zabezpieczenia i uprawnienia

Zespół Chrome zaprojektował i wdrożył komunikację NFC przy użyciu podstawowych zasad określonych w sekcji Kontrolowanie dostępu do funkcji platformy internetowej, takich jak kontrola użytkownika, przejrzystość i ergonomia.

Technologia NFC obejmuje domenę informacji potencjalnie dostępnych dla szkodliwych witryn, dlatego dostępność tej technologii jest ograniczona, by zmaksymalizować świadomość marki i kontrolę nad wykorzystaniem technologii NFC.

Zrzut ekranu przedstawiający komunikat NFC w internecie na stronie internetowej
Prompt użytkownika internetowego komunikacji NFC

Internetowa komunikacja NFC jest dostępna tylko w ramkach najwyższego poziomu i w kontekstach bezpiecznego przeglądania (tylko HTTPS). Źródła muszą najpierw prosić o uprawnienie "nfc" podczas wykonywania gestu użytkownika (np.kliknięcia przycisku). Metody NDEFReader scan(), write() i makeReadOnly() aktywują pytanie 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 zainicjowanej przez użytkownika prośby o przyznanie uprawnień i rzeczywistego, fizycznego ruchu polegającego na przeniesieniu urządzenia do docelowego tagu NFC odzwierciedla wzorzec wyboru w innych interfejsach API dostępu do plików i urządzenia.

Aby możliwe było skanowanie lub zapisywanie, strona internetowa musi być widoczna, gdy użytkownik dotknie tagu NFC swoim urządzeniem. Przeglądarka sygnalizuje dotknięcie na podstawie reakcji haptycznych. Dostęp do radia NFC jest zablokowany, gdy wyświetlacz jest wyłączony lub urządzenie jest zablokowane. W przypadku niewidocznych stron internetowych odbieranie i przekazywanie treści z użyciem NFC jest zawieszane, a następnie wznawiane, gdy strona znowu stanie się widoczna.

Interfejs Widoczność strony pozwala śledzić zmiany widoczności dokumentów.

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ładów kodu na dobry początek.

Sprawdź uprawnienia

Interfejs Permissions API pozwala sprawdzić, czy przyznano uprawnienie "nfc". Ten przykład pokazuje, jak skanować tagi NFC bez interakcji z użytkownikiem, jeśli dostęp został przyznany wcześniej, lub jak w innym przypadku wyświetlić przycisk. Pamiętaj, że ten sam mechanizm działa przy pisaniu tagów NFC i korzysta z tych samych uprawnień.

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

Przerwij operacje NFC

Użycie elementu podstawowego AbortController ułatwia przerywanie operacji NFC. Poniższy przykład pokazuje, jak przekazać signal obiektu AbortController za pomocą metod NDEFReader scan(), makeReadOnly(), write() i przerwać obie operacje NFC jednocześnie.

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

Czytaj po zapisaniu

Użycie write(), a następnie scan() z elementem podstawowym AbortController umożliwia odczytanie tagu NFC po napisaniu w nim wiadomości. Poniższy przykład pokazuje, jak napisać SMS-a na tag NFC i odczytać nową wiadomość w tagu NFC. Przestaje się skanować 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 zdekodować za pomocą instancji TextDecoder utworzonej z właściwością rekordu encoding. Język rekordu tekstowego jest dostępny za pomocą jego 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 napisać prosty rekord tekstowy, przekaż ciąg do metody write() NDEFReader.

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

Rekordy tekstowe mają domyślnie kodowanie UTF-8 i przyjmują język bieżącego dokumentu, ale obie właściwości (encoding i lang) można określić, korzystając z pełnej składni do utworzenia 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 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 adresu URL, przekaż słownik komunikatów NDEF do metody write() NDEFReader. Rekord URL zawarty w komunikacie NDEF jest zdefiniowany jako obiekt z kluczem recordType ustawionym na "url", a 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, aby umożliwić prawidłowe odkodowanie data. Na przykład użyj JSON.parse do zdekodowania tekstu w formacie JSON i elementu Image do zdekodowania 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 write() NDEFReader. 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 oraz klucz data ustawiony na obiekt, który może być obiektem ArrayBuffer lub udostępnia widok 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 bezwzględnego adresu URL

Rekord bezwzględny URL data można zdekodować za pomocą prostego elementu 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 bezwzględny URL, przekaż słownik wiadomości NDEF do metody write() NDEFReader. Rekord bezwzględny URL zawarty w wiadomości NDEF jest zdefiniowany jako obiekt z kluczem recordType ustawionym na "absolute-url" oraz 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 inteligentnego plakatu

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

Rekordy typu lokalnego są niepowtarzalne tylko w kontekście lokalnym zawierającym rekord NDEF. Używaj ich, gdy znaczenie typów nie ma znaczenia poza lokalnym kontekstem rekordu zawierającego oraz gdy wykorzystanie miejsca na dane stanowi sztywne ograniczenie. W Web NFC nazwy rekordów typu lokalnego zaczynają się zawsze od : (np.":t", ":s", ":act"). Służy to np. do odróżnienia rekordu tekstowego od lokalnego rekordu.

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 utworzyć rekord inteligentnego plakatu, przekaż wiadomość NDEF do metody write() NDEFReader. Rekord inteligentnego plakatu zawarty w wiadomości NDEF jest zdefiniowany jako obiekt z kluczem recordType ustawionym na "smart-poster" i kluczem data ustawionym na obiekt reprezentujący (ponownie) wiadomość NDEF zawartej w rekordzie inteligentnego plakatu.

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

Do tworzenia rekordów zdefiniowanych przez aplikację możesz używać rekordów typu zewnętrznego. Mogą one zawierać komunikat NDEF jako ładunek, do którego można uzyskać dostęp za pomocą toRecords(). Nazwa domeny zawiera nazwę domeny organizacji wydającej kartę, dwukropek i nazwę typu o długości co najmniej 1 znaku, na przykład "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 write() NDEFReader. 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 też być ArrayBuffer lub zawierać widok elementu 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 ma ładunku.

Aby zapisać pusty rekord, przekaż słownik komunikatów NDEF do metody write() NDEFReader. Pusty rekord zawarty w komunikacie 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ługiwane przeglądarki

Internetowa komunikacja NFC jest dostępna na urządzeniach z Androidem w Chrome 89.

Wskazówki dla programistów

Oto lista rzeczy, które chciałabym wiedzieć przed rozpoczęciem grania z technologią NFC:

  • Android obsługuje tagi NFC na poziomie systemu operacyjnego, zanim funkcja Web NFC zostanie uruchomiona.
  • Ikonę NFC znajdziesz na stronie material.io.
  • Użyj rekordu NDEF id, aby w razie potrzeby łatwo zidentyfikować rekord.
  • Niesformatowany tag NFC, który obsługuje NDEF, zawiera pojedynczy rekord pustego typu.
  • Pisanie rekordu aplikacji na Androida jest proste, co 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

Zapoznaj się z oficjalną próbką i obejrzyj kilka ciekawych prezentacji funkcji Web NFC:

Prezentacja kart internetowych NFC na Chrome Dev Summit 2019

Prześlij opinię

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

Opowiedz nam o projekcie interfejsu API

Czy jest coś, co nie działa w interfejsie API zgodnie z oczekiwaniami? A może brakuje metod lub właściwości, które są niezbędne do realizacji pomysłu?

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

Zgłoś problem z implementacją

Czy wystąpił błąd związany z implementacją przeglądarki Chrome? A może implementacja różni się od specyfikacji?

Zgłoś błąd na stronie https://new.crbug.com. Podaj jak najwięcej szczegółów i proste instrukcje odtworzenia błędu oraz ustaw Komponenty na Blink>NFC. Glitch to świetny sposób na udostępnianie szybkich i łatwych replik.

Okaż wsparcie

Czy zamierzasz korzystać z komunikacji internetowej z internetem? Twoje publiczne wsparcie pomaga zespołowi Chrome priorytetowo traktować funkcje i pokazuje innym dostawcom przeglądarek, jak ważne jest ich wsparcie.

Wyślij tweeta na adres @ChromiumDev, używając hashtagu #WebNFC, i daj nam znać, gdzie i w jaki sposób go używasz.

Przydatne linki

Podziękowania

Dziękujemy pracownikom firmy Intel za wdrożenie NFC. Działanie Google Chrome zależy od społeczności zaangażowanych użytkowników, którzy wspólnie pracują nad rozwojem projektu Chromium. Nie każdy użytkownik Chromium jest pracownikiem Google, a ci współtwórcy zasługują na specjalne wyróżnienie.