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

JavaScript ब्रिज API

QR और बारकोड स्कैनर

एक promise से Google की स्कैनर स्क्रीन, AppMint.scanCode() - कैमरे की अनुमति के बिना, और आम QR कोड के लिए पार्स किया हुआ URL, Wi-Fi, फ़ोन या कॉन्टैक्ट।

AppMint.scanCode हेल्पर#

AppMint.scanCode(options)

उदाहरण

Google की QR कोड और बारकोड स्कैनर स्क्रीन खोलता है और स्कैन किया हुआ देता है। एक कॉल - कैमरे की अनुमति नहीं, <video> नहीं, अपना UI नहीं।

लौटाता है: एक Promise जो हमेशा पूरा होता है: {ok: true, value, displayValue, format, type, …} या {ok: false, code, message}। ज़रूरत: कुछ चालू करने की ज़रूरत नहीं। फ़ोन में Google Play services होना चाहिए।

कोई भी कोड:

async function scan() {
  if (!(window.AppMint && AppMint.scanCode)) { alert('Open this page in the app to scan'); return; }
  var r = await AppMint.scanCode();
  if (!r.ok) {
    if (r.code === 'cancelled') return;                          // the user closed the scanner
    if (r.code === 'unavailable') alert('The scanner is not available on this phone');
    else if (r.code === 'busy') alert('A scan is already open');
    else alert('Scan failed: ' + r.message);                     // 'failed'
    return;
  }
  console.log(r.value, r.format, r.type);   // "TICKET-4821", "qr_code", "text"
}

सिर्फ़ कुछ फ़ॉर्मैट, और ख़राब लेबल के लिए "ख़ुद टाइप करें" विकल्प:

var r = await AppMint.scanCode({
  formats: ['ean_13', 'ean_8', 'upc_a', 'upc_e'],   // shop barcodes
  manualInput: true,                                // lets the user type the code
  autoZoom: true                                    // default true
});
if (r.ok) lookUpProduct(r.value);

तैयार हिस्से - सिर्फ़ वही हिस्सा मौजूद होता है जो r.type से मेल खाता है:

var r = await AppMint.scanCode({ formats: ['qr_code'] });
if (r.ok) {
  if (r.type === 'url')     openLink(r.url.url);                      // url: { url, title }
  if (r.type === 'wifi')    showWifi(r.wifi.ssid, r.wifi.password, r.wifi.encryption); // 'wpa'|'wep'|'open'
  if (r.type === 'phone')   callNumber(r.phone);                      // a string
  if (r.type === 'email')   writeMail(r.email.address, r.email.subject, r.email.body);
  if (r.type === 'sms')     writeSms(r.sms.phoneNumber, r.sms.message);
  if (r.type === 'geo')     showMap(r.geo.lat, r.geo.lng);
  if (r.type === 'contact') addContact(r.contact.name, r.contact.organization, r.contact.phones, r.contact.emails);
}

ध्यान दें: फ़ॉर्मैट नाम: qr_code, aztec, codabar, code_39, code_93, code_128, data_matrix, ean_8, ean_13, itf, pdf417, upc_a, upc_e (अनजान नाम अनदेखे किए जाते हैं; कुछ न देने पर सभी फ़ॉर्मैट)। type इनमें से एक है: url, wifi, text, phone, email, sms, geo, contact, calendar, isbn, product, driver_license, unknown। त्रुटि कोड: cancelled (बंद किया गया, Back से भी), unavailable (Play services नहीं हैं, या स्कैनर डाउनलोड नहीं हो सका), busy (स्कैन पहले से खुला है), failed। फ़ोन पर पहला स्कैन कुछ सेकंड ले सकता है, क्योंकि Play services स्कैनर डाउनलोड करता है। AI से बने ऐप @/lib/appmintNative से scanCode() इस्तेमाल करते हैं, जो वेब पर भी स्कैन करता है।

AppMint.textRecognition हेल्पर#

AppMint.textRecognition.recognize(image, {script}) / prepare(script, onProgress)

उदाहरण

