تعامل با دستگاه‌های NFC در Chrome for Android

خواندن و نوشتن در برچسب های NFC اکنون امکان پذیر است.

فرانسوا بوفور
François Beaufort

NFC مخفف Near Field Communications است، یک فناوری بی سیم با برد کوتاه که با فرکانس 13.56 مگاهرتز کار می کند و ارتباط بین دستگاه ها را در فاصله کمتر از 10 سانتی متر و سرعت انتقال تا 424 کیلوبیت بر ثانیه را امکان پذیر می کند.

وب NFC توانایی خواندن و نوشتن برچسب‌های NFC را زمانی که آنها در مجاورت دستگاه کاربر قرار دارند (معمولاً 5-10 سانتی متر، 2-4 اینچ) به سایت ها ارائه می دهد. دامنه فعلی به فرمت تبادل داده های NFC (NDEF)، یک قالب پیام باینری سبک وزن است که در قالب های مختلف برچسب کار می کند.

تلفن یک برچسب NFC را برای تبادل داده روشن می کند
نمودار یک عملیات NFC

موارد استفاده پیشنهادی

وب NFC به NDEF محدود می شود زیرا ویژگی های امنیتی خواندن و نوشتن داده های NDEF به راحتی قابل اندازه گیری است. عملیات I/O سطح پایین (مانند ISO-DEP، NFC-A/B، NFC-F)، حالت ارتباط نظیر به نظیر و شبیه سازی کارت مبتنی بر میزبان (HCE) پشتیبانی نمی شود.

نمونه هایی از سایت هایی که ممکن است از وب NFC استفاده کنند عبارتند از:

  • موزه‌ها و گالری‌های هنری می‌توانند اطلاعات بیشتری در مورد یک نمایشگر نمایش دهند وقتی کاربر دستگاه خود را به کارت NFC نزدیک نمایشگاه لمس می‌کند.
  • سایت‌های مدیریت موجودی می‌توانند داده‌ها را در برچسب NFC روی یک ظرف بخوانند یا بنویسند تا اطلاعات محتوای آن را به‌روزرسانی کنند.
  • سایت‌های کنفرانس می‌توانند از آن برای اسکن نشان‌های NFC در طول رویداد استفاده کنند و از قفل بودن آن‌ها برای جلوگیری از تغییرات بیشتر در اطلاعات نوشته شده روی آن‌ها مطمئن شوند.
  • سایت ها می توانند از آن برای به اشتراک گذاری اسرار اولیه مورد نیاز برای سناریوهای ارائه دستگاه یا خدمات و همچنین برای استقرار داده های پیکربندی در حالت عملیاتی استفاده کنند.
اسکن تلفن چندین تگ NFC
مدیریت موجودی NFC نشان داده شده است

وضعیت فعلی

مرحله وضعیت
1. توضیح دهنده ایجاد کنید کامل
2. پیش نویس اولیه مشخصات را ایجاد کنید کامل
3. جمع آوری بازخورد و تکرار در طراحی کامل
4. آزمایش مبدا کامل
5. راه اندازی کنید کامل

از وب NFC استفاده کنید

تشخیص ویژگی

تشخیص ویژگی برای سخت افزار با چیزی که احتمالاً به آن عادت کرده اید متفاوت است. وجود NDEFReader به شما می گوید که مرورگر از Web NFC پشتیبانی می کند، اما نه اینکه آیا سخت افزار مورد نیاز وجود دارد یا خیر. به طور خاص، اگر سخت افزار گم شده باشد، قولی که با تماس های خاص برگردانده می شود رد می شود. وقتی NDEFReader توصیف می کنم، جزئیات را ارائه خواهم کرد.

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

اصطلاحات

تگ NFC یک دستگاه NFC غیرفعال است، به این معنی که وقتی یک دستگاه NFC فعال (مانند تلفن) در مجاورت باشد، توسط القای مغناطیسی تغذیه می شود. برچسب‌های NFC در اشکال و مدل‌های مختلفی مانند برچسب، کارت اعتباری، مچ دست و موارد دیگر وجود دارند.

