التفاعل مع أجهزة NFC على Chrome لنظام Android

أصبحت إمكانية القراءة والكتابة باستخدام علامات NFC متاحة الآن.

François Beaufort
François Beaufort

ما هو الاتصال القصير المدى (NFC) على الويب؟

يعني الاختصار NFC "الاتصالات قريبة المدى"، وهي تقنية لاسلكية قصيرة المدى تعمل على تردد 13.56 ميغاهرتز وتتيح الاتصال بين الأجهزة على مسافة أقل من 10 سم وبمعدل نقل يصل إلى 424 كيلوبت/ثانية.

توفّر تقنية NFC على الويب للمواقع الإلكترونية إمكانية القراءة والكتابة في علامات NFC عندما تكون على مقربة من جهاز المستخدم (عادةً ما يكون من 5 إلى 10 سم أو 2 إلى 4 بوصة). يقتصر النطاق الحالي على تنسيق تبادل البيانات عبر NFC (NDEF)، وهو تنسيق بسيط للرسائل الثنائية يعمل على مستوى تنسيقات العلامات المختلفة.

هاتف يشغِّل علامة NFC لتبادل البيانات
مخطّط بياني لعملية NFC

حالات الاستخدام المقترَحة

وتقتصر تقنية NFC على الويب على NDEF نظرًا إلى سهولة قياس خصائص الأمان لقراءة بيانات NDEF وكتابتها. لا يتم دعم العمليات المنخفضة المستوى لوحدات الإدخال والإخراج (على سبيل المثال، 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، وهو تنسيق خفيف للرسالة الثنائية التي تم توحيدها في منتدى NFC.

الكائن NDEFReader مخصص للتعامل مع رسائل NDEF الواردة من علامات NFC وكتابة رسائل NDEF إلى علامات NFC ضمن النطاق.

إنّ علامة NFC التي تتوافق مع NDEF هي مثل الملاحظات الملصقة. يمكن لأي شخص قراءتها، وما لم تكن للقراءة فقط، يمكن لأي شخص الكتابة إليها. وهو يحتوي على رسالة 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 لا يجب استبدالها، اضبط السمة overwrite على false في الخيارات التي يتم تمريرها إلى الطريقة write(). في هذه الحالة، سيتم رفض الوعد الذي تم إرجاعه إذا كانت رسالة 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() على نظام التشغيل Android في الإصدار 100 من Chrome أو الإصدارات الأحدث، تحقَّق مما إذا كانت هذه الميزة متوافقة مع ما يلي:

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

الأمان والأذونات

لقد صمّم فريق Chrome وطبّقَ تقنية NFC على الويب باستخدام المبادئ الأساسية المحددة في التحكم في الوصول إلى الميزات الفعّالة لمنصة الويب الفعّالة، بما في ذلك التحكم في المستخدم والشفافية وهندسة التصميم.

نظرًا لأن NFC يوسّع نطاق المعلومات التي يُحتمل أن تكون متاحة للمواقع الإلكترونية الضارة، يتم تقييد توفّر تقنية NFC لزيادة الوعي لدى المستخدمين والتحكم في استخدامهم لهذه التقنية إلى أقصى حد.

لقطة شاشة لطلب باستخدام تقنية NFC على الويب على موقع إلكتروني
طلب من مستخدم تقنية NFC على الويب

لا يتوفر NFC على الويب إلا للإطارات ذات المستوى الأعلى وسياقات التصفح الآمن (HTTPS فقط). يجب أن تطلب المصادر أولاً إذن "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 مستهدفة تعكس نمط أداة الاختيار في الملفات الأخرى وواجهات برمجة التطبيقات للوصول إلى الجهاز.

لإجراء مسح ضوئي أو الكتابة، يجب أن تكون صفحة الويب مرئية عندما يلمس المستخدم علامة NFC بجهازه. يستخدم المتصفح التجاوب الحسّي للإشارة إلى النقر. يتم حظر الوصول إلى لاسلكي NFC إذا كانت الشاشة مغلقة أو تم قفل الجهاز. أما بالنسبة إلى صفحات الويب غير المرئية، فيتم تعليق عمليات تلقّي محتوى NFC ونشره واستئناف هذه العملية عند ظهور صفحة ويب من جديد.

بفضل واجهة برمجة تطبيقات مستوى رؤية الصفحة، أصبح من الممكن تتبع الحالات التي تتغير فيها مستوى رؤية المستند.

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 وعنصر صورة لفك ترميز بيانات الصور.

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 مطلق وكتابته

يمكن فك ترميز سجلّ عنوان URL المطلق data باستخدام عملية 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 كحمولته. عليك استدعاء record.toRecords() لتحويل data إلى قائمة بالسجلّات المضمّنة في سجلّ الملصق الذكي. يجب أن تشتمل على سجل عنوان URL، وسجل نصي للعنوان، وسجلّ من نوع MIME للصورة، وبعض السجلات من النوع المحلي المخصص، مثل ":t" و":act" و":s" على التوالي لنوع سجل الملصق الذكي والإجراء وحجمه.

تكون سجلّات النوع المحلي فريدة فقط في السياق المحلي لسجلّ NDEF الذي يحتوي على تلك البيانات. يمكنك استخدامها عندما لا يكون معنى الأنواع مهمًا خارج السياق المحلي للسجلّ الذي يتضمّنه وعندما يكون استخدام مساحة التخزين قيدًا صارمًا. تبدأ أسماء سجلّات الأنواع المحلية دائمًا بـ : في تقنية 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] });