लैटिन के अलावा दूसरी लिपियों का टेक्स्ट पढ़ता है: देवनागरी (हिंदी, मराठी, नेपाली …), चीनी, जापानी और कोरियाई - या 'auto', जो हर लिपि आज़माता है और सबसे ज़्यादा अक्षरों वाला नतीजा रखता है। यही विकल्प स्टैंडर्ड डिटेक्टर पर भी चलता है: new TextDetector({ script: 'devanagari' })। विकल्प के बिना सब कुछ पहले की तरह लैटिन में ही पढ़ा जाता है।

लौटाता है: recognize() → {script, text, blocks: [{text, box, corners, lines}]} का Promise (script = इस्तेमाल हुई लिपि); अनजान लिपि या Google Play services न होने पर NotSupportedError के साथ DOMException रिजेक्ट होता है, वरना OperationError के साथ। prepare() → {script, status: 'ready'} का Promise। ज़रूरत: Google Play services। हर लिपि का रिकग्नाइज़र Play services डाउनलोड है: आपके कोड में नाम वाली लिपियाँ ऐप के साथ इंस्टॉल होती हैं, बाकी पहले इस्तेमाल पर।

फ़ोटो से हिंदी टेक्स्ट:

document.getElementById('photo').addEventListener('change', async function (e) {
  var file = e.target.files[0];
  if (!file || !(window.AppMint && AppMint.textRecognition)) return;
  try {
    var r = await AppMint.textRecognition.recognize(file, { script: 'devanagari' });
    document.getElementById('out').textContent = r.text;
  } catch (err) {
    alert('Could not read the photo: ' + err.name);
  }
});

पहले किसी लिपि का मॉडल प्रोग्रेस के साथ डाउनलोड करें - वरना फ़ोन पर पहले इस्तेमाल में डाउनलोड का इंतज़ार करना पड़ता है:

async function getReady() {
  var bar = document.getElementById('model-progress');
  await AppMint.textRecognition.prepare('japanese', function (s) {
    if (s.progress != null) bar.value = s.progress;      // 0..1 while 'downloading'
  });
  bar.hidden = true;
}

// The same states arrive as events, also when a recognize() call starts a download:
window.addEventListener('appmint:ocr-model', function (e) {
  console.log(e.detail.script, e.detail.status, e.detail.progress);   // 'downloading' | 'ready' | 'failed'
});

मिले-जुले दस्तावेज़ - जिन लिपियों की आप उम्मीद करते हैं उनमें से ऐप को चुनने दें:

var r = await AppMint.textRecognition.recognize(img, { script: 'auto', scripts: ['latin', 'chinese', 'korean'] });
console.log('read as ' + r.script + ': ' + r.text);

var lines = await new TextDetector({ script: 'korean' }).detect(img);   // standard shape, one entry per line

ध्यान दें: scripts AppMint की सूची है: latin, devanagari, chinese, japanese, korean। अरबी, सिरिलिक, थाई और हिब्रू के लिए डिवाइस पर कोई रिकग्नाइज़र नहीं है। WebToApk.__ocrRecognizeWith(requestId, base64, optionsJson) अंदरूनी ट्रांसपोर्ट है; हेल्पर इस्तेमाल करें।

__ocrAvailable ब्रिज#

window.WebToApk.__ocrAvailable(): Boolean

TextDetector / recognizeText(): Google Play services मौजूद है (OCR मॉड्यूल का घर)।

उदाहरण

TextDetector के पीछे का अंदरूनी ट्रांसपोर्ट: क्या इस फ़ोन पर Google Play services है (जहाँ से रिकग्नाइज़र आता है)। पेज स्टैंडर्ड API इस्तेमाल करते हैं; इसे कभी सीधे कॉल न करें - __ वाले तरीके बिना सूचना के बदल सकते हैं।

लौटाता है: true या false। जब false हो, तब TextDetector बिल्कुल इंस्टॉल नहीं है। ज़रूरत: कुछ नहीं।

पब्लिक API इस्तेमाल करें:

if ('TextDetector' in window) scanButton.hidden = false;