عکس تگ NFC شفاف
یک تگ NFC شفاف

شی NDEFReader نقطه ورود در وب NFC است که عملکردی را برای آماده سازی اقدامات خواندن و/یا نوشتن که با نزدیک شدن یک تگ NDEF انجام می شود، نشان می دهد. NDEF در NDEFReader مخفف NFC Data Exchange Format، یک قالب پیام باینری سبک وزن است که توسط انجمن NFC استاندارد شده است.

شی NDEFReader برای اقدام بر روی پیام های NDEF ورودی از تگ های NFC و برای نوشتن پیام های NDEF به برچسب های NFC در محدوده است.

یک تگ NFC که از NDEF پشتیبانی می کند مانند یک یادداشت post-it است. همه می‌توانند آن را بخوانند، و مگر اینکه فقط خواندنی باشد، همه می‌توانند برای آن بنویسند. این شامل یک پیام NDEF واحد است که یک یا چند رکورد NDEF را محصور می کند. هر رکورد NDEF یک ساختار باینری است که حاوی یک بار داده و اطلاعات نوع مرتبط است. وب NFC انواع رکورد استاندارد شده انجمن NFC زیر را پشتیبانی می کند: خالی، متن، URL، پوستر هوشمند، نوع MIME، URL مطلق، نوع خارجی، نوع ناشناخته و نوع محلی.

نمودار یک پیام NDEF
نمودار یک پیام NDEF

اسکن برچسب های NFC

برای اسکن تگ های NFC، ابتدا یک شی NDEFReader جدید را نمونه برداری کنید. فراخوانی scan() یک وعده را برمی گرداند. اگر قبلاً دسترسی داده نشده باشد ، ممکن است از کاربر خواسته شود . در صورت تحقق همه شرایط زیر، این قول حل می شود:

  • فقط در پاسخ به یک حرکت کاربر مانند حرکت لمسی یا کلیک ماوس فراخوانی شد.
  • کاربر به وب سایت اجازه داده است با دستگاه های NFC تعامل داشته باشد.
  • گوشی کاربر از NFC پشتیبانی می کند.
  • کاربر NFC را روی گوشی خود فعال کرده است.

هنگامی که وعده حل شد، پیام های NDEF دریافتی با اشتراک در reading رویدادها از طریق شنونده رویداد در دسترس هستند. همچنین باید در رویدادهای readingerror مشترک شوید تا زمانی که برچسب‌های 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}.`);
});

هنگامی که یک تگ NFC در نزدیکی است، یک رویداد NDEFReadingEvent فعال می شود. این شامل دو ویژگی منحصر به فرد برای آن است:

  • serialNumber شماره سریال دستگاه (به عنوان مثال 00-11-22-33-44-55-66) یا یک رشته خالی را نشان می دهد، اگر هیچ کدام در دسترس نباشد.
  • message نشان دهنده پیام NDEF ذخیره شده در تگ NFC است.

برای خواندن محتوای پیام NDEF، در message.records حلقه بزنید و اعضای data آن‌ها را به‌طور مناسب بر اساس recordType پردازش کنید. عضو data به عنوان DataView در معرض دید قرار می گیرد زیرا امکان رسیدگی به مواردی را که داده ها در 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.
    }
  }
};

برچسب های NFC بنویسید

برای نوشتن تگ های NFC، ابتدا یک شی NDEFReader جدید را نمونه سازی کنید. فراخوانی write() یک وعده را برمی گرداند. اگر قبلاً دسترسی داده نشده باشد ، ممکن است از کاربر خواسته شود . در این مرحله، یک پیام NDEF "آماده شده" است و در صورت رعایت همه شرایط زیر، وعده حل خواهد شد:

  • فقط در پاسخ به یک حرکت کاربر مانند حرکت لمسی یا کلیک ماوس فراخوانی شد.
  • کاربر به وب سایت اجازه داده است با دستگاه های NFC تعامل داشته باشد.
  • گوشی کاربر از NFC پشتیبانی می کند.
  • کاربر NFC را روی گوشی خود فعال کرده است.
  • کاربر روی یک برچسب NFC ضربه زده است و یک پیام NDEF با موفقیت نوشته شده است.

برای نوشتن متن در یک تگ NFC، یک رشته را به متد write() ارسال کنید.

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

برای نوشتن یک رکورد URL در یک تگ NFC، یک فرهنگ لغت که نشان دهنده یک پیام NDEF است را برای write() ارسال کنید. در مثال زیر، پیام NDEF یک فرهنگ لغت با یک کلید records است. مقدار آن آرایه‌ای از رکوردها است - در این مورد، یک رکورد URL که به عنوان یک شی با یک کلید recordType روی "url" و یک کلید data مجموعه‌ای از رشته 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}.`);
});

