मुफ़्त APK बनाएँ

JavaScript ब्रिज API

NFC

window.AndroidNFC से टैग पढ़ना, और NDEFReader पॉलीफ़िल के पीछे का राइट वाला हिस्सा।

NDEFReader वेब स्टैंडर्ड#

new NDEFReader() — Web NFC

उदाहरण

मानक Web NFC: new NDEFReader() इंस्टॉल किए गए ऐप में NFC टैग पढ़ता, लिखता और लॉक करता है, उसी कोड से जो Android पर Chrome मानता है।

लौटाता है: Promise और reading / readingerror इवेंट, जैसे वेब मानक में। रिकॉर्ड NDEFRecord होते हैं: recordType ('text', 'url', 'absolute-url', 'mime', 'smart-poster', 'empty', 'unknown' या 'example.com:thing' जैसा बाहरी टाइप), mediaType (mime रिकॉर्ड), id, encoding और lang (टेक्स्ट रिकॉर्ड) और data एक DataView के रूप में। ज़रूरत: बिल्ड करते समय चरण 4 (Access) में Web NFC Support चालू करें। इसके बिना NDEFReader मौजूद नहीं होता। कोई रनटाइम अनुमति प्रॉम्प्ट नहीं; navigator.permissions.query({name:'nfc'}) जवाब देता है granted.

टैग पढ़ें। data को TextDecoder से डिकोड करें, बिल्कुल Chrome की तरह:

function describe(record) {
  if (record.recordType === 'text') return new TextDecoder(record.encoding).decode(record.data);
  if (record.recordType === 'url' || record.recordType === 'absolute-url') return new TextDecoder().decode(record.data);
  if (record.recordType === 'mime') return record.mediaType + ' (' + record.data.byteLength + ' bytes)';
  return record.recordType;
}

var scanStop = null;

document.getElementById('read').addEventListener('click', async function () {
  if (!('NDEFReader' in window)) { showStatus('NFC is not available in this app.'); return; }
  var reader = new NDEFReader();
  scanStop = new AbortController();
  reader.onreading = function (e) {
    showStatus('Tag ' + e.serialNumber + ': ' + e.message.records.map(describe).join(' | '));
  };
  reader.onreadingerror = function () { showStatus('That tag holds no NFC data this phone can read.'); };
  try {
    await reader.scan({ signal: scanStop.signal });
    showStatus('Hold a tag to the back of the phone.');
  } catch (err) {
    showStatus('NFC error: ' + err.name + ' ' + err.message);   // NotReadableError = NFC switched off
  }
});

document.getElementById('stop').addEventListener('click', function () {
  if (scanStop) scanStop.abort();   // the standard way to stop scanning
});

टेक्स्ट या लिंक लिखें। यूज़र के टैग टैप करने के बाद Promise पूरा होता है:

async function writeTag(kind, value) {
  if (!('NDEFReader' in window)) { showStatus('NFC is not available in this app.'); return; }
  var reader = new NDEFReader();
  showStatus('Tap a tag to write it...');
  try {
    if (kind === 'text') await reader.write(value);   // same as { records: [{ recordType: 'text', data: value }] }
    else await reader.write({ records: [{ recordType: 'url', data: value }] }, { overwrite: false });
    showStatus('Tag written.');
  } catch (err) {
    showStatus('Write failed: ' + err.name + ' ' + err.message);   // NotAllowedError: read-only, or overwrite:false on a used tag
  }
}

टैग को हमेशा के लिए लॉक करें। makeReadOnly() को वापस नहीं किया जा सकता - पहले पूछें:

async function lockTag() {
  if (!('NDEFReader' in window)) return;
  if (!confirm('Lock the next tag you tap? It can never be changed again.')) return;
  try { await new NDEFReader().makeReadOnly(); showStatus('Tag locked.'); }
  catch (err) { showStatus('Lock failed: ' + err.message); }
}