स्कैन फ़्लो और टाइप किए फ़ॉर्म में से एक बार, स्टार्ट-अप पर चुनें। जिस फ़ोन में Google Play services नहीं होती वहाँ डिटेक्टर होता ही नहीं, इसलिए पेज को अंदर आने का दूसरा रास्ता देना होगा:

function setUpReceiptEntry() {
  var canScan = typeof window.TextDetector === 'function';
  document.getElementById('scan-receipt').hidden = !canScan;
  document.getElementById('type-receipt').hidden = canScan;
  if (!canScan) document.getElementById('entry-hint').textContent =
    'Text scanning is not available on this phone. Type the total below.';
}
document.addEventListener('DOMContentLoaded', setUpReceiptEntry);

जो डिटेक्टर मौजूद है वह भी कॉल के समय कह सकता है कि पहचान अभी उपलब्ध नहीं है। दोनों विफलताओं को त्रुटि के नाम से अलग पहचानें:

async function readLabel(img) {
  if (typeof window.TextDetector !== 'function') return null;
  try {
    var lines = await new TextDetector().detect(img);
    return lines.map(function (l) { return l.rawValue; }).join('\n');
  } catch (e) {
    if (e.name === 'NotSupportedError') showMessage('Text recognition is not available right now.');
    else showMessage('Could not read the label: ' + e.message);
    return null;
  }
}

ध्यान दें: ऐप शेल में लागू है (TextRecognitionBridge.kt)।

__ocrRecognize ब्रिज#

window.WebToApk.__ocrRecognize(requestId: String, base64: String)

[base64] (PNG/JPEG) में मौजूद टेक्स्ट पहचानता है; जवाब `appmint:ocr {requestId, blocks|error}` के रूप में आता है।

उदाहरण

TextDetector.detect() के पीछे का आंतरिक ट्रांसपोर्ट: PNG/JPEG में टेक्स्ट पहचानता है। पेज स्टैंडर्ड API इस्तेमाल करते हैं; इसे कभी सीधे कॉल न करें - __ मेथड बिना सूचना बदल सकते हैं।

लौटाता है: कुछ नहीं; जवाब appmint:ocr इवेंट {requestId, blocks:[{text, box, corners, lines}]} या {requestId, error} (unavailable, bad-image, failed: …) के रूप में आता है। ज़रूरत: कुछ नहीं।

पब्लिक API इस्तेमाल करें:

const lines = await new TextDetector().detect(document.getElementById('receipt'));
console.log(lines.map((l) => l.rawValue));

यूज़र की चुनी फ़ोटो का टेक्स्ट पढ़ें। detect() <img>, <canvas> या के अलावा Blob/File भी स्वीकार करता है ImageData:

<input type="file" id="doc" accept="image/*" capture="environment">
<pre id="out"></pre>
<script>
document.getElementById('doc').addEventListener('change', async function (e) {
  var file = e.target.files[0];
  if (!file || typeof window.TextDetector !== 'function') return;
  try {
    var lines = await new TextDetector().detect(file);
    document.getElementById('out').textContent = lines.map(function (l) { return l.rawValue; }).join('\n');
  } catch (err) {
    document.getElementById('out').textContent = 'Could not read the photo (' + err.name + ')';
  }
});
</script>

पहचानी गई हर लाइन को इमेज के ऊपर आउटलाइन करें। boundingBox इमेज के अपने पिक्सल में है, इसलिए उसे दिखाए गए साइज़ के हिसाब से स्केल करें। इमेज पूरी लोड हो चुकी होनी चाहिए, वरना detect() इस त्रुटि के साथ रिजेक्ट होता है InvalidStateError:

async function highlightLines(img, overlay) {
  if (!img.complete) await new Promise(function (r) { img.onload = r; });
  var lines = await new TextDetector().detect(img);
  var sx = img.clientWidth / img.naturalWidth, sy = img.clientHeight / img.naturalHeight;
  overlay.innerHTML = '';
  lines.forEach(function (l) {
    var b = l.boundingBox, box = document.createElement('div');
    box.className = 'ocr-box';
    box.title = l.rawValue;
    box.style.cssText = 'position:absolute;left:' + b.x * sx + 'px;top:' + b.y * sy +
      'px;width:' + b.width * sx + 'px;height:' + b.height * sy + 'px';
    overlay.appendChild(box);
  });
}