همچنین امکان نوشتن چندین رکورد در یک تگ 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}.`);
});

اگر تگ NFC حاوی یک پیام NDEF است که قرار نیست بازنویسی شود، در گزینه‌های ارسال شده به متد write() ویژگی overwrite را روی false قرار دهید. در آن صورت، اگر یک پیام NDEF قبلاً در تگ 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}.`);
});

برچسب های NFC را فقط خواندنی کنید

برای جلوگیری از بازنویسی محتوای یک برچسب NFC توسط کاربران مخرب، می توان تگ های NFC را به صورت دائمی فقط خواندنی کرد. این عملیات یک فرآیند یک طرفه است و قابل برگشت نیست. وقتی یک تگ NFC فقط خواندنی شد، دیگر نمی توان آن را نوشت.

برای اینکه تگ های NFC فقط خواندنی باشند، ابتدا یک شی NDEFReader جدید را نمونه برداری کنید. فراخوانی makeReadOnly() یک وعده را برمی گرداند. اگر قبلاً دسترسی داده نشده باشد ، ممکن است از کاربر خواسته شود . در صورت تحقق همه شرایط زیر، این قول حل می شود:

  • فقط در پاسخ به یک حرکت کاربر مانند حرکت لمسی یا کلیک ماوس فراخوانی شد.
  • کاربر به وب سایت اجازه داده است با دستگاه های NFC تعامل داشته باشد.
  • گوشی کاربر از NFC پشتیبانی می کند.
  • کاربر NFC را روی گوشی خود فعال کرده است.
  • کاربر روی یک تگ NFC ضربه زده است و تگ NFC با موفقیت فقط خواندنی ساخته شده است.
const ndef = new NDEFReader();
ndef.makeReadOnly()
.then(() => {
  console.log("NFC tag has been made permanently read-only.");
}).catch(error => {
  console.log(`Operation failed: ${error}`);
});

در اینجا نحوه ایجاد یک برچسب NFC به صورت دائمی فقط خواندنی پس از نوشتن روی آن آورده شده است.

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

از آنجایی که makeReadOnly() در اندروید Chrome 100 یا جدیدتر موجود است، بررسی کنید که آیا این ویژگی با موارد زیر پشتیبانی می‌شود:

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

امنیت و مجوزها

تیم Chrome NFC وب را با استفاده از اصول اصلی تعریف شده در کنترل دسترسی به ویژگی‌های قدرتمند پلتفرم وب ، از جمله کنترل کاربر، شفافیت و ارگونومی، طراحی و پیاده‌سازی کرده است.

از آنجایی که NFC دامنه اطلاعاتی را که به طور بالقوه در دسترس وب سایت های مخرب است گسترش می دهد، در دسترس بودن NFC برای به حداکثر رساندن آگاهی و کنترل کاربران بر استفاده از NFC محدود شده است.

تصویری از یک درخواست وب NFC در یک وب سایت
درخواست کاربر وب NFC

