Ücretsiz APK oluştur

JavaScript köprü API'si

Cihazdaki bildirimler

Sunucusuz gΓΆnderme ve zamanlama, POST_NOTIFICATIONS izni, tam alarmlar ve ΓΆzel sesler.

AppMint.enableNotifications yardımcı#

AppMint.enableNotifications()

Örnek

Android'in bildirim isteΔini reddeden veya atlayan kullanΔ±cΔ±lar iΓ§in tek Γ§aΔrΔ±da "Bildirimleri aΓ§": Android hΓ’lΓ’ gΓΆsterebiliyorsa izin penceresi, deΔilse bu uygulamanΔ±n bildirim ayarlarΔ± β ve kullanΔ±cΔ± geri dΓΆndΓΌΔΓΌnde yeni durum.

DΓΆner deΔer: AppMint.enableNotifications() - her zaman {state, changed, openedSettings} ile Γ§ΓΆzΓΌlen bir Promise; state deΔeri 'granted' | 'prompt' | 'blocked' | 'unavailable'. AppMint.getNotificationState() - o durumun Promise'i. AppMint.openNotificationSettings() - ayarlar ekranΔ± aΓ§Δ±ldΔ±ΔΔ±nda true Promise'i. Gerekenler: enableNotifications() iΕlevini kullanΔ±cΔ±nΔ±n dokunduΔu bir dΓΌΔmeden Γ§aΔΔ±rΔ±n; bildirimler iΓ§in derlemede Bildirimler (veya Push / HatΔ±rlatΔ±cΔ±lar) gerekir.

// A banner that only shows while notifications are off, and turns them on in one tap.
async function setupNotifBanner() {
  if (!(window.AppMint && AppMint.enableNotifications)) return;   // a browser: no banner
  var banner = document.getElementById('notif-banner');
  var state = await AppMint.getNotificationState();
  banner.hidden = !(state === 'prompt' || state === 'blocked');
  document.getElementById('notif-turn-on').onclick = async function () {
    var r = await AppMint.enableNotifications();
    banner.hidden = r.state === 'granted';
    if (r.state === 'blocked') showToast('Switch on "Allow notifications" to get updates.');
  };
}
setupNotifBanner();

Kendi ayarlar sayfanΔ±zda dΓΌz bir "Bildirim ayarlarΔ±" baΔlantΔ±sΔ±:

document.getElementById('notif-settings').onclick = async function () {
  var opened = window.AppMint && AppMint.openNotificationSettings && await AppMint.openNotificationSettings();
  if (!opened) showToast('Open Settings > Apps > this app > Notifications.');
};

Notlar: baΔlantΔ±sΔ± appmint://notifications/enable olan bir push veya uygulama iΓ§i mesaj dΓΌΔmesi, hiΓ§bir sayfa kodu olmadan aynΔ± akΔ±ΕΔ± Γ§alΔ±ΕtΔ±rΔ±r (sayfa appmint:notifications olayΔ±nΔ± duyar). UygulamanΔ±n push kitlesi ("Bildirimler aΓ§Δ±k / kapalΔ±") kullanΔ±cΔ± bunlarΔ± aΓ§ar aΓ§maz gΓΌncellenir.

AppMint.getNotificationState yardımcı#

window.AppMint.getNotificationState

Örnek

AppMint.enableNotifications ile birlikte belgelenmiştir - oradaki örnek bunu da gösterir.

Android'in bildirim isteΔini reddeden veya atlayan kullanΔ±cΔ±lar iΓ§in tek Γ§aΔrΔ±da "Bildirimleri aΓ§": Android hΓ’lΓ’ gΓΆsterebiliyorsa izin penceresi, deΔilse bu uygulamanΔ±n bildirim ayarlarΔ± β ve kullanΔ±cΔ± geri dΓΆndΓΌΔΓΌnde yeni durum.

DΓΆner deΔer: AppMint.enableNotifications() - her zaman {state, changed, openedSettings} ile Γ§ΓΆzΓΌlen bir Promise; state deΔeri 'granted' | 'prompt' | 'blocked' | 'unavailable'. AppMint.getNotificationState() - o durumun Promise'i. AppMint.openNotificationSettings() - ayarlar ekranΔ± aΓ§Δ±ldΔ±ΔΔ±nda true Promise'i. Gerekenler: enableNotifications() iΕlevini kullanΔ±cΔ±nΔ±n dokunduΔu bir dΓΌΔmeden Γ§aΔΔ±rΔ±n; bildirimler iΓ§in derlemede Bildirimler (veya Push / HatΔ±rlatΔ±cΔ±lar) gerekir.

// A banner that only shows while notifications are off, and turns them on in one tap.
async function setupNotifBanner() {
  if (!(window.AppMint && AppMint.enableNotifications)) return;   // a browser: no banner
  var banner = document.getElementById('notif-banner');
  var state = await AppMint.getNotificationState();
  banner.hidden = !(state === 'prompt' || state === 'blocked');
  document.getElementById('notif-turn-on').onclick = async function () {
    var r = await AppMint.enableNotifications();
    banner.hidden = r.state === 'granted';
    if (r.state === 'blocked') showToast('Switch on "Allow notifications" to get updates.');
  };
}
setupNotifBanner();

Kendi ayarlar sayfanΔ±zda dΓΌz bir "Bildirim ayarlarΔ±" baΔlantΔ±sΔ±:

document.getElementById('notif-settings').onclick = async function () {
  var opened = window.AppMint && AppMint.openNotificationSettings && await AppMint.openNotificationSettings();
  if (!opened) showToast('Open Settings > Apps > this app > Notifications.');
};

Notlar: baΔlantΔ±sΔ± appmint://notifications/enable olan bir push veya uygulama iΓ§i mesaj dΓΌΔmesi, hiΓ§bir sayfa kodu olmadan aynΔ± akΔ±ΕΔ± Γ§alΔ±ΕtΔ±rΔ±r (sayfa appmint:notifications olayΔ±nΔ± duyar). UygulamanΔ±n push kitlesi ("Bildirimler aΓ§Δ±k / kapalΔ±") kullanΔ±cΔ± bunlarΔ± aΓ§ar aΓ§maz gΓΌncellenir.

AppMint.openNotificationSettings yardımcı#

window.AppMint.openNotificationSettings

Örnek

AppMint.enableNotifications ile birlikte belgelenmiştir - oradaki örnek bunu da gösterir.

Android'in bildirim isteΔini reddeden veya atlayan kullanΔ±cΔ±lar iΓ§in tek Γ§aΔrΔ±da "Bildirimleri aΓ§": Android hΓ’lΓ’ gΓΆsterebiliyorsa izin penceresi, deΔilse bu uygulamanΔ±n bildirim ayarlarΔ± β ve kullanΔ±cΔ± geri dΓΆndΓΌΔΓΌnde yeni durum.

DΓΆner deΔer: AppMint.enableNotifications() - her zaman {state, changed, openedSettings} ile Γ§ΓΆzΓΌlen bir Promise; state deΔeri 'granted' | 'prompt' | 'blocked' | 'unavailable'. AppMint.getNotificationState() - o durumun Promise'i. AppMint.openNotificationSettings() - ayarlar ekranΔ± aΓ§Δ±ldΔ±ΔΔ±nda true Promise'i. Gerekenler: enableNotifications() iΕlevini kullanΔ±cΔ±nΔ±n dokunduΔu bir dΓΌΔmeden Γ§aΔΔ±rΔ±n; bildirimler iΓ§in derlemede Bildirimler (veya Push / HatΔ±rlatΔ±cΔ±lar) gerekir.

// A banner that only shows while notifications are off, and turns them on in one tap.
async function setupNotifBanner() {
  if (!(window.AppMint && AppMint.enableNotifications)) return;   // a browser: no banner
  var banner = document.getElementById('notif-banner');
  var state = await AppMint.getNotificationState();
  banner.hidden = !(state === 'prompt' || state === 'blocked');
  document.getElementById('notif-turn-on').onclick = async function () {
    var r = await AppMint.enableNotifications();
    banner.hidden = r.state === 'granted';
    if (r.state === 'blocked') showToast('Switch on "Allow notifications" to get updates.');
  };
}
setupNotifBanner();

Kendi ayarlar sayfanΔ±zda dΓΌz bir "Bildirim ayarlarΔ±" baΔlantΔ±sΔ±:

document.getElementById('notif-settings').onclick = async function () {
  var opened = window.AppMint && AppMint.openNotificationSettings && await AppMint.openNotificationSettings();
  if (!opened) showToast('Open Settings > Apps > this app > Notifications.');
};

Notlar: baΔlantΔ±sΔ± appmint://notifications/enable olan bir push veya uygulama iΓ§i mesaj dΓΌΔmesi, hiΓ§bir sayfa kodu olmadan aynΔ± akΔ±ΕΔ± Γ§alΔ±ΕtΔ±rΔ±r (sayfa appmint:notifications olayΔ±nΔ± duyar). UygulamanΔ±n push kitlesi ("Bildirimler aΓ§Δ±k / kapalΔ±") kullanΔ±cΔ± bunlarΔ± aΓ§ar aΓ§maz gΓΌncellenir.

navigator.setAppBadge web standardı#

navigator.setAppBadge(count) / clearAppBadge()

Örnek

Standart Badging API: uygulamanΔ±n baΕlatΔ±cΔ± simgesinde, okunmamΔ±Ε sayΔ±sΔ± gibi bir sayΔ±.

DΓΆner deΔer: rozet ayarlandΔ±ΔΔ±nda Γ§ΓΆzΓΌlen bir Promise; negatif veya sayΔ± olmayan bir deΔer iΓ§in TypeError. Gerekenler: aΓ§Δ±lacak bir Εey yok. YalnΔ±zca baΕlatΔ±cΔ±sΔ± sayΔ± gΓΆsteren telefonlarda vardΔ±r (Samsung, Huawei, Xiaomi, OPPO, Sony, β¦); Pixel tarzΔ± baΕlatΔ±cΔ±larda 'setAppBadge' in navigator deΔeri false.

function updateBadge(unread) {
  if (!('setAppBadge' in navigator)) return;      // this launcher cannot show a count
  if (unread > 0) navigator.setAppBadge(unread);
  else navigator.clearAppBadge();
}

updateBadge(messages.filter((m) => !m.read).length);

KullanΔ±cΔ± uygulamaya baktΔ±ΔΔ± sΓΌrece rozeti temizleyin ve reddedilen bir gΓΌncellemeyi ele alΔ±n:

function setUnread(count) {
  if (!('setAppBadge' in navigator)) return;
  navigator.setAppBadge(count).catch(function (err) {
    console.warn('badge not updated:', err.name);   // NotAllowedError or TypeError
  });
}

document.addEventListener('visibilitychange', function () {
  if (!document.hidden && 'clearAppBadge' in navigator) {
    navigator.clearAppBadge().catch(function () {});
  }
});

Bir eΕitleme deΔiΕiklik bulur ama kesin sayΔ± yoksa dΓΌz bir "yeni bir Εey var" bayraΔΔ± gΓΆsterin:

async function afterSync(result) {
  if (!('setAppBadge' in navigator)) return;
  try {
    if (result.newCount > 0) await navigator.setAppBadge(result.newCount);
    else if (result.hasChanges) await navigator.setAppBadge();   // flag badge, shown as 1
    else await navigator.clearAppBadge();
  } catch (e) {
    console.warn('badge update failed', e);
  }
}

Notlar: sayΔ±sΔ±z setAppBadge(), spesifikasyonun "flag" rozetidir ve sayΔ± gΓΆsteren baΕlatΔ±cΔ±da 1 olarak gΓΆrΓΌnΓΌr. SayΔ± uygulama yeniden baΕlatΔ±lΔ±nca da korunur. AynΔ± depo @/lib/appmintNative iΓ§indeki badge.set() iΓ§in de kullanΔ±lΔ±r, bu yΓΌzden ikisi her zaman uyumludur.

Notification web standardı#

new Notification(title, options) / Notification.requestPermission()

Örnek

Standart Web Notifications API'si uygulama iΓ§inde Γ§alΔ±ΕΔ±r: new Notification() gerΓ§ek bir Android bildirimi gΓΆsterir, close() onu kaldΔ±rΔ±r ve Notification.requestPermission() Android izin penceresini gΓΆsterir ve kullanΔ±cΔ±nΔ±n yanΔ±tΔ±nΔ± bekler.