रसीद से राशि निकालें। कोई क्रॉस-ऑरिजिन इमेज जो कैनवास को दूषित कर दे, SecurityError के साथ रिजेक्ट होती है, इसलिए तस्वीर ऐप के अपने ऑरिजिन से दें:

async function findTotal(img) {
  try {
    var lines = await new TextDetector().detect(img);
    var hit = lines.find(function (l) { return /total/i.test(l.rawValue); });
    var m = hit && hit.rawValue.match(/(\d+[.,]\d{2})/);
    return m ? parseFloat(m[1].replace(',', '.')) : null;
  } catch (e) {
    if (e.name === 'SecurityError') console.warn('Image is from another origin; load it from the app instead.');
    else console.warn('OCR failed:', e.name, e.message);
    return null;
  }
}

ध्यान दें: ऐप शेल में लागू है (TextRecognitionBridge.kt)।

__ocrRecognizeWith ब्रिज#

window.WebToApk.__ocrRecognizeWith(requestId: String, base64: String, optionsJson: String)

[__ocrRecognize] विकल्प [optionsJson] के साथ `{script: 'latin'|'devanagari'|'chinese'|'japanese'|'korean'|'auto', scripts?}`; `appmint:ocr` जवाब में इस्तेमाल हुआ `script` भी बताया जाता है।

उदाहरण

AppMint.textRecognition के साथ दस्तावेज़ित - वहाँ का उदाहरण इसे भी दिखाता है।

लैटिन के अलावा दूसरी लिपियों का टेक्स्ट पढ़ता है: देवनागरी (हिंदी, मराठी, नेपाली …), चीनी, जापानी और कोरियाई - या 'auto', जो हर लिपि आज़माता है और सबसे ज़्यादा अक्षरों वाला नतीजा रखता है। यही विकल्प स्टैंडर्ड डिटेक्टर पर भी चलता है: new TextDetector({ script: 'devanagari' })। विकल्प के बिना सब कुछ पहले की तरह लैटिन में ही पढ़ा जाता है।

लौटाता है: recognize() → {script, text, blocks: [{text, box, corners, lines}]} का Promise (script = इस्तेमाल हुई लिपि); अनजान लिपि या Google Play services न होने पर NotSupportedError के साथ DOMException रिजेक्ट होता है, वरना OperationError के साथ। prepare() → {script, status: 'ready'} का Promise। ज़रूरत: Google Play services। हर लिपि का रिकग्नाइज़र Play services डाउनलोड है: आपके कोड में नाम वाली लिपियाँ ऐप के साथ इंस्टॉल होती हैं, बाकी पहले इस्तेमाल पर।

फ़ोटो से हिंदी टेक्स्ट:

document.getElementById('photo').addEventListener('change', async function (e) {
  var file = e.target.files[0];
  if (!file || !(window.AppMint && AppMint.textRecognition)) return;
  try {
    var r = await AppMint.textRecognition.recognize(file, { script: 'devanagari' });
    document.getElementById('out').textContent = r.text;
  } catch (err) {
    alert('Could not read the photo: ' + err.name);
  }
});

पहले किसी लिपि का मॉडल प्रोग्रेस के साथ डाउनलोड करें - वरना फ़ोन पर पहले इस्तेमाल में डाउनलोड का इंतज़ार करना पड़ता है:

async function getReady() {
  var bar = document.getElementById('model-progress');
  await AppMint.textRecognition.prepare('japanese', function (s) {
    if (s.progress != null) bar.value = s.progress;      // 0..1 while 'downloading'
  });
  bar.hidden = true;
}

// The same states arrive as events, also when a recognize() call starts a download:
window.addEventListener('appmint:ocr-model', function (e) {
  console.log(e.detail.script, e.detail.status, e.detail.progress);   // 'downloading' | 'ready' | 'failed'
});

