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

JavaScript ब्रिज API

बैकग्राउंड जॉब्स

ऐसा काम जो ऐप बंद होने के बाद भी चलता रहे: टिकाऊ ऑटो-सेव, समय-समय पर सिंक।

workCancel ब्रिज#

window.WebToApk.workCancel(id: String)

किसी अनुमति की ज़रूरत नहीं; नतीजे `appmint:work` / window.onAppMintWork के रूप में आते हैं।

इसे अलग से नहीं, बल्कि इसके समूह बैकग्राउंड जॉब्स (WorkManager): टिकाऊ ऑटो-सेव + समय-समय पर नेटिव सिंक में बताया गया है।

उदाहरण

किसी बैकग्राउंड जॉब (एक बार वाला या दोहराने वाला) को उसके id से रद्द करता है और उसका सहेजा हुआ अनुरोध मिटा देता है।

लौटाता है: सीधे कुछ नहीं। appmint:work इवेंट (और window.onAppMintWork) { id, status: 'cancelled' } के साथ जवाब देता है। ज़रूरत: कुछ नहीं।

function stopSync() {
  if (!(window.WebToApk && window.WebToApk.workCancel)) return;
  WebToApk.workCancel('sync');
}

window.addEventListener('appmint:work', function (e) {
  if (e.detail.id === 'sync' && e.detail.status === 'cancelled') {
    document.getElementById('sync-status').textContent = 'Background sync is off';
  }
});

ड्राफ़्ट हटाएँ: उसका जो ऑटो-सेव अभी भेजा नहीं गया है उसे रद्द करें, फिर Android की पुष्टि मिलने पर एडिटर साफ़ करें:

function discardDraft() {
  if (!(window.WebToApk && window.WebToApk.workCancel)) { clearEditor(); return; }
  function onWork(e) {
    if (e.detail.id !== 'autosave' || e.detail.status !== 'cancelled') return;
    window.removeEventListener('appmint:work', onWork);
    clearEditor();
  }
  window.addEventListener('appmint:work', onWork);
  WebToApk.workCancel('autosave');
}

साइन-आउट पर, इस ऐप के हर जॉब को रद्द करें, उन id से जो workList बताता है:

function cancelAllJobs() {
  if (!(window.WebToApk && window.WebToApk.workList && window.WebToApk.workCancel)) return;
  const requestId = 'signout-' + Date.now();
  function onWork(e) {
    if (String(e.detail.requestId) !== requestId) return;
    window.removeEventListener('appmint:work', onWork);
    (e.detail.jobs || []).forEach(function (job) {
      WebToApk.workCancel(job.id);                      // each answers { id, status: 'cancelled' }
    });
  }
  window.addEventListener('appmint:work', onWork);
  WebToApk.workList(requestId);
}

नोट: यह cancelled लौटाता है, चाहे उस id का कोई जॉब हो या न हो। जो ऑटो-सेव अभी भेजा नहीं गया है वह हटा दिया जाता है, इसलिए तभी रद्द करें जब आप सच में नहीं चाहते कि वह पहुँचे।

workEnqueueOnline ब्रिज#

window.WebToApk.workEnqueueOnline(id: String, url: String, method: String, headersJson: String, payload: String)

किसी अनुमति की ज़रूरत नहीं; नतीजे `appmint:work` / window.onAppMintWork के रूप में आते हैं।

इसे अलग से नहीं, बल्कि इसके समूह बैकग्राउंड जॉब्स (WorkManager): टिकाऊ ऑटो-सेव + समय-समय पर नेटिव सिंक में बताया गया है।

उदाहरण

एक HTTP अनुरोध Android को सौंपता है, जो फ़ोन के ऑनलाइन होने पर उसे भेजेगा - चाहे उपयोगकर्ता ऐप बंद कर दे या फ़ोन रीस्टार्ट करे। भरोसेमंद ऑटो-सेव के लिए इस्तेमाल करें।