وب NFC فقط برای فریم های سطح بالا و زمینه های مرور ایمن (فقط HTTPS) در دسترس است. Origins ابتدا باید مجوز "nfc" را در حین مدیریت ژست کاربر (مثلاً کلیک روی دکمه) درخواست کند. متدهای NDEFReader scan() ، write() و makeReadOnly() یک درخواست کاربر را راه اندازی می کنند، در صورتی که دسترسی قبلاً داده نشده بود.

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

ترکیبی از یک درخواست مجوز آغاز شده توسط کاربر و حرکت فیزیکی در دنیای واقعی که دستگاه را روی یک برچسب NFC هدف قرار می دهد، الگوی انتخابگر موجود در فایل های دیگر و API های دسترسی به دستگاه را منعکس می کند.

برای انجام اسکن یا نوشتن، صفحه وب باید زمانی که کاربر یک برچسب NFC را با دستگاه خود لمس می‌کند قابل مشاهده باشد. مرورگر از بازخورد لمسی برای نشان دادن ضربه استفاده می کند. در صورت خاموش بودن صفحه نمایش یا قفل بودن دستگاه، دسترسی به رادیو NFC مسدود می شود. برای صفحات وب غیر قابل مشاهده، دریافت و فشار دادن محتوای NFC به حالت تعلیق در می‌آید و زمانی که یک صفحه وب دوباره قابل مشاهده شد، از سر گرفته می‌شود.

به لطف صفحه Visibility API ، امکان ردیابی زمان تغییر نمایان بودن سند وجود دارد.

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

کتاب آشپزی

در اینجا چند نمونه کد برای شروع شما آورده شده است.

مجوز را بررسی کنید

Permissions API اجازه می دهد تا بررسی کنید که آیا مجوز "nfc" اعطا شده است یا خیر. این مثال نشان می‌دهد که چگونه می‌توان برچسب‌های NFC را بدون تعامل کاربر اسکن کرد، اگر قبلاً دسترسی داده شده بود، یا دکمه‌ای را در غیر این صورت نشان می‌دهد. توجه داشته باشید که مکانیسم مشابهی برای نوشتن تگ های NFC کار می کند زیرا از همان مجوز در زیر هود استفاده می کند.

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 را لغو کنید

استفاده از AbortController اولیه باعث می شود که عملیات NFC به راحتی متوقف شود. مثال زیر به شما نشان می دهد که چگونه signal یک AbortController را از طریق گزینه های متدهای NDEFReader scan() ، makeReadOnly() ، write() ارسال کنید و هر دو عملیات 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();
};

بعد از نوشتن بخوانید

استفاده از write() سپس scan() با AbortController اولیه، خواندن یک تگ NFC را پس از نوشتن یک پیام برای آن امکان پذیر می کند. مثال زیر به شما نشان می دهد که چگونه یک پیام متنی را به یک تگ NFC بنویسید و پیام جدید را در تگ NFC بخوانید. پس از سه ثانیه اسکن متوقف می شود.

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

خواندن و نوشتن یک رکورد متن

data رکورد متن را می‌توان با یک TextDecoder که با ویژگی encoding رکورد ساخته شده است، رمزگشایی کرد. توجه داشته باشید که زبان رکورد متن از طریق ویژگی lang آن در دسترس است.

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

برای نوشتن یک رکورد متنی ساده، یک رشته را به متد NDEFReader write() ارسال کنید.

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

رکوردهای متنی به طور پیش‌فرض UTF-8 هستند و زبان سند جاری را فرض می‌کنند، اما هر دو ویژگی ( encoding و lang ) را می‌توان با استفاده از نحو کامل برای ایجاد یک رکورد 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] });

یک رکورد URL را بخوانید و بنویسید

از TextDecoder برای رمزگشایی data رکورد استفاده کنید.

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

برای نوشتن یک رکورد URL، یک فرهنگ لغت پیام NDEF را به متد NDEFReader write() ارسال کنید. رکورد URL موجود در پیام NDEF به عنوان یک شی با یک کلید recordType روی "url" و یک کلید data تنظیم شده در رشته URL تعریف می شود.

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

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

