Interagir com dispositivos NFC no Chrome para Android

Agora é possível ler e gravar em tags NFC.

François Beaufort
François Beaufort

O que é a Web NFC?

NFC significa Near Field Communications, uma tecnologia sem fio de curto alcance que opera a 13,56 MHz e permite a comunicação entre dispositivos a uma distância inferior a 10 cm e uma taxa de transmissão de até 424 kbit/s.

A Web NFC permite que os sites leiam e gravem em tags NFC quando elas estão próximas ao dispositivo do usuário (geralmente de 5 a 10 cm). O escopo atual é limitado ao formato de troca de dados do NFC (NDEF), um formato de mensagem binária leve que funciona em diferentes formatos de tag.

Smartphone ativando uma tag NFC para trocar dados
Diagrama de uma operação NFC

Casos de uso sugeridos

A Web NFC é limitada ao NDEF porque as propriedades de segurança da leitura e gravação de dados NDEF são mais fáceis de quantificar. Operações de E/S de baixo nível (por exemplo, ISO-DEP, NFC-A/B, NFC-F), modo de comunicação ponto a ponto e emulação de cartão baseada em host (HCE) não são compatíveis.

Exemplos de sites que podem usar o Web NFC:

  • Museus e galerias de arte podem mostrar mais informações sobre uma exposição quando o usuário encosta o dispositivo em um cartão NFC perto da exibição.
  • Sites de gerenciamento de inventário podem ler ou gravar dados na tag NFC de um contêiner para atualizar informações sobre o conteúdo dele.
  • Os sites de conferências podem usar esse recurso para fazer a leitura de crachás NFC durante o evento e garantir que eles estejam bloqueados para evitar mais mudanças nas informações escritas neles.
  • Os sites podem usar o recurso para compartilhar os secrets iniciais necessários para cenários de provisionamento de dispositivos ou serviços e também para implantar dados de configuração no modo operacional.
Smartphone lendo várias tags NFC
Gerenciamento de inventário de NFC ilustrado

Status atual

Etapa Status
1. Criar explicação Concluído
2. Criar o rascunho inicial da especificação Concluído
3. Coletar feedback e iterar o design Concluído
4. Teste de origem Concluído
5. Iniciar Concluído

Usar a Web NFC

Detecção de recursos

A detecção de recursos para hardware é diferente do que você provavelmente está acostumado. A presença de NDEFReader indica que o navegador é compatível com a Web NFC, mas não se o hardware necessário está presente. Em particular, se o hardware estiver ausente, a promessa retornada por determinadas chamadas será rejeitada. Vou dar mais detalhes quando descrever NDEFReader.

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

Terminologia

Uma tag NFC é um dispositivo NFC passivo, ou seja, ela é alimentada por indução magnética quando um dispositivo NFC ativo (como um smartphone) está por perto. As tags NFC vêm em vários formatos e estilos, como adesivos, cartões de crédito, pulseiras e muito mais.

Foto de uma tag NFC transparente
Uma tag NFC transparente

O objeto NDEFReader é o ponto de entrada no Web NFC que expõe a funcionalidade para preparar ações de leitura e/ou gravação que são executadas quando uma tag NDEF se aproxima. O NDEF em NDEFReader significa NFC Data Exchange Format, um formato de mensagem binária leve padronizado pelo NFC Forum (link em inglês).

O objeto NDEFReader é usado para processar mensagens NDEF recebidas de tags NFC e para gravar mensagens NDEF em tags NFC dentro do alcance.

Uma tag NFC compatível com NDEF é como um post-it. Qualquer pessoa pode ler e, a menos que seja somente leitura, qualquer pessoa pode escrever nele. Ela contém uma única mensagem NDEF que encapsula um ou mais registros NDEF. Cada registro NDEF é uma estrutura binária que contém uma carga útil de dados e informações de tipo associadas. A Web NFC é compatível com os seguintes tipos de registros padronizados do Fórum NFC: vazio, texto, URL, pôster inteligente, tipo MIME, URL absoluto, tipo externo, desconhecido e tipo local.

Diagrama de uma mensagem NDEF
Diagrama de uma mensagem NDEF

Ler tags NFC

Para fazer isso, primeiro crie uma instância de um novo objeto NDEFReader. Chamar scan() retorna uma promessa. O usuário pode receber uma solicitação se o acesso não tiver sido concedido antes. A promessa será resolvida se todas as condições a seguir forem atendidas:

  • Ele só era chamado em resposta a um gesto do usuário, como um toque ou clique do mouse.
  • O usuário permitiu que o site interagisse com dispositivos NFC.
  • O smartphone do usuário é compatível com NFC.
  • O usuário ativou a NFC no smartphone.