ध्यान दें: write के रिकॉर्ड टाइप: text (स्ट्रिंग, या encoding के साथ बाइट), url और absolute-url (स्ट्रिंग), mime (बाइट + mediaType), smart-poster ({records: [...]}), बाहरी टाइप 'domain:thing' (बाइट या {records: [...]}), unknown (बाइट) और empty। सादी स्ट्रिंग टेक्स्ट रिकॉर्ड लिखती है; सादे बाइट application/octet-stream mime रिकॉर्ड लिखते हैं। सिर्फ़ जिन रीडर ने scan() बुलाया है उन्हें reading इवेंट मिलते हैं; signal पर AbortController.abort() उस रीडर को रोकता है (मानक में stop() नहीं है)। readingerror उस टैग के लिए चलता है जो NFC डेटा नहीं रख सकता। फ़ोन एक समय में सिर्फ़ एक टैग ऑपरेशन का इंतज़ार करता है: इंतज़ार के दौरान नया write() या makeReadOnly() उसे बदल देता है, और बदली गई कॉल AbortError के साथ रिजेक्ट होती है (Chrome इसे कतार में लगाता)। write() / makeReadOnly() पर signal इंतज़ार रद्द करता है। त्रुटियाँ: NotSupportedError (NFC नहीं है, या टैग NDEF नहीं रख सकता, या बहुत छोटा है), NotReadableError (NFC बंद है), NotAllowedError (रीड-ओनली टैग, या रिकॉर्ड वाले टैग पर overwrite: false), NetworkError (टैग हट गया), TypeError (ऐसा रिकॉर्ड जिसे मानक नहीं मानता)। NDEFReader मुख्य पेज में होता है, iframe के अंदर नहीं।

__nfcCancelWrite ब्रिज#

window.WebToApk.__nfcCancelWrite()

इंतज़ार कर रहे राइट/लॉक को रद्द करता है (ऑपरेशन का `signal` एबॉर्ट होने पर पॉलीफ़िल इसे बुलाता है)।

उदाहरण

कतार में लगा NFC राइट या लॉक हटा देता है ताकि अगला टैग टैप सामान्य रूप से पढ़ा जाए। पेज वेब मानक से रद्द करते हैं - एक AbortController signal - और NDEFReader पॉलीफ़िल उनके लिए इसे बुलाता है।

लौटाता है: कुछ नहीं। ज़रूरत: बिल्ड करते समय चरण 4 (Access) में Web NFC Support चालू हो।

मानक तरीका, जिसे ऐप मानता है - इंतज़ार करता write() रिजेक्ट होता है AbortError:

var controller = null;

async function writeWithCancel(text) {
  if (!('NDEFReader' in window)) { showStatus('NFC is not available in this app.'); return; }
  controller = new AbortController();
  showStatus('Tap a tag to write it... (or press Cancel)');
  try {
    await new NDEFReader().write(text, { signal: controller.signal });
    showStatus('Tag written.');
  } catch (err) {
    showStatus(err.name === 'AbortError' ? 'Cancelled.' : 'Write failed: ' + err.message);
  }
}

document.getElementById('cancel').addEventListener('click', function () {
  if (controller) controller.abort();
});

समय पर कोई टैग न आए तो खुद हार मान लें; सिग्नल को एबॉर्ट करने वाला टाइमर भी उसी तरह रद्द करता है:

async function writeWithTimeout(url, ms) {
  if (!('NDEFReader' in window)) { showStatus('NFC is not available in this app.'); return; }
  var controller = new AbortController();
  var timer = setTimeout(function () { controller.abort(); }, ms);
  showStatus('Tap a tag within ' + Math.round(ms / 1000) + ' seconds...');
  try {
    await new NDEFReader().write({ records: [{ recordType: 'url', data: url }] }, { signal: controller.signal });
    showStatus('Tag written.');
  } catch (err) {
    showStatus(err.name === 'AbortError' ? 'Timed out. Tap Write to try again.' : 'Write failed: ' + err.message);
  } finally {
    clearTimeout(timer);
  }
}

यूज़र के स्क्रीन छोड़ने पर इंतज़ार कर रहे लॉक (या राइट) को रद्द करें, ताकि बाद का टैप किसी टैग को न बदले:

var pendingTagOp = null;

window.addEventListener('hashchange', function () {
  if (pendingTagOp) { pendingTagOp.abort(); pendingTagOp = null; }
});