خواندن و نوشتن یک رکورد از نوع MIME

ویژگی mediaType یک رکورد نوع MIME نشان دهنده نوع MIME محموله رکورد NDEF است تا بتوان data را به درستی رمزگشایی کرد. به عنوان مثال، از JSON.parse برای رمزگشایی متن JSON و عنصر Image برای رمزگشایی داده های تصویر استفاده کنید.

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

برای نوشتن یک رکورد از نوع MIME، یک فرهنگ لغت پیام NDEF را به متد NDEFReader write() ارسال کنید. رکورد نوع MIME موجود در پیام NDEF به عنوان یک شی با یک کلید recordType تنظیم شده روی "mime" ، یک کلید mediaType تنظیم شده بر روی نوع MIME واقعی محتوا، و یک کلید data مجموعه ای برای یک شی تعریف می شود که می تواند یک ArrayBuffer یا نمایی از یک ArrayBuffer (به عنوان مثال 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] });

خواندن و نوشتن یک رکورد URL مطلق

data رکورد URL مطلق را می توان با یک TextDecoder ساده رمزگشایی کرد.

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

برای نوشتن یک رکورد URL مطلق، یک فرهنگ لغت پیام NDEF را به متد NDEFReader write() ارسال کنید. رکورد URL مطلق موجود در پیام NDEF به عنوان یک شی با یک کلید recordType تنظیم شده بر روی "absolute-url" و یک کلید data مجموعه ای برای رشته URL تعریف می شود.

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

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

یک رکورد پوستر هوشمند بخوانید و بنویسید

یک رکورد پوستر هوشمند (که در تبلیغات مجلات، آگهی‌ها، بیلبوردها و غیره استفاده می‌شود)، برخی از محتوای وب را به عنوان یک رکورد NDEF توصیف می‌کند که حاوی یک پیام NDEF به عنوان محموله آن است. برای تبدیل data به لیستی از رکوردهای موجود در رکورد پوستر هوشمند، record.toRecords() فراخوانی کنید. باید یک رکورد URL، یک رکورد متن برای عنوان، یک رکورد نوع MIME برای تصویر، و برخی رکوردهای نوع محلی سفارشی مانند ":t" ، ":act" و ":s" به ترتیب برای نوع، داشته باشد. اقدام و اندازه رکورد پوستر هوشمند.

رکوردهای نوع محلی فقط در زمینه محلی رکورد NDEF حاوی یک منحصر به فرد هستند. زمانی از آنها استفاده کنید که معنای انواع خارج از بافت محلی رکورد حاوی مهم نیست و زمانی که استفاده از ذخیره سازی یک محدودیت سخت است. نام رکوردهای نوع محلی همیشه با : در Web NFC شروع می شود (به عنوان مثال ":t" ، ":s" ، ":act" ). این برای متمایز کردن یک رکورد متنی از یک رکورد متنی نوع محلی است.

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

برای نوشتن یک رکورد پوستر هوشمند، یک پیام NDEF را به متد NDEFReader write() ارسال کنید. رکورد پوستر هوشمند موجود در پیام NDEF به عنوان یک شی با یک کلید recordType تنظیم شده روی "smart-poster" و یک کلید data تنظیم شده به یک شی که (یک بار دیگر) یک پیام NDEF موجود در رکورد پوستر هوشمند را نشان می دهد، تعریف می شود.

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

خواندن و نوشتن یک رکورد نوع خارجی

برای ایجاد رکوردهای تعریف شده برنامه، از رکوردهای نوع خارجی استفاده کنید. اینها ممکن است حاوی یک پیام NDEF به عنوان باری باشند که با toRecords() قابل دسترسی است. نام آنها شامل نام دامنه سازمان صادرکننده، یک دونقطه و یک نام نوع است که حداقل یک کاراکتر طول دارد، به عنوان مثال "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.
    }
  }
}