मिले-जुले दस्तावेज़ - जिन लिपियों की आप उम्मीद करते हैं उनमें से ऐप को चुनने दें:

var r = await AppMint.textRecognition.recognize(img, { script: 'auto', scripts: ['latin', 'chinese', 'korean'] });
console.log('read as ' + r.script + ': ' + r.text);

var lines = await new TextDetector({ script: 'korean' }).detect(img);   // standard shape, one entry per line

ध्यान दें: scripts AppMint की सूची है: latin, devanagari, chinese, japanese, korean। अरबी, सिरिलिक, थाई और हिब्रू के लिए डिवाइस पर कोई रिकग्नाइज़र नहीं है। WebToApk.__ocrRecognizeWith(requestId, base64, optionsJson) अंदरूनी ट्रांसपोर्ट है; हेल्पर इस्तेमाल करें।

prepareTextRecognition ब्रिज#

window.WebToApk.prepareTextRecognition(script: String): String

इस्तेमाल से पहले [script] के लिए टेक्स्ट रिकग्नाइज़र डाउनलोड करता है। "checking" लौटाता है (फिर `appmint:ocr-model {script, status: 'downloading'|'ready'|'failed', progress?}`), "unsupported-script" या "unavailable" (Google Play services नहीं है)।

उदाहरण

इस्तेमाल से पहले एक लिपि के लिए डिवाइस पर चलने वाला टेक्स्ट रिकग्नाइज़र डाउनलोड करता है, ताकि पहला recognize() इंतज़ार न करे। पेज आम तौर पर AppMint.textRecognition.prepare(script) कॉल करते हैं, जो इसे लपेटता है।

लौटाता है: तुरंत एक स्ट्रिंग - "checking" (नतीजा appmint:ocr-model इवेंट {script, status: 'downloading' | 'ready' | 'failed', progress?, error?} के रूप में आता है), "unsupported-script" या "unavailable" (Google Play services नहीं है)। 'auto' हर स्क्रिप्ट तैयार करता है। ज़रूरत: Google Play services।

if (window.WebToApk && typeof window.WebToApk.prepareTextRecognition === 'function') {
  window.addEventListener('appmint:ocr-model', function (e) {
    if (e.detail.script !== 'chinese') return;
    if (e.detail.status === 'downloading') console.log('downloading', Math.round((e.detail.progress || 0) * 100) + '%');
    if (e.detail.status === 'ready') document.getElementById('scan').disabled = false;
    if (e.detail.status === 'failed') console.warn(e.detail.error);
  });
  var state = window.WebToApk.prepareTextRecognition('chinese');
  if (state !== 'checking') console.warn('Chinese text recognition: ' + state);
}

पहले तैयार करें, फिर रैपर से स्कैन करें:

async function readSign(canvas) {
  if (!(window.AppMint && AppMint.textRecognition)) return null;
  try {
    await AppMint.textRecognition.prepare('japanese');
    return await AppMint.textRecognition.recognize(canvas, { script: 'japanese' });
  } catch (err) {
    console.warn('Text recognition:', err.name, err.message);   // e.g. NotSupportedError without Play services
    return null;
  }
}

असमर्थित लिपियाँ और Play services की कमी रिटर्न वैल्यू में बताई जाती हैं:

const W = window.WebToApk;
if (W && typeof W.prepareTextRecognition === 'function') {
  const state = W.prepareTextRecognition('arabic');
  if (state === 'unsupported-script') showMessage('Arabic text cannot be read on the phone.');
  else if (state === 'unavailable') showMessage('Text recognition needs Google Play services.');
}

ध्यान दें: लिपियाँ: latin, devanagari, chinese, japanese, korean, auto। फ़ोन में पहले से मौजूद लिपि तुरंत ready जवाब देती है।

scanCode ब्रिज#

window.WebToApk.scanCode(optionsJson: String, callbackId: String)

Google का कोड स्कैनर खोलता है; [optionsJson] `{formats?, autoZoom?, manualInput?}`। AppMint.scanCode promise [callbackId] को पूरा करता है।