document.getElementById('lock').addEventListener('click', function () {
  if (!('NDEFReader' in window)) { showStatus('NFC is not available in this app.'); return; }
  if (pendingTagOp) pendingTagOp.abort();
  var controller = pendingTagOp = new AbortController();
  showStatus('Tap the tag to lock it...');
  new NDEFReader().makeReadOnly({ signal: controller.signal })
    .then(function () { showStatus('Tag locked.'); })
    .catch(function (err) { if (err.name !== 'AbortError') showStatus('Lock failed: ' + err.message); })
    .finally(function () { if (pendingTagOp === controller) pendingTagOp = null; });
});

ध्यान दें: WebToApk.__nfcCancelWrite() को खुद न बुलाएँ: सीधे बुलाने पर यह नेटिव इंतज़ार हटा देता है पर पेज का Promise पूरा नहीं कर सकता। signal दोनों करता है। रद्द करना कतार में लगा भी हटा देता है makeReadOnly().

__nfcMakeReadOnly ब्रिज#

window.WebToApk.__nfcMakeReadOnly(): String

अगले टैग टैप के लिए स्थायी लॉक (`NDEFReader.makeReadOnly()`) कतार में लगाता है; उसकी op id लौटाता है, इस ऐप में NFC बंद होने पर ""।

उदाहरण

NDEFReader.makeReadOnly() के पीछे का अंदरूनी ट्रांसपोर्ट। पेज new NDEFReader().makeReadOnly() इस्तेमाल करते हैं; इसे कभी सीधे न बुलाएँ।

लौटाता है: (makeReadOnly के ज़रिए) एक Promise जो यूज़र के टैग टैप करने और उसके लॉक होने पर पूरा होता है, या DOMException के साथ रिजेक्ट होता है। ज़रूरत: बिल्ड करते समय चरण 4 (Access) में Web NFC Support चालू हो।

लॉक करना स्थायी है। पहले टैग लिखें, फिर उसे लॉक करें, और दोनों से पहले यूज़र से पूछें:

document.getElementById('publish-tag').addEventListener('click', async function () {
  if (!('NDEFReader' in window)) { showStatus('NFC is not available in this app.'); return; }
  if (!confirm('Write and lock this tag? A locked tag can never be changed.')) return;
  var reader = new NDEFReader();
  try {
    showStatus('Tap the tag to write it...');
    await reader.write({ records: [{ recordType: 'url', data: 'https://example.com/item/42' }] });
    showStatus('Now tap the same tag again to lock it...');
    await reader.makeReadOnly();
    showStatus('Tag written and locked.');
  } catch (err) {
    showStatus('Failed: ' + err.message);
  }
});

पहले से लिखे टैग को लॉक करें, और 20 सेकंड में कोई टैग न आए तो छोड़ दें:

async function lockTag() {
  if (!('NDEFReader' in window)) { showStatus('NFC is not available in this app.'); return; }
  if (!confirm('Lock this tag for good? It can never be changed again.')) return;
  var controller = new AbortController();
  var timer = setTimeout(function () { controller.abort(); }, 20000);
  showStatus('Tap the tag to lock it...');
  try {
    await new NDEFReader().makeReadOnly({ signal: controller.signal });
    showStatus('Tag locked.');
  } catch (err) {
    if (err.name === 'AbortError') showStatus('No tag was tapped. Try again when ready.');
    else if (err.name === 'NotAllowedError') showStatus('This kind of tag cannot be locked.');
    else showStatus('Lock failed: ' + err.message);
  } finally {
    clearTimeout(timer);
  }
}

पहले टैग पढ़ें और उसे लॉक करने का विकल्प तभी दें जब उसमें अपेक्षित लिंक हो:

async function checkThenLock(expectedUrl) {
  if (!('NDEFReader' in window)) { showStatus('NFC is not available in this app.'); return; }
  var reader = new NDEFReader();
  var scanning = new AbortController();
  var lockBtn = document.getElementById('lock-btn');
  reader.onreading = function (e) {
    var rec = e.message.records.find(function (r) { return r.recordType === 'url'; });
    var url = rec ? new TextDecoder().decode(rec.data) : null;
    showStatus(url ? 'Tag points to ' + url : 'This tag holds no link.');
    lockBtn.disabled = url !== expectedUrl;
  };
  await reader.scan({ signal: scanning.signal });
  showStatus('Hold the tag to the phone to check it.');

  lockBtn.onclick = async function () {
    if (!confirm('Lock this tag? It can never be changed again.')) return;
    scanning.abort();
    showStatus('Tap the tag again to lock it...');
    try { await reader.makeReadOnly(); showStatus('Tag locked.'); }
    catch (err) { showStatus('Lock failed: ' + err.message); }
  };
}