Depois que a promessa for resolvida, as mensagens NDEF recebidas estarão disponíveis ao se inscrever em eventos reading por um listener de eventos. Também é necessário se inscrever em eventos readingerror para receber notificações quando tags NFC incompatíveis estiverem próximas.

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

Quando uma tag NFC está por perto, um evento NDEFReadingEvent é disparado. Ele contém duas propriedades exclusivas:

  • serialNumber representa o número de série do dispositivo (por exemplo, 00-11-22-33-44-55-66) ou uma string vazia se nenhum estiver disponível.
  • message representa a mensagem NDEF armazenada na tag NFC.

Para ler o conteúdo da mensagem NDEF, faça um loop em message.records e processe os membros data adequadamente com base no recordType deles. O membro data é exposto como um DataView porque permite processar casos em que os dados são codificados em 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.
    }
  }
};

Gravar tags NFC

Para gravar tags NFC, primeiro crie uma instância de um novo objeto NDEFReader. Chamar write() retorna uma promessa. O usuário pode receber uma solicitação se o acesso não tiver sido concedido antes. Nesse ponto, uma mensagem NDEF é "preparada" e a promessa será resolvida se todas as condições a seguir forem atendidas:

  • Ele só era chamado em resposta a um gesto do usuário, como um toque ou clique do mouse.
  • O usuário permitiu que o site interagisse com dispositivos NFC.
  • O smartphone do usuário é compatível com NFC.
  • O usuário ativou a NFC no smartphone.
  • O usuário tocou em uma tag NFC e uma mensagem NDEF foi gravada.

Para gravar texto em uma tag NFC, transmita uma string ao método write().

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

Para gravar um registro de URL em uma tag NFC, transmita um dicionário que represente uma mensagem NDEF para write(). No exemplo abaixo, a mensagem NDEF é um dicionário com uma chave records. O valor é uma matriz de registros. Nesse caso, um registro de URL definido como um objeto com uma chave recordType definida como "url" e uma chave data definida como a string do 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}.`);
});

Também é possível gravar vários registros em uma tag 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}.`);
});

