JavaScript köprü API'si
Arka plan işleri
Uygulama kapandıktan sonra da süren işler: kalıcı bir otomatik kaydetme, periyodik bir eşitleme.
workCancel köprü#
window.WebToApk.workCancel(id: String)
İzin gerekmez; sonuçlar `appmint:work` / window.onAppMintWork olarak yankılanır.
Tek başına değil, grubu olan Arka plan işleri (WorkManager): kalıcı otomatik kaydetme + periyodik yerel eşitleme altında açıklanır.
Örnek
Bir arka plan işini (tek seferlik veya tekrarlanan) kimliğiyle iptal eder ve kaydedilmiş isteğini siler.
Döndürür: doğrudan hiçbir şey. appmint:work olayı (ve window.onAppMintWork) { id, status: 'cancelled' } yanıtını verir. Gerekenler: hiçbir şey.
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';
}
});Bir taslağı atın: henüz gönderilmemiş otomatik kaydetmesini iptal edin, sonra Android onaylayınca düzenleyiciyi temizleyin:
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');
}Oturumu kapatırken, workList'in bildirdiği kimlikleri kullanarak bu uygulamanın her işini iptal edin:
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);
}Notlar: o kimlikte hiç iş olmasa bile cancelled yanıtı verir. Henüz gönderilmemiş bir otomatik kaydetme bırakılır, bu yüzden yalnızca gerçekten iletilmesini istemediğinizde iptal edin.
workEnqueueOnline köprü#
window.WebToApk.workEnqueueOnline(id: String, url: String, method: String, headersJson: String, payload: String)
İzin gerekmez; sonuçlar `appmint:work` / window.onAppMintWork olarak yankılanır.
Tek başına değil, grubu olan Arka plan işleri (WorkManager): kalıcı otomatik kaydetme + periyodik yerel eşitleme altında açıklanır.
Örnek
Telefon çevrimiçi olduğunda gönderilmek üzere Android'e bir HTTP isteği verir - kullanıcı uygulamayı kapatsa veya telefonu yeniden başlatsa bile. Güvenilir bir otomatik kaydetme için kullanın.
Döndürür: doğrudan hiçbir şey. Yanıt appmint:work olayı olarak gelir (ve tanımlarsanız window.onAppMintWork(detail)): { id, status: 'enqueued' }, veya invalid_arguments ya da enqueue_failed nedeniyle { id, status: 'failed', reason } (boş kimlik ya da http ile başlamayan bir URL). Gerekenler: hiçbir şey.
Kalıcı otomatik kaydetme: aynı kimlik henüz gönderilmemiş bir kaydetmenin yerine geçer, böylece en yeni durum kazanır.
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);
});Her form gönderimini kendi işi olarak kuyruğa alın (gönderim başına benzersiz bir kimlik, böylece ikincisi birincinin yerine geçmez) ve Android'in yanıtını bekleyin:
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 }));
});
}Bir notu PUT ile düz metin olarak kaydedin; kendi Content-Type değerinizi ayarlamak JSON varsayılanının eklenmesini engeller:
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);
});Notlar: enqueued Android'in işi kabul ettiği anlamına gelir, sunucunun aldığı değil; iletildiğinde olay yoktur. Teslim kuralları: 2xx yanıtı işi bitirir; 4xx yanıtı durdurur (yeniden deneme yok); ağ hatası veya 5xx, artan gecikmelerle en fazla 8 deneme yapar. Siz bir tane ayarlamadıysanız Content-Type: application/json eklenir. GET gövde göndermez. Sayfanın JavaScript'i arka planda çalışmaz - yalnızca bu yerel istek çalışır.
workList köprü#
window.WebToApk.workList(requestId: String)
İzin gerekmez; sonuçlar `appmint:work` / window.onAppMintWork olarak yankılanır.
Tek başına değil, grubu olan Arka plan işleri (WorkManager): kalıcı otomatik kaydetme + periyodik yerel eşitleme altında açıklanır.
Örnek
Bu uygulamanın kuyruğa aldığı veya zamanladığı arka plan işlerini listeler.
Döndürür: doğrudan hiçbir şey. appmint:work olayı (ve window.onAppMintWork) { requestId, jobs: [{ id, periodic, url, createdAt, pendingDelivery }] } yanıtını verir. pendingDelivery, tek seferlik bir iş henüz iletilmemişken true olur (periyodik iş için her zaman). Gerekenler: hiçbir şey.
Yanıtı requestId ile eşleştiren küçük bir Promise sarmalayıcı:
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';
});Ayarlar ekranında her işi, ne zaman kuyruğa alındığıyla birlikte gösterin:
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');Uygulama açıldığında, tekrarlanan 'sync' işinin hâlâ kayıtlı olup olmadığına göre bir "Arka plan eşitleme" anahtarı ayarlayın:
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');
});Notlar: tek seferlik bir iş, iletildiğinde, 4xx ile reddedildiğinde veya 8 denemeden sonra vazgeçildiğinde listeden çıkar. Sayısal bir requestId sayı olarak dönebilir, bu yüzden şununla karşılaştırın: String(...).
workSchedulePeriodic köprü#
window.WebToApk.workSchedulePeriodic(id: String, url: String, method: String, headersJson: String, payload: String, intervalMinutes: Int)
İzin gerekmez; sonuçlar `appmint:work` / window.onAppMintWork olarak yankılanır.
Tek başına değil, grubu olan Arka plan işleri (WorkManager): kalıcı otomatik kaydetme + periyodik yerel eşitleme altında açıklanır.
Örnek
Android'in arka planda (çevrimiçiyken), uygulama kapalıyken bile gönderdiği tekrarlanan bir HTTP isteği zamanlar. Bir eşitleme tetikleyicisi veya kalp atışı için iyidir.
Döndürür: doğrudan hiçbir şey. Yanıt appmint:work olayı olarak gelir (ve window.onAppMintWork(detail)): { id, status: 'scheduled', intervalMinutes }, veya invalid_arguments ya da schedule_failed nedeniyle { id, status: 'failed', reason }. Gerekenler: hiçbir şey.
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);
};Saatte bir kalp atışı: GET gövde göndermez, bu yüzden boş bir dize verin; başlık gerekmiyorsa '{}':
function startHeartbeat(deviceId) {
if (!(window.WebToApk && window.WebToApk.workSchedulePeriodic)) return;
WebToApk.workSchedulePeriodic(
'heartbeat',
'https://api.example.com/ping?device=' + encodeURIComponent(deviceId),
'GET',
'{}',
'',
60
);
}Kullanıcının eşitleme sıklığını seçmesine izin verin ve Android'in gerçekte kullandığı aralığı gösterin (15'ten küçük her değer 15 olarak döner):
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 + ')';
}
});Notlar: Kesin anı Android belirler; 15 dakika en kısa aralıktır ve pil tasarrufu çalıştırmaları geciktirebilir. Gövde zamanladığınızda sabitlenir; değiştirmek için aynı kimlikle yeniden zamanlayın. 4xx yanıtı periyodik bir işi iptal etmez; sonraki çalıştırma yeniden dener. Şununla durdurun: workCancel('sync').