JavaScript köprü API'si
Arka planda çalışma
Sayfanın başlatıp durdurduğu bir ön plan hizmeti, uygulama arka plandayken gelmeye devam eden konum, uygulama kapalıyken tetiklenen coğrafi çitler ve yeniden başlatmadan sonra periyodik olarak çalıştırılan kendi kodunuz. Her biri derlemede kendi anahtarını ve bir Play Console beyanını gerektirir.
AppMint.background yardımcı#
AppMint.background.register(name, options) / unregister / list / runNow / done / isBackgroundRun / currentRun / onRun
Örnek
Sayfanızın KENDİ kodunu uygulama kapalıyken periyodik olarak çalıştırır - veriyi yenileyin, bir fiyatı kontrol edin, bildirim gönderin. Her çalıştırma sayfanızı görünmez şekilde yükler (aynı origin, aynı localStorage/IndexedDB, ekran yok, reklam yok) ?appmint_background=1&appmint_task=<name>&appmint_run=<runId> ile, yüklendikten sonra bir kez appmint:background { name, runId } tetikler ve done(runId, { ok }) bekler. Bir çalıştırma yaklaşık 9 dakika sonra kesilir.
Döndürür: her yöntem bir Promise döndürür. register → { ok: true, name, intervalMinutes } veya { ok: false, reason } (not_enabled, invalid_name, interval_below_15_minutes, invalid_interval, schedule_failed). unregister → true / false. list → [{ name, intervalMinutes, requiresNetwork, requiresCharging, registeredAt, lastRunAt, lastResult }] (lastResult: ok, retry, failed, timeout, unsupported_mode, page_load_failed, …). runNow → { ok } (koşullar izin verir vermez bir çalıştırma - test için). done → çalıştırma sonlandırıldığında true. isBackgroundRun() ve currentRun() eşzamanlıdır. Gerekenler: Kapalıyken sayfa kodunu çalıştır işaretleyin (Erişim adımı → Arka plan). Web sitesi ve çevrimdışı/ZIP uygulamaları; belge ve medya uygulamalarında çalıştırılacak sayfa kodu yoktur.
Tek sayfa, iki rol:
function startApp() {
const bg = window.AppMint && AppMint.background;
if (bg && bg.isBackgroundRun()) return; // a background run: no UI work
renderUi();
if (bg) bg.register('prices', { intervalMinutes: 60, requiresNetwork: true }).then(function (r) {
if (!r.ok) console.warn('background task not scheduled:', r.reason);
});
}
// Runs only in the background copy of the page.
window.addEventListener('appmint:background', async function (e) {
const run = e.detail; // { name: 'prices', runId: '…' }
try {
const price = await fetch('https://api.example.com/price').then(function (r) { return r.json(); });
const last = Number(localStorage.getItem('lastPrice') || 0);
if (price.value < last) {
WebToApk.notify(JSON.stringify({ title: 'Price dropped', body: 'Now ' + price.value, tag: 'price' }));
}
localStorage.setItem('lastPrice', String(price.value));
AppMint.background.done(run.runId, { ok: true });
} catch (err) {
AppMint.background.done(run.runId, { ok: false, retry: true }); // retried with backoff
}
});
startApp();Geç bağlanan sayfalar (React, tembel rota) çalıştırma zaten başladıysa da tetiklenen onRun veya sayfa kancasını kullanır:
if (window.AppMint && AppMint.background) {
AppMint.background.onRun(function (run) { syncInbox().then(function () { AppMint.background.done(run.runId, { ok: true }); }); });
}
window.onAppMintBackground = function (run) { console.log('background run', run.name, run.runId, AppMint.background.currentRun()); };Yönet:
AppMint.background.list().then(function (tasks) { console.table(tasks); });
AppMint.background.runNow('prices');
AppMint.background.unregister('prices');Notlar: Tam anı Android belirler; 15 dakika en kısa aralıktır ve pil tasarrufu çalıştırmaları geciktirebilir. Telefon yeniden başlatıldıktan sonra başlat ile her görev yeniden başlatmadan sonra bir kez de çalışır. Bir çalıştırmanın WebToApk nesnesinde yalnızca notify, showNotification, konum tamponu, coğrafi çitler, workEnqueueOnline, isBackgroundServiceRunning ve bu görev yöntemleri bulunur; başka her şey yoktur (özelliği algılayın).
addGeofence köprü#
window.WebToApk.addGeofence(json: String): String
Bir coğrafi çit ekler {id, lat, lng, radiusM, events, dwellMs?, notify?} → JSON {ok, status:'adding'} veya {ok:false, reason}; sonuç şudur appmint:geofence-added.
Örnek
Uygulama kapalıyken enter, exit ve/veya dwell tetikleyen, isteğe bağlı olarak bildirim gönderen bir daire. Coğrafi çitler telefon yeniden başlatıldığında da korunur (otomatik olarak geri eklenirler).
Döndürür: addGeofence → bir JSON dizesi { ok: true, status: 'adding', id } veya { ok: false, reason } - not_enabled, invalid_id, invalid_position, invalid_radius (1 m … 100 km), invalid_events, location_permission_required, background_permission_required, foreign_origin. Play hizmetlerinin cevabı appmint:geofence-added (window.onAppMintGeofenceAdded) = { id, ok, reason? } (location_off, too_many_geofences - uygulama başına 100, play_services_unavailable) olarak gelir. Bir geçiş appmint:geofence (window.onAppMintGeofence) = { id, event: 'enter' | 'exit' | 'dwell', time, lat, lng, queued? } olarak gelir - uygulama kapalıyken gerçekleştiyse ve bir sonraki başlangıçta teslim edildiyse queued: true. removeGeofence → varsa true; getGeofences → eklediklerinizin JSON dizisi. Gerekenler: derlemede Coğrafi çitler işaretleyin ve "Her zaman izin ver" (requestBackgroundLocation()).
function watchOffice() {
const b = window.WebToApk;
if (!(b && b.addGeofence)) return;
const r = JSON.parse(b.addGeofence(JSON.stringify({
id: 'office', lat: 51.5033, lng: -0.1196, radiusM: 150,
events: ['enter', 'exit', 'dwell'], dwellMs: 5 * 60000,
notify: {
enter: { title: 'At the office', body: 'Tap to check in' },
exit: { title: 'Left the office', body: 'Tap to check out' }
}
})));
if (!r.ok && r.reason === 'background_permission_required') b.requestBackgroundLocation();
}
window.addEventListener('appmint:geofence-added', function (e) {
if (!e.detail.ok) showMessage('Geofence ' + e.detail.id + ' not added: ' + e.detail.reason);
});
window.addEventListener('appmint:geofence', function (e) {
logVisit(e.detail.id, e.detail.event, e.detail.time);
});
console.log(JSON.parse(WebToApk.getGeofences()).map(function (g) { return g.id; }));
WebToApk.removeGeofence('office');Özelliği algılayın ve her reddi bildirin:
function addCircle(id, lat, lng, radiusM) {
const b = window.WebToApk;
if (!(b && b.addGeofence)) { showMessage('Place alerts need the app'); return false; }
const r = JSON.parse(b.addGeofence(JSON.stringify({ id: id, lat: lat, lng: lng, radiusM: radiusM, events: ['enter'] })));
if (r.ok) return true;
if (r.reason === 'not_enabled') showMessage('Geofences are not switched on in this build');
else if (r.reason === 'background_permission_required') b.requestBackgroundLocation();
else if (r.reason === 'invalid_radius') showMessage('Pick a radius between 1 m and 100 km');
else showMessage('Could not add the place: ' + r.reason);
return false;
}Kayıtlı olanları listeleyin ve birini kaldırın:
const mine = JSON.parse(WebToApk.getGeofences()); // [] when none
mine.forEach(function (g) { addRow(g.id); });
document.getElementById('forget').onclick = function () {
const existed = WebToApk.removeGeofence('office'); // true if it was there
if (!existed) showMessage('That place was not registered');
};backgroundDone köprü#
window.WebToApk.backgroundDone(runId: String, resultJson: String): Boolean
AppMint.background.done(runId, result): bir arka plan çalıştırmasını bitirir; uygulamanın kendisinde her zaman false.
Örnek
WebToApk.backgroundRegister ile birlikte belgelenmiştir - oradaki örnek bunu da gösterir.
AppMint.background arkasındaki ham yöntemler - AppMint.background.register(...) kullanın (promise döndürür ve çalıştırma olayını yönetir). Her köprü yönteminin bir örneği olsun diye burada listelenmiştir.
Döndürür: backgroundRegister → JSON { ok: true, name, intervalMinutes } veya { ok: false, reason } (not_enabled, invalid_name - harfler, rakamlar, _, -, en fazla 64 - interval_below_15_minutes, invalid_interval, schedule_failed). backgroundUnregister → varsa true. backgroundList → JSON dizisi. backgroundRunNow → JSON { ok, name } veya { ok: false, reason: 'not_registered' }. backgroundDone(runId, resultJson) → arka plan çalıştırmasında true, uygulamada her zaman false. isBackgroundRun() → uygulamada false, arka plan çalıştırmasında true. Gerekenler: Kapalıyken sayfa kodunu çalıştır işaretleyin.
const b = window.WebToApk;
if (b && b.backgroundRegister) {
const r = JSON.parse(b.backgroundRegister('refresh', JSON.stringify({ intervalMinutes: 60, requiresNetwork: true })));
if (!r.ok) console.warn('not scheduled:', r.reason);
console.log(JSON.parse(b.backgroundList()));
console.log(b.isBackgroundRun()); // false here: this is the app on screen
// b.backgroundRunNow('refresh'); b.backgroundUnregister('refresh');
// In a run: b.backgroundDone(runId, JSON.stringify({ ok: true }))
}Özelliği algılayın ve uygulama çalıştırmasını arka plan çalıştırmasından ayırt edin:
const b = window.WebToApk;
if (!(b && b.backgroundRegister)) {
console.log('background tasks are only in the app');
} else if (b.isBackgroundRun()) {
// the invisible copy: do the work, no UI
} else {
const r = JSON.parse(b.backgroundRegister('sync', JSON.stringify({ intervalMinutes: 5 })));
if (!r.ok) console.warn(r.reason); // 'interval_below_15_minutes'
}Bir görevi test edin ve temizleyin:
const run = JSON.parse(WebToApk.backgroundRunNow('sync'));
if (!run.ok && run.reason === 'not_registered') WebToApk.backgroundRegister('sync', JSON.stringify({ intervalMinutes: 30 }));
JSON.parse(WebToApk.backgroundList()).forEach(function (t) { console.log(t.name, t.intervalMinutes, t.lastResult); });
WebToApk.backgroundUnregister('old-task'); // true if it existedbackgroundList köprü#
window.WebToApk.backgroundList(): String
AppMint.background.list(): {name, intervalMinutes, requiresNetwork, requiresCharging, registeredAt, lastRunAt, lastResult} JSON dizisi.
Örnek
WebToApk.backgroundRegister ile birlikte belgelenmiştir - oradaki örnek bunu da gösterir.
AppMint.background arkasındaki ham yöntemler - AppMint.background.register(...) kullanın (promise döndürür ve çalıştırma olayını yönetir). Her köprü yönteminin bir örneği olsun diye burada listelenmiştir.
Döndürür: backgroundRegister → JSON { ok: true, name, intervalMinutes } veya { ok: false, reason } (not_enabled, invalid_name - harfler, rakamlar, _, -, en fazla 64 - interval_below_15_minutes, invalid_interval, schedule_failed). backgroundUnregister → varsa true. backgroundList → JSON dizisi. backgroundRunNow → JSON { ok, name } veya { ok: false, reason: 'not_registered' }. backgroundDone(runId, resultJson) → arka plan çalıştırmasında true, uygulamada her zaman false. isBackgroundRun() → uygulamada false, arka plan çalıştırmasında true. Gerekenler: Kapalıyken sayfa kodunu çalıştır işaretleyin.
const b = window.WebToApk;
if (b && b.backgroundRegister) {
const r = JSON.parse(b.backgroundRegister('refresh', JSON.stringify({ intervalMinutes: 60, requiresNetwork: true })));
if (!r.ok) console.warn('not scheduled:', r.reason);
console.log(JSON.parse(b.backgroundList()));
console.log(b.isBackgroundRun()); // false here: this is the app on screen
// b.backgroundRunNow('refresh'); b.backgroundUnregister('refresh');
// In a run: b.backgroundDone(runId, JSON.stringify({ ok: true }))
}Özelliği algılayın ve uygulama çalıştırmasını arka plan çalıştırmasından ayırt edin:
const b = window.WebToApk;
if (!(b && b.backgroundRegister)) {
console.log('background tasks are only in the app');
} else if (b.isBackgroundRun()) {
// the invisible copy: do the work, no UI
} else {
const r = JSON.parse(b.backgroundRegister('sync', JSON.stringify({ intervalMinutes: 5 })));
if (!r.ok) console.warn(r.reason); // 'interval_below_15_minutes'
}Bir görevi test edin ve temizleyin:
const run = JSON.parse(WebToApk.backgroundRunNow('sync'));
if (!run.ok && run.reason === 'not_registered') WebToApk.backgroundRegister('sync', JSON.stringify({ intervalMinutes: 30 }));
JSON.parse(WebToApk.backgroundList()).forEach(function (t) { console.log(t.name, t.intervalMinutes, t.lastResult); });
WebToApk.backgroundUnregister('old-task'); // true if it existedbackgroundRegister köprü#
window.WebToApk.backgroundRegister(name: String, optionsJson: String): String
AppMint.background.register(name, {intervalMinutes >= 15, requiresNetwork, requiresCharging}) → JSON {ok, name, intervalMinutes} veya {ok:false, reason}.
Örnek
AppMint.background arkasındaki ham yöntemler - AppMint.background.register(...) kullanın (promise döndürür ve çalıştırma olayını yönetir). Her köprü yönteminin bir örneği olsun diye burada listelenmiştir.
Döndürür: backgroundRegister → JSON { ok: true, name, intervalMinutes } veya { ok: false, reason } (not_enabled, invalid_name - harfler, rakamlar, _, -, en fazla 64 - interval_below_15_minutes, invalid_interval, schedule_failed). backgroundUnregister → varsa true. backgroundList → JSON dizisi. backgroundRunNow → JSON { ok, name } veya { ok: false, reason: 'not_registered' }. backgroundDone(runId, resultJson) → arka plan çalıştırmasında true, uygulamada her zaman false. isBackgroundRun() → uygulamada false, arka plan çalıştırmasında true. Gerekenler: Kapalıyken sayfa kodunu çalıştır işaretleyin.
const b = window.WebToApk;
if (b && b.backgroundRegister) {
const r = JSON.parse(b.backgroundRegister('refresh', JSON.stringify({ intervalMinutes: 60, requiresNetwork: true })));
if (!r.ok) console.warn('not scheduled:', r.reason);
console.log(JSON.parse(b.backgroundList()));
console.log(b.isBackgroundRun()); // false here: this is the app on screen
// b.backgroundRunNow('refresh'); b.backgroundUnregister('refresh');
// In a run: b.backgroundDone(runId, JSON.stringify({ ok: true }))
}Özelliği algılayın ve uygulama çalıştırmasını arka plan çalıştırmasından ayırt edin:
const b = window.WebToApk;
if (!(b && b.backgroundRegister)) {
console.log('background tasks are only in the app');
} else if (b.isBackgroundRun()) {
// the invisible copy: do the work, no UI
} else {
const r = JSON.parse(b.backgroundRegister('sync', JSON.stringify({ intervalMinutes: 5 })));
if (!r.ok) console.warn(r.reason); // 'interval_below_15_minutes'
}Bir görevi test edin ve temizleyin:
const run = JSON.parse(WebToApk.backgroundRunNow('sync'));
if (!run.ok && run.reason === 'not_registered') WebToApk.backgroundRegister('sync', JSON.stringify({ intervalMinutes: 30 }));
JSON.parse(WebToApk.backgroundList()).forEach(function (t) { console.log(t.name, t.intervalMinutes, t.lastResult); });
WebToApk.backgroundUnregister('old-task'); // true if it existedbackgroundRunNow köprü#
window.WebToApk.backgroundRunNow(name: String): String
AppMint.background.runNow(name): koşullar izin verir vermez tek bir arka plan çalıştırması.
Örnek
WebToApk.backgroundRegister ile birlikte belgelenmiştir - oradaki örnek bunu da gösterir.
AppMint.background arkasındaki ham yöntemler - AppMint.background.register(...) kullanın (promise döndürür ve çalıştırma olayını yönetir). Her köprü yönteminin bir örneği olsun diye burada listelenmiştir.
Döndürür: backgroundRegister → JSON { ok: true, name, intervalMinutes } veya { ok: false, reason } (not_enabled, invalid_name - harfler, rakamlar, _, -, en fazla 64 - interval_below_15_minutes, invalid_interval, schedule_failed). backgroundUnregister → varsa true. backgroundList → JSON dizisi. backgroundRunNow → JSON { ok, name } veya { ok: false, reason: 'not_registered' }. backgroundDone(runId, resultJson) → arka plan çalıştırmasında true, uygulamada her zaman false. isBackgroundRun() → uygulamada false, arka plan çalıştırmasında true. Gerekenler: Kapalıyken sayfa kodunu çalıştır işaretleyin.
const b = window.WebToApk;
if (b && b.backgroundRegister) {
const r = JSON.parse(b.backgroundRegister('refresh', JSON.stringify({ intervalMinutes: 60, requiresNetwork: true })));
if (!r.ok) console.warn('not scheduled:', r.reason);
console.log(JSON.parse(b.backgroundList()));
console.log(b.isBackgroundRun()); // false here: this is the app on screen
// b.backgroundRunNow('refresh'); b.backgroundUnregister('refresh');
// In a run: b.backgroundDone(runId, JSON.stringify({ ok: true }))
}Özelliği algılayın ve uygulama çalıştırmasını arka plan çalıştırmasından ayırt edin:
const b = window.WebToApk;
if (!(b && b.backgroundRegister)) {
console.log('background tasks are only in the app');
} else if (b.isBackgroundRun()) {
// the invisible copy: do the work, no UI
} else {
const r = JSON.parse(b.backgroundRegister('sync', JSON.stringify({ intervalMinutes: 5 })));
if (!r.ok) console.warn(r.reason); // 'interval_below_15_minutes'
}Bir görevi test edin ve temizleyin:
const run = JSON.parse(WebToApk.backgroundRunNow('sync'));
if (!run.ok && run.reason === 'not_registered') WebToApk.backgroundRegister('sync', JSON.stringify({ intervalMinutes: 30 }));
JSON.parse(WebToApk.backgroundList()).forEach(function (t) { console.log(t.name, t.intervalMinutes, t.lastResult); });
WebToApk.backgroundUnregister('old-task'); // true if it existedbackgroundUnregister köprü#
window.WebToApk.backgroundUnregister(name: String): Boolean
AppMint.background.unregister(name); bu adda görev yoksa false.
Örnek
WebToApk.backgroundRegister ile birlikte belgelenmiştir - oradaki örnek bunu da gösterir.
AppMint.background arkasındaki ham yöntemler - AppMint.background.register(...) kullanın (promise döndürür ve çalıştırma olayını yönetir). Her köprü yönteminin bir örneği olsun diye burada listelenmiştir.
Döndürür: backgroundRegister → JSON { ok: true, name, intervalMinutes } veya { ok: false, reason } (not_enabled, invalid_name - harfler, rakamlar, _, -, en fazla 64 - interval_below_15_minutes, invalid_interval, schedule_failed). backgroundUnregister → varsa true. backgroundList → JSON dizisi. backgroundRunNow → JSON { ok, name } veya { ok: false, reason: 'not_registered' }. backgroundDone(runId, resultJson) → arka plan çalıştırmasında true, uygulamada her zaman false. isBackgroundRun() → uygulamada false, arka plan çalıştırmasında true. Gerekenler: Kapalıyken sayfa kodunu çalıştır işaretleyin.
const b = window.WebToApk;
if (b && b.backgroundRegister) {
const r = JSON.parse(b.backgroundRegister('refresh', JSON.stringify({ intervalMinutes: 60, requiresNetwork: true })));
if (!r.ok) console.warn('not scheduled:', r.reason);
console.log(JSON.parse(b.backgroundList()));
console.log(b.isBackgroundRun()); // false here: this is the app on screen
// b.backgroundRunNow('refresh'); b.backgroundUnregister('refresh');
// In a run: b.backgroundDone(runId, JSON.stringify({ ok: true }))
}Özelliği algılayın ve uygulama çalıştırmasını arka plan çalıştırmasından ayırt edin:
const b = window.WebToApk;
if (!(b && b.backgroundRegister)) {
console.log('background tasks are only in the app');
} else if (b.isBackgroundRun()) {
// the invisible copy: do the work, no UI
} else {
const r = JSON.parse(b.backgroundRegister('sync', JSON.stringify({ intervalMinutes: 5 })));
if (!r.ok) console.warn(r.reason); // 'interval_below_15_minutes'
}Bir görevi test edin ve temizleyin:
const run = JSON.parse(WebToApk.backgroundRunNow('sync'));
if (!run.ok && run.reason === 'not_registered') WebToApk.backgroundRegister('sync', JSON.stringify({ intervalMinutes: 30 }));
JSON.parse(WebToApk.backgroundList()).forEach(function (t) { console.log(t.name, t.intervalMinutes, t.lastResult); });
WebToApk.backgroundUnregister('old-task'); // true if it existedclearBufferedLocations köprü#
window.WebToApk.clearBufferedLocations(): Boolean
getBufferedLocations işlevinin okuduğu tamponu boşaltır (noktaları kaydettikten sonra çağırın).
Örnek
WebToApk.getBufferedLocations ile birlikte belgelenmiştir - oradaki örnek bunu da gösterir.
Sayfanız yokken (uygulama arka planda veya kapalı) kaydedilen konumlar, en eskiden başlayarak, 10.000'e kadar.
Döndürür: getBufferedLocations() → { type: 'fix', lat, lng, accuracy, time, …, background: true } değerlerinin JSON dize dizisi; Arka plan konumu kapalıyken '[]'. clearBufferedLocations() → boşaltıldığında true. Gerekenler: derlemede Arka plan konumu.
function syncTrack() {
if (!(window.WebToApk && WebToApk.getBufferedLocations)) return;
const points = JSON.parse(WebToApk.getBufferedLocations());
if (!points.length) return;
points.forEach(function (p) { drawPoint(p.lat, p.lng); });
saveTrack(points).then(function () { WebToApk.clearBufferedLocations(); });
}
document.addEventListener('visibilitychange', function () { if (!document.hidden) syncTrack(); });Takibi başlatın, sonra bir reddi ele alın. Başlatma çağrısı bir JSON dizesiyle cevap verir.
function startTracking() {
if (!(window.WebToApk && WebToApk.startLocationUpdates)) return;
const r = JSON.parse(WebToApk.startLocationUpdates(JSON.stringify({
intervalMs: 15000, accuracy: 'balanced', background: true
})));
if (!r.ok) showMessage('Tracking not started: ' + r.reason); // not_enabled, location_permission_required, ...
}Sayfa açıkken canlı konumlar appmint:location olarak gelir; kalanını tampon tutar.
window.addEventListener('appmint:location', function (e) {
drawPoint(e.detail.lat, e.detail.lng);
});
document.getElementById('stop').addEventListener('click', function () {
if (window.WebToApk && WebToApk.stopLocationUpdates) WebToApk.stopLocationUpdates();
if (WebToApk.getBufferedLocations) {
const left = JSON.parse(WebToApk.getBufferedLocations());
console.log(left.length + ' fixes still buffered');
}
});clearGeofenceEvents köprü#
window.WebToApk.clearGeofenceEvents(): Boolean
getGeofenceEvents işlevinin okuduğu geçiş geçmişini boşaltır.
Örnek
WebToApk.getGeofenceEvents ile birlikte belgelenmiştir - oradaki örnek bunu da gösterir.
Son 100 coğrafi çit geçişi, en eskiden başlayarak - uygulama kapalıyken gerçekleşenler dahil. Sayfanız geç bağlanıyorsa ve kuyruğa alınan appmint:geofence olaylarını kaçırabilirse bunu başlangıçta okuyun.
Döndürür: getGeofenceEvents() → { id, event, time, lat, lng } değerlerinin JSON dize dizisi; clearGeofenceEvents() → true. Gerekenler: derlemede Coğrafi çitler.
if (window.WebToApk && WebToApk.getGeofenceEvents) {
JSON.parse(WebToApk.getGeofenceEvents()).forEach(function (ev) {
logVisit(ev.id, ev.event, ev.time);
});
WebToApk.clearGeofenceEvents();
}Bir coğrafi çit ekleyin, sonra geçişleri izleyin (sayfa açıkken).
if (window.WebToApk && WebToApk.addGeofence) {
const r = JSON.parse(WebToApk.addGeofence(JSON.stringify({
id: 'shop-1', lat: 12.9716, lng: 77.5946, radiusM: 150, events: ['enter', 'exit']
})));
if (!r.ok) showMessage('Geofence refused: ' + r.reason); // not_enabled, invalid_radius, ...
}
window.addEventListener('appmint:geofence', function (e) {
logVisit(e.detail.id, e.detail.event, e.detail.time);
});Kullanıcı bir özellikten ayrıldığında kayıtlı olanları listeleyin ve birini kaldırın.
function dropGeofence(id) {
if (!(window.WebToApk && WebToApk.removeGeofence)) return false;
const known = JSON.parse(WebToApk.getGeofences()).length;
const removed = WebToApk.removeGeofence(id);
console.log(removed ? 'removed' : 'not found', 'of', known, 'registered');
return removed;
}getBufferedLocations köprü#
window.WebToApk.getBufferedLocations(): String
Sayfa yokken kaydedilen konumların JSON dizisi, en eskiden başlayarak (10.000'e kadar).
Örnek
Sayfanız yokken (uygulama arka planda veya kapalı) kaydedilen konumlar, en eskiden başlayarak, 10.000'e kadar.
Döndürür: getBufferedLocations() → { type: 'fix', lat, lng, accuracy, time, …, background: true } değerlerinin JSON dize dizisi; Arka plan konumu kapalıyken '[]'. clearBufferedLocations() → boşaltıldığında true. Gerekenler: derlemede Arka plan konumu.
function syncTrack() {
if (!(window.WebToApk && WebToApk.getBufferedLocations)) return;
const points = JSON.parse(WebToApk.getBufferedLocations());
if (!points.length) return;
points.forEach(function (p) { drawPoint(p.lat, p.lng); });
saveTrack(points).then(function () { WebToApk.clearBufferedLocations(); });
}
document.addEventListener('visibilitychange', function () { if (!document.hidden) syncTrack(); });Takibi başlatın, sonra bir reddi ele alın. Başlatma çağrısı bir JSON dizesiyle cevap verir.
function startTracking() {
if (!(window.WebToApk && WebToApk.startLocationUpdates)) return;
const r = JSON.parse(WebToApk.startLocationUpdates(JSON.stringify({
intervalMs: 15000, accuracy: 'balanced', background: true
})));
if (!r.ok) showMessage('Tracking not started: ' + r.reason); // not_enabled, location_permission_required, ...
}Sayfa açıkken canlı konumlar appmint:location olarak gelir; kalanını tampon tutar.
window.addEventListener('appmint:location', function (e) {
drawPoint(e.detail.lat, e.detail.lng);
});
document.getElementById('stop').addEventListener('click', function () {
if (window.WebToApk && WebToApk.stopLocationUpdates) WebToApk.stopLocationUpdates();
if (WebToApk.getBufferedLocations) {
const left = JSON.parse(WebToApk.getBufferedLocations());
console.log(left.length + ' fixes still buffered');
}
});getGeofenceEvents köprü#
window.WebToApk.getGeofenceEvents(): String
Son 100 coğrafi çit geçişinin {id, event, time, lat, lng} JSON dizisi, en eskiden başlayarak.
Örnek
Son 100 coğrafi çit geçişi, en eskiden başlayarak - uygulama kapalıyken gerçekleşenler dahil. Sayfanız geç bağlanıyorsa ve kuyruğa alınan appmint:geofence olaylarını kaçırabilirse bunu başlangıçta okuyun.
Döndürür: getGeofenceEvents() → { id, event, time, lat, lng } değerlerinin JSON dize dizisi; clearGeofenceEvents() → true. Gerekenler: derlemede Coğrafi çitler.
if (window.WebToApk && WebToApk.getGeofenceEvents) {
JSON.parse(WebToApk.getGeofenceEvents()).forEach(function (ev) {
logVisit(ev.id, ev.event, ev.time);
});
WebToApk.clearGeofenceEvents();
}Bir coğrafi çit ekleyin, sonra geçişleri izleyin (sayfa açıkken).
if (window.WebToApk && WebToApk.addGeofence) {
const r = JSON.parse(WebToApk.addGeofence(JSON.stringify({
id: 'shop-1', lat: 12.9716, lng: 77.5946, radiusM: 150, events: ['enter', 'exit']
})));
if (!r.ok) showMessage('Geofence refused: ' + r.reason); // not_enabled, invalid_radius, ...
}
window.addEventListener('appmint:geofence', function (e) {
logVisit(e.detail.id, e.detail.event, e.detail.time);
});Kullanıcı bir özellikten ayrıldığında kayıtlı olanları listeleyin ve birini kaldırın.
function dropGeofence(id) {
if (!(window.WebToApk && WebToApk.removeGeofence)) return false;
const known = JSON.parse(WebToApk.getGeofences()).length;
const removed = WebToApk.removeGeofence(id);
console.log(removed ? 'removed' : 'not found', 'of', known, 'registered');
return removed;
}getGeofences köprü#
window.WebToApk.getGeofences(): String
Bu uygulamanın eklediği coğrafi çitlerin JSON dizisi (yeniden başlatmalarda korunurlar).
Örnek
WebToApk.addGeofence ile birlikte belgelenmiştir - oradaki örnek bunu da gösterir.
Uygulama kapalıyken enter, exit ve/veya dwell tetikleyen, isteğe bağlı olarak bildirim gönderen bir daire. Coğrafi çitler telefon yeniden başlatıldığında da korunur (otomatik olarak geri eklenirler).
Döndürür: addGeofence → bir JSON dizesi { ok: true, status: 'adding', id } veya { ok: false, reason } - not_enabled, invalid_id, invalid_position, invalid_radius (1 m … 100 km), invalid_events, location_permission_required, background_permission_required, foreign_origin. Play hizmetlerinin cevabı appmint:geofence-added (window.onAppMintGeofenceAdded) = { id, ok, reason? } (location_off, too_many_geofences - uygulama başına 100, play_services_unavailable) olarak gelir. Bir geçiş appmint:geofence (window.onAppMintGeofence) = { id, event: 'enter' | 'exit' | 'dwell', time, lat, lng, queued? } olarak gelir - uygulama kapalıyken gerçekleştiyse ve bir sonraki başlangıçta teslim edildiyse queued: true. removeGeofence → varsa true; getGeofences → eklediklerinizin JSON dizisi. Gerekenler: derlemede Coğrafi çitler işaretleyin ve "Her zaman izin ver" (requestBackgroundLocation()).
function watchOffice() {
const b = window.WebToApk;
if (!(b && b.addGeofence)) return;
const r = JSON.parse(b.addGeofence(JSON.stringify({
id: 'office', lat: 51.5033, lng: -0.1196, radiusM: 150,
events: ['enter', 'exit', 'dwell'], dwellMs: 5 * 60000,
notify: {
enter: { title: 'At the office', body: 'Tap to check in' },
exit: { title: 'Left the office', body: 'Tap to check out' }
}
})));
if (!r.ok && r.reason === 'background_permission_required') b.requestBackgroundLocation();
}
window.addEventListener('appmint:geofence-added', function (e) {
if (!e.detail.ok) showMessage('Geofence ' + e.detail.id + ' not added: ' + e.detail.reason);
});
window.addEventListener('appmint:geofence', function (e) {
logVisit(e.detail.id, e.detail.event, e.detail.time);
});
console.log(JSON.parse(WebToApk.getGeofences()).map(function (g) { return g.id; }));
WebToApk.removeGeofence('office');Özelliği algılayın ve her reddi bildirin:
function addCircle(id, lat, lng, radiusM) {
const b = window.WebToApk;
if (!(b && b.addGeofence)) { showMessage('Place alerts need the app'); return false; }
const r = JSON.parse(b.addGeofence(JSON.stringify({ id: id, lat: lat, lng: lng, radiusM: radiusM, events: ['enter'] })));
if (r.ok) return true;
if (r.reason === 'not_enabled') showMessage('Geofences are not switched on in this build');
else if (r.reason === 'background_permission_required') b.requestBackgroundLocation();
else if (r.reason === 'invalid_radius') showMessage('Pick a radius between 1 m and 100 km');
else showMessage('Could not add the place: ' + r.reason);
return false;
}Kayıtlı olanları listeleyin ve birini kaldırın:
const mine = JSON.parse(WebToApk.getGeofences()); // [] when none
mine.forEach(function (g) { addRow(g.id); });
document.getElementById('forget').onclick = function () {
const existed = WebToApk.removeGeofence('office'); // true if it was there
if (!existed) showMessage('That place was not registered');
};getLocationPermissionState köprü#
window.WebToApk.getLocationPermissionState(): String
JSON {foreground:'granted'|'denied', background:'granted'|'denied', precise: boolean}.
Örnek
WebToApk.requestBackgroundLocation ile birlikte belgelenmiştir - oradaki örnek bunu da gösterir.
Konum ister, sonra "Her zaman izin ver" ister (Android 10+ bunları ayrı ayrı sorar; Android 11+ üzerinde ikinci adım uygulamanın konum ayarları sayfasını açar). Coğrafi çitler buna ihtiyaç duyar; telefon yeniden başlatıldıktan sonra konum takibini yeniden başlatmak da öyle.
Döndürür: doğrudan hiçbir şey; cevap appmint:location-permission (ve window.onAppMintLocationPermission(detail)) = { foreground: 'granted' | 'denied', background: 'granted' | 'denied', precise: boolean, error?: 'not_enabled' } olarak gelir. getLocationPermissionState() → aynı nesne, sormadan JSON dizesi olarak. Gerekenler: derlemede Arka plan konumu veya Coğrafi çitler.
function askAlways() {
const b = window.WebToApk;
if (!(b && b.requestBackgroundLocation)) return;
const now = JSON.parse(b.getLocationPermissionState());
if (now.background === 'granted') { enableGeofences(); return; }
// Explain first: Play requires an in-app disclosure before this request.
if (!confirm('Allow location "all the time" so we can remind you when you arrive?')) return;
b.requestBackgroundLocation();
}
window.addEventListener('appmint:location-permission', function (e) {
if (e.detail.background === 'granted') enableGeofences();
else showMessage('Choose "Allow all the time" in the location settings to use arrival reminders.');
});Önce durumu kontrol edin ve kullanıcının neye dokunması gerektiğini açıklayın:
const b = window.WebToApk;
if (b && b.getLocationPermissionState) {
const s = JSON.parse(b.getLocationPermissionState());
if (s.foreground !== 'granted') showMessage('Location is off for this app.');
else if (s.background !== 'granted') showMessage('Tap "Allow all the time" to enable arrival reminders.');
else if (!s.precise) showMessage('Precise location is off; arrival alerts may be late.');
}İzni isteyin, sonra verildiğinde bir coğrafi çit (geofence) ekleyin:
window.addEventListener('appmint:location-permission', function (e) {
if (e.detail.error === 'not_enabled') return showMessage('This build has no background location.');
if (e.detail.background !== 'granted') return;
const r = JSON.parse(WebToApk.addGeofence(JSON.stringify({
id: 'home', lat: 51.5033, lng: -0.1196, radiusM: 120, events: ['enter']
})));
if (!r.ok) showMessage('Could not add the place: ' + r.reason);
}, { once: true });
WebToApk.requestBackgroundLocation();isBackgroundRun köprü#
window.WebToApk.isBackgroundRun(): Boolean
Burada false: uygulamanın kendi sayfası asla bir arka plan çalıştırması değildir (başsız bir çalıştırma true döndürür).
Örnek
WebToApk.backgroundRegister ile birlikte belgelenmiştir - oradaki örnek bunu da gösterir.
AppMint.background arkasındaki ham yöntemler - AppMint.background.register(...) kullanın (promise döndürür ve çalıştırma olayını yönetir). Her köprü yönteminin bir örneği olsun diye burada listelenmiştir.
Döndürür: backgroundRegister → JSON { ok: true, name, intervalMinutes } veya { ok: false, reason } (not_enabled, invalid_name - harfler, rakamlar, _, -, en fazla 64 - interval_below_15_minutes, invalid_interval, schedule_failed). backgroundUnregister → varsa true. backgroundList → JSON dizisi. backgroundRunNow → JSON { ok, name } veya { ok: false, reason: 'not_registered' }. backgroundDone(runId, resultJson) → arka plan çalıştırmasında true, uygulamada her zaman false. isBackgroundRun() → uygulamada false, arka plan çalıştırmasında true. Gerekenler: Kapalıyken sayfa kodunu çalıştır işaretleyin.
const b = window.WebToApk;
if (b && b.backgroundRegister) {
const r = JSON.parse(b.backgroundRegister('refresh', JSON.stringify({ intervalMinutes: 60, requiresNetwork: true })));
if (!r.ok) console.warn('not scheduled:', r.reason);
console.log(JSON.parse(b.backgroundList()));
console.log(b.isBackgroundRun()); // false here: this is the app on screen
// b.backgroundRunNow('refresh'); b.backgroundUnregister('refresh');
// In a run: b.backgroundDone(runId, JSON.stringify({ ok: true }))
}Özelliği algılayın ve uygulama çalıştırmasını arka plan çalıştırmasından ayırt edin:
const b = window.WebToApk;
if (!(b && b.backgroundRegister)) {
console.log('background tasks are only in the app');
} else if (b.isBackgroundRun()) {
// the invisible copy: do the work, no UI
} else {
const r = JSON.parse(b.backgroundRegister('sync', JSON.stringify({ intervalMinutes: 5 })));
if (!r.ok) console.warn(r.reason); // 'interval_below_15_minutes'
}Bir görevi test edin ve temizleyin:
const run = JSON.parse(WebToApk.backgroundRunNow('sync'));
if (!run.ok && run.reason === 'not_registered') WebToApk.backgroundRegister('sync', JSON.stringify({ intervalMinutes: 30 }));
JSON.parse(WebToApk.backgroundList()).forEach(function (t) { console.log(t.name, t.intervalMinutes, t.lastResult); });
WebToApk.backgroundUnregister('old-task'); // true if it existedisBackgroundServiceRunning köprü#
window.WebToApk.isBackgroundServiceRunning(): Boolean
Uygulamanın ön plan hizmetinin çalışıp çalışmadığı (çalışmaya devam etme veya arka plan konumu için).
Örnek
WebToApk.startBackgroundService ile birlikte belgelenmiştir - oradaki örnek bunu da gösterir.
Kullanıcı uzaktayken uygulamanızı çalışır tutar: bildirimli gerçek bir Android ön plan hizmeti. Çalışırken sayfa duraklatılmaz, bu yüzden JavaScript'i, <audio> ve uygulamanın arka plan müziği devam eder (Android hâlâ kimsenin göremediği bir sayfanın zamanlayıcılarını yavaşlatır).
Döndürür: startBackgroundService → bir JSON dizesi { ok: true, status: 'starting', type, notificationShown } veya { ok: false, reason } - neden not_enabled, invalid_options, type_not_declared, invalid_progress, location_permission_required, start_not_allowed. updateBackgroundService → { ok: true } veya { ok: false, reason: 'not_running' }. stopBackgroundService / isBackgroundServiceRunning → true / false. Durum değişiklikleri appmint:background-service (ve window.onAppMintBackgroundService(detail)) olarak gelir: { state: 'running' | 'stopped' | 'failed' | 'not_restarted', reason?, types?, restored?, queued? }. Gerekenler: Arka planda çalışmaya devam et işaretleyin (Erişim adımı → Arka plan) ve hizmet türünü seçin. Android 13+ üzerinde bildirim yalnızca kullanıcı bildirimlere izin verdikten sonra görünür (aksi halde notificationShown: false - hizmet yine de çalışır).
function startWorkout() {
const b = window.WebToApk;
if (!(b && b.startBackgroundService)) return; // browser
const r = JSON.parse(b.startBackgroundService(JSON.stringify({
title: 'Workout in progress',
text: '00:00 elapsed',
stopLabel: 'Stop', // a Stop button on the notification
progress: { value: 0, max: 100 }
})));
if (!r.ok) showMessage('Could not keep running: ' + r.reason);
}
function tick(seconds) {
if (window.WebToApk && WebToApk.isBackgroundServiceRunning()) {
WebToApk.updateBackgroundService(JSON.stringify({
title: 'Workout in progress', text: seconds + ' s elapsed', stopLabel: 'Stop',
progress: { value: Math.min(100, seconds / 18), max: 100 }
}));
}
}
function finishWorkout() {
if (window.WebToApk && WebToApk.stopBackgroundService) WebToApk.stopBackgroundService();
}
window.addEventListener('appmint:background-service', function (e) {
// reason: 'user' (Stop button), 'page', 'timeout' (Android 15 dataSync 6-hour limit),
// 'task_removed' (app swiped away); after a phone restart, state 'not_restarted' with
// 'android_forbids_type_at_boot' | 'background_permission_required' | 'start_not_allowed'
if (e.detail.state === 'stopped') showMessage('Stopped (' + e.detail.reason + ')');
});Derlemenin veya telefonun bunu yapamayacağı anlamına gelen cevapları ele alın:
function startKeepAlive() {
const b = window.WebToApk;
if (!(b && typeof b.startBackgroundService === 'function')) return;
const r = JSON.parse(b.startBackgroundService(JSON.stringify({ title: 'Syncing', text: 'Uploading photos' })));
if (r.ok) return;
if (r.reason === 'not_enabled') showMessage('Keep running in background is not on in this build.');
else if (r.reason === 'type_not_declared') showMessage('This build declares no service type.');
else showMessage('Could not start: ' + r.reason);
}Bir yükleme döngüsüyle birleştirin: yalnızca kuyrukta iş varken çalışmaya devam edin.
async function uploadAll(files) {
const b = window.WebToApk;
const keep = b && b.startBackgroundService &&
JSON.parse(b.startBackgroundService(JSON.stringify({ title: 'Uploading', text: '0 of ' + files.length }))).ok;
for (let i = 0; i < files.length; i++) {
await upload(files[i]);
if (keep) b.updateBackgroundService(JSON.stringify({ title: 'Uploading', text: (i + 1) + ' of ' + files.length }));
}
if (keep) b.stopBackgroundService();
}Notlar: tür, derlemenin bildirdiği türlerden biri olmalıdır (sihirbazda seçilen, ayrıca Arka plan konumu açıksa location). Uygulamayı kaydırarak kapatmak, keepAfterSwipe: true vermediğiniz sürece çalışmaya devam eden bir hizmeti durdurur (o zaman sayfanın kendisi gitmiştir). Play Console, bildirilen her tür için kısa bir videoyla ön plan hizmeti beyanı ister.
isIgnoringBatteryOptimizations köprü#
window.WebToApk.isIgnoringBatteryOptimizations(): Boolean
Kullanıcının bu uygulamayı pil optimizasyonundan (Doze uygulama beklemesi) muaf tutup tutmadığı.
Örnek
Pil optimizasyonu muafiyetini kontrol eder ve ister; böylece Doze arka plan işinizi ertelemez.
Döndürür: isIgnoringBatteryOptimizations() → true / false. requestIgnoreBatteryOptimizations() → 'already_ignoring', 'dialog_opened' (sistemin İzin Ver/Reddet iletişim kutusu - yalnızca derleme Pil optimizasyonunu atlamak için doğrudan sor seçeneğini işaretlediyse), 'settings_opened' (pil optimizasyonu listesi; izin yok, Play beyanı yok) veya 'unavailable'. Gerekenler: ayarlar listesi için hiçbir şey. Doğrudan iletişim kutusu REQUEST_IGNORE_BATTERY_OPTIMIZATIONS bildirir; Play bunu yalnızca uygulamanın temel işlevi olduğunda kabul eder.
document.getElementById('reliable').addEventListener('click', function () {
const b = window.WebToApk;
if (!(b && b.isIgnoringBatteryOptimizations)) return;
if (b.isIgnoringBatteryOptimizations()) { showMessage('Already unrestricted'); return; }
const how = b.requestIgnoreBatteryOptimizations();
if (how === 'settings_opened') showMessage('Find this app in the list and choose "Not optimised".');
});Her cevap için ne olduğunu söyleyin.
function askBatteryExemption() {
const b = window.WebToApk;
if (!(b && b.requestIgnoreBatteryOptimizations)) { showMessage('Only available in the app'); return; }
const how = b.requestIgnoreBatteryOptimizations();
const text = {
already_ignoring: 'Already unrestricted',
dialog_opened: 'Please tap Allow',
settings_opened: 'Choose "Not optimised" for this app',
unavailable: 'This phone has no such setting'
};
showMessage(text[how] || how);
}Arka plan takibiyle eşleştirin, çünkü Doze onu duraklatırdı.
if (window.WebToApk && WebToApk.startLocationUpdates) {
const r = JSON.parse(WebToApk.startLocationUpdates(JSON.stringify({ intervalMs: 30000 })));
if (r.ok && !WebToApk.isIgnoringBatteryOptimizations()) {
showMessage('For steady tracking, turn off battery optimisation for this app.');
}
}removeGeofence köprü#
window.WebToApk.removeGeofence(id: String): Boolean
Bu kimliğe sahip coğrafi çiti kaldırır; yoksa false.
Örnek
WebToApk.addGeofence ile birlikte belgelenmiştir - oradaki örnek bunu da gösterir.
Uygulama kapalıyken enter, exit ve/veya dwell tetikleyen, isteğe bağlı olarak bildirim gönderen bir daire. Coğrafi çitler telefon yeniden başlatıldığında da korunur (otomatik olarak geri eklenirler).
Döndürür: addGeofence → bir JSON dizesi { ok: true, status: 'adding', id } veya { ok: false, reason } - not_enabled, invalid_id, invalid_position, invalid_radius (1 m … 100 km), invalid_events, location_permission_required, background_permission_required, foreign_origin. Play hizmetlerinin cevabı appmint:geofence-added (window.onAppMintGeofenceAdded) = { id, ok, reason? } (location_off, too_many_geofences - uygulama başına 100, play_services_unavailable) olarak gelir. Bir geçiş appmint:geofence (window.onAppMintGeofence) = { id, event: 'enter' | 'exit' | 'dwell', time, lat, lng, queued? } olarak gelir - uygulama kapalıyken gerçekleştiyse ve bir sonraki başlangıçta teslim edildiyse queued: true. removeGeofence → varsa true; getGeofences → eklediklerinizin JSON dizisi. Gerekenler: derlemede Coğrafi çitler işaretleyin ve "Her zaman izin ver" (requestBackgroundLocation()).
function watchOffice() {
const b = window.WebToApk;
if (!(b && b.addGeofence)) return;
const r = JSON.parse(b.addGeofence(JSON.stringify({
id: 'office', lat: 51.5033, lng: -0.1196, radiusM: 150,
events: ['enter', 'exit', 'dwell'], dwellMs: 5 * 60000,
notify: {
enter: { title: 'At the office', body: 'Tap to check in' },
exit: { title: 'Left the office', body: 'Tap to check out' }
}
})));
if (!r.ok && r.reason === 'background_permission_required') b.requestBackgroundLocation();
}
window.addEventListener('appmint:geofence-added', function (e) {
if (!e.detail.ok) showMessage('Geofence ' + e.detail.id + ' not added: ' + e.detail.reason);
});
window.addEventListener('appmint:geofence', function (e) {
logVisit(e.detail.id, e.detail.event, e.detail.time);
});
console.log(JSON.parse(WebToApk.getGeofences()).map(function (g) { return g.id; }));
WebToApk.removeGeofence('office');Özelliği algılayın ve her reddi bildirin:
function addCircle(id, lat, lng, radiusM) {
const b = window.WebToApk;
if (!(b && b.addGeofence)) { showMessage('Place alerts need the app'); return false; }
const r = JSON.parse(b.addGeofence(JSON.stringify({ id: id, lat: lat, lng: lng, radiusM: radiusM, events: ['enter'] })));
if (r.ok) return true;
if (r.reason === 'not_enabled') showMessage('Geofences are not switched on in this build');
else if (r.reason === 'background_permission_required') b.requestBackgroundLocation();
else if (r.reason === 'invalid_radius') showMessage('Pick a radius between 1 m and 100 km');
else showMessage('Could not add the place: ' + r.reason);
return false;
}Kayıtlı olanları listeleyin ve birini kaldırın:
const mine = JSON.parse(WebToApk.getGeofences()); // [] when none
mine.forEach(function (g) { addRow(g.id); });
document.getElementById('forget').onclick = function () {
const existed = WebToApk.removeGeofence('office'); // true if it was there
if (!existed) showMessage('That place was not registered');
};requestBackgroundLocation köprü#
window.WebToApk.requestBackgroundLocation()
Konum ister, sonra "Her zaman izin ver" ister; sonuç şu olarak gelir appmint:location-permission.
Örnek
Konum ister, sonra "Her zaman izin ver" ister (Android 10+ bunları ayrı ayrı sorar; Android 11+ üzerinde ikinci adım uygulamanın konum ayarları sayfasını açar). Coğrafi çitler buna ihtiyaç duyar; telefon yeniden başlatıldıktan sonra konum takibini yeniden başlatmak da öyle.
Döndürür: doğrudan hiçbir şey; cevap appmint:location-permission (ve window.onAppMintLocationPermission(detail)) = { foreground: 'granted' | 'denied', background: 'granted' | 'denied', precise: boolean, error?: 'not_enabled' } olarak gelir. getLocationPermissionState() → aynı nesne, sormadan JSON dizesi olarak. Gerekenler: derlemede Arka plan konumu veya Coğrafi çitler.
function askAlways() {
const b = window.WebToApk;
if (!(b && b.requestBackgroundLocation)) return;
const now = JSON.parse(b.getLocationPermissionState());
if (now.background === 'granted') { enableGeofences(); return; }
// Explain first: Play requires an in-app disclosure before this request.
if (!confirm('Allow location "all the time" so we can remind you when you arrive?')) return;
b.requestBackgroundLocation();
}
window.addEventListener('appmint:location-permission', function (e) {
if (e.detail.background === 'granted') enableGeofences();
else showMessage('Choose "Allow all the time" in the location settings to use arrival reminders.');
});Önce durumu kontrol edin ve kullanıcının neye dokunması gerektiğini açıklayın:
const b = window.WebToApk;
if (b && b.getLocationPermissionState) {
const s = JSON.parse(b.getLocationPermissionState());
if (s.foreground !== 'granted') showMessage('Location is off for this app.');
else if (s.background !== 'granted') showMessage('Tap "Allow all the time" to enable arrival reminders.');
else if (!s.precise) showMessage('Precise location is off; arrival alerts may be late.');
}İzni isteyin, sonra verildiğinde bir coğrafi çit (geofence) ekleyin:
window.addEventListener('appmint:location-permission', function (e) {
if (e.detail.error === 'not_enabled') return showMessage('This build has no background location.');
if (e.detail.background !== 'granted') return;
const r = JSON.parse(WebToApk.addGeofence(JSON.stringify({
id: 'home', lat: 51.5033, lng: -0.1196, radiusM: 120, events: ['enter']
})));
if (!r.ok) showMessage('Could not add the place: ' + r.reason);
}, { once: true });
WebToApk.requestBackgroundLocation();requestIgnoreBatteryOptimizations köprü#
window.WebToApk.requestIgnoreBatteryOptimizations(): String
Pil muafiyetini ister: 'already_ignoring' | 'dialog_opened' | 'settings_opened' | 'unavailable'.
Örnek
WebToApk.isIgnoringBatteryOptimizations ile birlikte belgelenmiştir - oradaki örnek bunu da gösterir.
Pil optimizasyonu muafiyetini kontrol eder ve ister; böylece Doze arka plan işinizi ertelemez.
Döndürür: isIgnoringBatteryOptimizations() → true / false. requestIgnoreBatteryOptimizations() → 'already_ignoring', 'dialog_opened' (sistemin İzin Ver/Reddet iletişim kutusu - yalnızca derleme Pil optimizasyonunu atlamak için doğrudan sor seçeneğini işaretlediyse), 'settings_opened' (pil optimizasyonu listesi; izin yok, Play beyanı yok) veya 'unavailable'. Gerekenler: ayarlar listesi için hiçbir şey. Doğrudan iletişim kutusu REQUEST_IGNORE_BATTERY_OPTIMIZATIONS bildirir; Play bunu yalnızca uygulamanın temel işlevi olduğunda kabul eder.
document.getElementById('reliable').addEventListener('click', function () {
const b = window.WebToApk;
if (!(b && b.isIgnoringBatteryOptimizations)) return;
if (b.isIgnoringBatteryOptimizations()) { showMessage('Already unrestricted'); return; }
const how = b.requestIgnoreBatteryOptimizations();
if (how === 'settings_opened') showMessage('Find this app in the list and choose "Not optimised".');
});Her cevap için ne olduğunu söyleyin.
function askBatteryExemption() {
const b = window.WebToApk;
if (!(b && b.requestIgnoreBatteryOptimizations)) { showMessage('Only available in the app'); return; }
const how = b.requestIgnoreBatteryOptimizations();
const text = {
already_ignoring: 'Already unrestricted',
dialog_opened: 'Please tap Allow',
settings_opened: 'Choose "Not optimised" for this app',
unavailable: 'This phone has no such setting'
};
showMessage(text[how] || how);
}Arka plan takibiyle eşleştirin, çünkü Doze onu duraklatırdı.
if (window.WebToApk && WebToApk.startLocationUpdates) {
const r = JSON.parse(WebToApk.startLocationUpdates(JSON.stringify({ intervalMs: 30000 })));
if (r.ok && !WebToApk.isIgnoringBatteryOptimizations()) {
showMessage('For steady tracking, turn off battery optimisation for this app.');
}
}startBackgroundService köprü#
window.WebToApk.startBackgroundService(optionsJson: String): String
Uygulamanın ön plan hizmetini başlatır: {title, text, type?, progress?, stopLabel?, keepAfterSwipe?} → JSON {ok, status, type, notificationShown} veya {ok:false, reason}.
Örnek
Kullanıcı uzaktayken uygulamanızı çalışır tutar: bildirimli gerçek bir Android ön plan hizmeti. Çalışırken sayfa duraklatılmaz, bu yüzden JavaScript'i, <audio> ve uygulamanın arka plan müziği devam eder (Android hâlâ kimsenin göremediği bir sayfanın zamanlayıcılarını yavaşlatır).
Döndürür: startBackgroundService → bir JSON dizesi { ok: true, status: 'starting', type, notificationShown } veya { ok: false, reason } - neden not_enabled, invalid_options, type_not_declared, invalid_progress, location_permission_required, start_not_allowed. updateBackgroundService → { ok: true } veya { ok: false, reason: 'not_running' }. stopBackgroundService / isBackgroundServiceRunning → true / false. Durum değişiklikleri appmint:background-service (ve window.onAppMintBackgroundService(detail)) olarak gelir: { state: 'running' | 'stopped' | 'failed' | 'not_restarted', reason?, types?, restored?, queued? }. Gerekenler: Arka planda çalışmaya devam et işaretleyin (Erişim adımı → Arka plan) ve hizmet türünü seçin. Android 13+ üzerinde bildirim yalnızca kullanıcı bildirimlere izin verdikten sonra görünür (aksi halde notificationShown: false - hizmet yine de çalışır).
function startWorkout() {
const b = window.WebToApk;
if (!(b && b.startBackgroundService)) return; // browser
const r = JSON.parse(b.startBackgroundService(JSON.stringify({
title: 'Workout in progress',
text: '00:00 elapsed',
stopLabel: 'Stop', // a Stop button on the notification
progress: { value: 0, max: 100 }
})));
if (!r.ok) showMessage('Could not keep running: ' + r.reason);
}
function tick(seconds) {
if (window.WebToApk && WebToApk.isBackgroundServiceRunning()) {
WebToApk.updateBackgroundService(JSON.stringify({
title: 'Workout in progress', text: seconds + ' s elapsed', stopLabel: 'Stop',
progress: { value: Math.min(100, seconds / 18), max: 100 }
}));
}
}
function finishWorkout() {
if (window.WebToApk && WebToApk.stopBackgroundService) WebToApk.stopBackgroundService();
}
window.addEventListener('appmint:background-service', function (e) {
// reason: 'user' (Stop button), 'page', 'timeout' (Android 15 dataSync 6-hour limit),
// 'task_removed' (app swiped away); after a phone restart, state 'not_restarted' with
// 'android_forbids_type_at_boot' | 'background_permission_required' | 'start_not_allowed'
if (e.detail.state === 'stopped') showMessage('Stopped (' + e.detail.reason + ')');
});Derlemenin veya telefonun bunu yapamayacağı anlamına gelen cevapları ele alın:
function startKeepAlive() {
const b = window.WebToApk;
if (!(b && typeof b.startBackgroundService === 'function')) return;
const r = JSON.parse(b.startBackgroundService(JSON.stringify({ title: 'Syncing', text: 'Uploading photos' })));
if (r.ok) return;
if (r.reason === 'not_enabled') showMessage('Keep running in background is not on in this build.');
else if (r.reason === 'type_not_declared') showMessage('This build declares no service type.');
else showMessage('Could not start: ' + r.reason);
}Bir yükleme döngüsüyle birleştirin: yalnızca kuyrukta iş varken çalışmaya devam edin.
async function uploadAll(files) {
const b = window.WebToApk;
const keep = b && b.startBackgroundService &&
JSON.parse(b.startBackgroundService(JSON.stringify({ title: 'Uploading', text: '0 of ' + files.length }))).ok;
for (let i = 0; i < files.length; i++) {
await upload(files[i]);
if (keep) b.updateBackgroundService(JSON.stringify({ title: 'Uploading', text: (i + 1) + ' of ' + files.length }));
}
if (keep) b.stopBackgroundService();
}Notlar: tür, derlemenin bildirdiği türlerden biri olmalıdır (sihirbazda seçilen, ayrıca Arka plan konumu açıksa location). Uygulamayı kaydırarak kapatmak, keepAfterSwipe: true vermediğiniz sürece çalışmaya devam eden bir hizmeti durdurur (o zaman sayfanın kendisi gitmiştir). Play Console, bildirilen her tür için kısa bir videoyla ön plan hizmeti beyanı ister.
startLocationUpdates köprü#
window.WebToApk.startLocationUpdates(optionsJson: String): String
Konum güncellemeleri {intervalMs, minDistanceM, accuracy, background, uploadUrl?, headers?} → JSON {ok, background, backgroundPermission, precise} veya {ok:false, reason}; konumlar şu olarak gelir appmint:location.
Örnek
Uygulama arka plandayken gelmeye devam eden konum güncellemeleri (koşu takipçisi, teslimat uygulaması). background: true ile (varsayılan) uygulamanın ön plan hizmetinin içinde çalışırlar. Her konum, sayfa oradayken appmint:location olarak sayfaya, değilken bir tampona (getBufferedLocations()) ve - bir uploadUrl verirseniz - yerel koddan JSON POST olarak sunucunuza gider; böylece sayfa gitmiş olsa da takip çalışır.
Döndürür: bir JSON dizesi { ok: true, background, backgroundPermission, precise } veya { ok: false, reason } - not_enabled, invalid_options, invalid_interval (1 sn … 24 sa), invalid_distance, invalid_accuracy, invalid_upload_url, location_permission_required, start_not_allowed, foreign_origin. stopLocationUpdates() → bir şey çalışıyorsa true. Konumlar: appmint:location / window.onAppMintLocation(detail) = { type: 'fix', lat, lng, accuracy, altitude?, speed?, bearing?, time, provider, background } veya { type: 'error', reason: 'play_services_unavailable' | 'location_unavailable' | 'location_permission_required' }. Gerekenler: Arka plan konumu işaretleyin (Erişim adımı → Arka plan) ve önce kullanıcının konum izni.
function startTracking(token) {
const b = window.WebToApk;
if (!(b && b.startLocationUpdates)) return;
navigator.geolocation.getCurrentPosition(function () { // asks for location first
const r = JSON.parse(b.startLocationUpdates(JSON.stringify({
intervalMs: 10000, minDistanceM: 10, accuracy: 'high', background: true,
uploadUrl: 'https://api.example.com/track',
headers: { Authorization: 'Bearer ' + token }
})));
if (!r.ok) showMessage('Tracking not started: ' + r.reason);
});
}
window.addEventListener('appmint:location', function (e) {
if (e.detail.type === 'fix') drawPoint(e.detail.lat, e.detail.lng);
else showMessage('Location stopped: ' + e.detail.reason);
});
function stopTracking() { if (window.WebToApk) WebToApk.stopLocationUpdates(); }Hatalı bir seçeneği veya eksik bir izni cevabın şu alanıyla bildirin reason:
function tryTrack() {
const b = window.WebToApk;
if (!(b && typeof b.startLocationUpdates === 'function')) {
showMessage('Background tracking needs the installed app.');
return;
}
const r = JSON.parse(b.startLocationUpdates(JSON.stringify({ intervalMs: 500 })));
if (!r.ok && r.reason === 'invalid_interval') showMessage('Interval must be 1 second or more.');
if (!r.ok && r.reason === 'location_permission_required') showMessage('Allow location first.');
}Tamponla doğal bir çift: vardiya sonunda durun ve sayfa yokken kaydedilenleri yükleyin.
async function endShift() {
if (!window.WebToApk) return;
WebToApk.stopLocationUpdates();
const points = JSON.parse(WebToApk.getBufferedLocations());
if (points.length) {
await fetch('/api/shift/points', { method: 'POST', body: JSON.stringify(points) });
WebToApk.clearBufferedLocations();
}
}Notlar: uygulamadan başlatılan bir konum hizmeti "Her zaman izin ver" olmadan arka planda konum almaya devam eder; telefon yeniden başlatıldıktan sonra yeniden başlatmak buna ihtiyaç duyar (requestBackgroundLocation()). Başarısız olan bir POST WorkManager'a devredilir ve ağ geri geldiğinde gönderilir. Google Play hizmetleri olmayan telefonlar play_services_unavailable döndürür. Play Console bir arka plan konumu beyanı gerektirir.
stopBackgroundService köprü#
window.WebToApk.stopBackgroundService(): Boolean
startBackgroundService ile başlatılan hizmeti durdurur (arka plan konumu çalışıyorsa devam eder).
Örnek
WebToApk.startBackgroundService ile birlikte belgelenmiştir - oradaki örnek bunu da gösterir.
Kullanıcı uzaktayken uygulamanızı çalışır tutar: bildirimli gerçek bir Android ön plan hizmeti. Çalışırken sayfa duraklatılmaz, bu yüzden JavaScript'i, <audio> ve uygulamanın arka plan müziği devam eder (Android hâlâ kimsenin göremediği bir sayfanın zamanlayıcılarını yavaşlatır).
Döndürür: startBackgroundService → bir JSON dizesi { ok: true, status: 'starting', type, notificationShown } veya { ok: false, reason } - neden not_enabled, invalid_options, type_not_declared, invalid_progress, location_permission_required, start_not_allowed. updateBackgroundService → { ok: true } veya { ok: false, reason: 'not_running' }. stopBackgroundService / isBackgroundServiceRunning → true / false. Durum değişiklikleri appmint:background-service (ve window.onAppMintBackgroundService(detail)) olarak gelir: { state: 'running' | 'stopped' | 'failed' | 'not_restarted', reason?, types?, restored?, queued? }. Gerekenler: Arka planda çalışmaya devam et işaretleyin (Erişim adımı → Arka plan) ve hizmet türünü seçin. Android 13+ üzerinde bildirim yalnızca kullanıcı bildirimlere izin verdikten sonra görünür (aksi halde notificationShown: false - hizmet yine de çalışır).
function startWorkout() {
const b = window.WebToApk;
if (!(b && b.startBackgroundService)) return; // browser
const r = JSON.parse(b.startBackgroundService(JSON.stringify({
title: 'Workout in progress',
text: '00:00 elapsed',
stopLabel: 'Stop', // a Stop button on the notification
progress: { value: 0, max: 100 }
})));
if (!r.ok) showMessage('Could not keep running: ' + r.reason);
}
function tick(seconds) {
if (window.WebToApk && WebToApk.isBackgroundServiceRunning()) {
WebToApk.updateBackgroundService(JSON.stringify({
title: 'Workout in progress', text: seconds + ' s elapsed', stopLabel: 'Stop',
progress: { value: Math.min(100, seconds / 18), max: 100 }
}));
}
}
function finishWorkout() {
if (window.WebToApk && WebToApk.stopBackgroundService) WebToApk.stopBackgroundService();
}
window.addEventListener('appmint:background-service', function (e) {
// reason: 'user' (Stop button), 'page', 'timeout' (Android 15 dataSync 6-hour limit),
// 'task_removed' (app swiped away); after a phone restart, state 'not_restarted' with
// 'android_forbids_type_at_boot' | 'background_permission_required' | 'start_not_allowed'
if (e.detail.state === 'stopped') showMessage('Stopped (' + e.detail.reason + ')');
});Derlemenin veya telefonun bunu yapamayacağı anlamına gelen cevapları ele alın:
function startKeepAlive() {
const b = window.WebToApk;
if (!(b && typeof b.startBackgroundService === 'function')) return;
const r = JSON.parse(b.startBackgroundService(JSON.stringify({ title: 'Syncing', text: 'Uploading photos' })));
if (r.ok) return;
if (r.reason === 'not_enabled') showMessage('Keep running in background is not on in this build.');
else if (r.reason === 'type_not_declared') showMessage('This build declares no service type.');
else showMessage('Could not start: ' + r.reason);
}Bir yükleme döngüsüyle birleştirin: yalnızca kuyrukta iş varken çalışmaya devam edin.
async function uploadAll(files) {
const b = window.WebToApk;
const keep = b && b.startBackgroundService &&
JSON.parse(b.startBackgroundService(JSON.stringify({ title: 'Uploading', text: '0 of ' + files.length }))).ok;
for (let i = 0; i < files.length; i++) {
await upload(files[i]);
if (keep) b.updateBackgroundService(JSON.stringify({ title: 'Uploading', text: (i + 1) + ' of ' + files.length }));
}
if (keep) b.stopBackgroundService();
}Notlar: tür, derlemenin bildirdiği türlerden biri olmalıdır (sihirbazda seçilen, ayrıca Arka plan konumu açıksa location). Uygulamayı kaydırarak kapatmak, keepAfterSwipe: true vermediğiniz sürece çalışmaya devam eden bir hizmeti durdurur (o zaman sayfanın kendisi gitmiştir). Play Console, bildirilen her tür için kısa bir videoyla ön plan hizmeti beyanı ister.
stopLocationUpdates köprü#
window.WebToApk.stopLocationUpdates(): Boolean
startLocationUpdates ile başlatılan konum güncellemelerini durdurur; hiçbiri çalışmıyorsa false.
Örnek
WebToApk.startLocationUpdates ile birlikte belgelenmiştir - oradaki örnek bunu da gösterir.
Uygulama arka plandayken gelmeye devam eden konum güncellemeleri (koşu takipçisi, teslimat uygulaması). background: true ile (varsayılan) uygulamanın ön plan hizmetinin içinde çalışırlar. Her konum, sayfa oradayken appmint:location olarak sayfaya, değilken bir tampona (getBufferedLocations()) ve - bir uploadUrl verirseniz - yerel koddan JSON POST olarak sunucunuza gider; böylece sayfa gitmiş olsa da takip çalışır.
Döndürür: bir JSON dizesi { ok: true, background, backgroundPermission, precise } veya { ok: false, reason } - not_enabled, invalid_options, invalid_interval (1 sn … 24 sa), invalid_distance, invalid_accuracy, invalid_upload_url, location_permission_required, start_not_allowed, foreign_origin. stopLocationUpdates() → bir şey çalışıyorsa true. Konumlar: appmint:location / window.onAppMintLocation(detail) = { type: 'fix', lat, lng, accuracy, altitude?, speed?, bearing?, time, provider, background } veya { type: 'error', reason: 'play_services_unavailable' | 'location_unavailable' | 'location_permission_required' }. Gerekenler: Arka plan konumu işaretleyin (Erişim adımı → Arka plan) ve önce kullanıcının konum izni.
function startTracking(token) {
const b = window.WebToApk;
if (!(b && b.startLocationUpdates)) return;
navigator.geolocation.getCurrentPosition(function () { // asks for location first
const r = JSON.parse(b.startLocationUpdates(JSON.stringify({
intervalMs: 10000, minDistanceM: 10, accuracy: 'high', background: true,
uploadUrl: 'https://api.example.com/track',
headers: { Authorization: 'Bearer ' + token }
})));
if (!r.ok) showMessage('Tracking not started: ' + r.reason);
});
}
window.addEventListener('appmint:location', function (e) {
if (e.detail.type === 'fix') drawPoint(e.detail.lat, e.detail.lng);
else showMessage('Location stopped: ' + e.detail.reason);
});
function stopTracking() { if (window.WebToApk) WebToApk.stopLocationUpdates(); }Hatalı bir seçeneği veya eksik bir izni cevabın şu alanıyla bildirin reason:
function tryTrack() {
const b = window.WebToApk;
if (!(b && typeof b.startLocationUpdates === 'function')) {
showMessage('Background tracking needs the installed app.');
return;
}
const r = JSON.parse(b.startLocationUpdates(JSON.stringify({ intervalMs: 500 })));
if (!r.ok && r.reason === 'invalid_interval') showMessage('Interval must be 1 second or more.');
if (!r.ok && r.reason === 'location_permission_required') showMessage('Allow location first.');
}Tamponla doğal bir çift: vardiya sonunda durun ve sayfa yokken kaydedilenleri yükleyin.
async function endShift() {
if (!window.WebToApk) return;
WebToApk.stopLocationUpdates();
const points = JSON.parse(WebToApk.getBufferedLocations());
if (points.length) {
await fetch('/api/shift/points', { method: 'POST', body: JSON.stringify(points) });
WebToApk.clearBufferedLocations();
}
}Notlar: uygulamadan başlatılan bir konum hizmeti "Her zaman izin ver" olmadan arka planda konum almaya devam eder; telefon yeniden başlatıldıktan sonra yeniden başlatmak buna ihtiyaç duyar (requestBackgroundLocation()). Başarısız olan bir POST WorkManager'a devredilir ve ağ geri geldiğinde gönderilir. Google Play hizmetleri olmayan telefonlar play_services_unavailable döndürür. Play Console bir arka plan konumu beyanı gerektirir.
updateBackgroundService köprü#
window.WebToApk.updateBackgroundService(optionsJson: String): String
Çalışan hizmetin bildirimini değiştirir (startBackgroundService ile aynı seçenekler) → JSON {ok} veya {ok:false, reason:'not_running'}.
Örnek
WebToApk.startBackgroundService ile birlikte belgelenmiştir - oradaki örnek bunu da gösterir.
Kullanıcı uzaktayken uygulamanızı çalışır tutar: bildirimli gerçek bir Android ön plan hizmeti. Çalışırken sayfa duraklatılmaz, bu yüzden JavaScript'i, <audio> ve uygulamanın arka plan müziği devam eder (Android hâlâ kimsenin göremediği bir sayfanın zamanlayıcılarını yavaşlatır).
Döndürür: startBackgroundService → bir JSON dizesi { ok: true, status: 'starting', type, notificationShown } veya { ok: false, reason } - neden not_enabled, invalid_options, type_not_declared, invalid_progress, location_permission_required, start_not_allowed. updateBackgroundService → { ok: true } veya { ok: false, reason: 'not_running' }. stopBackgroundService / isBackgroundServiceRunning → true / false. Durum değişiklikleri appmint:background-service (ve window.onAppMintBackgroundService(detail)) olarak gelir: { state: 'running' | 'stopped' | 'failed' | 'not_restarted', reason?, types?, restored?, queued? }. Gerekenler: Arka planda çalışmaya devam et işaretleyin (Erişim adımı → Arka plan) ve hizmet türünü seçin. Android 13+ üzerinde bildirim yalnızca kullanıcı bildirimlere izin verdikten sonra görünür (aksi halde notificationShown: false - hizmet yine de çalışır).
function startWorkout() {
const b = window.WebToApk;
if (!(b && b.startBackgroundService)) return; // browser
const r = JSON.parse(b.startBackgroundService(JSON.stringify({
title: 'Workout in progress',
text: '00:00 elapsed',
stopLabel: 'Stop', // a Stop button on the notification
progress: { value: 0, max: 100 }
})));
if (!r.ok) showMessage('Could not keep running: ' + r.reason);
}
function tick(seconds) {
if (window.WebToApk && WebToApk.isBackgroundServiceRunning()) {
WebToApk.updateBackgroundService(JSON.stringify({
title: 'Workout in progress', text: seconds + ' s elapsed', stopLabel: 'Stop',
progress: { value: Math.min(100, seconds / 18), max: 100 }
}));
}
}
function finishWorkout() {
if (window.WebToApk && WebToApk.stopBackgroundService) WebToApk.stopBackgroundService();
}
window.addEventListener('appmint:background-service', function (e) {
// reason: 'user' (Stop button), 'page', 'timeout' (Android 15 dataSync 6-hour limit),
// 'task_removed' (app swiped away); after a phone restart, state 'not_restarted' with
// 'android_forbids_type_at_boot' | 'background_permission_required' | 'start_not_allowed'
if (e.detail.state === 'stopped') showMessage('Stopped (' + e.detail.reason + ')');
});Derlemenin veya telefonun bunu yapamayacağı anlamına gelen cevapları ele alın:
function startKeepAlive() {
const b = window.WebToApk;
if (!(b && typeof b.startBackgroundService === 'function')) return;
const r = JSON.parse(b.startBackgroundService(JSON.stringify({ title: 'Syncing', text: 'Uploading photos' })));
if (r.ok) return;
if (r.reason === 'not_enabled') showMessage('Keep running in background is not on in this build.');
else if (r.reason === 'type_not_declared') showMessage('This build declares no service type.');
else showMessage('Could not start: ' + r.reason);
}Bir yükleme döngüsüyle birleştirin: yalnızca kuyrukta iş varken çalışmaya devam edin.
async function uploadAll(files) {
const b = window.WebToApk;
const keep = b && b.startBackgroundService &&
JSON.parse(b.startBackgroundService(JSON.stringify({ title: 'Uploading', text: '0 of ' + files.length }))).ok;
for (let i = 0; i < files.length; i++) {
await upload(files[i]);
if (keep) b.updateBackgroundService(JSON.stringify({ title: 'Uploading', text: (i + 1) + ' of ' + files.length }));
}
if (keep) b.stopBackgroundService();
}Notlar: tür, derlemenin bildirdiği türlerden biri olmalıdır (sihirbazda seçilen, ayrıca Arka plan konumu açıksa location). Uygulamayı kaydırarak kapatmak, keepAfterSwipe: true vermediğiniz sürece çalışmaya devam eden bir hizmeti durdurur (o zaman sayfanın kendisi gitmiştir). Play Console, bildirilen her tür için kısa bir videoyla ön plan hizmeti beyanı ister.