Se a tag NFC tiver uma mensagem NDEF que não pode ser substituída, defina a propriedade overwrite como false nas opções transmitidas ao método write(). Nesse caso, a promessa retornada será rejeitada se uma mensagem NDEF já estiver armazenada na tag 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}.`);
});

Tornar tags NFC somente leitura

Para evitar que usuários mal-intencionados substituam o conteúdo de uma tag NFC, é possível tornar as tags NFC permanentemente somente leitura. Essa operação é um processo unidirecional e não pode ser revertida. Depois que uma tag NFC é definida como somente leitura, não é possível gravar mais nada nela.

Para tornar as tags NFC somente leitura, primeiro crie uma instância de um novo objeto NDEFReader. Chamar makeReadOnly() retorna uma promessa. O usuário pode receber uma solicitação se o acesso não tiver sido concedido antes. A promessa será resolvida se todas as condições a seguir forem atendidas:

  • Ele só era chamado em resposta a um gesto do usuário, como um toque ou clique do mouse.
  • O usuário permitiu que o site interagisse com dispositivos NFC.
  • O smartphone do usuário é compatível com NFC.
  • O usuário ativou a NFC no smartphone.
  • O usuário tocou em uma tag NFC, e ela foi definida como somente leitura.
const ndef = new NDEFReader();
ndef.makeReadOnly()
.then(() => {
  console.log("NFC tag has been made permanently read-only.");
}).catch(error => {
  console.log(`Operation failed: ${error}`);
});

Veja como tornar uma tag NFC permanentemente somente leitura depois de gravar nela.

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

Como o makeReadOnly() está disponível no Android no Chrome 100 ou versões mais recentes, verifique se esse recurso é compatível com o seguinte:

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

Segurança e permissões

A equipe do Chrome projetou e implementou o NFC da Web usando os princípios básicos definidos em Controlling Access to Powerful Web Platform Features (em inglês), incluindo controle do usuário, transparência e ergonomia.

Como o NFC expande o domínio de informações potencialmente disponíveis para sites maliciosos, a disponibilidade do NFC é restrita para maximizar a conscientização e o controle dos usuários sobre o uso do NFC.

Captura de tela de uma solicitação da Web NFC em um site
Solicitação do usuário da Web NFC

A NFC da Web está disponível apenas para frames de nível superior e contextos de navegação seguros (somente HTTPS). As origens precisam primeiro solicitar a permissão "nfc" ao processar um gesto do usuário (por exemplo, um clique em um botão). Os métodos NDEFReader scan(), write() e makeReadOnly() acionam uma solicitação ao usuário se o acesso não foi concedido antes.

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

A combinação de uma solicitação de permissão iniciada pelo usuário e o movimento físico real de aproximar o dispositivo de uma tag NFC alvo espelha o padrão de escolha encontrado nas outras APIs de acesso a arquivos e dispositivos.

Para realizar uma leitura ou gravação, a página da Web precisa estar visível quando o usuário toca em uma tag NFC com o dispositivo. O navegador usa o retorno tátil para indicar um toque. O acesso ao rádio NFC é bloqueado se a tela estiver desligada ou o dispositivo estiver bloqueado. Para páginas da Web não visíveis, o recebimento e o envio de conteúdo NFC são suspensos e retomados quando uma página da Web volta a ficar visível.

Graças à API Page Visibility, é possível rastrear quando a visibilidade do documento muda.

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

Manual

Confira alguns exemplos de código para começar.

Verificar permissão

Com a API Permissions, é possível verificar se a permissão "nfc" foi concedida. Este exemplo mostra como fazer a leitura de tags NFC sem interação do usuário se o acesso foi concedido anteriormente ou mostrar um botão caso contrário. O mesmo mecanismo funciona para gravar tags NFC, já que usa a mesma permissão por baixo do capô.

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

Cancelar operações de NFC

Usar o primitivo AbortController facilita a interrupção das operações de NFC. O exemplo abaixo mostra como transmitir o signal de um AbortController pelas opções dos métodos scan(), makeReadOnly() e write() do NDEFReader e cancelar as duas operações de NFC ao mesmo tempo.

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

Leitura após gravação

Usar write() e scan() com a primitiva AbortController permite ler uma tag NFC depois de gravar uma mensagem nela. O exemplo abaixo mostra como gravar uma mensagem de texto em uma tag NFC e ler a nova mensagem na tag NFC. Ele para de fazer a verificação após três segundos.

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

Ler e gravar um registro de texto

O registro de texto data pode ser decodificado com um TextDecoder instanciado com a propriedade de registro encoding. O idioma do registro de texto está disponível na propriedade lang.

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

Para gravar um registro de texto simples, transmita uma string para o método write() do NDEFReader.

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

Os registros de texto são UTF-8 por padrão e presumem o idioma do documento atual, mas as duas propriedades (encoding e lang) podem ser especificadas usando a sintaxe completa para criar um registro NDEF personalizado.

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

Ler e gravar um registro de URL

Use TextDecoder para decodificar o data do registro.

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

Para gravar um registro de URL, transmita um dicionário de mensagens NDEF ao método NDEFReader write(). O registro de URL contido na mensagem NDEF é definido como um objeto com uma chave recordType definida como "url" e uma chave data definida como a string do URL.

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

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

Ler e gravar um registro de tipo MIME

A propriedade mediaType de um registro de tipo MIME representa o tipo MIME da carga útil do registro NDEF para que data possa ser decodificado corretamente. Por exemplo, use JSON.parse para decodificar texto JSON e um elemento de imagem para decodificar dados de imagem.

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

Para gravar um registro de tipo MIME, transmita um dicionário de mensagens NDEF ao método write() do NDEFReader. O registro de tipo MIME contido na mensagem NDEF é definido como um objeto com uma chave recordType definida como "mime", uma chave mediaType definida como o tipo MIME real do conteúdo e uma chave data definida como um objeto que pode ser um ArrayBuffer ou fornecer uma visualização de um ArrayBuffer (por exemplo, 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] });

Ler e gravar um registro de URL absoluto

O registro de URL absoluto data pode ser decodificado com um TextDecoder simples.

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

Para gravar um registro de URL absoluto, transmita um dicionário de mensagens NDEF ao método write() do NDEFReader. O registro de URL absoluto contido na mensagem NDEF é definido como um objeto com uma chave recordType definida como "absolute-url" e uma chave data definida como a string de URL.

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

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

Ler e gravar um registro de pôster inteligente

Um registro de pôster inteligente (usado em anúncios de revistas, panfletos, outdoors etc.) descreve algum conteúdo da Web como um registro NDEF que contém uma mensagem NDEF como payload. Chame record.toRecords() para transformar data em uma lista de registros contidos no registro do pôster inteligente. Ele precisa ter um registro de URL, um registro de texto para o título, um registro de tipo MIME para a imagem e alguns registros de tipo local personalizados, como ":t", ":act" e ":s", respectivamente, para o tipo, a ação e o tamanho do registro de pôster inteligente.

Os registros de tipo local são exclusivos apenas no contexto local do registro NDEF que os contém. Use-os quando o significado dos tipos não importa fora do contexto local do registro que os contém e quando o uso do armazenamento é uma restrição rígida. Os nomes de registros de tipo local sempre começam com : no Web NFC (por exemplo, ":t", ":s", ":act"). Isso é para diferenciar um registro de texto de um registro de texto de tipo local, por exemplo.

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

Para gravar um registro de pôster inteligente, transmita uma mensagem NDEF ao método write() NDEFReader. O registro do pôster inteligente contido na mensagem NDEF é definido como um objeto com uma chave recordType definida como "smart-poster" e uma chave data definida como um objeto que representa (mais uma vez) uma mensagem NDEF contida no registro do pôster inteligente.

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

Ler e gravar um registro de tipo externo

Para criar registros definidos pelo aplicativo, use registros de tipo externo. Eles podem conter uma mensagem NDEF como payload acessível com toRecords(). O nome deles contém o nome de domínio da organização emissora, dois pontos e um nome de tipo com pelo menos um caractere, por exemplo, "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.
    }
  }
}

Para gravar um registro de tipo externo, transmita um dicionário de mensagens NDEF ao método NDEFReader write(). O registro de tipo externo contido na mensagem NDEF é definido como um objeto com uma chave recordType definida como o nome do tipo externo e uma chave data definida como um objeto que representa uma mensagem NDEF contida no registro de tipo externo. A chave data também pode ser um ArrayBuffer ou fornecer uma visualização de um ArrayBuffer (por exemplo, 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] });

Ler e gravar um registro vazio

Um registro vazio não tem payload.

Para gravar um registro vazio, transmita um dicionário de mensagens NDEF ao método NDEFReader write(). O registro vazio contido na mensagem NDEF é definido como um objeto com uma chave recordType definida como "empty".

const emptyRecord = {
  recordType: "empty"
};

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

Suporte ao navegador

O NFC na Web está disponível no Android no Chrome 89.

Dicas para desenvolvedores

Confira uma lista de coisas que eu gostaria de ter sabido quando comecei a usar a API Web NFC:

  • O Android processa as tags NFC no nível do SO antes que o Web NFC esteja operacional.
  • Você pode encontrar um ícone de NFC em material.io.
  • Use o registro NDEF id para identificar facilmente um registro quando necessário.
  • Uma tag NFC não formatada que oferece suporte a NDEF contém um único registro do tipo vazio.
  • Escrever um registro de aplicativo Android é fácil, conforme mostrado abaixo.
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] });

Demonstrações

Teste a amostra oficial e confira algumas demonstrações legais da Web NFC:

Demonstração de cartões Web NFC na Chrome Dev Summit 2019

Feedback

O Grupo da comunidade Web NFC e a equipe do Chrome querem saber sua opinião e suas experiências com o Web NFC.

Fale sobre o design da API

Há algo na API que não funciona como esperado? Ou há métodos ou propriedades ausentes que você precisa implementar para sua ideia?

Registre um problema de especificação no repositório do GitHub da Web NFC ou adicione suas ideias a um problema existente.

Informar um problema com a implementação

Você encontrou um bug na implementação do Chrome? Ou a implementação é diferente da especificação?

Registre um bug em https://new.crbug.com. Inclua o máximo de detalhes possível, forneça instruções simples para reproduzir o bug e defina Componentes como Blink>NFC.

Mostrar apoio

Você pretende usar a NFC da Web? Seu apoio público ajuda a equipe do Chrome a priorizar recursos e mostra a outros fornecedores de navegadores a importância de oferecer suporte a eles.

Envie um tweet para @ChromiumDev usando a hashtag #WebNFC e conte para nós onde e como você está usando.

Links úteis

Agradecimentos

Agradecemos muito ao pessoal da Intel por implementar o Web NFC. O Google Chrome depende de uma comunidade de committers que trabalham juntos para avançar o projeto Chromium. Nem todo committer do Chromium é um Googler, e esses colaboradores merecem reconhecimento especial.