Create Free APK

JavaScript bridge API

Background jobs

Work that keeps going after the app is closed: a durable auto-save, a periodic sync.

workCancel bridge#

window.WebToApk.workCancel(id: String)

No permission needed; results echo as `appmint:work` / window.onAppMintWork.

Described by its group, Background jobs (WorkManager): durable auto-save + periodic native sync, rather than on its own.

Example

Cancels a background job (one-off or repeating) by its id and deletes its saved request.

Returns: nothing directly. The appmint:work event (and window.onAppMintWork) answers { id, status: 'cancelled' }. Needs: nothing.

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

Notes: it answers cancelled even when no job had that id. An auto-save that has not been sent yet is dropped, so cancel only when you really do not want it delivered.

workEnqueueOnline bridge#

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

No permission needed; results echo as `appmint:work` / window.onAppMintWork.

Described by its group, Background jobs (WorkManager): durable auto-save + periodic native sync, rather than on its own.

Example

Hands one HTTP request to Android to send when the phone is online - even if the user closes the app or restarts the phone. Use it for a reliable auto-save.

Returns: nothing directly. The answer comes as the appmint:work event (and window.onAppMintWork(detail) if you define it): { id, status: 'enqueued' }, or { id, status: 'failed', reason } with reason invalid_arguments (empty id or a URL not starting with http) or enqueue_failed. Needs: nothing.

Durable auto-save: the same id replaces a save that has not been sent yet, so the newest state wins.

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

Notes: enqueued means Android accepted the job, not that the server got it; there is no event when it is delivered. Delivery rules: a 2xx reply finishes the job; a 4xx reply stops it (no retry); a network error or 5xx retries with growing delays, up to 8 tries. Content-Type: application/json is added unless you set one. A GET sends no body. The page's JavaScript does not run in the background - only this native request does.

workList bridge#

window.WebToApk.workList(requestId: String)

No permission needed; results echo as `appmint:work` / window.onAppMintWork.

Described by its group, Background jobs (WorkManager): durable auto-save + periodic native sync, rather than on its own.

Example

Lists the background jobs this app has queued or scheduled.

Returns: nothing directly. The appmint:work event (and window.onAppMintWork) answers { requestId, jobs: [{ id, periodic, url, createdAt, pendingDelivery }] }. pendingDelivery is true while a one-off job has not been delivered yet (and always for a periodic job). Needs: nothing.

A small Promise wrapper that matches the answer by 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';
});

Notes: a one-off job leaves the list once it is delivered, rejected with a 4xx, or given up after 8 tries. A numeric requestId may come back as a number, so compare with String(...).

workSchedulePeriodic bridge#

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

No permission needed; results echo as `appmint:work` / window.onAppMintWork.

Described by its group, Background jobs (WorkManager): durable auto-save + periodic native sync, rather than on its own.

Example

Schedules a repeating HTTP request that Android sends in the background (when online), even while the app is closed. Good for a sync trigger or a heartbeat.

Returns: nothing directly. The answer comes as the appmint:work event (and window.onAppMintWork(detail)): { id, status: 'scheduled', intervalMinutes }, or { id, status: 'failed', reason } with reason invalid_arguments or schedule_failed. Needs: nothing.

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

Notes: Android decides the exact moment; 15 minutes is the shortest interval, and battery saving can delay runs. The body is fixed when you schedule; to change it, schedule again with the same id. A 4xx reply does not cancel a periodic job; the next run tries again. Stop it with workCancel('sync').

Generated from the app runtime and its example files on every docs build. Read it as Markdown ยท All families.

Checked against the shipped bridge on 2026-09-23.