المتصفحات المتوافقة

تتوفّر تقنية NFC على الويب على أجهزة Android في الإصدار 89 من Chrome.

نصائح للمطوّرين

إليك قائمة بالأمور التي تمنيت لو كنت أعرفها عندما بدأت اللعب باستخدام تقنية NFC على الويب:

  • يتعامل Android مع علامات NFC على مستوى نظام التشغيل قبل تشغيل تكنولوجيا NFC على الويب.
  • يمكنك العثور على رمز NFC على material.io.
  • يمكنك استخدام سجلّ NDEF id لتحديد أحد السجلات بسهولة عند الحاجة.
  • تحتوي علامة NFC غير منسّقة التي تتوافق مع NDEF على سجلّ واحد من النوع الفارغ.
  • من السهل كتابة سجلّ تطبيق Android، كما هو موضّح أدناه.
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

إضافة ملاحظات

يسعدنا معرفة رأيك وتجاربك في استخدام تقنية Web NFC من خلال مجموعة منتدى Web NFC وفريق Chrome.

أخبرنا عن تصميم واجهة برمجة التطبيقات

هل هناك أي مشكلة في واجهة برمجة التطبيقات لا تعمل كما هو متوقع؟ أو هل هناك طرق أو خصائص مفقودة تحتاج إلى تنفيذ فكرتك؟

يمكنك الإبلاغ عن مشكلة في المواصفات في مستودع Web NFC GitHub أو إضافة رأيك حول مشكلة حالية.

الإبلاغ عن مشكلة في التنفيذ

هل واجهت خطأً في تنفيذ Chrome؟ أم أن التنفيذ مختلف عن المواصفات؟

عليك الإبلاغ عن الخطأ على https://new.crbug.com. واحرص على تضمين أكبر قدر ممكن من التفاصيل، وتقديم تعليمات بسيطة لإعادة إنتاج الخطأ، وضبط المكوّنات على Blink>NFC. تعمل Glitch بشكل رائع لمشاركة عمليات إعادة الإنشاء السريعة والسهلة.

إظهار الدعم

هل تخطّط لاستخدام تكنولوجيا NFC على الويب؟ يساعد الدعم العام فريق Chrome في تحديد أولويات الميزات ويعرض لمورّدي المتصفِّح الآخرين مدى أهمية دعمهم.

يمكنك إرسال تغريدة إلى @ChromiumDev باستخدام الهاشتاغ #WebNFC وإعلامنا بمكان استخدامك لها وطريقة استخدامك لها.

روابط مفيدة

شكر وتقدير

شكرًا للعمل في Intel لتنفيذ تكنولوجيا NFC على الويب. يعتمد Google Chrome على مجتمع من الملتزمين الذين يعملون معًا للمضي قدمًا في مشروع Chromium. ليس كل مشارك في Chromium موظفًا في Google، وهؤلاء المساهمون يستحقون التقدير الخاص.