उदाहरण

AppMint.scanCode() के पीछे का अंदरूनी तंत्र - पेज वही Promise हेल्पर इस्तेमाल करते हैं, जो Google का QR/बारकोड स्कैनर खोलता है और नतीजे के साथ पूरा होता है।

लौटाता है: सीधे कुछ नहीं; नतीजा AppMint.scanCode() promise को पूरा करता है। ज़रूरत: कुछ चालू करने की ज़रूरत नहीं (कैमरे की अनुमति नहीं)। फ़ोन में Google Play services होना चाहिए।

पब्लिक API:

async function scanTicket() {
  if (!(window.AppMint && AppMint.scanCode)) { alert('Open this page in the app to scan'); return; }
  var r = await AppMint.scanCode({ formats: ['qr_code'] });
  if (r.ok) checkTicket(r.value);                  // r.format, r.type, r.displayValue…
  else if (r.code !== 'cancelled') alert('Scan failed (' + r.code + ')');
}

छपे QR कोड से Wi-Fi नेटवर्क से जुड़ें। Wi-Fi कोड type: 'wifi' और एक wifi ऑब्जेक्ट के साथ वापस आता है:

async function scanWifi() {
  if (!(window.AppMint && AppMint.scanCode)) return;
  var r = await AppMint.scanCode({ formats: ['qr_code'] });
  if (!r.ok) { if (r.code !== 'cancelled') alert('Scan failed (' + r.code + ')'); return; }
  if (r.type !== 'wifi') { alert('That is not a Wi-Fi code.'); return; }
  showWifiCard(r.wifi.ssid, r.wifi.password, r.wifi.encryption);   // encryption: 'wpa' | 'wep' | 'open'
}

दुकान के बारकोड से प्रोडक्ट खोजें, और लेबल ख़राब होने पर यूज़र को अंक ख़ुद टाइप करने दें (manualInput)। फ़ोन पर पहला स्कैन स्कैनर डाउनलोड कर सकता है, जो ऑफ़लाइन होने पर unavailable के साथ विफल होता है:

async function scanProduct() {
  if (!(window.AppMint && AppMint.scanCode)) { showManualEntry(); return; }
  var r = await AppMint.scanCode({ formats: ['ean_13', 'ean_8', 'upc_a', 'upc_e'], manualInput: true });
  if (r.ok) return lookUpProduct(r.value, r.format);            // e.g. '4006381333931', 'ean_13'
  if (r.code === 'busy') return;                                  // a scan is already open
  if (r.code === 'unavailable') alert('The scanner is not available: ' + r.message);
  else if (r.code !== 'cancelled') alert('Scan failed (' + r.code + ')');
}

QR कोड जिस चीज़ की ओर इशारा करता है उसे उसके डिकोड किए हुए से खोलें type:

async function scanAndOpen() {
  var r = await AppMint.scanCode({ formats: ['qr_code'], autoZoom: true });
  if (!r.ok) return;
  if (r.type === 'url') location.href = r.url.url;
  else if (r.type === 'phone') location.href = 'tel:' + r.phone;
  else if (r.type === 'email') location.href = 'mailto:' + r.email.address;
  else if (r.type === 'geo') showOnMap(r.geo.lat, r.geo.lng);
  else if (r.type === 'contact') saveContact(r.contact.name, r.contact.phones, r.contact.emails);
  else showText(r.displayValue);
}

ध्यान दें: सीधा तरीका optionsJson ({formats?, autoZoom?, manualInput?} JSON स्ट्रिंग के रूप में) और एक callbackId लेता है; जवाब हेल्पर की अंदरूनी रिप्लाई तालिका में पहुँचाया जाता है, इसलिए जो पेज इसे सीधे कॉल करता है उसे जवाब नहीं मिलता। एक समय में सिर्फ़ एक स्कैन चलता है - दूसरी कॉल code: 'busy' जवाब देती है। हर नतीजा फ़ील्ड और त्रुटि कोड के लिए AppMint.scanCode देखें।

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

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