برای نوشتن یک رکورد نوع خارجی، یک فرهنگ لغت پیام NDEF را به متد NDEFReader write() ارسال کنید. رکورد نوع خارجی موجود در پیام NDEF به عنوان یک شی با یک کلید recordType تنظیم شده به نام نوع خارجی و یک کلید data مجموعه به یک شی که نشان دهنده یک پیام NDEF موجود در رکورد نوع خارجی است، تعریف می شود. توجه داشته باشید که کلید data همچنین می‌تواند یک ArrayBuffer باشد یا یک نمای ArrayBuffer (به عنوان مثال 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] });

یک رکورد خالی را بخوانید و بنویسید

یک رکورد خالی هیچ باری ندارد.

برای نوشتن یک رکورد خالی، یک فرهنگ لغت پیام NDEF را به متد NDEFReader write() ارسال کنید. رکورد خالی موجود در پیام NDEF به عنوان یک شی با یک کلید recordType روی "empty" تعریف می شود.

const emptyRecord = {
  recordType: "empty"
};

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

پشتیبانی از مرورگر

Web NFC در اندروید کروم 89 در دسترس است.

نکات برنامه نویس

در اینجا لیستی از چیزهایی است که آرزو می کردم وقتی شروع به بازی با Web NFC کردم می دانستم:

  • Android تگ های NFC را در سطح سیستم عامل قبل از عملیاتی شدن وب NFC کنترل می کند.
  • می توانید یک نماد NFC را در material.io پیدا کنید.
  • id رکورد NDEF برای شناسایی آسان رکورد در صورت نیاز استفاده کنید.
  • یک تگ NFC فرمت نشده که از NDEF پشتیبانی می کند حاوی یک رکورد واحد از نوع خالی است.
  • همانطور که در زیر نشان داده شده است، نوشتن رکورد برنامه اندروید آسان است.
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] });

دموها

نمونه رسمی را امتحان کنید و چند دموی جالب وب NFC را بررسی کنید:

نسخه ی نمایشی کارت های NFC وب در Chrome Dev Summit 2019

بازخورد

گروه انجمن وب NFC و تیم Chrome مایلند در مورد افکار و تجربیات شما در مورد Web NFC بشنوند.

در مورد طراحی API به ما بگویید

آیا چیزی در مورد API وجود دارد که مطابق انتظار کار نمی کند؟ یا آیا روش ها یا ویژگی هایی وجود دارد که برای اجرای ایده خود به آنها نیاز دارید؟

یک مشکل مشخصات را در مخزن وب NFC GitHub ثبت کنید یا افکار خود را به یک مشکل موجود اضافه کنید.

گزارش مشکل در اجرا

آیا اشکالی در پیاده سازی کروم پیدا کردید؟ یا اجرا با مشخصات متفاوت است؟

یک اشکال را در https://new.crbug.com ثبت کنید. مطمئن شوید که تا جایی که می توانید جزئیات را درج کنید، دستورالعمل های ساده ای را برای بازتولید اشکال ارائه دهید و Components را روی Blink>NFC تنظیم کنید. Glitch برای به اشتراک گذاری سریع و آسان تکرارها عالی عمل می کند.

نشان دادن پشتیبانی

آیا قصد دارید از وب NFC استفاده کنید؟ پشتیبانی عمومی شما به تیم Chrome کمک می‌کند ویژگی‌ها را اولویت‌بندی کند و به سایر فروشندگان مرورگر نشان می‌دهد که چقدر حمایت از آنها ضروری است.

با استفاده از هشتگ #WebNFC یک توییت به ChromiumDev@ ارسال کنید و به ما اطلاع دهید کجا و چگونه از آن استفاده می‌کنید.

لینک های مفید

قدردانی ها

با تشکر فراوان از اینتل برای پیاده سازی وب NFC. Google Chrome به جامعه ای از committer ها بستگی دارد که با هم کار می کنند تا پروژه Chromium را به جلو ببرند. هر committer Chromium کارمند Google نیست و این مشارکت کنندگان شایسته تقدیر ویژه هستند!