ध्यान दें: हर चरण को अपना टैप चाहिए। कॉल एक ऑपरेशन id लौटाती है और नतीजा window.__appmintNfcDone से आता है। रिजेक्शन: NotSupportedError "Tag does not support NDEF", NotAllowedError "This tag cannot be made read-only" (कई टैग लॉक नहीं हो सकते), NetworkError जब टैग हट जाए। लॉक के इंतज़ार में write() शुरू करने पर लॉक बदल जाता है, और वह AbortError के साथ रिजेक्ट होता है। makeReadOnly({ signal }) को दिया गया signal इंतज़ार रद्द कर देता है।

__nfcState ब्रिज#

window.WebToApk.__nfcState(): String

"on", "off" (फ़ोन की सेटिंग्स में NFC बंद है) या "none" (NFC नहीं है, या इस ऐप में चालू नहीं है) - जिसे `NDEFReader.scan()` सबसे पहले जाँचता है।

उदाहरण

NDEFReader.scan() के पीछे की अंदरूनी जाँच: क्या यह ऐप अभी NFC इस्तेमाल कर सकता है। पेज scan() बुलाते हैं और उसकी रिजेक्शन पढ़ते हैं।

लौटाता है: 'on', 'off' (फ़ोन की सेटिंग्स में NFC बंद है) या 'none' (फ़ोन में NFC नहीं है, या ऐप Web NFC Support के बिना बना है)। ज़रूरत: बिल्ड करते समय चरण 4 (Access) में Web NFC Support चालू हो।

मानक तरीका - scan() उसी जवाब के साथ रिजेक्ट होता है:

async function startReading() {
  if (!('NDEFReader' in window)) { showStatus('NFC is not available in this app.'); return; }
  try {
    await new NDEFReader().scan();
    showStatus('Hold a tag to the back of the phone.');
  } catch (err) {
    if (err.name === 'NotReadableError') showStatus('Turn on NFC in the phone settings, then try again.');
    else if (err.name === 'NotSupportedError') showStatus('This phone has no NFC.');
    else showStatus('NFC error: ' + err.message);
  }
}

स्क्रीन खुलने पर एक बार जाँचें, ताकि NFC पैनल, "turn on NFC" संकेत और NFC को पूरी तरह छिपाने में से चुन सकें। प्रोब के स्कैन को तुरंत एबॉर्ट करने से कुछ चलता नहीं रहता:

async function nfcStatus() {
  if (!('NDEFReader' in window)) return 'none';
  var probe = new AbortController();
  try {
    await new NDEFReader().scan({ signal: probe.signal });
    return 'on';
  } catch (err) {
    return err.name === 'NotReadableError' ? 'off' : 'none';
  } finally {
    probe.abort();
  }
}

async function refreshNfcUi() {
  var state = await nfcStatus();
  document.getElementById('nfc-panel').hidden = state !== 'on';
  document.getElementById('nfc-off-hint').hidden = state !== 'off';
}

refreshNfcUi();
document.addEventListener('visibilitychange', function () {
  if (document.visibilityState === 'visible') refreshNfcUi(); // back from the phone settings
});

टैग सिर्फ़ तब पढ़ें जब एक स्क्रीन खुली हो, और खाली या न पढ़े जा सकने वाले टैग को NFC बंद होने से अलग पहचानें:

var tagScreen = null;

async function openTagScreen() {
  if (!('NDEFReader' in window)) { showStatus('NFC is not available in this app.'); return; }
  tagScreen = new AbortController();
  var reader = new NDEFReader();
  reader.onreading = function (e) {
    var n = e.message.records.length;
    showStatus(n ? 'Tag ' + e.serialNumber + ' holds ' + n + ' record(s).' : 'This tag is empty.');
  };
  reader.onreadingerror = function () { showStatus('This tag cannot be read. Try another one.'); };
  try {
    await reader.scan({ signal: tagScreen.signal });
    showStatus('Hold a tag to the back of the phone.');
  } catch (err) {
    showStatus(err.name === 'NotReadableError' ? 'NFC is off. Turn it on in the phone settings.' : 'NFC error: ' + err.message);
  }
}