लौटाता है: सीधे कुछ नहीं। जवाब appmint:work इवेंट के रूप में आता है (और अगर आपने परिभाषित किया हो तो window.onAppMintWork(detail) में): { id, status: 'enqueued' }, या { id, status: 'failed', reason } जिसकी वजह invalid_arguments (खाली id या ऐसा URL जो http से शुरू नहीं होता) या enqueue_failed होती है। ज़रूरत: कुछ नहीं।

टिकाऊ ऑटो-सेव: वही id उस सेव को बदल देता है जो अभी भेजा नहीं गया है, इसलिए सबसे नई स्थिति ही बचती है।

function autoSave(state, token) {
  if (!(window.WebToApk && window.WebToApk.workEnqueueOnline)) {
    showMessage('Offline auto-save works in the installed app only.');
    return;
  }
  WebToApk.workEnqueueOnline(
    'autosave',                                        // your job id
    'https://api.example.com/save',                    // http(s) URL
    'POST',                                            // POST | PUT | GET ...
    JSON.stringify({ Authorization: 'Bearer ' + token }), // headers as a JSON string
    JSON.stringify(state)                              // body as a string ('' for none)
  );
}

window.addEventListener('appmint:work', function (e) {
  const d = e.detail;
  if (d.id !== 'autosave') return;
  if (d.status === 'enqueued') showSavedBadge('Will sync when online');
  if (d.status === 'failed') showMessage('Could not queue the save: ' + d.reason);
});

हर फ़ॉर्म सबमिशन को उसके अपने जॉब के रूप में कतार में लगाएँ (हर सबमिशन के लिए अलग id, ताकि दूसरा पहले को न बदले) और Android के जवाब का इंतज़ार करें:

function queueFeedback(form) {
  return new Promise(function (resolve, reject) {
    if (!(window.WebToApk && window.WebToApk.workEnqueueOnline)) {
      reject(new Error('not_in_app'));
      return;
    }
    const id = 'feedback-' + Date.now();
    function onWork(e) {
      if (e.detail.id !== id) return;                  // another job's answer
      window.removeEventListener('appmint:work', onWork);
      if (e.detail.status === 'enqueued') resolve(id);
      else reject(new Error(e.detail.reason));         // invalid_arguments | enqueue_failed
    }
    window.addEventListener('appmint:work', onWork);
    WebToApk.workEnqueueOnline(id, 'https://api.example.com/feedback', 'POST', '{}',
      JSON.stringify({ rating: form.rating.value, text: form.text.value }));
  });
}

PUT से नोट को सादे टेक्स्ट के रूप में सेव करें; अपना Content-Type सेट करने से JSON वाला डिफ़ॉल्ट नहीं जुड़ता:

function saveNote(noteId, text) {
  if (!(window.WebToApk && window.WebToApk.workEnqueueOnline)) return;
  WebToApk.workEnqueueOnline(
    'note-' + noteId,                                  // same note, same id: only the newest text is sent
    'https://api.example.com/notes/' + encodeURIComponent(noteId),
    'PUT',
    JSON.stringify({ 'Content-Type': 'text/plain; charset=utf-8' }),
    text
  );
}

document.getElementById('note').addEventListener('change', function (e) {
  saveNote(e.target.dataset.noteId, e.target.value);
});

नोट: enqueued का मतलब है कि Android ने जॉब स्वीकार कर लिया, यह नहीं कि सर्वर को मिल गया; पहुँचने पर कोई इवेंट नहीं आता। डिलीवरी के नियम: 2xx जवाब से जॉब पूरा हो जाता है; 4xx जवाब उसे रोक देता है (दोबारा कोशिश नहीं); नेटवर्क त्रुटि या 5xx पर बढ़ती देरी के साथ 8 कोशिशों तक दोबारा कोशिश होती है। जब तक आप अपना न दें, Content-Type: application/json जोड़ दिया जाता है। GET कोई बॉडी नहीं भेजता। पेज की JavaScript बैकग्राउंड में नहीं चलती - सिर्फ़ यही नेटिव अनुरोध चलता है।

