Buradan başlayın
Uygulamanız için HTML yazma
Uygulama çalışma zamanının sayfanıza sunduğu şeyler - kişiler, SMS, bildirimler, cihaz bilgisi, biyometri - ve doğru çağırma kuralları
1Kural 1 - her zaman önce kontrol edin#
window.WebToApk yalnızca derlenmiş uygulamanızın içinde bulunur. Tarayıcıda yoktur.
Bu yüzden çağırmadan önce her zaman kontrol edin. Etmezseniz sayfanız uygulamanın içi dışında her yerde bozulur.
Bazı şeyler hiç kontrol gerektirmez: navigator.vibrate(), speechSynthesis ve Notification zaten çalışır - uygulama bunları sizin için bağlar. Normal web kodunu kullanmanız yeterli.
// GOOD — safe everywhere
if (window.WebToApk) {
WebToApk.playClick();
}
// BAD — this breaks your page in a browser
WebToApk.playClick();2Kural 2 - bazı yanıtlar sonra gelir#
Kişileri, SMS'leri veya arama geçmişini okumak zaman alır. Bu yüzden bunlar hemen yanıt vermez. Verselerdi uygulamanız donardı.
Çağrıya bir ad (id) verirsiniz. Yanıt sonra bir olay olarak gelir. O olayı dinlersiniz.
Olay adları: appmint:contacts, appmint:calllog, appmint:sms, appmint:sms-received, appmint:notification-action.
// 1. Listen for the answer
window.addEventListener('appmint:contacts', function (e) {
if (e.detail.error) {
alert('Problem: ' + e.detail.error);
return;
}
console.log(e.detail.contacts);
});
// 2. Ask the question ('my1' is any name you choose)
WebToApk.listContacts('my1', 50, 0);3Kural 3 - iki anahtar AÇIK olmalı#
Bir telefon özelliği İKİ şey ister:
- Uygulamayı oluştururken bunu Adım 4'te (Access) açtınız. Açmadıysanız 'not_enabled' hatası alırsınız ve kullanıcı hiçbir şey görmez.
- Kullanıcı telefonda Evet dedi. Hayır derse 'permission_denied' hatası alırsınız.
Kullanıcının ne olduğunu bilmesi için her iki hatayı da her zaman işleyin.
Daha kolay yol: pickContact() ve composeSms() HİÇBİR izin gerektirmez. Uyduklarında bunları kullanın - aynı işi daha az zahmetle yaparlar.
window.addEventListener('appmint:contacts', function (e) {
if (e.detail.error === 'not_enabled') {
alert('Turn on Contacts when you build the app');
} else if (e.detail.error === 'permission_denied') {
alert('Please allow contacts access');
} else {
showContacts(e.detail.contacts);
}
});4Resimli ve düğmeli bildirimler#
notify() bir seçenek listesi alır. Büyük bir resim, bir simge, düğmeler ve bir ilerleme çubuğu ekleyebilirsiniz.
channel şunlardan biri olabilir: urgent, default, quiet veya ongoing.
Kullanıcının kaydırarak kaldıramayacağı bir bildirim için ongoing:true kullanın. Not: yine de Android ayarlarından kaldırabilirler. Hiçbir uygulama kaldırılması imkânsız bir bildirim yapamaz.
Ad vermek için tag kullanın. Aynı tag ile yeniden göndermek yeni bir bildirim eklemek yerine eskisinin yerini alır.
WebToApk.notify(JSON.stringify({
title: 'Order shipped',
body: 'Arriving Tuesday',
channel: 'urgent',
image: 'https://mysite.com/box.jpg',
actions: [{ id: 'track', label: 'Track' }],
tag: 'order-482'
}));
// Know which button the user pressed
window.addEventListener('appmint:notification-action', function (e) {
if (e.detail.actionId === 'track') showTracking();
});5Telefon bilgisi ve parmak izi#
getDeviceInfo() izin gerektirmez. Android sürümünü, sürüm kimliğini (buildId), telefon modelini, ekran boyutunu, pil düzeyini ve daha fazlasını verir.
Cihaz kimliği hakkında: IMEI veya seri numarası YOKTUR. Android bunu Android 10'dan itibaren tüm uygulamalar için engelledi. Bunun yerine getInstallId() kullanın - bu kuruluma ait, güncellemelerden sonra da aynı kalan sabit bir kimlik.
var info = JSON.parse(WebToApk.getDeviceInfo());
info.android.release; // "14"
info.android.buildId; // "TQ3A.230805.001" <- version ID
info.hardware.model; // "Pixel 7"
info.runtime.batteryLevel; // 82
// Fingerprint
window.__webToApkAuth = window.__webToApkAuth || {};
window.__webToApkAuth['unlock'] = function (json) {
var r = JSON.parse(json);
if (r.ok) showMyApp();
};
WebToApk.authenticateBiometricEx('unlock', JSON.stringify({
title: 'Unlock',
allowDeviceCredential: true
}));6Sayfanızı ekranı dolduracak şekilde yapın#
Fullscreen'i açtığınızda uygulama Android çubuklarını sizin için gizler. Ama içeriğiniz telefonun çentiğinin altında kalmasın diye bu CSS'i ekleyin.
Önemli: Fullscreen ANDROID çubuklarını (saat, pil, geri düğmeleri) gizler. Uygulamanızın üstteki kendi renkli çubuğu 'Show top bar' adlı farklı bir anahtardır. Fullscreen'i açtıktan sonra hâlâ bir çubuk görüyorsanız kapatmanız gereken odur.
Ayrıca: uygulamanızı döndürerek test edin. Yatay modda çentik yana kayar.
body {
padding-top: env(safe-area-inset-top);
padding-bottom: env(safe-area-inset-bottom);
min-height: 100vh; /* old phones */
min-height: 100dvh; /* correct when bars are hidden */
}7İndirmeler seçtiğiniz dosya adını korur#
Normal indirme kodunuz zaten çalışır. Sayfanız bir dosya kaydettiğinde - bir PDF raporu, bir CSV dışa aktarımı, bir yedek - uygulama bunu yakalar ve SİZİN dosya adınız önceden doldurulmuş olarak Android 'Farklı kaydet…' sayfasını açar.
Bu, her olağan yöntemi kapsar: <a download="...">, koddan a.click(), html2pdf / jsPDF, FileSaver.js saveAs() ve bir blob URL'sinde window.open(). Bir File nesnesi kendi adını taşır.
Bir <a> etiketi oluşturmak yerine doğrudan sormayı tercih ederseniz şunu kullanın AppMint.downloadFile().
Bilmeniz gereken bir şey: ad yalnızca sayfanızın JavaScript'inde yaşar - Android onu kendi başına asla görmez. Bu yüzden her seferinde download= ayarlayın (veya bir ad verin), yoksa dosya 'download' olarak kaydedilir.
// The usual way — saves as Site_Report_2026-08.pdf
const blob = await html2pdf().from(el).outputPdf('blob');
const a = document.createElement('a');
a.download = 'Site_Report_2026-08.pdf';
a.href = URL.createObjectURL(blob);
a.click();
// Or ask directly
AppMint.downloadFile(base64String, 'Ledger_Q3.csv', 'text/csv');
AppMint.saveBlob(myBlob, 'Backup.json');8Geri düğmesi SİZİN uygulamanızın beklediğini yapsın#
Uygulamanız ekranları öğeleri göstererek ve gizleyerek değiştiriyorsa (URL değişikliği yok, history.pushState yok), Android'in Geri düğmesi bu ekranları göremez - geçmişi boştur, bu yüzden Geri her yerden uygulamadan çıkar.
Bir geri işleyici kaydedin ve kendiniz karar verin: basışı siz işlediyseniz (bir menüyü kapattınız, bir ekran geri gittiniz) true döndürün, normal davranışın çalışması için false döndürün - sayfa geçmişinde geri, sonra çıkış onayı, sonra çıkış.
Her ekran için history.pushState kullanan uygulamalarda buna gerek yoktur: Geri zaten geçmişlerinde gezinir. Uygulamanın donmasından da endişe etmeyin - işleyiciniz asla takılırsa, kısa bir süre sonra telefonun Geri tuşu yerel olarak çalışmaya devam eder.
AppMint.setBackHandler(() => {
if (isMenuOpen) { closeMenu(); return true; } // consumed
if (screen !== 'home') { goTo('home'); return true; }
return false; // nothing open — normal exit behaviour
});
// Or listen instead: e.preventDefault() consumes the press
window.addEventListener('appmint:back', e => {
if (closeTopmost()) e.preventDefault();
});9İnsanların uygulamanızla paylaştıklarını alın - bağlantılar, fotoğraflar, videolar, dosyalar#
Derleme sihirbazında 'Diğer uygulamalardan paylaşım al'ı açın ve uygulamanızın neleri kabul ettiğini işaretleyin: metin ve bağlantılar, veri dosyaları (JSON, CSV, TXT, XML, Markdown, GPX, TCX, FIT), fotoğraflar, videolar, ses, belgeler (PDF, Word, Excel, PowerPoint). Uygulamanız bu türler için diğer tüm uygulamaların Paylaş menüsünde görünür - metin için bir not uygulaması, videolar için bir oynatıcı.
Bir bağlantı veya metin (YouTube uygulamasından bir YouTube videosu paylaşmak bağlantısını gönderir) WebToApk.getSharedText() ile okunur ve appmint:shared olarak duyurulur. Bir dosya AppMint.getOpenedFile() ile istenir - hazır olduğunuzda isteyin, dosya sizi bekler. Bu React, Vue ve Angular uygulamaları için önemlidir: sayfa yüklendikten SONRA başlamayı bitirirler, bu yüzden yalnızca olayı dinleyen bir uygulama dosyayı kaçırıp sadece ana ekranını gösteriyordu.
f.kind neyin geldiğini söyler: image, video, audio, document veya data. Fotoğraflar, videolar ve ses f.url olarak gelir - doğrudan <video src>, <img src> veya <audio src> içine koyabileceğiniz akışa uygun, aranabilir bir adres; böylece 300 MB'lık bir klibin belleğe sığması gerekmez; baytlara gerçekten ihtiyaç duyduğunuzda f.getFile() File'ı getirir. Veri dosyaları ve belgeler ayrıca f.file ile, metin biçimleri için f.text ve küçük ikili dosyalar için f.base64 ile kısayol olarak gelir. Başlıkla paylaşılan bir fotoğraf başlığı da paylaşılan metin olarak iletir.
// A link or text someone shared
const shared = JSON.parse(WebToApk.getSharedText() || 'null');
if (shared) saveLink(shared.url || shared.text);
window.addEventListener('appmint:shared', e => saveLink(e.detail.url || e.detail.text));
// A photo, video, audio clip, document or data file — ask on startup, however late
const f = await AppMint.getOpenedFile(); // null if opened normally
if (f) {
if (f.kind === 'video') player.src = f.url; // streams, seekable
else if (f.kind === 'image') img.src = f.url;
else if (f.kind === 'document') await upload(await f.getFile()); // a real File
else importActivity(f.text ?? await f.file.text()); // data files
}
// Or listen, if you prefer
window.addEventListener('appmint:fileopen', e => handle(e.detail));10Bluetooth sensörleri - standart Web Bluetooth#
Kalp atış hızı kayışları, pedal ritmi ve hız sensörleri, güç ölçerler, akıllı antrenörler, tartılar - Bluetooth LE konuşan her şey.
navigator.bluetooth kullanın; masaüstünde Chrome için yazacağınız kodun aynısı. AppMint bunu uygulama içinde sağlar; düz bir Android WebView'da yoktur, bu yüzden bu kod başka uygulama oluşturucularda hiçbir şey yapmaz.
Cihaz seçici, tarayıcınınki gibi uygulama tarafından çizilir - sayfanız yalnızca kullanıcının seçtiği cihaza ulaşabilir.
Adım 4'te (Access) Bluetooth iznini açın. Kodunuz navigator.bluetooth'tan söz ediyorsa, ZIP'inizi seçtiğinizde AppMint bunu sizin için açar.
Kullanılamaz: getDevices(), watchAdvertisements() ve requestLEScan() - NotSupportedError ile reddedilir, bu yüzden kullanmadan önce kontrol edin.
const device = await navigator.bluetooth.requestDevice({
filters: [{ services: ['heart_rate'] }]
});
const server = await device.gatt.connect();
const service = await server.getPrimaryService('heart_rate');
const chr = await service.getCharacteristic('heart_rate_measurement');
chr.addEventListener('characteristicvaluechanged', e => {
const v = e.target.value; // a DataView
const bpm = (v.getUint8(0) & 1) ? v.getUint16(1, true) : v.getUint8(1);
document.getElementById('bpm').textContent = bpm;
});
await chr.startNotifications();
device.addEventListener('gattserverdisconnected', () => showReconnect());11Fotoğraf yükleme - Android fotoğraf seçici, izin yok#
Normal bir dosya girişi kullanın. Eklenecek başka bir şey yok.
Uygulamada <input type="file" accept="image/*"> Android fotoğraf seçicisini açar: kullanıcının fotoğrafları bir ızgarada görünür ve sayfanız yalnızca seçtiklerini alır. Depolama izni yok, 'Fotoğraflara erişime izin verilsin mi?' penceresi yok. Eski telefonlarda da çalışır - orada Google Play services seçiciyi kurar.
- accept="image/*" - yalnızca fotoğraflar
- accept="video/*" - yalnızca videolar
- accept="image/*,video/*" - ikisi de
- multiple ekleyin - kullanıcı birden fazla seçebilir
- capture="environment" ekleyin - bunun yerine kamerayı açar (Adım 4'te (Access) Kamera işaretli olmalı)
Başka dosyalar da ekleyin (accept="image/*,.pdf"); bu durumda normal dosya seçici açılır, böylece PDF de seçilebilir.
<input type="file" id="photos" accept="image/*" multiple>
<script>
document.getElementById('photos').onchange = function (e) {
for (const file of e.target.files) {
const img = document.createElement('img');
img.src = URL.createObjectURL(file);
document.body.appendChild(img);
}
};
</script>12QR kod veya barkod tarayın - tek satır#
AppMint.scanCode() Google'ın tarayıcı ekranını açar. Kullanıcı kamerayı kodun üzerine tutar ve kodu geri alırsınız.
Kamera izni yok. Video öğesi yok. Çizilecek bir şey yok. Tarayıcı küçük kodlar için kendiliğinden yakınlaştırır. Bir telefonda ilk seferde Google Play services tarayıcıyı indirir (birkaç saniye).
Yanıt value (koddaki metin) ve format (qr_code, ean_13, …) içerir. Yaygın QR kodları için parçalar da hazır gelir: url, wifi (ssid, password), phone, email, sms, geo, contact.
ok false ise code nedenini söyler: cancelled (kullanıcı kapattı), unavailable (Google Play services yok veya indirme başarısız), busy (zaten bir tarama açık).
AppMint.scanCode yalnızca uygulamanın içinde bulunur - önce varlığını kontrol edin.
async function scan() {
if (!window.AppMint || !AppMint.scanCode) return; // in a browser
const r = await AppMint.scanCode({ formats: ['qr_code'] });
if (!r.ok) return; // closed, or no scanner
console.log(r.value); // the text inside the code
if (r.url) location.href = r.url.url;
}
// Any code type: AppMint.scanCode()
// Let the user type it when it will not scan: AppMint.scanCode({ manualInput: true })13Passkey'ler - parmak izi veya yüzle giriş, parola yok#
Web sitenizde zaten passkey'ler varsa artık uygulamanızın içinde de çalışırlar. Normal bir Android WebView passkey yapamaz; AppMint navigator.credentials'ı Android'in passkey yöneticisine bağlar, böylece SimpleWebAuthn, Hanko, Corbado veya Auth0 gibi kütüphaneler değişmeden çalışır.
Passkey seçeneklerini üreten ve yanıtı kontrol eden bir sunucuya ihtiyacınız var (örneğin arka ucunuzda SimpleWebAuthn). Bir passkey sayfanın içinde doğrulanamaz.
Bir kez kurmanız gereken iki şey:
- Web siteniz uygulamaya güvendiğini söylemelidir.
AppMint.passkey.assetLinks() dosyasını https://YOUR-DOMAIN/.well-known/assetlinks.json adresine koyun. Dosyayı Google Play'DEN yüklenen uygulamadan alın - Play uygulamanızı kendi anahtarıyla imzalar, bu yüzden bir test APK'sından alınan dosya Play kullanıcılarıyla eşleşmez. Alan adı tam olarak sunucunuzun rpID'si olmalıdır (www ve www'suz farklıdır).
- Sunucunuz uygulamanın kaynağını kabul etmelidir. Uygulamadan gelen yanıt https://… yerine origin 'android:apk-key-hash:…' der - bu değeri
AppMint.passkey.origin() ile alın ve sunucunuzun izinli kaynaklarına ekleyin.
Hatalar: NotAllowedError = kullanıcı iptal etti veya bu telefonda passkey yok. InvalidStateError = bu passkey zaten var. SecurityError = assetlinks.json uygulamayı listelemiyor.
Passkey'ler Google Play services olan Android 9 veya üstünü gerektirir - AppMint.passkey.isAvailable() size söyler. Bir metin alanında passkey otomatik doldurma (mediation: 'conditional') uygulamalarda yoktur; girişi bir düğmeden başlatın.
// Your normal passkey code works as it is:
const cred = await navigator.credentials.get({ publicKey: options });
// Or with your server's JSON options (SimpleWebAuthn style):
const options = await (await fetch('/passkey/login-options')).json();
const answer = await AppMint.passkey.get(options);
await fetch('/passkey/login-verify', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(answer)
});
// Once, on the Play-installed app — copy these to your server setup:
console.log(JSON.stringify(AppMint.passkey.assetLinks(), null, 2));
console.log(AppMint.passkey.origin());14Ana ekran widget'ı - verilerinizi ana ekranda gösterin#
Uygulamanızın bir ana ekran widget'ı vardır. Kullanıcı bunu telefonun widget listesinden ekler (ana ekrana basılı tutun, sonra Widget'lar) veya siz AppMint.widget.requestPin() ile Ekle sayfasını açarsınız.
Widget, sayfanız doldurana kadar boş kalır ("Henüz gösterilecek bir şey yok"). Bu bir web sayfası değil, küçük bir Android kartıdır, bu yüzden HTML'inizi gösteremez. Ona bir başlık, bir büyük değer, en fazla altı kısa satır ve renkler verirsiniz.
Uygulama açıldığında ve gösterdiği veri her değiştiğinde AppMint.widget.set() çağırın. Widget, yeniden başlatmadan sonra bile son kartı korur. route, widget'a dokunulunca uygulamanızın açılacağı yerdir.
function updateWidget() {
if (!window.AppMint || !AppMint.widget) return; // in a browser
AppMint.widget.set({
title: 'Today',
value: '3 events',
lines: ['09:00 Dentist', '13:00 Lunch with Sam', '18:30 Gym'],
route: '/',
bg: '#0E7C86', ink: '#FFFFFF', accent: '#FFE08A'
});
}
updateWidget(); // on start-up, and after every change
// An "Add to home screen" button:
async function addWidget() {
if ((await AppMint.widget.placedCount()) > 0) return;
await AppMint.widget.requestPin();
}15Kopyalama koruması ve uzun basma menüsü#
Adım 3 (Integrate) içinde, Display Options altında iki anahtar. İkisi de siz açana kadar kapalıdır.
- Bağlantılarda ve görsellerde uzun basma menüsü: bir bağlantıyı veya resmi açmak, kopyalamak, paylaşmak ya da kaydetmek için basılı tutun. Varsayılan olarak kapalıdır, bu yüzden bir bağlantıya uzun basmak hiçbir şey yapmaz. Bir sayfa yine de contextmenu olayını iptal ederek bir öğede menüyü reddedebilir.
- Kopyalama koruması: uygulamanızdaki metni kimse seçemez, kopyalayamaz veya kesemez. Formlara yazmak yine çalışır. Uzun basma menüsünü de kapalı tutar.
Sayfanız şunu anlayabilir: AppMint.copyProtection, koruma açıkken true, kapalıyken (ve tarayıcıda) tanımsızdır. Salt okunurdur. Koruma açıkken kendi Kopyala düğmelerinizi gizleyin, çünkü hiçbir şey kopyalamazlar.
const protectedApp = !!(window.AppMint && window.AppMint.copyProtection === true);
// A Copy button would copy nothing, so hide it
document.querySelectorAll('[data-copy-button]').forEach(btn => {
btn.hidden = protectedApp;
});16{exampleCount} hazır örnek - burada açın#
Kopyalayabileceğiniz çalışan kodlar: SMS gönderme, kişileri okuma, resimli bildirim gösterme, parmak izi kilidi, telefon bilgisi, dosya kaydetme, Bluetooth sensörleri ve daha fazlası. Her biri kısadır ve basit kelimelerle açıklanmıştır.
AppMint içinde açılır. İçinde arama yapabilirsiniz ve her kod bloğunda bir Kopyala düğmesi vardır.
Aynı ekranda ayrıca 'Tüm yöntemler' bulunur - uygulamanızın çağırabileceği {methodCount} şeyin hepsi ve her biri kopyalayabileceğiniz çalışan bir örnekle gelir. Bu liste uygulama çalışma zamanından üretilir, bu yüzden uygulamanızın yapabildikleriyle her zaman birebir uyuşur.
17Örnekleri telefonunuza veya bilgisayarınıza kaydedin#
Downloads/AppMint/Guides klasörüne üç dosya kaydeder:
- Örnekler - yukarıdaki {exampleCount} örnek
- Yöntem listesi - tüm {methodCount} yöntem
- index.html - hazır bir test sayfası
Test sayfasında cihaz bilgisi, titreşim, bildirimler ve kişi seçici için düğmeler vardır. Her şeyin çalıştığını görmek için uygulama olarak derleyin, sonra kendi uygulamanıza dönüştürün. Normal bir tarayıcıda da sorunsuz açılır - hiçbir şey bozulmaz, sadece uygulamanın içinde olmadığını söyler.
Uygulamada, bu adımın düğmesi bunları telefonunuza kaydeder. Burada doğrudan indirilebilir.
AppMint-examples.md AppMint-all-methods.md index.html18Kilit ekranında çalan alarm saati#
Access adımında Alarm saati kutusunu işaretleyin. alarm: true ile scheduleNotificationEx, uygulama kapalıyken bile kullanıcı kapatana veya erteleyene kadar sizin sesinizle çalar. Tekrar günlük, haftalık, hafta içi, aylık veya yıllık olabilir ya da haftanın günlerini seçebilirsiniz.
Zamanlamadan önce getAlarmSupport() ile sorun. 'ready', 'not_enabled', 'needs_exact_alarm' veya 'needs_notification_permission' yanıtı verir. Ardından stopAlarm(id), snoozeAlarm(id, minutes) ve isAlarmRinging(id) çalan bir alarmı yönetir.
const B = window.WebToApk;
if (B && B.getAlarmSupport && B.getAlarmSupport() === 'ready') {
B.scheduleNotificationEx('wake', JSON.stringify({
at: firstAtMs, alarm: true, title: 'Wake up', repeat: 'weekdays', sound: '/audio/alarm.mp3'
}));
}
document.getElementById('snooze').onclick = () => B.snoozeAlarm('wake', 10);19Sistem ses düzeyi#
getVolume(stream) medya, alarm, zil, bildirim veya arama ses düzeyini JSON olarak okur. setVolume(stream, percent, showUi) değiştirir. watchVolume(true) her değişiklikte bir appmint:volume olayı gönderir. Zil sesini kısmak Rahatsız Etme erişimi gerektirir: requestDndAccess().
if (window.WebToApk && WebToApk.getVolume) {
const v = JSON.parse(WebToApk.getVolume('alarm'));
if (v.percent === 0) alert('Alarm volume is off');
window.addEventListener('appmint:volume', (e) => console.log(e.detail.stream, e.detail.percent));
WebToApk.watchVolume(true);
}20Arka plan hizmeti, arka plan konumu, geofence'ler ve görevler#
startBackgroundService, kullanıcı uzaktayken sayfanızı, sesi ve zamanlayıcıları bir bildirimle çalışır tutar. requestBackgroundLocation 'Her zaman izin ver' ister. addGeofence uygulama kapalıyken giriş, çıkış veya bekleme olayı tetikler. AppMint.background.register kendi sayfa kodunuzu her 15 dakikada veya daha seyrek çalıştırır. Hepsi telefon yeniden başladıktan sonra tekrar başlar.
Bunların sihirbazda (Access adımı) kendi anahtarı olmalıdır; anahtar olmadan bir çağrı { ok: false, reason: 'not_enabled' } yanıtı verir.
const r = JSON.parse(WebToApk.startBackgroundService(JSON.stringify({ title: 'Syncing', text: 'Keeping data fresh' })));
if (!r.ok) console.warn(r.reason);
if (AppMint.background.isBackgroundRun()) {
window.addEventListener('appmint:background', async (e) => {
await refreshData();
AppMint.background.done(e.detail.runId, { ok: true });
});
} else {
AppMint.background.register('refresh', { intervalMinutes: 60 });
}21Çökme raporları#
Integrate adımında Çökme raporları kutusunu işaretleyin. Yakalanmayan hatalar sizin için kaydedilir. logError(message, stack) yakaladığınız birini kaydeder, setCrashUserId(id) raporları kendi kullanıcı kimliğinizle etiketler (asla e-posta değil) ve getLastCrash() en yeni çökmeyi JSON olarak veya boş bir dize olarak döndürür. Raporları Uygulamayı Güncelle, sonra uygulamanız, sonra Çökme raporları bölümünde okuyun.
if (window.WebToApk && WebToApk.logError) {
try { risky(); } catch (err) { WebToApk.logError(err.message, err.stack || ''); }
WebToApk.setCrashUserId('u_42');
const last = WebToApk.getLastCrash(); // '' when none
}22Cihaz bütünlüğü ve Play Integrity#
Integrate adımında Cihaz bütünlüğü kontrolleri kutusunu işaretleyin. getDeviceIntegrity(), root, emülatör ve hata ayıklayıcı belirtilerini JSON olarak döndürür; bu bir uyarıdır, kanıt değildir. Güvenilir bir karar için requestIntegrityToken(nonce, '') çağırın ve appmint:integrity olayındaki belirteci Google Play'den karar isteyecek SİZİN sunucunuza gönderin.
const d = JSON.parse(WebToApk.getDeviceIntegrity());
if (d.rooted || d.emulator) alert('This phone is modified');
window.addEventListener('appmint:integrity', (e) => sendToServer(e.detail.token));
WebToApk.requestIntegrityToken(serverNonceBase64, '');23Alternatif uygulama simgeleri ve TV#
Basic adımında en fazla 4 alternatif simge ekleyin. setAppIcon(name) başlatıcı simgesini değiştirir ('default' geri döner), getAppIcon() geçerli olanı adlandırır ve getAvailableIcons() hepsini listeler. isTv() uygulamanın bir televizyonda olduğunu söyler, böylece kumanda dostu bir düzen gösterebilirsiniz.
if (window.WebToApk && WebToApk.setAppIcon) WebToApk.setAppIcon('dark');
if (window.WebToApk && WebToApk.isTv && WebToApk.isTv()) {
document.documentElement.classList.add('tv');
}24Facebook girişi, analitik ve RevenueCat#
Facebook girişi desteklenir. Integrate adımında Facebook App ID ve Client Token girin; giriş bir tarayıcı sekmesinde açılır ve uygulamaya döner. AppMint.facebook.login(['public_profile', 'email']) çağırın ve belirteci sunucunuza gönderin. AppMint.analytics (Firebase) ve AppMint.facebook.logEvent (Meta App Events) yalnızca kullanıcı kabul ettikten sonra kayıt yapar. AppMint.revenuecat abonelikleri herkese açık Android anahtarınızla yönetir.
const r = await AppMint.facebook.login(['public_profile', 'email']);
if (r.ok) await fetch('/api/login/facebook', { method: 'POST', body: JSON.stringify({ token: r.accessToken }) });
AppMint.analytics.log('share', { method: 'whatsapp' });
const offerings = await AppMint.revenuecat.getOfferings();25Fotoğraflardan, PDF'lerden ve widget'lardan metin#
AppMint.textRecognition.recognize(image, { script }) Latin, Devanagari, Çince, Japonca veya Korece metni okur. AppMint.pdf.fromPage() ve fromHtml(html, options) yazdırma penceresi olmadan gerçek bir PDF üretir. AppMint.widget.set(card) ana ekran widget'ını doldurur.
const r = await AppMint.textRecognition.recognize(file, { script: 'devanagari' });
const pdf = await AppMint.pdf.fromHtml('<h1>Invoice</h1>', { fileName: 'invoice', save: 'share' });
await AppMint.widget.set({ title: 'Today', value: '3 events', route: '/calendar' });26Sağlık verileri ve Bluetooth işaretçileri#
AppMint.health adımları, kalp atış hızını, uykuyu, kiloyu ve egzersizi Health Connect üzerinden okur ve yazar; Access adımında Sağlık verileri ve türleri işaretleyin. AppMint.beacons.startScan() iBeacon ve Eddystone işaretçilerini bulur ve appmint:beacon olayları gönderir.
const a = await AppMint.health.isAvailable();
if (a.available) {
await AppMint.health.requestPermissions({ read: ['steps'] });
const steps = await AppMint.health.read('steps', { start: new Date(Date.now() - 864e5), end: new Date(), aggregate: true });
}
window.addEventListener('appmint:beacon', (e) => console.log(e.detail));
await AppMint.beacons.startScan();27Hazır eklentiler: SQLite, bildirimler, push, tarayıcı, kişiler#
Uygulamanın kendi sunduğu sayfalarda window.Capacitor.Plugins; CapacitorSQLite (özel bir veritabanı), LocalNotifications, PushNotifications, CapacitorBarcodeScanner ve Contacts içerir. Önce eklentinin var olduğunu kontrol edin: Website modundaki bir uygulamada window.Capacitor yalnızca kendi sitesinin sayfalarında bulunur, başka alan adlarında asla.
const P = window.Capacitor && window.Capacitor.Plugins;
if (P && P.CapacitorBarcodeScanner) {
const s = await P.CapacitorBarcodeScanner.scanBarcode({ hint: 17 });
console.log(s.ScanResult);
}
if (P && P.LocalNotifications) await P.LocalNotifications.requestPermissions();