function closeTagScreen() {
  if (tagScreen) { tagScreen.abort(); tagScreen = null; }
}

ध्यान दें: पॉलीफ़िल की प्लंबिंग; scan() इस्तेमाल करें। window.AndroidNFC.startScan() वही सवाल बूलियन में जवाबता है और NFC बंद होने पर "Please enable NFC" संदेश दिखाता है।

__nfcWrite ब्रिज#

window.WebToApk.__nfcWrite(messageJson: String): String

अगले टैग टैप के लिए [messageJson] (`{records:[…], overwrite}`, जिसे `NDEFReader.write()` बनाता है) कतार में लगाता है और उसकी op id लौटाता है; इस ऐप में NFC चालू न होने पर ""।

उदाहरण

NDEFReader.write(message) के पीछे का अंदरूनी ट्रांसपोर्ट। पेज new NDEFReader().write(...) इस्तेमाल करते हैं; इसे कभी सीधे न बुलाएँ।

लौटाता है: (write के ज़रिए) एक Promise जो यूज़र के टैग टैप करने और उसमें लिखे जाने पर पूरा होता है, या DOMException के साथ रिजेक्ट होता है। ज़रूरत: बिल्ड करते समय चरण 4 (Access) में Web NFC Support चालू हो।

document.getElementById('write-table-tag').addEventListener('click', async function () {
  if (!('NDEFReader' in window)) { showStatus('NFC is not available in this app.'); return; }
  showStatus('Tap a tag to write it...');
  try {
    await new NDEFReader().write({
      records: [
        { recordType: 'url', data: 'https://example.com/menu' },
        { recordType: 'text', data: 'Table 12', lang: 'en' },
        { recordType: 'mime', mediaType: 'application/json',
          data: new TextEncoder().encode(JSON.stringify({ table: 12 })) }
      ]
    });
    showStatus('Tag written.');
  } catch (err) {
    showStatus('Write failed: ' + err.message);
  }
});

सिर्फ़ खाली टैग पर लिखें, ताकि जिस टैग में पहले से डेटा है उसे गलती से बदला न जाए:

async function writeToBlankTag(url) {
  if (!('NDEFReader' in window)) { showStatus('NFC is not available in this app.'); return; }
  showStatus('Tap a blank tag...');
  try {
    await new NDEFReader().write(
      { records: [{ recordType: 'url', data: url }] },
      { overwrite: false }
    );
    showStatus('Tag written.');
  } catch (err) {
    if (err.name === 'NotAllowedError') showStatus('That tag already holds data or is locked. Use a blank tag.');
    else if (err.name === 'NetworkError') showStatus('Hold the tag still until it is written.');
    else showStatus('Write failed: ' + err.message);
  }
}

स्मार्ट पोस्टर लिखें, यानी एक लिंक अपने शीर्षक के साथ, एक रिकॉर्ड के रूप में:

document.getElementById('write-poster').addEventListener('click', async function () {
  if (!('NDEFReader' in window)) { showStatus('NFC is not available in this app.'); return; }
  showStatus('Tap a tag to write the poster...');
  try {
    await new NDEFReader().write({
      records: [{
        recordType: 'smart-poster',
        data: { records: [
          { recordType: 'url', data: 'https://example.com/events/spring-fair' },
          { recordType: 'text', data: 'Spring Fair tickets', lang: 'en' }
        ] }
      }]
    });
    showStatus('Poster tag written.');
  } catch (err) {
    showStatus(err.name === 'NotSupportedError' ? 'This tag is too small or cannot hold NFC data.' : 'Write failed: ' + err.message);
  }
});

ध्यान दें: पॉलीफ़िल रिकॉर्ड जाँचता है, उन्हें {records:[{recordType, id, data(base64), encoding, lang, mediaType, records?}], overwrite} में बदलता है और JSON स्ट्रिंग यहाँ पास करता है। कॉल एक ऑपरेशन id लौटाती है; नतीजा पेज को window.__appmintNfcDone(id, errorName, message) से मिलता है, इसलिए बदले जा चुके राइट का जवाब नए राइट को कभी पूरा नहीं करता। बिना फ़ॉर्मैट वाले टैग पहले फ़ॉर्मैट होते हैं। रिजेक्शन: NotAllowedError ("Tag is read-only", या overwrite false होने पर रिकॉर्ड वाला टैग), NotSupportedError ("Tag does not support NDEF", "Tag too small (N bytes available)"), NetworkError (टैग हट गया), SyntaxError (ऐसा रिकॉर्ड जिसे टैग का फ़ॉर्मैट नहीं रख सकता)। ऐप अपने छोटे "Ready to write" और "NFC tag written" संदेश भी दिखाता है।