workList ब्रिज#

window.WebToApk.workList(requestId: String)

किसी अनुमति की ज़रूरत नहीं; नतीजे `appmint:work` / window.onAppMintWork के रूप में आते हैं।

इसे अलग से नहीं, बल्कि इसके समूह बैकग्राउंड जॉब्स (WorkManager): टिकाऊ ऑटो-सेव + समय-समय पर नेटिव सिंक में बताया गया है।

उदाहरण

इस ऐप के कतार में लगाए या शेड्यूल किए गए बैकग्राउंड जॉब्स की सूची देता है।

लौटाता है: सीधे कुछ नहीं। appmint:work इवेंट (और window.onAppMintWork) { requestId, jobs: [{ id, periodic, url, createdAt, pendingDelivery }] } के साथ जवाब देता है। जब तक एक बार वाला जॉब पहुँचा नहीं है, pendingDelivery का मान true रहता है (और दोहराने वाले जॉब के लिए हमेशा)। ज़रूरत: कुछ नहीं।

एक छोटा Promise रैपर जो जवाब को requestId से मिलाता है:

function listJobs() {
  return new Promise(function (resolve) {
    if (!(window.WebToApk && window.WebToApk.workList)) { resolve([]); return; }
    const requestId = 'jobs-' + Date.now();
    function onWork(e) {
      if (String(e.detail.requestId) !== requestId) return;   // not our answer
      window.removeEventListener('appmint:work', onWork);
      resolve(e.detail.jobs || []);
    }
    window.addEventListener('appmint:work', onWork);
    WebToApk.workList(requestId);
  });
}

listJobs().then(function (jobs) {
  const unsent = jobs.filter(function (j) { return !j.periodic && j.pendingDelivery; });
  document.getElementById('unsent').textContent =
    unsent.length ? unsent.length + ' change(s) waiting for network' : 'All changes saved';
});

सेटिंग्स स्क्रीन पर हर जॉब दिखाएँ, साथ में यह कि वह कब कतार में लगा:

window.addEventListener('appmint:work', function (e) {
  if (e.detail.requestId !== 'settings-jobs') return;
  const list = document.getElementById('jobs');
  list.innerHTML = '';
  (e.detail.jobs || []).forEach(function (job) {
    const li = document.createElement('li');
    li.textContent = job.id + (job.periodic ? ' (repeats)' : job.pendingDelivery ? ' (waiting)' : '') +
      ' - since ' + new Date(job.createdAt).toLocaleString();
    list.appendChild(li);
  });
});

if (window.WebToApk && window.WebToApk.workList) WebToApk.workList('settings-jobs');

ऐप खुलने पर, "बैकग्राउंड सिंक" स्विच इस आधार पर सेट करें कि दोहराने वाला 'sync' जॉब अब भी रजिस्टर है या नहीं:

window.addEventListener('appmint:work', function (e) {
  if (e.detail.requestId !== 'startup') return;
  const on = (e.detail.jobs || []).some(function (j) { return j.id === 'sync' && j.periodic; });
  document.getElementById('sync-toggle').checked = on;
});

document.addEventListener('DOMContentLoaded', function () {
  if (window.WebToApk && window.WebToApk.workList) WebToApk.workList('startup');
});

नोट: एक बार वाला जॉब तब सूची से हट जाता है जब वह पहुँच जाए, 4xx से अस्वीकार हो, या 8 कोशिशों के बाद छोड़ दिया जाए। संख्या वाला requestId संख्या के रूप में लौट सकता है, इसलिए तुलना इस तरह करें: String(...).

workSchedulePeriodic ब्रिज#

window.WebToApk.workSchedulePeriodic(id: String, url: String, method: String, headersJson: String, payload: String, intervalMinutes: Int)

किसी अनुमति की ज़रूरत नहीं; नतीजे `appmint:work` / window.onAppMintWork के रूप में आते हैं।