DΓΆner deΔer: Notification.permission, 'granted', 'denied' veya 'default' olur ve doΔrudan telefondan okunur (Ayarlar'daki bir deΔiΕiklik yenileme olmadan gΓΆrΓΌnΓΌr). requestPermission(), 'granted' veya 'denied' Promise'i dΓΆndΓΌrΓΌr (geri Γ§aΔrΔ± biΓ§imi de Γ§alΔ±ΕΔ±r). Yeni bir bildirim gΓΆnderildiΔinde show, izin yoksa error tetikler. Gerekenler: derleme yaparken EriΕim adΔ±mΔ±nda (AdΔ±m 4) Bildirimler aΓ§Δ±n.

async function notifyWhenSaved() {
  if (!('Notification' in window)) return;
  let perm = Notification.permission;
  if (perm === 'default') perm = await Notification.requestPermission();
  if (perm !== 'granted') {
    showMessage('Turn on notifications for this app in Settings to get alerts.');
    return;
  }
  const n = new Notification('Saved', {
    body: 'Your note was saved',
    icon: 'https://example.com/avatar.png',   // shown as the large icon
    image: 'https://example.com/note.jpg',    // big picture
    tag: 'note'                               // same tag replaces the old one
  });
  n.onshow = function () { console.log('posted'); };
  n.onerror = function () { console.log('not posted'); };
  setTimeout(function () { n.close(); }, 60000);   // removes it from the shade
}

document.getElementById('save').addEventListener('click', notifyWhenSaved);

Geri Γ§aΔrΔ± biΓ§imi (eski kod):

Notification.requestPermission(function (result) {
  if (result === 'granted') new Notification('Welcome!', { body: 'Alerts are on', silent: true });
});

Service worker tarzΔ± (PWA kodu) da uygulama ΓΌzerinden gΓΆnderir, ancak yalnΔ±zca WebView'Δ±n kendisinde navigator.serviceWorker olmayan yerlerde (ΓΆrneΔin file:// veya http:// sayfalarΔ±):

if ('serviceWorker' in navigator && Notification.permission === 'granted') {
  navigator.serviceWorker.ready.then(function (reg) {
    return reg.showNotification('Backup done', { body: '12 files', tag: 'backup' });
  });
}

Bir dokunuΕ bildirimde click olayΔ±nΔ± tetikler - uygulama ΓΆne gelir ve sayfa onu alΔ±r. Uygulama kapalΔ±ysa (dokunuΕ onu baΕlattΔ±ysa) nesne yoktur, bu yΓΌzden pencere bunun yerine bir service worker'Δ±nkine benzer Εekilde bir notificationclick olayΔ± alΔ±r - event.notification.tag / title / body / data:

const n = new Notification('Order shipped', { body: '#7', tag: 'order-7', data: { orderId: 7 } });
n.onclick = () => openOrder(7);                         // the app was running
window.addEventListener('notificationclick', (e) => {   // the tap started the app
  if (e.notification.data && e.notification.data.orderId) openOrder(e.notification.data.orderId);
});

Notlar: kullanΔ±lan seΓ§enekler: body, icon, image, tag, silent, data (JSON, 16 KB altΔ±nda). DokunuΕ, aΓ§Δ±lΔ±Ε ekranΔ± ve PIN ekranlarΔ± ΓΌzerinden sayfaya ulaΕΔ±r (arkasΔ±ndaki olay: appmint:notification-click). Android 12 ve eskisinde Γ§alΔ±Εma zamanΔ± izni yoktur, bu yΓΌzden kullanΔ±cΔ± bildirimleri kapatmadΔ±kΓ§a 'granted' olur. Web Push (pushManager.subscribe) desteklenmez; AppMint Push kullanΔ±n. DΓΌΔmeler, ilerleme veya yapΔ±ΕkΔ±n bildirim iΓ§in WebToApk.notify(...) kullanΔ±n. AynΔ± kod normal bir tarayΔ±cΔ±da da Γ§alΔ±ΕΔ±r.

__badgeSupported köprü#

window.WebToApk.__badgeSupported(): Boolean

Bu baΕlatΔ±cΔ±nΔ±n rozet sayΔ±sΔ± gΓΆsterip gΓΆsteremeyeceΔi (navigator.setAppBadge yalnΔ±zca o zaman vardΔ±r).

Örnek

navigator.setAppBadge varlΔ±ΔΔ±nΔ±n arkasΔ±ndaki iΓ§ aktarΔ±m. Sayfalar standart API'yi kullanΔ±r; bunu asla doΔrudan Γ§aΔΔ±rmayΔ±n β __ yΓΆntemleri haber verilmeden deΔiΕebilir.

DΓΆner deΔer: bu telefonun baΕlatΔ±cΔ±sΔ± rozet sayΔ±sΔ± gΓΆsteriyorsa true. Gerekenler: aΓ§Δ±lacak bir Εey yok.

Genel API'yi kullanın:

if ('setAppBadge' in navigator) navigator.setAppBadge(unreadCount);

"Uygulama simgesinde rozet" ayarΔ±nΔ± yalnΔ±zca baΕlatΔ±cΔ±sΔ± sayΔ± gΓΆsterebilen telefonlarda gΓΆsterin:

function renderBadgeSetting() {
  const row = document.getElementById('badge-setting');
  // setAppBadge exists only when this launcher shows counts
  row.hidden = !('setAppBadge' in navigator);
}
renderBadgeSetting();

KullanΔ±cΔ± gelen kutusunu aΓ§tΔ±ΔΔ±nda, sayΔ± gΓΆsteren herhangi bir baΕlatΔ±cΔ±da sayΔ±yΔ± temizleyin:

function openInbox() {
  showInbox();
  if ('clearAppBadge' in navigator) {
    navigator.clearAppBadge().catch(function (e) {
      console.warn('badge not cleared', e.name);   // NotAllowedError
    });
  }
}

Notlar: Badging API yalnΔ±zca baΕlatΔ±cΔ±nΔ±n sayΔ± gΓΆsterebildiΔi yerlerde kurulur (Samsung, Huawei, Xiaomi, OPPO, Sony, β¦); Pixel tarzΔ± baΕlatΔ±cΔ±larda, rozet desteΔi olmayan bir tarayΔ±cΔ±daki gibi bulunmaz.

__closeNotification köprü#

window.WebToApk.__closeNotification(tag: String): Boolean

Notification.close(): sayfanΔ±n gΓΆnderdiΔi bir bildirimi etiketine gΓΆre kaldΔ±rΔ±r.

Örnek

Notification.prototype.close() arkasΔ±ndaki iΓ§ altyapΔ± β sayfalar new Notification(...) kullanΔ±r ve onun ΓΌzerinde close() Γ§aΔΔ±rΔ±r. Bir bildirimi etiketine gΓΆre bildirim gΓΆlgesinden kaldΔ±rΔ±r.

DΓΆner deΔer: kaldΔ±rma isteΔi yapΔ±ldΔ±ΔΔ±nda true (o etikete sahip hiΓ§bir Εey olmadΔ±ΔΔ±nda da); iΓ§ hatada false. Gerekenler: hiΓ§bir Εey.

Genel API'yi kullanın:

let uploadNote = null;

function showUploading() {
  if (!('Notification' in window) || Notification.permission !== 'granted') return;
  uploadNote = new Notification('Uploading…', { body: 'Keep the app open', tag: 'upload', silent: true });
  uploadNote.onclose = function () { uploadNote = null; };
}

function uploadFinished() {
  if (uploadNote) uploadNote.close();   // removes it from the notification shade
}

Bildirime dokunulduΔunda doΔru sohbeti aΓ§Δ±n, sonra bildirim gΓΆlgesinden kaldΔ±rΔ±n:

function notifyNewMessage(msg) {
  if (!('Notification' in window) || Notification.permission !== 'granted') return;
  const n = new Notification(msg.from, {
    body: msg.text,
    tag: 'chat-' + msg.threadId,          // one notification per chat
    data: { threadId: msg.threadId }
  });
  n.onclick = function () {
    openThread(n.data.threadId);
    n.close();
  };
}

Beq saniye sonra kendiliΔinden kalkan kΔ±sa bir onay gΓΆsterin:

function confirmCopied() {
  if (!('Notification' in window) || Notification.permission !== 'granted') return;
  const n = new Notification('Link copied', { body: 'Paste it anywhere', tag: 'copied', silent: true });
  setTimeout(function () { n.close(); }, 5000);
}

Notlar: WebToApk.__closeNotification iΕlevini doΔrudan Γ§aΔΔ±rmayΔ±n; __ yΓΆntemleri haber verilmeden deΔiΕebilir. close(), bildirimin close olayΔ±nΔ± tetikler.

__setAppBadge köprü#

window.WebToApk.__setAppBadge(contents: Long): Boolean

navigator.setAppBadge(n): n >= 0 bir sayΔ±dΔ±r (0 temizler), -1 spesifikasyonun bayrak rozetidir.

Örnek

navigator.setAppBadge(count) / clearAppBadge() arkasΔ±ndaki iΓ§ aktarΔ±m. Sayfalar standart API'yi kullanΔ±r; bunu asla doΔrudan Γ§aΔΔ±rmayΔ±n β __ yΓΆntemleri haber verilmeden deΔiΕebilir.

DΓΆner deΔer: sayΔ± uygulandΔ±ysa true. Gerekenler: aΓ§Δ±lacak bir Εey yok.

Genel API'yi kullanın:

if ('setAppBadge' in navigator) navigator.setAppBadge(unreadCount);

Simge sayΔ±sΔ±nΔ± okunmamΔ±Ε sayΔ±sΔ±yla uyumlu tutun ve sΔ±fΔ±rda temizleyin:

async function syncBadge(unread) {
  if (!('setAppBadge' in navigator)) return;
  try {
    if (unread > 0) await navigator.setAppBadge(unread);
    else await navigator.clearAppBadge();
  } catch (e) {
    console.warn('badge not applied', e.name);   // NotAllowedError when the launcher refused it
  }
}
syncBadge(messages.filter(function (m) { return !m.read; }).length);

EΕitlenmemiΕ iΕ varken simgeye bir bayrak rozeti (sayΔ±sΔ±z) koyun:

function markPendingSync(hasPending) {
  if (!('setAppBadge' in navigator)) return;
  const p = hasPending
    ? navigator.setAppBadge()      // no argument = flag badge; a count launcher shows 1
    : navigator.clearAppBadge();
  p.catch(function () {});
}

Notlar: -1, spesifikasyonun bayrak rozetidir (sayΔ±sΔ±z) ve sayΔ± gΓΆsteren baΕlatΔ±cΔ± bunu 1 olarak gΓΆsterir.

cancelAllNotifications köprü#

window.WebToApk.cancelAllNotifications(): Boolean

POST_NOTIFICATIONS iznini okuma ve isteme, ve sayfanΔ±n zaten zamanladΔ±ΔΔ± bildirimleri yΓΆnetme. GΓΆnderme ve zamanlama kendi yΓΆntemlerinde belgelenmiΕtir.

Kendi baΕΔ±na deΔil, grubu Bildirim izni, iptal ve listeleme ΓΌzerinden aΓ§Δ±klanΔ±r.

Örnek

Bu uygulamanΔ±n zamanladΔ±ΔΔ± her hatΔ±rlatΔ±cΔ±yΔ± iptal eder.

DΓΆner deΔer: iΕlem tamamlandΔ±ΔΔ±nda true; yalnΔ±zca iΓ§ hatada false. Gerekenler: ek olarak hiΓ§bir Εey.

document.getElementById('reset-reminders').addEventListener('click', function () {
  if (!(window.WebToApk && window.WebToApk.cancelAllNotifications)) return;
  if (!confirm('Remove all your reminders?')) return;
  const ok = WebToApk.cancelAllNotifications();
  showMessage(ok ? 'All reminders removed' : 'Could not remove reminders');
});

Oturum kapatΔ±lΔ±rken ΓΆnceki kullanΔ±cΔ±nΔ±n hatΔ±rlatΔ±cΔ±larΔ±nΔ± durdurun ve simge sayΔ±sΔ±nΔ± temizleyin:

async function signOut() {
  if (window.WebToApk && window.WebToApk.cancelAllNotifications) {
    WebToApk.cancelAllNotifications();
  }
  if ('clearAppBadge' in navigator) navigator.clearAppBadge().catch(function () {});
  await auth.signOut();
  showLoginScreen();
}

TΓΌm gΓΌnlΓΌk programΔ± kayΔ±tlΔ± saatlerden yeniden oluΕturun (hepsini iptal edin, sonra her birini ekleyin):

function applyMedicineTimes(times) {        // e.g. ['08:00', '20:00']
  const b = window.WebToApk;
  if (!(b && b.cancelAllNotifications)) return;
  b.cancelAllNotifications();
  times.forEach(function (hhmm, i) {
    const parts = hhmm.split(':');
    const at = new Date();
    at.setHours(Number(parts[0]), Number(parts[1]), 0, 0);
    if (at.getTime() <= Date.now()) at.setDate(at.getDate() + 1);   // next occurrence
    b.scheduleNotification('med-' + i, 'Medicine', 'Time for your ' + hhmm + ' dose',
      String(at.getTime()), 'daily');
  });
}

Notlar: zamanlanmΔ±Ε listeyi temizler, bΓΆylece daha sonra hiΓ§bir Εey Γ§almaz ve yeniden baΕlatmadan sonra hiΓ§bir Εey tekrar kurulmaz. Tepsi'de zaten gΓΆrΓΌnen bildirimler orada kalΔ±r.

cancelNotification köprü#

window.WebToApk.cancelNotification(id: String): Boolean

POST_NOTIFICATIONS iznini okuma ve isteme, ve sayfanΔ±n zaten zamanladΔ±ΔΔ± bildirimleri yΓΆnetme. GΓΆnderme ve zamanlama kendi yΓΆntemlerinde belgelenmiΕtir.

Kendi baΕΔ±na deΔil, grubu Bildirim izni, iptal ve listeleme ΓΌzerinden aΓ§Δ±klanΔ±r.

Örnek

ZamanlanmΔ±Ε bir hatΔ±rlatΔ±cΔ±yΔ± kimliΔine gΓΆre iptal eder, bΓΆylece bir daha Γ§almaz.

DΓΆner deΔer: true (o kimlikte hatΔ±rlatΔ±cΔ± olmadΔ±ΔΔ±nda da); yalnΔ±zca iΓ§ hatada false. Gerekenler: ek olarak hiΓ§bir Εey (hatΔ±rlatΔ±cΔ±lar derleme zamanΔ±nda β° HatΔ±rlatΔ±cΔ±lar gerektirir).

function stopWaterReminder() {
  if (!(window.WebToApk && window.WebToApk.cancelNotification)) return;
  WebToApk.cancelNotification('water');   // the id you gave scheduleNotification / scheduleNotificationEx

  // Check it is gone:
  const left = JSON.parse(WebToApk.getScheduledNotifications() || '[]');
  const stillThere = left.some(function (r) { return r.id === 'water'; });
  console.log('water reminder still scheduled?', stillThere);   // false
}

AynΔ± kimlikle zamanlayan veya iptal eden, ayarlardaki bir hatΔ±rlatΔ±cΔ± anahtarΔ±:

document.getElementById('water-toggle').addEventListener('change', function (e) {
  const b = window.WebToApk;
  if (!(b && b.cancelNotification && b.scheduleNotification)) return;
  if (e.target.checked) {
    b.scheduleNotification('water', 'Drink water', 'Time for a glass of water',
      String(Date.now() + 60 * 60 * 1000), 'hourly');
  } else {
    b.cancelNotification('water');
  }
});

Bir gΓΆrev silindiΔinde ona ait her hatΔ±rlatΔ±cΔ±yΔ± iptal edin:

function cancelTaskReminders(taskId) {
  const b = window.WebToApk;
  if (!(b && b.cancelNotification)) return;
  let list = [];
  try { list = JSON.parse(b.getScheduledNotifications() || '[]'); } catch (e) { list = []; }
  list
    .filter(function (r) { return r.id.indexOf('task-' + taskId + '-') === 0; })
    .forEach(function (r) { b.cancelNotification(r.id); });
}

Notlar: bu, henΓΌz Γ§almamΔ±Ε bir hatΔ±rlatΔ±cΔ±yΔ± (tek seferlik veya tekrarlayΔ±cΔ±) iptal eder. Tepsi'de zaten gΓΆrΓΌnen bir bildirimi kaldΔ±rmaz ve Εununla gΓΆnderilen bildirimleri etkilemez notify() / showNotification().

canOpenAppAtTime köprü#

window.WebToApk.canOpenAppAtTime(): String

ZamanlanmΔ±Ε bir bildirimin UYGULAMANIN KENDΔ°SΔ°NΔ° ekrana getirip getiremeyeceΔi (`openApp`). "granted" - tam ekran bir uyarΔ± kilit ekranΔ±nΔ±n ΓΌzerinde gΓΆrΓΌnΓΌr. "denied" - Android 14+ bunu vermedi; requestOpenAppPermission() Γ§aΔΔ±rΔ±n. UygulamanΔ±n arka planda sessizce kendini baΕlattΔ±ΔΔ± ΓΌΓ§ΓΌncΓΌ bir yanΔ±t yoktur: Android, Android 10'dan beri arka plan etkinlik baΕlatmalarΔ±nΔ± engeller ve tam ekran intent'i geriye kalanΔ±n tamamΔ±dΔ±r.

Örnek

openApp: true olan bir hatΔ±rlatΔ±cΔ±nΔ±n uygulamanΔ±n kendisini ekrana getirip getiremeyeceΔini sΓΆyler (kilit ekranΔ±nda da gΓΆrΓΌnen tam ekran bir uyarΔ±).

DΓΆner deΔer: eΕzamanlΔ± olarak bir dize: 'granted' veya 'denied'. Android 14'ΓΌn altΔ±nda her zaman 'granted'. Gerekenler: derleme yaparken EriΕim adΔ±mΔ±nda (AdΔ±m 4) β° HatΔ±rlatΔ±cΔ±lar aΓ§Δ±n.

function prepareAlarm() {
  const b = window.WebToApk;
  if (!(b && b.canOpenAppAtTime)) return;
  if (b.canOpenAppAtTime() === 'denied') {
    showMessage('To open the app at alarm time, allow "full-screen notifications" for this app.');
    b.requestOpenAppPermission();
    return;
  }
  const t = new Date();
  t.setDate(t.getDate() + 1);
  t.setHours(7, 0, 0, 0);                    // tomorrow 07:00
  b.scheduleNotificationEx('wake-up', JSON.stringify({
    at: t.getTime(), repeat: 'daily',
    title: 'Wake up', body: 'Good morning!',
    openApp: true
  }));
}

window.addEventListener('appmint:reminder', function (e) {
  // e.detail.overLockScreen is true when the app was shown as a full-screen alert
  if (e.detail.overLockScreen) showBigAlarmScreen(e.detail.id);
});

Her iki alarm anahtarΔ±nΔ± mevcut durumlarΔ±yla gΓΆsteren bir ayarlar ekranΔ±:

function renderAlarmStatus() {
  const b = window.WebToApk;
  if (!(b && b.canOpenAppAtTime && b.getAlarmPrecision)) return;
  const openApp = b.canOpenAppAtTime();       // 'granted' | 'denied'
  const precision = b.getAlarmPrecision();    // 'exact' | 'inexact' | 'unavailable'
  document.getElementById('open-app-state').textContent =
    openApp === 'granted' ? 'Opens over the lock screen' : 'Notification only';
  document.getElementById('open-app-fix').hidden = openApp === 'granted';
  document.getElementById('timing-state').textContent =
    precision === 'exact' ? 'On the minute' : 'May be late';
}

renderAlarmStatus();
document.addEventListener('visibilitychange', function () {
  if (!document.hidden) renderAlarmStatus();  // back from Settings
});

KayΔ±tlΔ± alarmlar uygulamayΔ± aΓ§acak Εekilde kurulmuΕ ama Android Εu anda buna izin vermiyorsa uyarΔ±n:

function checkSavedAlarms() {
  const b = window.WebToApk;
  if (!(b && b.canOpenAppAtTime && b.getScheduledNotifications)) return;
  if (b.canOpenAppAtTime() === 'granted') return;
  // [{ id, title, body, trigger, repeat, options }] - options is the JSON string you scheduled
  const items = JSON.parse(b.getScheduledNotifications());
  const affected = items.filter(function (r) {
    try { return JSON.parse(r.options || '{}').openApp === true; } catch (e) { return false; }
  });
  if (affected.length) {
    showMessage(affected.length + ' alarm(s) will only show a notification. Tap "Allow" to let them open the app.');
  }
}

Notlar: 'denied' iken, bir openApp hatΔ±rlatΔ±cΔ±sΔ± yine de bir heads-up bildirimi gΓΆnderir ama uygulama kendiliΔinden aΓ§Δ±lmaz. Android, bir uygulamanΔ±n arka planda kendini baΕlatmasΔ± iΓ§in baΕka bir yola izin vermez.

clearNotificationSounds köprü#

window.WebToApk.clearNotificationSounds(): Int

Kopyalanan ses dosyalarΔ±nΔ± bΔ±rakΔ±r ve kaΓ§ tanesinin silindiΔini dΓΆndΓΌrΓΌr. Bir bildirim (veya zamanlanmΔ±Ε bir hatΔ±rlatΔ±cΔ±, tetiklendiΔinde) o sesi bir sonraki kullandΔ±ΔΔ±nda dosya yeniden kopyalanΔ±r β aynΔ± dosya adΔ±nΔ± gΓΆstermeye devam eden mevcut bir kanalda da (NotificationBridge.restoreBundleSound).

Örnek

Γzel bildirim seslerinizin, uygulamanΔ±n paketinizden yaptΔ±ΔΔ± kopyalarΔ±nΔ± siler.

DΓΆner deΔer: eΕzamanlΔ± olarak bir sayΔ±: kaΓ§ dosyanΔ±n silindiΔi. Gerekenler: hiΓ§bir Εey.

Temizleyin, sonra hΓ’lΓ’ kullandΔ±ΔΔ±nΔ±z sesleri geri koyun:

document.getElementById('reset-sounds').addEventListener('click', function () {
  const b = window.WebToApk;
  if (!(b && b.clearNotificationSounds)) return;
  const removed = b.clearNotificationSounds();

  // Sounds still in use must be copied again, or they play the default sound:
  ['/audio/alarm.mp3', '/audio/chime.mp3'].forEach(function (path) {
    if (!b.prepareNotificationSound(path)) console.warn('missing sound', path);
  });
  showMessage(removed + ' sound file(s) refreshed');
});

Kopyalanan ses dosyalarΔ±nΔ± boΕaltan ve kaΓ§Δ±nΔ±n kaldΔ±rΔ±ldΔ±ΔΔ±nΔ± sΓΆyleyen bir depolama ekranΔ± dΓΌΔmesi:

document.getElementById('free-space').addEventListener('click', function () {
  const b = window.WebToApk;
  if (!(b && b.clearNotificationSounds)) return;
  const removed = b.clearNotificationSounds();
  showMessage(removed === 0 ? 'No sound files to remove.' : 'Removed ' + removed + ' sound file(s).');
});

Oturum kapatΔ±lΔ±rken her hatΔ±rlatΔ±cΔ±yΔ± iptal edin ve bu kullanΔ±cΔ±ya ait ses kopyalarΔ±nΔ± silin:

function signOutAndReset() {
  const b = window.WebToApk;
  if (b && b.cancelAllNotifications) b.cancelAllNotifications();
  if (b && b.clearNotificationSounds) b.clearNotificationSounds();
  localStorage.removeItem('alarmSound');
  goToLoginScreen();
}

Notlar: buna nadiren ihtiyaΓ§ duyarsΔ±nΔ±z; kopyalar kΓΌΓ§ΓΌktΓΌr. Bir ses, onu kullanan bir Εey olduΔunda yeniden kopyalanΔ±r β notify(), Γ§aldΔ±ΔΔ±nda bir hatΔ±rlatΔ±cΔ±, scheduleNotificationEx veya prepareNotificationSound(path) β zaten var olan bir bildirim kanalΔ±nda da, bΓΆylece ΓΆzel ses Γ§almaya devam eder.

enableNotifications köprü#

window.WebToApk.enableNotifications(callbackId: String)

KullanΔ±cΔ±yΔ± bildirimlere geri getirir: hΓ’lΓ’ gΓΆsterilebiliyorsa sistem penceresi, deΔilse uygulamanΔ±n bildirim ayarlarΔ±. `window.__appmintReplies[callbackId]` deΔerini {state, changed, openedSettings} ile Γ§ΓΆzer (AppMint.enableNotifications() promise sarmalayΔ±cΔ±sΔ±dΔ±r).

Örnek

Bildirimleri reddeden veya atlayan bir kullanΔ±cΔ±yΔ± geri getirir: hΓ’lΓ’ gΓΆsterilebiliyorsa Android'in izin penceresini gΓΆsterir, deΔilse bu uygulamanΔ±n bildirim ayarlarΔ±nΔ± aΓ§ar ve kullanΔ±cΔ± geri dΓΆndΓΌΔΓΌnde yanΔ±t verir.

DΓΆner deΔer: doΔrudan hiΓ§bir Εey. {state, changed, openedSettings} yanΔ±tΔ± window.__appmintReplies[callbackId] iΓ§ine iletilir; state 'granted' | 'prompt' | 'blocked' | 'unavailable' olur, changed Γ§aΔrΔ±dan ΓΆncekinden farklΔ±ysa true olur, openedSettings ayarlar ekranΔ± kullanΔ±ldΔ±ysa true olur. Zaten 'granted' (veya 'unavailable') ise hemen yanΔ±t verir. Gerekenler: kullanΔ±cΔ±nΔ±n dokunduΔu bir dΓΌΔmeden Γ§aΔΔ±rΔ±n; bildirimler iΓ§in derlemede Bildirimler (veya Push / HatΔ±rlatΔ±cΔ±lar) gerekir.

AppMint.enableNotifications() Promise sarmalayΔ±cΔ±sΔ±nΔ± tercih edin. Kendi yanΔ±tlarΔ±nΔ± yΓΆneten kod iΓ§in ham Γ§aΔrΔ±:

function enableNotificationsRaw() {
  return new Promise(function (resolve) {
    if (!(window.WebToApk && WebToApk.enableNotifications)) return resolve({ state: 'unavailable', changed: false, openedSettings: false });
    var replies = window.__appmintReplies = window.__appmintReplies || {};
    var id = 'my_notif_' + Date.now();
    replies[id] = resolve;
    WebToApk.enableNotifications(id);
  });
}

document.getElementById('turn-on-btn').onclick = async function () {
  var r = await enableNotificationsRaw();
  if (r.state === 'granted') document.getElementById('notif-banner').hidden = true;
};

BitmiΕ her akΔ±Ε da duyurulur, bir push dΓΌΔmesinin baΕlattΔ±ΔΔ± akΔ±Ε dahil (appmint://notifications/enable):

window.addEventListener('appmint:notifications', function (e) {
  // e.detail = { state, changed, openedSettings }
  if (e.detail.state === 'granted') document.getElementById('notif-banner').hidden = true;
});

Notlar: baΔlantΔ±sΔ± appmint://notifications/enable olan bir push veya uygulama iΓ§i mesaj dΓΌΔmesi bu akΔ±ΕΔ±n aynΔ±sΔ±nΔ± Γ§alΔ±ΕtΔ±rΔ±r; appmint://notifications/settings ayarlar ekranΔ±nΔ± aΓ§ar. UygulamanΔ±n push kitlesi yeni durumu hemen gΓΆrΓΌr.

getAlarmPrecision köprü#

window.WebToApk.getAlarmPrecision(): String

"exact" - hatΔ±rlatΔ±cΔ±lar tam dakikada Γ§alar. "inexact" - kullanΔ±cΔ± (veya OEM) bu uygulama iΓ§in tam alarmlarΔ± kapattΔ±, bu yΓΌzden Doze bunlarΔ± dakikalarca toplu halde erteleyebilir. DΓΌzeltmek iΓ§in [requestExactAlarms] isteyin. "unavailable" - Android 12+ ve sistem alarm hizmetine ulaΕΔ±lamadΔ±, bu yΓΌzden hassasiyet okunamaz (Εimdi zamanlanan bir hatΔ±rlatΔ±cΔ± da Γ§almayabilir). ZamanΔ±nda olmasΔ± gereken bir sayfa bunu varsaymak yerine denetlemelidir. @return `"exact"`, `"inexact"` veya `"unavailable"`.

Örnek

HatΔ±rlatΔ±cΔ±larΔ±n tam dakikada mΔ± Γ§alacaΔΔ±nΔ±, yoksa kullanΔ±cΔ± (veya telefon ΓΌreticisi) bu uygulama iΓ§in tam alarmlarΔ± kapattΔ±ΔΔ± iΓ§in geΓ§ kalabileceΔini sΓΆyler.

DΓΆner deΔer: eΕzamanlΔ± olarak bir dize: 'exact', 'inexact' (pil tasarrufuyla, genellikle dakikalarca, toplu halde ertelenebilir) veya 'unavailable' (telefonda alarm hizmeti yok). Gerekenler: derleme yaparken EriΕim adΔ±mΔ±nda (AdΔ±m 4) β° HatΔ±rlatΔ±cΔ±lar aΓ§Δ±n.

function checkReminderTiming() {
  if (!(window.WebToApk && window.WebToApk.getAlarmPrecision)) return;
  const precision = WebToApk.getAlarmPrecision();
  const warn = document.getElementById('timing-warning');
  warn.hidden = precision === 'exact';
  if (precision === 'inexact') {
    warn.textContent = 'Reminders may be a few minutes late. Tap to allow exact alarms.';
    warn.onclick = function () { WebToApk.requestExactAlarms(); };
  }
}
checkReminderTiming();
// Re-check when the user returns from Settings:
document.addEventListener('visibilitychange', function () {
  if (!document.hidden) checkReminderTiming();
});

Bir uyandΔ±rma alarmΔ± kurmadan ΓΆnce denetleyin ve geΓ§ kalabileceΔini kullanΔ±cΔ±ya sΓΆyleyin:

function setWakeUp(atMs) {
  const b = window.WebToApk;
  if (!(b && b.getAlarmPrecision && b.scheduleNotificationEx)) return;
  const precision = b.getAlarmPrecision();
  if (precision === 'unavailable') { showMessage('Alarms cannot be set on this phone right now.'); return; }
  b.scheduleNotificationEx('wake', JSON.stringify({ at: atMs, title: 'Wake up', body: 'Good morning', openApp: true }));
  if (precision === 'inexact') {
    showMessage('Alarm set, but it may ring a few minutes late. Allow exact alarms for on-time alarms.');
  }
}

HatΔ±rlatΔ±cΔ± zamanlamasΔ±nΔ± ayarlar ekranΔ±nda bir satΔ±r olarak gΓΆsterin:

function renderTimingRow() {
  if (!(window.WebToApk && window.WebToApk.getAlarmPrecision)) return;
  const labels = {
    exact: 'Reminders arrive on time',
    inexact: 'Reminders may be a few minutes late',
    unavailable: 'Reminders are not available on this phone'
  };
  document.getElementById('timing-row').textContent = labels[WebToApk.getAlarmPrecision()];
}
renderTimingRow();

Notlar: Android 11 ve eskisi her zaman 'exact' yanΔ±tΔ±nΔ± verir. 'inexact' bir hatΔ±rlatΔ±cΔ± yine de Γ§alar, ama tam dakikada deΔil.

getAlarmSupport köprü#

window.WebToApk.getAlarmSupport(): String

`scheduleNotificationEx(id, {alarm: true, ...})` iΕlevinin Εimdi zamanlanΔ±p zamanlanamayacaΔΔ±: "ready" | "not_enabled" (bu derlemede Alarm saati kapalΔ±) | "needs_exact_alarm" (requestExactAlarms Γ§aΔΔ±rΔ±n) | "needs_notification_permission".

Örnek

Bu telefonda Εimdi bir alarm saati (scheduleNotificationEx(id, { alarm: true, ... })) kurulup kurulamayacaΔΔ±nΔ± ve kurulamΔ±yorsa kullanΔ±cΔ±nΔ±n ΓΆnce neye izin vermesi gerektiΔini sΓΆyler.

DΓΆner deΔer: eΕzamanlΔ± olarak bir dize: 'ready', 'not_enabled' (uygulama π Alarm saati olmadan derlendi), 'needs_exact_alarm' (Android 12+: bu uygulama iΓ§in tam alarmlar kapalΔ± β requestExactAlarms() Γ§aΔΔ±rΔ±n) veya 'needs_notification_permission' (Android 13+: bildirim izni yok, bu yΓΌzden Kapat dΓΌΔmesi olmaz β requestNotificationPermission() Γ§aΔΔ±rΔ±n). Gerekenler: derleme yaparken EriΕim adΔ±mΔ±nda (AdΔ±m 4) π Alarm saati aΓ§Δ±n.

function prepareAlarms() {
  const b = window.WebToApk;
  if (!(b && b.getAlarmSupport)) { showMessage('Alarms work in the installed app only.'); return false; }
  switch (b.getAlarmSupport()) {
    case 'ready': return true;
    case 'needs_exact_alarm':
      showMessage('Allow "Alarms & reminders" for this app, then come back.');
      b.requestExactAlarms();
      return false;
    case 'needs_notification_permission':
      b.requestNotificationPermission();
      return false;
    default:
      showMessage('This app was built without alarm clocks.');
      return false;
  }
}

KullanΔ±cΔ± Ayarlar'dan geri dΓΆndΓΌΔΓΌnde yeniden denetleyin:

document.addEventListener('visibilitychange', function () {
  if (document.hidden || !(window.WebToApk && window.WebToApk.getAlarmSupport)) return;
  document.getElementById('alarm-setup').hidden = WebToApk.getAlarmSupport() === 'ready';
});

Bir alarmΔ± yalnΔ±zca telefon hazΔ±rken oluΕturun:

function setAlarmIn(hours) {
  const b = window.WebToApk;
  if (!(b && b.getAlarmSupport)) return false;
  if (b.getAlarmSupport() !== 'ready') { prepareAlarms(); return false; }   // asks for what is missing
  return b.scheduleNotificationEx('wake-up', JSON.stringify({
    at: Date.now() + hours * 3600 * 1000,
    alarm: true,
    title: 'Wake up',
    body: 'Good morning'
  }));
}

Notlar: alarm: true ile scheduleNotificationEx, bu 'ready' olmadΔ±ΔΔ± her durumda false dΓΆndΓΌrΓΌr β asla Γ§alamayacak bir alarm hiΓ§ saklanmaz.

getNotificationPermission köprü#

window.WebToApk.getNotificationPermission(): String

Εu anki bildirim izni, doΔrudan iΕletim sisteminden okunur. Polyfill eskiden her sayfa yΓΌklemesinde `Notification.permission = 'default'` deΔerini sabit kodluyordu, bu yΓΌzden Γ§ok yaygΔ±n olan if (Notification.permission === 'granted') new Notification(...) kalΔ±bΔ± hiΓ§ Γ§alΔ±ΕmΔ±yordu β izni zaten vermiΕ bir kullanΔ±cΔ± iΓ§in bile, ve bildirimlerin hiΓ§ Γ§alΔ±Εma zamanΔ± izni gerektirmediΔi Android 12 ve ΓΆncesinde de.

Örnek

Bu uygulamanΔ±n Εu anda bildirim gΓΆnderip gΓΆnderemeyeceΔini okur.

DΓΆner deΔer: eΕzamanlΔ± olarak bir dize: 'granted'; 'denied' (kullanΔ±cΔ± kesin olarak reddetti veya Ayarlar'dan bu uygulamanΔ±n bildirimlerini kapattΔ± β gΓΆnderilen bildirim gΓΆrΓΌnmez); ya da 'default' (henΓΌz karar verilmedi, uygulama hΓ’lΓ’ sorabilir). Gerekenler: Γ§aΔΔ±rmak iΓ§in hiΓ§bir Εey; gΓΆndermek iΓ§in derleme yaparken EriΕim adΔ±mΔ±nda (AdΔ±m 4) Bildirimler aΓ§Δ±k olmalΔ±.

Standart web API'si aynΔ± canlΔ± deΔeri okur:

if ('Notification' in window && Notification.permission === 'granted') {
  document.getElementById('alerts-on').hidden = false;
}

Ham Γ§aΔrΔ±, ΓΆrneΔin kullanΔ±cΔ± Ayarlar'dan geri dΓΆnΓΌnce:

function refreshAlertSetting() {
  if (!(window.WebToApk && window.WebToApk.getNotificationPermission)) return;
  const perm = WebToApk.getNotificationPermission();   // 'granted' | 'denied' | 'default'
  document.getElementById('enable-alerts').hidden = perm !== 'default';   // can still ask
  document.getElementById('open-settings-hint').hidden = perm !== 'denied';
}
document.addEventListener('visibilitychange', function () {
  if (!document.hidden) refreshAlertSetting();
});
refreshAlertSetting();

Zamanlamadan ΓΆnce sorup sormayacaΔΔ±nΔ±za, aΓ§Δ±klayΔ±p aΓ§Δ±klamayacaΔΔ±nΔ±za ya da devam edip etmeyeceΔinize karar verin:

async function ensureAlerts() {
  const b = window.WebToApk;
  if (!(b && b.getNotificationPermission)) return false;
  const perm = b.getNotificationPermission();
  if (perm === 'granted') return true;
  if (perm === 'denied') {
    showMessage('Notifications are off for this app. Turn them on in Settings.');
    return false;
  }
  // 'default': the app can still ask
  return (await Notification.requestPermission()) === 'granted';
}

Notlar: navigator.permissions.query({ name: 'notifications' }) ile aynΔ± yanΔ±tΔ± verir. KullanΔ±cΔ±ya sormak iΓ§in Εunu kullanΔ±n Notification.requestPermission().

getNotificationState köprü#

window.WebToApk.getNotificationState(): String

'granted' | 'prompt' (Android hΓ’lΓ’ sorabilir) | 'blocked' (kesin olarak reddedildi veya Ayarlar'da kapatΔ±ldΔ± β yalnΔ±zca Ayarlar dΓΌzeltir) | 'unavailable' (Android 13+ ve bu derleme bildirim iznini bildirmiyor). Bkz. NotificationOptIn.

Örnek

Bu uygulamanΔ±n bildirimlerinin Εu anda aΓ§Δ±k olup olmadΔ±ΔΔ±nΔ± okur β deΔilse, uygulamanΔ±n hΓ’lΓ’ sorup soramayacaΔΔ±nΔ± ya da bunlarΔ± yalnΔ±zca Ayarlar'Δ±n geri aΓ§abileceΔini sΓΆyler.

DΓΆner deΔer: eΕzamanlΔ± olarak bir dize: 'granted' (bildirimler telefona ulaΕΔ±r); 'prompt' (Android hΓ’lΓ’ izin penceresini gΓΆsterebilir); 'blocked' (kullanΔ±cΔ± kesin olarak reddetti veya sistem Ayarlar'Δ±nda bu uygulamanΔ±n bildirimlerini kapattΔ± β yalnΔ±zca Ayarlar dΓΌzeltebilir); ya da 'unavailable' (Android 13+ ve uygulama Bildirimler / HatΔ±rlatΔ±cΔ±lar / Push olmadan derlendi, bu yΓΌzden hiΓ§bir Εey bunlarΔ± aΓ§amaz). Gerekenler: Γ§aΔΔ±rmak iΓ§in hiΓ§bir Εey.

Ham Γ§aΔrΔ±, bir "Bildirimleri aΓ§Δ±n" bandΔ± gΓΆsterip gΓΆstermeyeceΔinize karar vermek iΓ§in:

function refreshNotifBanner() {
  if (!(window.WebToApk && WebToApk.getNotificationState)) return;
  var state = WebToApk.getNotificationState();   // 'granted' | 'prompt' | 'blocked' | 'unavailable'
  var banner = document.getElementById('notif-banner');
  banner.hidden = !(state === 'prompt' || state === 'blocked');
  banner.querySelector('.hint').textContent = state === 'blocked'
    ? 'Notifications are off. Tap to open Settings and switch them on.'
    : 'Get order updates. Tap to turn on notifications.';
}
document.addEventListener('visibilitychange', function () {
  if (!document.hidden) refreshNotifBanner();
});
refreshNotifBanner();

Notlar: getNotificationPermission() eski sayfalar iΓ§in kendi sΓΆzcΓΌklerini ('granted' / 'default' / 'denied') korur. KullanΔ±cΔ±yΔ± geri getirmek iΓ§in AppMint.enableNotifications() Γ§aΔΔ±rΔ±n (sizin iΓ§in pencereyi veya Ayarlar'Δ± seΓ§er).

getScheduledNotifications köprü#

window.WebToApk.getScheduledNotifications(): String

POST_NOTIFICATIONS iznini okuma ve isteme, ve sayfanΔ±n zaten zamanladΔ±ΔΔ± bildirimleri yΓΆnetme. GΓΆnderme ve zamanlama kendi yΓΆntemlerinde belgelenmiΕtir.

Kendi baΕΔ±na deΔil, grubu Bildirim izni, iptal ve listeleme ΓΌzerinden aΓ§Δ±klanΔ±r.

Örnek

HΓ’lΓ’ zamanlanmΔ±Ε olan hatΔ±rlatΔ±cΔ±larΔ± listeler.

DΓΆner deΔer: eΕzamanlΔ± olarak bir JSON dizesi. AyrΔ±ΕtΔ±rΔ±n. Her ΓΆΔe: { id, title, body, trigger, repeat, options? } - trigger sonraki tetiklenme zamanΔ±dΔ±r (epoch ms), repeat none|minutely|hourly|daily|weekly deΔeridir ve options (yalnΔ±zca scheduleNotificationEx iΓ§in) JSON dizesi olarak seΓ§eneklerdir. CanlΔ± alanlar, nasΔ±l teslim edileceΔini canlΔ± okunarak sΓΆyler: precision ("exact"; "inexact" = "Alarmlar ve hatΔ±rlatΔ±cΔ±lar" uygulama iΓ§in kapalΔ±, bu yΓΌzden Android telefon uyanΔ±kken 10 dakikalΔ±k bir pencerede teslim eder ve uykudayken daha uzun tutabilir; alarm: true iΓ§in "alarm_clock"), windowMs + latestAt (Android'e verilen pencere: kesin olduΔunda 0 / trigger, kesin olmadΔ±ΔΔ±nda 600000 / trigger + 600000) ve notificationsEnabled (false = tetiklenir ama uygulamanΔ±n bildirimleri kapalΔ± olduΔu iΓ§in Android hiΓ§bir Εey gΓΆstermez). Hi Γ§biri yoksa '[]'. Gerekenler: ek olarak hiΓ§bir Εey.

function renderReminders() {
  if (!(window.WebToApk && window.WebToApk.getScheduledNotifications)) return;
  let list = [];
  try { list = JSON.parse(WebToApk.getScheduledNotifications() || '[]'); } catch (e) { list = []; }

  const ul = document.getElementById('reminders');
  ul.innerHTML = '';
  list.sort(function (a, b) { return a.trigger - b.trigger; }).forEach(function (r) {
    const li = document.createElement('li');
    li.textContent = r.title + ' — ' + new Date(r.trigger).toLocaleString() +
      (r.repeat !== 'none' ? ' (' + r.repeat + ')' : '');
    ul.appendChild(li);
  });
}

Bir hatΔ±rlatΔ±cΔ±nΔ±n aΓ§Δ±k olup olmadΔ±ΔΔ±nΔ± ve bir sonraki ne zaman Γ§alacaΔΔ±nΔ± gΓΆsterin:

function describeReminder(id) {
  if (!(window.WebToApk && window.WebToApk.getScheduledNotifications)) return 'Not available';
  let list = [];
  try { list = JSON.parse(WebToApk.getScheduledNotifications() || '[]'); } catch (e) { list = []; }
  const r = list.find(function (x) { return x.id === id; });
  return r ? 'Next: ' + new Date(r.trigger).toLocaleString() : 'Off';
}
document.getElementById('water-status').textContent = describeReminder('water');

Εununla oluΕturulan hatΔ±rlatΔ±cΔ±larΔ±n ek seΓ§eneklerini okuyun scheduleNotificationEx:

function listAlarmStyleReminders() {
  if (!(window.WebToApk && window.WebToApk.getScheduledNotifications)) return [];
  let list = [];
  try { list = JSON.parse(WebToApk.getScheduledNotifications() || '[]'); } catch (e) { list = []; }
  return list.filter(function (r) {
    if (!r.options) return false;                  // made with scheduleNotification
    let o = {};
    try { o = JSON.parse(r.options); } catch (e) { return false; }
    return o.openApp === true;                     // puts the app on screen when it fires
  }).map(function (r) { return r.id; });
}

Notlar: tek seferlik bir hatΔ±rlatΔ±cΔ± tetiklendiΔinde listeden Γ§Δ±kar. TekrarlayanΔ± kalΔ±r ve trigger sonraki zamana ilerler. Telefon kapalΔ±yken veya uygulama zorla durdurulmuΕken zamanΔ± geΓ§en bir hatΔ±rlatΔ±cΔ±, uygulama veya telefon bir sonraki baΕladΔ±ΔΔ±nda bir kez, geΓ§ olarak gΓΆsterilir; geΓ§ kalan bir alarm: true Γ§almak yerine missed olarak bildirilir. GΓΌnlΓΌk, haftalΔ±k, aylΔ±k veya yΔ±llΔ±k bir hatΔ±rlatΔ±cΔ±, telefon saat dilimini deΔiΕtirdiΔinde yerel saatini korur.

HatΔ±rlatΔ±cΔ±lar zamanΔ±nda gelmeyecekse uyarΔ±n:

function reminderHealth() {
  if (!(window.WebToApk && window.WebToApk.getScheduledNotifications)) return '';
  let list = [];
  try { list = JSON.parse(WebToApk.getScheduledNotifications() || '[]'); } catch (e) { list = []; }
  if (!list.length) return '';
  if (list.some(function (r) { return r.notificationsEnabled === false; })) return 'Notifications are off for this app: reminders will not appear.';
  if (list.some(function (r) { return r.precision === 'inexact'; })) return 'Reminders may arrive late. Turn on Alarms & reminders.';
  return '';
}

isAlarmRinging köprü#

window.WebToApk.isAlarmRinging(): Boolean

Bir alarm saati Γ§alΔ±yorsa true.

Örnek

UygulamanΔ±n alarm saatlerinden birinin Εu anda Γ§alΔ±p Γ§almadΔ±ΔΔ±nΔ± sΓΆyler, bΓΆylece sayfa kendi durdur / ertele ekranΔ±nΔ± gΓΆsterebilir.

DΓΆner deΔer: bir alarm Γ§alarken true, aksi halde false (eΕzamanlΔ± olarak). Gerekenler: derleme yaparken EriΕim adΔ±mΔ±nda (AdΔ±m 4) π Alarm saati.

function showRingScreenIfNeeded() {
  const b = window.WebToApk;
  const ringing = !!(b && b.isAlarmRinging && b.isAlarmRinging());
  document.getElementById('ring-screen').hidden = !ringing;
}
showRingScreenIfNeeded();
document.addEventListener('visibilitychange', showRingScreenIfNeeded);

Γalan alarmΔ± kendi ekranΔ±nΔ±zdan durdurun eΕleΕen Γ§aΔrΔ±larla.

document.getElementById('stop').addEventListener('click', function () {
  const b = window.WebToApk;
  if (b && b.isAlarmRinging && b.isAlarmRinging()) b.stopAlarm('');   // '' = whichever is ringing
});
document.getElementById('snooze').addEventListener('click', function () {
  const b = window.WebToApk;
  if (b && b.snoozeAlarm && !b.snoozeAlarm('', 10)) showMessage('Nothing is ringing');
});

UygulamanΔ±n Γ§alan bir alarm tarafΔ±ndan aΓ§Δ±lmasΔ±na tepki verin.

window.addEventListener('appmint:reminder', function (e) {
  if (e.detail.action === 'open' && e.detail.ringing) {
    document.getElementById('ring-screen').hidden = false;
  }
});

Notlar: Γ§alan alarm uygulamayΔ± aΓ§tΔ±ΔΔ±nda appmint:reminder de ΕunlarΔ± taΕΔ±yarak gelir { action: 'open', ringing: true }.

notify köprü#

window.WebToApk.notify(optionsJson: String): Boolean

Zengin bildirim. Tam seΓ§enek listesi iΓ§in NotificationBridge.show'a bakΔ±n: channel (urgent|default|quiet|ongoing), image, largeIcon, bigText, ongoing, actions, progress, sound, silent, group, color. Resim alma ve Γ§ΓΆzme ana iΕ parΓ§acΔ±ΔΔ± dΔ±ΕΔ±nda yapΔ±lΔ±r, bu yΓΌzden uzak bir resim sayfayΔ± asla engelleyemez.

Örnek

Εimdi bir bildirim gΓΆnderir; resim, bΓΌyΓΌk metin, dΓΌΔmeler, ilerleme Γ§ubuΔu, yapΔ±ΕkΔ±n (ongoing), kanal, ses, renk ve etiket seΓ§eneklerinin herhangi bir karΔ±ΕΔ±mΔ±yla.

DΓΆner deΔer: seΓ§enekler geΓ§erli JSON ise ve bildirim sisteme teslim edildiyse true (arka plan iΕ parΓ§acΔ±ΔΔ±nda oluΕturulur, bu yΓΌzden bozuk bir resim URL'si sayfayΔ± engellemez); geΓ§ersiz JSON iΓ§in false. Gerekenler: derleme yaparken EriΕim adΔ±mΔ±nda (AdΔ±m 4) Bildirimler aΓ§Δ±n ve Android 13+ ΓΌzerinde kullanΔ±cΔ±nΔ±n izni (Εununla isteyin Notification.requestPermission()).

Basit bildirim. tag bir kimliktir: aynΔ± etiketle yeniden gΓΆndermek eskisinin yerini alΔ±r.

async function notifyOrderReady() {
  if (!(window.WebToApk && window.WebToApk.notify)) return;
  if (window.Notification && Notification.permission !== 'granted') {
    const p = await Notification.requestPermission();
    if (p !== 'granted') { showMessage('Notifications are off for this app.'); return; }
  }
  WebToApk.notify(JSON.stringify({
    title: 'Order ready',
    body: 'Your order is ready to collect',
    channel: 'default',            // urgent | default | quiet | ongoing
    tag: 'order-42'
  }));
}

Resim, bΓΌyΓΌk simge ve uzun metin. Ikisi de verildiΔinde image, bigText deΔerini geΓ§er.

WebToApk.notify(JSON.stringify({
  title: 'New photo',
  body: 'Tap to see it',
  image: 'https://example.com/photo.jpg',     // expanded big picture
  largeIcon: 'https://example.com/avatar.png', // round icon on the right
  color: '#00C6FF',
  tag: 'photo-7'
}));

WebToApk.notify(JSON.stringify({
  title: 'Weekly summary',
  body: '3 tasks done, 2 left',
  bigText: 'Done: pay rent, call bank, water plants. Left: tax form, dentist.',
  channel: 'quiet',                            // no sound, low priority
  group: 'summaries'
}));

DΓΌΔmeler (en fazla 3). DokunuΕ appmint:notification-action olayΔ± olarak geri gelir.

WebToApk.notify(JSON.stringify({
  title: 'Ali sent you a message',
  body: 'Are we still on for 6pm?',
  channel: 'urgent',                           // heads-up banner
  tag: 'chat-ali',
  actions: [
    { id: 'open', label: 'Open chat' },
    { id: 'done', label: 'Mark read' }
  ]
}));

window.addEventListener('appmint:notification-action', function (e) {
  // e.detail = { actionId: 'done', tag: 'chat-ali' }
  if (e.detail.actionId === 'open') openChat(e.detail.tag);
  if (e.detail.actionId === 'done') markRead(e.detail.tag);
});

YapΔ±ΕkΔ±n ilerleme (ongoing). GΓΌncellemek iΓ§in aynΔ± etiketle yeniden gΓΆnderin. Δ°Ε bittiΔinde, kullanΔ±cΔ± kaydΔ±rarak kaldΔ±rabilsin diye son durumu ongoing: false ile gΓΆnderin.

function showUpload(percent) {
  WebToApk.notify(JSON.stringify({
    title: 'Uploading', body: percent + '%',
    ongoing: true,                             // cannot be swiped away
    progress: { current: percent, max: 100 },  // or { indeterminate: true }
    silent: true,
    tag: 'upload'
  }));
}
showUpload(40);
// finished:
WebToApk.notify(JSON.stringify({ title: 'Upload complete', body: '3 photos saved', tag: 'upload' }));

DiΔer seΓ§enekler: sound (paketinizdeki '/audio/ding.mp3' gibi bir dosya, bir data:audio/... URL'si veya 'silent'), smallIcon (bir drawable adΔ±), when (zaman olarak gΓΆsterilen epoch ms), openApp: true (tam ekran uyarΔ±; bkz. scheduleNotificationEx).

Notlar: dΓΌΔmelerin satΔ±r iΓ§i yanΔ±t kutusu yoktur ve bir dΓΌΔme dokunuΕu sayfaya yalnΔ±zca uygulama Γ§alΔ±ΕΔ±rken ulaΕΔ±r (uygulamayΔ± aΓ§maz); tanΔ±mladΔ±ysanΔ±z olay ayrΔ±ca window.onAppMintNotificationAction(detail) iΕlevini Γ§aΔΔ±rΔ±r. image ve largeIcon, bir https:// veya data: URL'si ya da uygulamanΔ±zla paketlenmiΕ, sayfanΔ±zΔ±n adlandΔ±rdΔ±ΔΔ± gibi adlandΔ±rΔ±lmΔ±Ε bir resim ('img/logo.png', '/img/logo.png' veya tam https://appassets.androidplatform.net/assets/… adresi) alΔ±r. Bozuk bir resim atlanΔ±r, bildirim yine de gΓΆrΓΌnΓΌr. ongoing: true her zaman sessiz "Ongoing" kanalΔ±nΔ± kullanΔ±r. notify()'in herkese aΓ§Δ±k bir "kaldΔ±r" eΕi yoktur: cancelNotification yalnΔ±zca zamanlanmΔ±Ε hatΔ±rlatΔ±cΔ±larΔ± iptal eder. Daha sonra sayfadan kaldΔ±rmak istediΔiniz bir bildirim new Notification(...) ile gΓΆnderilmeli ve close() ile kaldΔ±rΔ±lmalΔ±dΔ±r; yapΔ±ΕkΔ±n bir ilerleme kartΔ± ise Capacitor.AppwrightLiveProgress ile (end). Android bir kanalΔ±n sesini kanal oluΕturulurken sabitler, bu yΓΌzden yeni bir sound deΔeri yeni bir kanal oluΕturur.

openNotificationSettings köprü#

window.WebToApk.openNotificationSettings(): Boolean

Bu uygulamanΔ±n bildirim ayarlarΔ±nΔ± aΓ§ar; ekran aΓ§Δ±labildiyse true.

Örnek

Bu uygulamanΔ±n kendi bildirim ayarlarΔ± ekranΔ±nΔ± aΓ§ar; kullanΔ±cΔ± buradan bildirimleri (ve her kanalΔ±) aΓ§Δ±p kapatabilir.

DΓΆner deΔer: ekran eΕzamanlΔ± olarak aΓ§Δ±ldΔ±ysa true; aΓ§Δ±lamadΔ±ysa false (Android 13+ ve derlemede bildirim yok). Android 8+ ΓΌzerinde uygulamanΔ±n bildirim sayfasΔ±dΔ±r; daha eski Android'de Uygulama bilgisi ekranΔ±. Gerekenler: aΓ§Δ±lacak bir Εey yok.

document.getElementById('notif-settings-link').onclick = function () {
  if (!(window.WebToApk && WebToApk.openNotificationSettings && WebToApk.openNotificationSettings())) {
    showMessage('Open Settings > Apps > this app > Notifications.');
  }
};

Notlar: kullanΔ±cΔ±yΔ± tek dokunuΕta geri getirmek iΓ§in bunun yerine AppMint.enableNotifications() kullanΔ±n: Android hΓ’lΓ’ izin veriyorsa izin penceresini gΓΆsterir, vermiyorsa yalnΔ±zca bu ekranΔ± aΓ§ar.

prepareNotificationSound köprü#

window.WebToApk.prepareNotificationSound(spec: String): Boolean

Pakete dahil bir ses dosyasΔ±nΔ± ΓΆnceden yerine kopyalar ve bildirim sesi olarak kullanΔ±labilir olup olmadΔ±ΔΔ±nΔ± bildirir. Δ°steΔe baΔlΔ± β `notify()` ve `scheduleNotificationEx()` bunu kendileri yapar β ama bir ayarlar ekranΔ±nΔ±n kullanΔ±cΔ± bir ses seΓ§er seΓ§mez onu doΔrulamasΔ±na izin verir.

Örnek

UygulamanΔ±zdaki bir ses dosyasΔ±nΔ±n bildirim sesi olarak kullanΔ±labileceΔini denetler ve Εimdi yerine kopyalar. Δ°steΔe baΔlΔ±: notify() ve scheduleNotificationEx() bunu kendileri yapar; bu, bir ayarlar ekranΔ±nΔ±n kullanΔ±cΔ± bir ses seΓ§er seΓ§mez onu denetlemesine izin verir.

DΓΆner deΔer: ses kullanΔ±labilirse true; dosya yoksa veya desteklenen bir ses tΓΌrΓΌ deΔilse false. Gerekenler: hiΓ§bir Εey.

function chooseAlarmSound(path) {             // e.g. '/audio/chime.mp3'
  if (!(window.WebToApk && window.WebToApk.prepareNotificationSound)) return;
  if (!WebToApk.prepareNotificationSound(path)) {
    showMessage('This sound file is missing from the app: ' + path);
    return;
  }
  localStorage.setItem('alarmSound', path);
  // Use it:
  WebToApk.notify(JSON.stringify({ title: 'Sound test', body: 'This is your alarm sound', sound: path, tag: 'sound-test' }));
}

Bir ses seΓ§iciyi yalnΔ±zca gerΓ§ekten kullanΔ±labilir seslerle doldurun:

const SOUNDS = [
  { label: 'Chime', path: '/audio/chime.mp3' },
  { label: 'Bell',  path: '/audio/bell.ogg' },
  { label: 'Beep',  path: '/audio/beep.wav' }
];

function renderSoundPicker(select) {
  const b = window.WebToApk;
  if (!(b && b.prepareNotificationSound)) return;
  select.innerHTML = '';
  SOUNDS.forEach(function (s) {
    if (!b.prepareNotificationSound(s.path)) return;   // missing or unsupported file
    const opt = document.createElement('option');
    opt.value = s.path; opt.textContent = s.label;
    select.appendChild(opt);
  });
}

KullanΔ±cΔ±nΔ±n kendi ses dosyasΔ±nΔ± seΓ§mesine ve bunu gΓΌnlΓΌk bir hatΔ±rlatΔ±cΔ± iΓ§in data: URL'si olarak vermesine izin verin:

document.getElementById('own-sound').addEventListener('change', function (e) {
  const file = e.target.files[0];
  const b = window.WebToApk;
  if (!file || !(b && b.prepareNotificationSound)) return;
  const reader = new FileReader();
  reader.onload = function () {
    const dataUrl = reader.result;                 // 'data:audio/mpeg;base64,...'
    if (!b.prepareNotificationSound(dataUrl)) {
      showMessage('That file cannot be used as a notification sound.');
      return;
    }
    b.scheduleNotificationEx('daily-walk', JSON.stringify({
      at: nextEvening(), repeat: 'daily',
      title: 'Walk time', body: 'Time for your evening walk', sound: dataUrl
    }));
  };
  reader.readAsDataURL(file);
});

Kabul edilen deΔerler: web paketinizdeki bir yol ('/audio/chime.mp3', 'audio/chime.mp3') veya sayfanΔ±zΔ±n oluΕturduΔu bir data:audio/...;base64,... URL'si. TΓΌrler: mp3, wav, ogg, oga, m4a, aac, flac, opus, mid, midi.

Notlar: klasΓΆrsΓΌz ve uzantΔ±sΔ±z yalΔ±n bir ad (bir res/raw sesi) burada denetlenmez ve notify({sound: 'name'}) bunu kullanabilse de false dΓΆndΓΌrΓΌr. Android kanal baΕΔ±na bir ses tutar, bu yΓΌzden sesi deΔiΕtirmek yeni bir kanal oluΕturur ve kullanΔ±cΔ±nΔ±n o kanal iΓ§in ayarlarΔ±nΔ± sΔ±fΔ±rlar.

requestExactAlarms köprü#

window.WebToApk.requestExactAlarms(): Boolean

Tam alarmlarΔ±n verildiΔi sistem ekranΔ±nΔ± aΓ§ar. Android 12+.

Örnek

KullanΔ±cΔ±nΔ±n bu uygulamanΔ±n tam alarmlarΔ± kullanmasΔ±na izin verdiΔi Android 12+ sistem ekranΔ±nΔ± aΓ§ar, bΓΆylece hatΔ±rlatΔ±cΔ±lar tam dakikada Γ§alar.

DΓΆner deΔer: ayarlar ekranΔ± aΓ§Δ±ldΔ±ysa (ve hiΓ§bir Εeyin gerekmediΔi Android 11 ve eskisinde) true; ekran aΓ§Δ±lamadΔ±ysa false. KullanΔ±cΔ±nΔ±n seΓ§imini sΓΆylemez. Gerekenler: derleme yaparken EriΕim adΔ±mΔ±nda (AdΔ±m 4) β° HatΔ±rlatΔ±cΔ±lar aΓ§Δ±n.

document.getElementById('allow-exact').addEventListener('click', function () {
  if (!(window.WebToApk && window.WebToApk.requestExactAlarms)) return;
  if (WebToApk.getAlarmPrecision() === 'exact') return;   // already fine
  WebToApk.requestExactAlarms();
});

// The user comes back from Settings: read the real answer.
document.addEventListener('visibilitychange', function () {
  if (document.hidden || !window.WebToApk) return;
  const exact = WebToApk.getAlarmPrecision() === 'exact';
  document.getElementById('allow-exact').hidden = exact;
});

Zaman aΓ§Δ±sΔ±ndan kritik bir hatΔ±rlatΔ±cΔ±yΔ± kaydetmeden ΓΆnce, ayarlar ekranΔ±nΔ± yalnΔ±zca zamanlama gerΓ§ekten kapalΔ±ysa sunun:

function saveMedicineReminder(at) {
  const b = window.WebToApk;
  if (!(b && b.scheduleNotificationEx && b.getAlarmPrecision)) return;
  b.scheduleNotificationEx('medicine', JSON.stringify({
    at: at, repeat: 'daily', title: 'Medicine', body: 'Time for your tablet'
  }));
  const precision = b.getAlarmPrecision();   // 'exact' | 'inexact' | 'unavailable'
  if (precision === 'inexact') {
    showBanner('Reminders may arrive a few minutes late.', 'Fix timing', function () {
      b.requestExactAlarms();                // runs from the banner button tap
    });
  } else if (precision === 'unavailable') {
    showBanner('The phone\'s alarm service is not answering; this reminder may not fire.');
  }
}

Ayarlar ekranΔ± aΓ§Δ±lamadΔ±ΔΔ±nda (false), kullanΔ±cΔ±ya anahtarΔ± nerede bulacaΔΔ±nΔ± sΓΆyleyin:

document.getElementById('fix-timing').addEventListener('click', function () {
  const b = window.WebToApk;
  if (!(b && b.requestExactAlarms)) return;
  const opened = b.requestExactAlarms();
  if (!opened) {
    showMessage('Open Settings > Apps > this app > "Alarms & reminders" and turn it on.');
  }
  // When it did open, read the answer on return with getAlarmPrecision().
});

Notlar: bir dΓΌΔme dokunuΕundan Γ§aΔΔ±rΔ±n ve ΓΆnce nedenini aΓ§Δ±klayΔ±n β uygulamanΔ±zdan Γ§Δ±kar. Zaten zamanlanmΔ±Ε hatΔ±rlatΔ±cΔ±lar her iki durumda da Γ§alΔ±Εmaya devam eder; yalnΔ±zca zamanlamalarΔ± deΔiΕir.

requestNotificationPermission köprü#

window.WebToApk.requestNotificationPermission(): String

POST_NOTIFICATIONS iznini okuma ve isteme, ve sayfanΔ±n zaten zamanladΔ±ΔΔ± bildirimleri yΓΆnetme. GΓΆnderme ve zamanlama kendi yΓΆntemlerinde belgelenmiΕtir.

Kendi baΕΔ±na deΔil, grubu Bildirim izni, iptal ve listeleme ΓΌzerinden aΓ§Δ±klanΔ±r.

Örnek

Android 13+ "Bildirimlere izin verilsin mi?" penceresini gΓΆsterir. Sayfalar normalde bunu Γ§aΔΔ±ran ve kullanΔ±cΔ±nΔ±n yanΔ±tΔ±nΔ± bekleyen Notification.requestPermission() kullanΔ±r.

DΓΆner deΔer: eΕzamanlΔ± olarak bir dize: zaten izin verilmiΕse (veya Android 12 ve eskisinde) 'granted', aksi halde pencere aΓ§Δ±lΔ±rken 'default'. KullanΔ±cΔ±nΔ±n yanΔ±tΔ±nΔ± dΓΆndΓΌremez. Gerekenler: derleme yaparken EriΕim adΔ±mΔ±nda (AdΔ±m 4) Bildirimler aΓ§Δ±n.

Promise API'sini kullanΔ±n - gerΓ§ek yanΔ±tla Γ§ΓΆzΓΌlΓΌr ('granted' veya 'denied'):

document.getElementById('enable-alerts').addEventListener('click', async function () {
  if (!('Notification' in window)) return;
  const perm = await Notification.requestPermission();
  if (perm === 'granted') {
    showMessage('Alerts are on');
  } else {
    showMessage('Alerts are off. You can turn them on in Settings.');
  }
});

Ham Γ§aΔrΔ±, yalnΔ±zca beklemeden pencereyi aΓ§mak iΓ§in:

if (window.WebToApk && window.WebToApk.requestNotificationPermission) {
  const now = WebToApk.requestNotificationPermission();  // 'granted' or 'default'
  if (now === 'granted') enableAlertFeatures();
  // otherwise re-check later with WebToApk.getNotificationPermission()
  // ('granted' | 'denied' | 'default')
}

Notification.requestPermission iΕlevine geri Γ§aΔrΔ± geΓ§iren eski kod aynΔ± nihai yanΔ±tΔ± alΔ±r:

document.getElementById('turn-on-reminders').addEventListener('click', function () {
  if (!('Notification' in window)) return;
  if (Notification.permission !== 'default') { updateReminderUi(Notification.permission); return; }
  Notification.requestPermission(function (perm) {
    updateReminderUi(perm);   // 'granted' or 'denied', once the user answers
  });
});

Notlar: net bir gerekΓ§eyle bir dΓΌΔme dokunuΕundan isteyin. KullanΔ±cΔ± iki kez reddettikten sonra Android pencereyi gΓΆstermeyi bΔ±rakΔ±r ve yanΔ±t hemen 'denied' olur; kullanΔ±cΔ± bunu uygulamanΔ±n Ayarlar'Δ±ndan vermelidir.

requestOpenAppPermission köprü#

window.WebToApk.requestOpenAppPermission(): Boolean

Tam ekran uyarΔ±nΔ±n verildiΔi sistem ekranΔ±nΔ± aΓ§ar. Android 14+.

Örnek

KullanΔ±cΔ±nΔ±n bu uygulama iΓ§in tam ekran uyarΔ±lara izin verdiΔi Android 14+ sistem ekranΔ±nΔ± aΓ§ar, bΓΆylece bir openApp: true hatΔ±rlatΔ±cΔ±sΔ± uygulamayΔ± ekrana getirebilir.

DΓΆner deΔer: ayarlar ekranΔ± aΓ§Δ±ldΔ±ysa (ve hiΓ§bir Εeyin gerekmediΔi Android 14'ΓΌn altΔ±nda) true; aΓ§Δ±lamadΔ±ysa false. KullanΔ±cΔ±nΔ±n seΓ§imini sΓΆylemez. Gerekenler: derleme yaparken EriΕim adΔ±mΔ±nda (AdΔ±m 4) β° HatΔ±rlatΔ±cΔ±lar aΓ§Δ±n.

document.getElementById('allow-open-app').addEventListener('click', function () {
  const b = window.WebToApk;
  if (!(b && b.requestOpenAppPermission)) return;
  if (b.canOpenAppAtTime() === 'granted') return;
  b.requestOpenAppPermission();
});

// Read the real answer when the user comes back:
document.addEventListener('visibilitychange', function () {
  if (document.hidden || !window.WebToApk) return;
  const ok = WebToApk.canOpenAppAtTime() === 'granted';
  document.getElementById('allow-open-app').hidden = ok;
});

KullanΔ±cΔ±nΔ±n kurmakta olduΔu alarmΔ± hatΔ±rlayΔ±n, onu Ayarlar'a gΓΆnderin ve geri dΓΆndΓΌΔΓΌnde tamamlayΔ±n:

let pendingAlarm = null;

function setWakeAlarm(at) {
  const b = window.WebToApk;
  if (!(b && b.requestOpenAppPermission)) return;
  if (b.canOpenAppAtTime() === 'denied') {
    pendingAlarm = at;
    b.requestOpenAppPermission();
    return;
  }
  b.scheduleNotificationEx('wake', JSON.stringify({ at: at, title: 'Alarm', body: 'Wake up', openApp: true }));
}

document.addEventListener('visibilitychange', function () {
  if (document.hidden || pendingAlarm === null || !window.WebToApk) return;
  if (WebToApk.canOpenAppAtTime() === 'granted') setWakeAlarm(pendingAlarm);
  else showMessage('Without that setting the alarm cannot open the app by itself.');
  pendingAlarm = null;
});

Ayarlar ekranΔ± aΓ§Δ±lamadΔ±ΔΔ±nda (false), anahtarΔ±n nerede olduΔunu sΓΆyleyin:

document.getElementById('allow-fullscreen').addEventListener('click', function () {
  const b = window.WebToApk;
  if (!(b && b.requestOpenAppPermission)) return;
  if (!b.requestOpenAppPermission()) {
    showMessage('Open Settings > Apps > this app > Notifications and allow full-screen notifications.');
  }
});

Notlar: nedenini aΓ§Δ±kladΔ±ktan sonra bir dΓΌΔme dokunuΕundan Γ§aΔΔ±rΔ±n β uygulamanΔ±zdan Γ§Δ±kar.

scheduleNotification köprü#

window.WebToApk.scheduleNotification(id: String, title: String, body: String, triggerAtMillis: String, repeat: String): Boolean

POST_NOTIFICATIONS iznini okuma ve isteme, ve sayfanΔ±n zaten zamanladΔ±ΔΔ± bildirimleri yΓΆnetme. GΓΆnderme ve zamanlama kendi yΓΆntemlerinde belgelenmiΕtir.

Kendi baΕΔ±na deΔil, grubu Bildirim izni, iptal ve listeleme ΓΌzerinden aΓ§Δ±klanΔ±r.

Örnek

Gelecekteki bir zaman iΓ§in basit bir hatΔ±rlatΔ±cΔ± (baΕlΔ±k ve metin) zamanlar. Uygulama kapalΔ±yken de Γ§alar ve telefon yeniden baΕlatΔ±ldΔ±ktan sonra tekrar kurulur.

DΓΆner deΔer: zamanlandΔ±ysa true; id boΕsa veya zaman sayΔ± deΔilse false. Gerekenler: derleme yaparken EriΕim adΔ±mΔ±nda (AdΔ±m 4) β° HatΔ±rlatΔ±cΔ±lar aΓ§Δ±n (Bildirimler'i de aΓ§ar) ve Android 13+ ΓΌzerinde kullanΔ±cΔ±nΔ±n bildirim izni.

function remindToDrinkWater() {
  if (!(window.WebToApk && window.WebToApk.scheduleNotification)) {
    showMessage('Reminders work in the installed app only.');
    return;
  }
  const ok = WebToApk.scheduleNotification(
    'water',                                  // your own id; same id replaces the old reminder
    'Drink water',                            // title
    'Time for a glass of water',              // body
    String(Date.now() + 60 * 60 * 1000),      // epoch milliseconds, AS A STRING
    'daily'                                   // none | minutely | hourly | daily | weekly
  );
  if (!ok) showMessage('Could not schedule the reminder');
}

Bir hatΔ±rlatΔ±cΔ±nΔ±n uygulamayΔ± ne zaman aΓ§tΔ±ΔΔ±nΔ± bilin (kullanΔ±cΔ± ona dokundu):

window.addEventListener('appmint:reminder', function (e) {
  // e.detail = { id: 'water', overLockScreen: false }
  if (e.detail.id === 'water') openWaterLog();
});

Bir gΓΆrevin son tarihi olan gΓΌn saat 8:00'de tek seferlik bir hatΔ±rlatΔ±cΔ±:

function remindTask(task) {
  if (!(window.WebToApk && window.WebToApk.scheduleNotification)) return false;
  const at = new Date(task.dueDate);
  at.setHours(8, 0, 0, 0);
  if (at.getTime() <= Date.now()) return false;     // that morning has passed
  return WebToApk.scheduleNotification(
    'task-' + task.id,
    'Due today',
    task.title,
    String(at.getTime()),                           // epoch ms as a string
    'none'
  );
}

Notlar: hatΔ±rlatΔ±cΔ± "urgent" (heads-up) stilini kullanΔ±r ve etiketi kimliΔidir. Telefon kapalΔ±yken kaΓ§Δ±rΔ±lan tekrarlayΔ±cΔ± bir hatΔ±rlatΔ±cΔ± bir sonraki adΔ±mda Γ§alar. Resim, dΓΌΔmeler, kendi sesiniz veya kilit ekranΔ± ΓΌzerinde uygulamayΔ± aΓ§mak iΓ§in scheduleNotificationEx kullanΔ±n. Uygulama iΓ§in tam alarmlar kapalΔ±ysa zaman dakikalarca kayabilir; denetleyin getAlarmPrecision().

scheduleNotificationEx köprü#

window.WebToApk.scheduleNotificationEx(id: String, optionsJson: String): Boolean

[scheduleNotification] iΓ§in tam biΓ§im: `notify()` iΓ§inde kabul edilen her Εey, uygulama kapalΔ±yken gelecekteki bir zamanda tetiklenir. WebToApk.scheduleNotificationEx('dose-1', JSON.stringify({ at: Date.now() + 3600000, // epoch millis (takma ad: triggerAt) repeat: 'daily', // none|minutely|hourly|daily|weekly|weekdays|monthly|yearly // days: [1, 3, 5], // 'weekdays' ile: ISO Pzt=1..Paz=7 (varsayΔ±lan Pzt-Cum) // alarm: true, // alarm saati gibi Γ§al (getAlarmSupport()) title: 'Time for your dose', body: 'Vitamin D - 1 tablet', sound: '/audio/chime.mp3', // SΔ°ZΔ°N paketinizdeki bir dosya; sessiz iΓ§in 'silent' openApp: true // uygulamanΔ±n kendisini kilit ekranΔ± ΓΌzerinde aΓ§ })); Paketlenen bir ses bu Γ§aΔrΔ± sΔ±rasΔ±nda yerine kopyalanΔ±r, bΓΆylece yanlΔ±Ε bir dosya adΔ± gΓΌnler sonra varsayΔ±lan sese dΓΆnΓΌΕmek yerine hemen (false) bildirilir.

Örnek

notify() iΓ§indeki tΓΌm seΓ§eneklerle (resim, dΓΌΔmeler, ses, kanal, uygulamayΔ± aΓ§ma) gelecekteki bir zaman iΓ§in hatΔ±rlatΔ±cΔ± zamanlar. Uygulama kapalΔ±yken de Γ§alar ve yeniden baΕlatmadan sonra korunur.

DΓΆner deΔer: zamanlandΔ±ysa true. Zaman verilmediyse (at, triggerAt, triggerAtMillis veya inSeconds), kimlik boΕsa, JSON bozuksa veya sound uygulamanΔ±zda olmayan bir dosyayΔ± adlandΔ±rΔ±yorsa false. Gerekenler: derleme yaparken EriΕim adΔ±mΔ±nda (AdΔ±m 4) β° HatΔ±rlatΔ±cΔ±lar aΓ§Δ±n ve Android 13+ ΓΌzerinde kullanΔ±cΔ±nΔ±n bildirim izni.

Kendi sesinizle uygulamayΔ± aΓ§an gΓΌnlΓΌk bir hatΔ±rlatΔ±cΔ± (kilit ekranΔ± ΓΌzerinde):

function scheduleStandup(tomorrowAt9am) {
  const b = window.WebToApk;
  if (!(b && b.scheduleNotificationEx)) { showMessage('Reminders work in the installed app only.'); return; }

  // Both are user settings: check, and ask if needed.
  if (b.getAlarmPrecision() === 'inexact') b.requestExactAlarms();
  if (b.canOpenAppAtTime() === 'denied') b.requestOpenAppPermission();

  const ok = b.scheduleNotificationEx('standup', JSON.stringify({
    at: tomorrowAt9am,          // epoch ms (or triggerAt, or inSeconds: 3600)
    repeat: 'daily',            // none | minutely | hourly | daily | weekly | weekdays | monthly | yearly
    title: 'Stand-up',
    body: 'Daily sync starts now',
    sound: '/audio/alarm.mp3',  // a file in YOUR app; 'silent' for none
    openApp: true               // full-screen alert that puts the app on screen
  }));
  if (!ok) showMessage('Check the sound file path — nothing was scheduled.');
}

window.addEventListener('appmint:reminder', function (e) {
  // e.detail = { id: 'standup', overLockScreen: true, action: 'open', ringing: false }
  openMeetingScreen(e.detail.id);
});

YalnΔ±zca spor gΓΌnleri β Pazartesi, Γarkamba ve Cuma saat 18:00 (days ISO'dur: Pazartesi = 1 β¦ Pazar = 7; days olmadan 'weekdays' Pazartesi-Cuma demektir):

WebToApk.scheduleNotificationEx('gym', JSON.stringify({
  at: nextAt(18, 0),          // epoch ms of the first time; moved to the next listed day if needed
  repeat: 'weekdays',
  days: [1, 3, 5],
  title: 'Gym time',
  body: 'Leg day'
}));

// Rent on the 31st: 'monthly' rings on the last day of shorter months (28/29/30) and on the 31st again when there is one.
WebToApk.scheduleNotificationEx('rent', JSON.stringify({ at: rentDueAt, repeat: 'monthly', title: 'Rent is due' }));
// A birthday: same date every year (29 February rings on the 28th in other years).
WebToApk.scheduleNotificationEx('bday-ana', JSON.stringify({ at: anaBirthdayAt9am, repeat: 'yearly', title: 'Ana\'s birthday' }));

GerΓ§ek bir alarm saati (alarm: true): telefonun ALARM sesiyle Γ§alar β sessiz moddan ve kullanΔ±cΔ± alarmlara izin verdiΔinde RahatsΔ±z Etmeyin'den de geΓ§er β ve Kapat / Ertele veya ringSeconds olana kadar Γ§almaya devam eder. Durum Γ§ubuΔunda alarm simgesini gΓΆsterir ve kilit ekranΔ±nΔ±n ΓΌzerinde ekrana gelir:

function setWakeAlarm(atMs) {
  const b = window.WebToApk;
  if (!(b && b.getAlarmSupport)) { showMessage('Alarms work in the installed app only.'); return; }
  const support = b.getAlarmSupport();   // 'ready' | 'not_enabled' | 'needs_exact_alarm' | 'needs_notification_permission'
  if (support === 'needs_exact_alarm') { b.requestExactAlarms(); return; }
  if (support !== 'ready') { showMessage('Alarms are not available: ' + support); return; }

  const ok = b.scheduleNotificationEx('wake', JSON.stringify({
    at: atMs,
    repeat: 'weekdays',          // daily/weekly/weekdays/monthly/yearly keep 07:00 across clock changes
    title: 'Wake up',
    body: 'Good morning',
    alarm: true,
    sound: '',                   // '' = the phone's alarm tone; or '/audio/rooster.mp3'; 'silent' = vibrate only
    vibrate: true,               // needs Vibration on in the build
    ringSeconds: 300,            // stop and count as missed after 5 minutes (default 600, max 3600)
    snoozeMinutes: 9,            // 0 hides the Snooze button (default 10)
    snoozeLabel: 'Snooze', dismissLabel: 'Stop'
  }));
  if (!ok) showMessage('The alarm was not set.');
}

window.addEventListener('appmint:reminder', function (e) {
  const d = e.detail;
  // Opened by the ringing alarm:  { id: 'wake', action: 'open', ringing: true, overLockScreen: true }
  // How a ring ended (also delivered later if the app was closed):
  //   { id: 'wake', action: 'dismiss' | 'snooze' | 'missed' | 'error', alarm: true,
  //     source: 'notification' | 'page' | 'timeout' | 'replaced' | 'system',
  //     snoozeMinutes?, snoozedUntil?, error?, soundError? }
  if (d.action === 'open' && d.ringing) showRingScreen(d.id);   // your Stop / Snooze buttons call stopAlarm / snoozeAlarm
  if (d.action === 'missed') logMissedAlarm(d.id);
});

30 dakika iΓ§inde dΓΌΔmeli bir hatΔ±rlatΔ±cΔ±:

WebToApk.scheduleNotificationEx('dose-1', JSON.stringify({
  inSeconds: 30 * 60,
  title: 'Time for your dose',
  body: 'Vitamin D — 1 tablet',
  actions: [{ id: 'taken', label: 'Taken' }, { id: 'snooze', label: 'Snooze' }]
}));

window.addEventListener('appmint:notification-action', function (e) {
  // e.detail = { actionId: 'taken', tag: 'dose-1' }
  if (e.detail.actionId === 'snooze') {
    WebToApk.scheduleNotificationEx(e.detail.tag, JSON.stringify({ inSeconds: 600, title: 'Time for your dose', body: 'Snoozed reminder' }));
  }
});

Bir satΔ±Ε baΕladΔ±ΔΔ±nda normal kanalda, resimli tek seferlik bir hatΔ±rlatΔ±cΔ±:

function remindSale(sale) {                        // sale.startsAt = epoch ms
  if (!(window.WebToApk && window.WebToApk.scheduleNotificationEx)) return false;
  return WebToApk.scheduleNotificationEx('sale-' + sale.id, JSON.stringify({
    at: sale.startsAt,
    title: 'The sale starts now',
    body: sale.name,
    image: 'https://example.com/banners/' + sale.id + '.jpg',   // expanded picture
    channel: 'default'                             // not the heads-up style reminders use by default
  }));
}

Notlar: aynΔ± kimlik eski bir hatΔ±rlatΔ±cΔ±nΔ±n yerini alΔ±r. VarsayΔ±lanlar: etiket = kimlik, kanal = urgent, bigText = gΓΆvde. Bir dΓΌΔme dokunuΕu sayfaya yalnΔ±zca uygulama Γ§alΔ±ΕΔ±rken ulaΕΔ±r. Ses dosyasΔ± zamanlarken kopyalanΔ±r, bΓΆylece yanlΔ±Ε bir yol gΓΌnler sonra deΔil Εimdi hata verir; mp3, wav, ogg, m4a, aac, flac ve opus Γ§alΔ±ΕΔ±r. openApp, bir uygulamanΔ±n belirli bir zamanda kendiliΔinden ekrana gelebilmesinin tek yoludur; Android 14+ ΓΌzerinde kullanΔ±cΔ±nΔ±n buna izin vermesi gerekir (canOpenAppAtTime). 1-7 dΕ±ΕΔ±nda days ile repeat: 'weekdays', false dΓΆndΓΌrΓΌr. alarm: true, EriΕim adΔ±mΔ±nda (AdΔ±m 4) π Alarm saati gerektirir ve getAlarmSupport() 'ready' olmadΔ±kΓ§a false dΓΆndΓΌrΓΌr; aynΔ± anda yalnΔ±zca bir alarm Γ§alar (yenisi ΓΆncekini missed olarak bitirir). Bir alarmΔ±n kendi ses dosyasΔ± Γ§alacaΔΔ± zamana kadar kaybolmuΕsa (bir Uzaktan GΓΌncelleme kaldΔ±rdΔ±ysa), telefonun alarm sesiyle Γ§alar ve olay Εunu taΕΔ±r soundError: true.

showNotification köprü#

window.WebToApk.showNotification(title: String, body: String, icon: String, tag: String): Boolean

ORΔ°JΔ°NAL dΓΆrt baΔΔ±msΔ±z deΔiΕkenli biΓ§im; zaten kullanΔ±mdaki her uygulama ve her rehber kod parΓ§asΔ± Γ§alΔ±Εmaya devam etsin diye adaptΓΆr olarak olduΔu gibi korunur. ArtΔ±k zengin oluΕturucuya iletir β bu da eski uygulamanΔ±n sessizce yok saydΔ±ΔΔ± `icon` baΔΔ±msΔ±z deΔiΕkeninin sonunda bir iΕe yaramasΔ± demektir.

Örnek

Orijinal dΓΆrt baΔΔ±msΔ±z deΔiΕkenli bildirim Γ§aΔrΔ±sΔ±. BaΕlΔ±k, metin, isteΔe baΔlΔ± bir bΓΌyΓΌk simge ve bir etiketle bildirim gΓΆsterir. Yeni kod, daha fazlasΔ±nΔ± yapan notify(optionsJson) veya new Notification(...) kullanmalΔ±dΔ±r.

DΓΆner deΔer: bildirim sisteme teslim edildiyse true. Gerekenler: derleme yaparken EriΕim adΔ±mΔ±nda (AdΔ±m 4) Bildirimler aΓ§Δ±n ve Android 13+ ΓΌzerinde kullanΔ±cΔ±nΔ±n izni.

Standart web API'si (bu yΓΆntemi sizin iΓ§in Γ§aΔΔ±rΔ±r):

async function tellUser() {
  if (!('Notification' in window)) return;
  const p = Notification.permission === 'granted' ? 'granted' : await Notification.requestPermission();
  if (p === 'granted') new Notification('Saved', { body: 'Your note was saved', tag: 'note' });
}

Ham Γ§aΔrΔ±. BaΔΔ±msΔ±z deΔiΕkenler: baΕlΔ±k, gΓΆvde, simge, etiket. Simge veya etiket yoksa '' verin.

if (window.WebToApk && window.WebToApk.showNotification) {
  WebToApk.showNotification(
    'Saved',                                  // title
    'Your note was saved',                    // body
    'https://example.com/avatar.png',         // large icon (https://, data:, or 'img/x.png' in your app), or ''
    'note'                                    // tag: same tag replaces the old notification
  );
}

AynΔ± etiketi yeniden kullanarak bir durum bildirimini yerinde gΓΌncelleyin:

function showSyncStatus(done, total) {
  const b = window.WebToApk;
  if (!(b && b.showNotification)) return;
  if (b.getNotificationPermission() !== 'granted') return;
  b.showNotification(
    'Syncing photos',
    done + ' of ' + total + ' uploaded',
    '',          // no large icon
    'sync'       // same tag every time: the text updates, no new notification
  );
}

Notlar: varsayΔ±lan kanalda notify({title, body, largeIcon: icon, tag}) iΕlevine iletir. Etiket yoksa her Γ§aΔrΔ± yeni bir bildirim ekler. Resim, dΓΌΔme, ilerleme veya yapΔ±ΕkΔ±n bildirim iΓ§in Εunu kullanΔ±n notify.

snoozeAlarm köprü#

window.WebToApk.snoozeAlarm(id: String, minutes: Int): Boolean

Γalan [id] alarmΔ±nΔ± ("" = hangisi Γ§alΔ±yorsa) durdurur ve [minutes] dakika (1-1440; 0 = alarmΔ±n kendi snoozeMinutes deΔeri) sonra yeniden Γ§alar. Γalmiyorsa False.

Örnek

Γalan bir alarm saatini durdurur ve Ertele dΓΌΔmesi gibi birkaΓ§ dakika sonra yeniden Γ§alar. YalnΔ±zca bu Γ§alma kayar: gΓΌnlΓΌk bir alarm yarΔ±n yine her zamanki saatinde Γ§alar.

DΓΆner deΔer: alarm Γ§alΔ±yorsa ve ertelendiyse true; Γ§almΔ±yorsa false. id '' = hangisi Γ§alΔ±yorsa; minutes 1-1440 veya alarmΔ±n kendi snoozeMinutes deΔeri iΓ§in 0 (varsayΔ±lan 10). Gerekenler: derleme yaparken EriΕim adΔ±mΔ±nda (AdΔ±m 4) π Alarm saati.

document.getElementById('snooze').onclick = function () {
  if (!(window.WebToApk && window.WebToApk.snoozeAlarm)) return;
  if (WebToApk.snoozeAlarm('', 5)) showMessage('Ringing again in 5 minutes');
  hideRingScreen();
};

window.addEventListener('appmint:reminder', function (e) {
  // { id: 'wake', action: 'snooze', alarm: true, source: 'page', snoozeMinutes: 5, snoozedUntil: 1767340800000 }
  if (e.detail.action === 'snooze') updateNextAlarmLabel(e.detail.snoozedUntil);
});

Bir alarm saati zamanlayΔ±n, sonra bir kapat dΓΌΔmesi baΔlayΔ±n:

const b = window.WebToApk;
if (b && b.snoozeAlarm && b.getAlarmSupport() === 'ready') {
  b.scheduleNotificationEx('wake', JSON.stringify({
    at: Date.now() + 8 * 3600000, repeat: 'daily', alarm: true,
    title: 'Wake up', body: 'Good morning'
  }));
}
document.getElementById('dismiss').onclick = () => {
  if (WebToApk.isAlarmRinging()) WebToApk.stopAlarm('');
};

AlarmΔ±n kendi sΓΌresi kadar erteleyin ve "hiΓ§bir Εey Γ§almΔ±yor" durumunu ele alΔ±n:

document.getElementById('snooze').onclick = () => {
  if (!(window.WebToApk && WebToApk.snoozeAlarm)) return;
  const ok = WebToApk.snoozeAlarm('', 0);   // 0 = the alarm's own snoozeMinutes (default 10)
  if (!ok) showMessage('No alarm is ringing right now.');
};

Notlar: ertelenen Γ§alma getScheduledNotifications() tarafΔ±ndan <id>#snooze olarak listelenir; cancelNotification(id) onu da kaldΔ±rΔ±r.

stopAlarm köprü#

window.WebToApk.stopAlarm(id: String): Boolean

Γalan [id] alarmΔ±nΔ± ("" = hangisi Γ§alΔ±yorsa) Kapat dΓΌΔmesi gibi durdurur. TekrarlayΔ±cΔ± bir alarm bir sonraki zamanΔ± iΓ§in zamanlanmΔ±Ε kalΔ±r. Γalmiyorsa False.

Örnek

Γalan bir alarm saatini Kapat dΓΌΔmesi gibi durdurur. TekrarlayΔ±cΔ± bir alarm bir sonraki zamanΔ± iΓ§in kurulu kalΔ±r; kaldΔ±rmak iΓ§in cancelNotification(id) kullanΔ±n.

DΓΆner deΔer: o alarm Γ§alΔ±yorsa ve Εimdi durdurulduysa true; Γ§almΔ±yorsa false. Hangi alarm Γ§alΔ±yorsa onu durdurmak iΓ§in '' verin. Gerekenler: derleme yaparken EriΕim adΔ±mΔ±nda (AdΔ±m 4) π Alarm saati.

window.addEventListener('appmint:reminder', function (e) {
  const d = e.detail;                 // { id, action: 'open', ringing: true, overLockScreen }
  if (d.action === 'open' && d.ringing) showRingScreen(d.id);
});

document.getElementById('stop').onclick = function () {
  if (window.WebToApk && window.WebToApk.stopAlarm) WebToApk.stopAlarm(currentAlarmId);
  hideRingScreen();
};

Durdur dΓΌΔmesini yalnΔ±zca kΓΆprΓΌnΓΌn bulunduΔu yerde sunun ve yanΔ±tΔ± okuyun:

const stopBtn = document.getElementById('stop');
if (window.WebToApk && typeof WebToApk.stopAlarm === 'function') {
  stopBtn.onclick = function () {
    const wasRinging = WebToApk.stopAlarm('');      // '' = whichever alarm is ringing
    if (!wasRinging) showMessage('Nothing was ringing.');
  };
} else {
  stopBtn.hidden = true;                             // plain browser: no alarm clock
}

SayfanΔ±n, o yokken baΕlayan bir Γ§alma iΓ§in Γ§alma ekranΔ±nΔ± gΓΆsterebilmesi iΓ§in isAlarmRinging() ile eΕleyin:

document.addEventListener('visibilitychange', function () {
  if (document.hidden || !window.WebToApk) return;
  if (WebToApk.isAlarmRinging && WebToApk.isAlarmRinging()) showRingScreen();
  else hideRingScreen();
});

Notlar: sayfa bu durumda ayrΔ±ca appmint:reminder olayΔ±nΔ± ΕunlarΔ± taΕΔ±yarak alΔ±r { id, action: 'dismiss', alarm: true, source: 'page' }.

Her belge derlemesinde uygulama çalışma zamanından ve örnek dosyalarından oluşturulur. Markdown olarak okuyun · Tüm aileler.

22.10.2026 tarihinde yayınlanan köprüyle karşılaştırılarak kontrol edildi.