startScan ब्रिज#

window.AndroidNFC.startScan(): Boolean

पुराना उपलब्धता प्रोब, जो सिर्फ़ तब मौजूद होता है जब क्रिएटर ने NFC चालू किया हो। असली NFC काम मानक NDEFReader पॉलीफ़िल (window.WebToApk.__nfc*) से होता है, जिसे पेज को इस्तेमाल करना चाहिए; यह सिर्फ़ बताता है कि एडाप्टर चालू है या नहीं।

इसे अकेले नहीं, अपने समूह Web NFC से समझाया गया है।

उदाहरण

बताता है कि फ़ोन का NFC चालू है या नहीं। यह window.AndroidNFC पर रहता है, window.WebToApk पर नहीं, और टैग नहीं पढ़ता - पढ़ना इससे होता है NDEFReader.

लौटाता है: फ़ोन में NFC होने और चालू होने पर (तुरंत) true; फ़ोन में NFC न होने या बंद होने पर false (तब ऐप एक छोटा "Please enable NFC" संदेश भी दिखाता है)। ज़रूरत: बिल्ड करते समय चरण 4 (Access) में Web NFC Support चालू हो; इसके बिना window.AndroidNFC मौजूद नहीं होता।

NFC बटन दिखाने से पहले जाँचें:

function nfcReady() {
  if (!window.AndroidNFC || typeof window.AndroidNFC.startScan !== 'function') return false;
  return window.AndroidNFC.startScan();
}

document.getElementById('scan-tag').addEventListener('click', async function () {
  if (!nfcReady()) { showStatus('Turn on NFC in the phone settings, then try again.'); return; }
  var reader = new NDEFReader();
  reader.addEventListener('reading', function (e) { showStatus('Tag ' + e.serialNumber); });
  await reader.scan();
  showStatus('Hold a tag to the back of the phone.');
});

राइट से ठीक पहले जाँचें: NFC बंद होने पर राइट ऐसे टैप का इंतज़ार करता रहेगा जो कभी नहीं आएगा, जबकि startScan() तुरंत जवाब देता है और ऐप का "Please enable NFC" संदेश दिखाता है:

document.getElementById('write-pass').addEventListener('click', async function () {
  if (!window.AndroidNFC || typeof window.AndroidNFC.startScan !== 'function') {
    showStatus('NFC is not available in this app.');
    return;
  }
  if (!window.AndroidNFC.startScan()) { showStatus('NFC is off, or this phone has no NFC.'); return; }
  showStatus('Tap a tag to write it...');
  try {
    await new NDEFReader().write('Visitor pass #1042');
    showStatus('Tag written.');
  } catch (err) {
    showStatus('Write failed: ' + err.message);
  }
});

यूज़र के लौटकर "I've turned it on" टैप करने पर फिर से जाँचें:

var retry = document.getElementById('nfc-retry');
retry.addEventListener('click', function () {
  if (!window.AndroidNFC || typeof window.AndroidNFC.startScan !== 'function') {
    showStatus('NFC is not available in this app.');
    return;
  }
  if (window.AndroidNFC.startScan()) {
    retry.hidden = true;
    document.getElementById('nfc-panel').hidden = false;
    startReading(); // your own NDEFReader.scan() code
  } else {
    showStatus('NFC is still off, or this phone has no NFC.');
  }
});

ध्यान दें: window.AndroidNFC पेज की पहली स्क्रिप्ट से ही मौजूद होता है। यूज़र के सेटिंग्स में NFC चालू करके लौटने के बाद टैग पढ़ना अपने-आप शुरू हो जाता है।

हर डॉक्स बिल्ड पर ऐप रनटाइम और उसकी उदाहरण फ़ाइलों से बनाया जाता है। Markdown में पढ़ें · सभी फ़ैमिली.

2026-10-03 को शिप किए गए ब्रिज से मिलाकर जाँचा गया।