इसे अलग से नहीं, बल्कि इसके समूह बैकग्राउंड जॉब्स (WorkManager): टिकाऊ ऑटो-सेव + समय-समय पर नेटिव सिंक में बताया गया है।

उदाहरण

एक दोहराने वाला HTTP अनुरोध शेड्यूल करता है जिसे Android बैकग्राउंड में (ऑनलाइन होने पर) भेजता है, ऐप बंद होने पर भी। सिंक ट्रिगर या हार्टबीट के लिए अच्छा है।

लौटाता है: सीधे कुछ नहीं। जवाब appmint:work इवेंट के रूप में आता है (और window.onAppMintWork(detail)): { id, status: 'scheduled', intervalMinutes }, या { id, status: 'failed', reason } जिसकी वजह invalid_arguments या schedule_failed होती है। ज़रूरत: कुछ नहीं।

function startBackgroundSync(userId) {
  if (!(window.WebToApk && window.WebToApk.workSchedulePeriodic)) {
    showMessage('Background sync works in the installed app only.');
    return;
  }
  WebToApk.workSchedulePeriodic(
    'sync',                                   // job id (scheduling again updates it)
    'https://api.example.com/sync',
    'POST',
    JSON.stringify({ 'X-User': userId }),     // headers as a JSON string
    JSON.stringify({ userId: userId }),       // the same body is sent every time
    30                                        // minutes; values under 15 become 15
  );
}

// Optional page hook instead of addEventListener:
window.onAppMintWork = function (d) {
  if (d.id === 'sync' && d.status === 'scheduled') {
    console.log('sync every', d.intervalMinutes, 'minutes');
  }
  if (d.status === 'failed') console.warn('job', d.id, 'failed:', d.reason);
};

घंटे में एक बार की हार्टबीट: GET कोई बॉडी नहीं भेजता, इसलिए खाली स्ट्रिंग दें, और जब हेडर न चाहिए हों तो '{}':

function startHeartbeat(deviceId) {
  if (!(window.WebToApk && window.WebToApk.workSchedulePeriodic)) return;
  WebToApk.workSchedulePeriodic(
    'heartbeat',
    'https://api.example.com/ping?device=' + encodeURIComponent(deviceId),
    'GET',
    '{}',
    '',
    60
  );
}

उपयोगकर्ता को चुनने दें कि सिंक कितनी बार हो, और वह अंतराल दिखाएँ जो Android असल में इस्तेमाल करता है (15 से कम कुछ भी 15 बनकर आता है):

document.getElementById('sync-every').addEventListener('change', function (e) {
  if (!(window.WebToApk && window.WebToApk.workSchedulePeriodic)) return;
  const minutes = parseInt(e.target.value, 10);        // e.g. 5, 30, 120
  WebToApk.workSchedulePeriodic('sync', 'https://api.example.com/sync', 'POST', '{}',
    JSON.stringify({ reason: 'periodic' }), minutes);  // same id: updates the existing job
});

window.addEventListener('appmint:work', function (e) {
  const d = e.detail;
  if (d.id !== 'sync') return;
  if (d.status === 'scheduled') {
    document.getElementById('sync-note').textContent = 'Syncing about every ' + d.intervalMinutes + ' minutes';
  } else if (d.status === 'failed') {
    document.getElementById('sync-note').textContent = 'Could not schedule sync (' + d.reason + ')';
  }
});

नोट: सही समय Android तय करता है; 15 मिनट सबसे छोटा अंतराल है, और बैटरी बचत से रन देर से हो सकते हैं। बॉडी शेड्यूल करते समय तय हो जाती है; उसे बदलने के लिए उसी id से दोबारा शेड्यूल करें। 4xx जवाब दोहराने वाले जॉब को रद्द नहीं करता; अगला रन फिर कोशिश करता है। इसे रोकने के लिए यह इस्तेमाल करें: workCancel('sync').

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

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