Buat APK Gratis

API jembatan JavaScript

Plugin Capacitor

Plugin Capacitor yang dimuat aplikasi. Halaman yang ditulis manual mengaksesnya sebagai window.Capacitor.Plugins.<Name>; aplikasi buatan AI memakai wrapper @/lib/appmintNative yang disebut di setiap contoh.

Capacitor.ActionSheet Capacitor#

Capacitor.Plugins.ActionSheet β€” showActions({ title, message, options })

Contoh

Menampilkan bottom sheet native berisi daftar pilihan dan memberi tahu pilihan mana yang diketuk (@capacitor/action-sheet 8.1.1).

Mengembalikan: Promise { index, canceled } - index adalah opsi yang diketuk; saat sheet ditutup canceled bernilai true dan index berada di luar daftar (-1). Memerlukan: tidak ada yang perlu diaktifkan - setiap aplikasi sudah memuat plugin ini. window.Capacitor ada di halaman yang disajikan aplikasi sendiri (aplikasi HTML, ZIP, dan buatan AI) dan, pada aplikasi mode Situs web, di situs Anda sendiri (domain dan subdomainnya) - tidak pernah di situs lain yang dibuka aplikasi. Deteksi fitur terlebih dahulu.

Setiap opsi berupa { title, style? } dengan style 'DEFAULT', 'DESTRUCTIVE' atau 'CANCEL'.

var ActionSheet = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.ActionSheet;

async function photoMenu() {
  if (!ActionSheet) return;
  var opts = [
    { title: 'Share', style: 'DEFAULT' },
    { title: 'Edit', style: 'DEFAULT' },
    { title: 'Delete', style: 'DESTRUCTIVE' }
  ];
  var r = await ActionSheet.showActions({ title: 'Photo', message: 'Choose an action', options: opts });
  if (r.canceled || r.index < 0 || r.index >= opts.length) return;   // dismissed
  if (opts[r.index].title === 'Delete') deletePhoto();
}

Di aplikasi buatan AI wrapper berbentuk Capacitor mengembalikan { index: -1 } saat ditutup; bentuk singkat actionSheet() mengembalikan null:

import { ActionSheet, actionSheet } from '@/lib/appmintNative';

const { index } = await ActionSheet.showActions({
  title: 'Photo',
  options: [{ title: 'Share' }, { title: 'Delete', destructive: true }],
});
if (index === 1) deletePhoto();

const i = await actionSheet('Sort by', [{ title: 'Name' }, { title: 'Date' }]);   // number | null

Konfirmasi hapus yang juga berfungsi di browser biasa:

async function confirmDelete(name) {
  const AS = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.ActionSheet;
  if (!AS) return window.confirm('Delete ' + name + '?');
  const r = await AS.showActions({
    title: 'Delete ' + name + '?',
    options: [{ title: 'Delete', style: 'DESTRUCTIVE' }, { title: 'Keep it', style: 'CANCEL' }]
  });
  return !r.canceled && r.index === 0;
}

Catatan: Selalu periksa batas indeks - jangan pernah menganggap sembarang indeks sebagai pilihan nyata. Bentuk opsi wrapper adalah { title, destructive? }; ini memetakan destructive ke gaya 'DESTRUCTIVE' milik plugin.

Capacitor.App Capacitor#

Capacitor.Plugins.App β€” getInfo(), getState(), exitApp(), minimizeApp(), addListener(...)

Contoh

Identitas dan siklus hidup aplikasi: nama, id paket, versi, apakah aplikasi sedang di depan, dan event jeda/lanjut (@capacitor/app 8.1.0).

Mengembalikan: getInfo() β†’ { name, id, build, version }; getState() β†’ { isActive }; getLaunchUrl() β†’ { url } atau tidak ada; getAppLanguage() β†’ { value }; exitApp() / minimizeApp() β†’ void. addListener() β†’ Promise berisi handle dengan remove(), seperti API Capacitor sendiri - await atau sambungkan .then(); nilai yang dikembalikan juga memiliki remove() sendiri. Membutuhkan: tidak ada yang perlu diaktifkan - setiap aplikasi menjalankan plugin ini. window.Capacitor ada di halaman yang disajikan aplikasi sendiri (HTML, ZIP dan aplikasi buatan AI) dan, pada aplikasi mode Website, di situs Anda sendiri (domain dan sub-domainnya) - tidak pernah di situs lain yang dibuka aplikasi. Deteksi fitur.

var App = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.App;
if (App) {
  App.getInfo().then(function (i) {
    document.getElementById('about').textContent = i.name + ' ' + i.version + ' (' + i.build + ')';
  });
}

Jeda dan lanjutkan - simpan draf saat pengguna pergi, segarkan saat mereka kembali:

if (App) {
  App.addListener('appStateChange', function (s) {
    if (!s.isActive) saveDraft();      // went to the background
    else refreshInbox();               // back in front
  });
  App.addListener('pause', function () { console.log('paused'); });
  App.addListener('resume', function () { console.log('resumed'); });
}

Di aplikasi buatan AI:

import { App } from '@/lib/appmintNative';

const info = await App.getInfo();   // { name, id, build, version }
App.exitApp();                      // closes the app on Android

Catatan: Event backButton tidak pernah dipicu: shell mempertahankan tombol kembali (plugin berjalan dengan disableBackButtonHandler). Tangani kembali dengan AppMint.setBackHandler(fn) atau wrapper onBackGesture. Untuk deep link gunakan WebToApk.getLaunchUrl() / event appmint:deep-link (atau launchUrl() / onDeepLink() di aplikasi buatan AI). minimizeApp() hanya untuk Android. Jangan jadikan tombol Keluar satu-satunya jalan maju.

Capacitor.AppLauncher Capacitor#

Capacitor.Plugins.AppLauncher β€” canOpenUrl({ url }), openUrl({ url })

Contoh

Membuka aplikasi lain lewat tautan (whatsapp://send?text=…, tel:, geo:, tautan https) dan menanyakan apakah ada yang bisa menanganinya (@capacitor/app-launcher 8.0.1).

Mengembalikan: canOpenUrl() β†’ Promise { value: boolean }. openUrl() β†’ Promise { completed: boolean } (false bila tidak ada aplikasi yang menangani tautan). Memerlukan: tidak ada yang perlu diaktifkan - setiap aplikasi sudah memuat plugin ini. window.Capacitor ada di halaman yang disajikan aplikasi sendiri (aplikasi HTML, ZIP, dan buatan AI) dan, pada aplikasi mode Situs web, di situs Anda sendiri (domain dan subdomainnya) - tidak pernah di situs lain yang dibuka aplikasi. Deteksi fitur terlebih dahulu.

var AL = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.AppLauncher;

async function chatOnWhatsApp(text) {
  if (!AL) return;
  var url = 'whatsapp://send?text=' + encodeURIComponent(text);
  var can = await AL.canOpenUrl({ url: url });
  if (!can.value) { alert('WhatsApp is not installed'); return; }
  var r = await AL.openUrl({ url: url });
  if (!r.completed) alert('Could not open WhatsApp');
}

Di aplikasi buatan AI:

import { appLauncher } from '@/lib/appmintNative';

if (await appLauncher.canOpen('tel:+15551234567')) await appLauncher.open('tel:+15551234567');

Buka tautan peta tanpa bertanya dulu:

async function openMap(query) {
  const AL = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.AppLauncher;
  if (!AL) { window.open('https://maps.google.com/?q=' + encodeURIComponent(query)); return; }
  const r = await AL.openUrl({ url: 'geo:0,0?q=' + encodeURIComponent(query) });
  if (!r.completed) alert('No maps app could open this');
}

Catatan: Di Android 11+ aplikasi hanya bisa "melihat" aplikasi lain yang dideklarasikannya. Aplikasi yang dihasilkan mendeklarasikan tautan https, geo, google.navigation, tel, mailto, sms, whatsapp, intent, dan upi, sehingga canOpenUrl menjawab false untuk skema lain (misalnya spotify:) meskipun aplikasinya terpasang. openUrl tetap berfungsi untuk skema itu - panggil dan periksa completed. Di Android canOpenUrl juga menerima nama paket ('com.whatsapp'), dengan batasan visibilitas yang sama.

Capacitor.AppUpdate Capacitor#

Capacitor.Plugins.AppUpdate β€” getAppUpdateInfo(), performImmediateUpdate(), startFlexibleUpdate(), completeFlexibleUpdate(), openAppStore()

Contoh

Memeriksa Google Play untuk versi aplikasi yang lebih baru dan memulai pembaruan dalam aplikasi dari Play. Dibundel @capawesome/capacitor-app-update (template/plugins/app-update).

Mengembalikan: getAppUpdateInfo() β†’ { currentVersionName, currentVersionCode, availableVersionCode, updateAvailability, updatePriority, immediateUpdateAllowed, flexibleUpdateAllowed, clientVersionStalenessDays?, installStatus } (kode versi berupa string; updateAvailability 2 = pembaruan tersedia). performImmediateUpdate() / startFlexibleUpdate() β†’ { code }: 0 OK, 1 dibatalkan, 2 gagal, 3 tidak tersedia, 4 tidak diizinkan, 5 panggil getAppUpdateInfo() dahulu. openAppStore() β†’ void. Memerlukan: tidak ada yang perlu diaktifkan; aplikasi harus dipasang dari Google Play. window.Capacitor ada di halaman yang disajikan aplikasi sendiri (aplikasi HTML, ZIP, dan buatan AI) dan, pada aplikasi mode Situs web, di situs Anda sendiri (domain dan subdomainnya) - tidak pernah di situs lain yang dibuka aplikasi. Deteksi fitur terlebih dahulu.

var AU = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.AppUpdate;

async function checkForUpdate() {
  if (!AU) return;
  try {
    var info = await AU.getAppUpdateInfo();          // must come first
    if (info.updateAvailability !== 2) return;       // up to date
    if (info.immediateUpdateAllowed) {
      var r = await AU.performImmediateUpdate();     // Play's full-screen update
      if (r.code === 1) console.log('user said not now');
    } else {
      await AU.openAppStore();                       // the Play listing
    }
  } catch (e) {
    console.log('Play update check failed:', e.message);  // e.g. no Play services
  }
}

Pembaruan fleksibel - unduh di latar belakang, lalu mulai ulang saat pengguna setuju:

async function flexibleUpdate() {
  if (!AU) return;
  var info = await AU.getAppUpdateInfo();
  if (info.updateAvailability !== 2 || !info.flexibleUpdateAllowed) return;
  await AU.addListener('onFlexibleUpdateStateChange', function (s) {
    if (s.installStatus === 2) console.log(s.bytesDownloaded + ' / ' + s.totalBytesToDownload);
    if (s.installStatus === 11) showRestartButton();   // 11 = DOWNLOADED
  });
  await AU.startFlexibleUpdate();
}
function restartNow() { if (AU) AU.completeFlexibleUpdate(); }

Di aplikasi buatan AI:

import { appUpdate } from '@/lib/appmintNative';

const info = await appUpdate.check();          // null on the web / without Play
if (info?.inPlace) await appUpdate.start();    // Android: immediate update

Catatan: Gunakan updateAvailability === 2 sebagai satu-satunya uji "pembaruan tersedia". check() milik wrapper membandingkan currentVersionName dengan availableVersionCode, yang tidak pernah sama di Android, sehingga updateAvailable-nya tidak andal di sana - uji inPlace sebagai gantinya. start() resolve true bahkan saat pengguna membatalkan.

Capacitor.AppwrightDocScanner Capacitor#

Capacitor.Plugins.AppwrightDocScanner β€” scan({ pageLimit, pdf, quality }), isSupported()

Contoh

Membuka pemindai dokumen Google ML Kit: pengguna memotret satu halaman atau lebih (atau mengimpornya), tepinya dideteksi dan diluruskan, lalu halaman dikembalikan sebagai gambar JPEG. Plugin milik Appwright sendiri (AppwrightDocScannerPlugin.kt).

Mengembalikan: scan() β†’ Promise yang selalu RESOLVE: { ok: true, pages: string[] (JPEG data URLs), pdfDataUrl?, pdfPath?, pdfError? } bila berhasil, { ok: false, cancelled: true } bila pengguna membatalkan, { ok: false, error } bila pemindai tidak bisa dimulai. isSupported() β†’ { value: boolean } (Google Play services tersedia). Memerlukan: tidak ada yang perlu diaktifkan dan tanpa izin kamera (pemindai berjalan di dalam Play services, yang mengunduh modelnya saat pertama digunakan).

var Scanner = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.AppwrightDocScanner;

async function scanReceipt() {
  if (!Scanner) { alert('Scanning is not available here'); return; }
  var s = await Scanner.isSupported();
  if (!s.value) { alert('This phone has no Google Play services'); return; }
  var r = await Scanner.scan({ pageLimit: 1, pdf: false, quality: 0.8 });
  if (r.cancelled) return;
  if (!r.ok) { alert('Scanner error: ' + r.error); return; }
  document.getElementById('preview').src = r.pages[0];
}

pageLimit 0 = tanpa batas. quality adalah 0,1-1 untuk JPEG. Dengan pdf: true pemindai juga menulis PDF: pdfDataUrl adalah PDF itu sebagai URL data:application/pdf;base64,… yang bisa diunduh, diunggah, atau ditampilkan halaman, dan pdfPath adalah salinannya di folder cache aplikasi. Jika PDF tidak bisa dibaca, halaman tetap dikembalikan dan pdfError menjelaskan alasannya.

Di aplikasi buatan AI (null saat dibatalkan, terjadi kesalahan, atau di web):

import { docScanner, can } from '@/lib/appmintNative';

if (can('docScanner') !== 'none') {
  const res = await docScanner.scan({ pageLimit: 5, pdf: true });
  if (res) setPages(res.pages);          // res.pdfPath when pdf: true
}

Pindai beberapa halaman dan tawarkan PDF:

async function scanContract() {
  const Scanner = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.AppwrightDocScanner;
  if (!Scanner) return;
  const r = await Scanner.scan({ pageLimit: 0, pdf: true, quality: 0.9 });
  if (!r.ok) { if (!r.cancelled) alert('Scanner error: ' + r.error); return; }
  if (r.pdfDataUrl) {
    const a = document.createElement('a');
    a.href = r.pdfDataUrl; a.download = 'contract.pdf'; a.click();
  } else if (r.pdfError) console.warn('PDF not made:', r.pdfError);
  console.log(r.pages.length + ' pages scanned');
}

Catatan: Halaman berupa data URL lengkap dan bisa besar - perkecil sebelum menyimpan banyak di localStorage. Gunakan pdfDataUrl, bukan pdfPath - path file perangkat bukan URL yang bisa dimuat halaman. Halaman yang tidak bisa dibaca dilewati; sisanya tetap dikembalikan.

Capacitor.AppwrightGallery Capacitor#

Capacitor.Plugins.AppwrightGallery β€” save({ source, fileName, album, kind })

Contoh

Menyimpan foto atau video ke galeri ponsel (Pictures/<album> atau Movies/<album>). Plugin milik shell aplikasi sendiri (AppwrightGalleryPlugin.kt).

Mengembalikan: Promise { uri } dari item yang disimpan. Ditolak dengan code: bad-source, download-failed, permission-denied (Android 7-9, penyimpanan ditolak) atau failed. Memerlukan: tidak ada yang perlu diaktifkan; tanpa izin di Android 10+ (Android 7-9 meminta penyimpanan saat pertama kali).

const Gallery = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.AppwrightGallery;

async function saveCard(canvas) {
  const dataUrl = canvas.toDataURL('image/png');
  if (!Gallery) { const a = document.createElement('a'); a.href = dataUrl; a.download = 'card.png'; a.click(); return; }
  try {
    await Gallery.save({ source: dataUrl, fileName: 'birthday-card.png', album: 'Cards' });
    toast('Saved to your gallery');
  } catch (e) {
    toast('Could not save: ' + e.message);
  }
}

Simpan video dari server Anda ke album tersendiri, dengan pesan untuk setiap kode kegagalan:

const Gallery = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.AppwrightGallery;

async function saveClip(url) {
  if (!Gallery) { window.open(url, '_blank'); return; }
  try {
    await Gallery.save({ source: url, fileName: 'highlight.mp4', album: 'Highlights', kind: 'video' });
    toast('Video saved to Movies/Highlights');
  } catch (e) {
    if (e.code === 'download-failed') toast('Could not download the video. Check your connection.');
    else if (e.code === 'permission-denied') toast('Allow storage access to save videos.');
    else toast('Could not save: ' + e.message);
  }
}

Simpan foto yang diedit pengguna sebagai Blob (misalnya dari canvas.toBlob) dengan mengubahnya menjadi URL data: terlebih dahulu:

const Gallery = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.AppwrightGallery;

function blobToDataUrl(blob) {
  return new Promise((resolve, reject) => {
    const r = new FileReader();
    r.onload = () => resolve(r.result);
    r.onerror = () => reject(r.error);
    r.readAsDataURL(blob);
  });
}

async function saveEditedPhoto(canvas) {
  if (!Gallery) return;
  const blob = await new Promise((res) => canvas.toBlob(res, 'image/jpeg', 0.92));
  const { uri } = await Gallery.save({ source: await blobToDataUrl(blob), fileName: 'edit-' + Date.now() + '.jpg', album: 'My Edits' });
  console.log('saved as', uri);
}

Catatan: source adalah URL data:, URL http(s), atau URI content:///file://; kind ('image'/'video') dibaca dari tipe MIME bila dihilangkan. Aplikasi buatan AI memakai saveToGallery() dari @/lib/appmintNative.

Capacitor.AppwrightHaptics Capacitor#

Capacitor.Plugins.AppwrightHaptics

Contoh

Plugin milik AppMint sendiri untuk pola getaran kaya: daftar ketukan, masing-masing dengan waktu mulai, durasi, dan kekuatannya sendiri.

Mengembalikan: play({ events }) me-resolve { ok: true } atau { ok: false, error } ('unsupported' = tanpa vibrator, 'empty' = tanpa event, atau pesan sistem). Tidak pernah ditolak. isSupported() me-resolve { value: true/false }. Memerlukan: tidak ada yang perlu diaktifkan - setiap aplikasi mendeklarasikan izin getar, baik Getar dicentang di Langkah 4 (Akses) maupun tidak. window.Capacitor ada di halaman yang disajikan aplikasi sendiri (aplikasi HTML, ZIP, dan buatan AI) dan, pada aplikasi mode Situs web, di situs Anda sendiri (domain dan subdomainnya) - tidak pernah di situs lain yang dibuka aplikasi. Deteksi fitur terlebih dahulu.

Setiap event berupa { at, duration, intensity, sharpness }: at = awal dalam ms, duration = durasi dalam ms (di bawah 20 menjadi ketukan 30 ms), intensity = 0-1 (default 0,8). sharpness diterima tetapi diabaikan di Android.

var AH = window.Capacitor && window.Capacitor.Plugins ? window.Capacitor.Plugins.AppwrightHaptics : null;

async function heartbeat() {
  if (!AH) return false;
  var r = await AH.play({
    events: [
      { at: 0,   intensity: 0.8 },
      { at: 140, intensity: 0.5 },
      { at: 700, intensity: 0.8 },
      { at: 840, intensity: 0.5 }
    ]
  });
  if (!r.ok) console.log('pattern not played:', r.error);
  return r.ok;
}

document.getElementById('like').addEventListener('click', heartbeat);

Sembunyikan tombol di ponsel yang tidak punya vibrator:

(async function () {
  var btn = document.getElementById('feel-it');
  var ok = false;
  if (AH) { try { ok = (await AH.isSupported()).value; } catch (e) {} }
  btn.hidden = !ok;
})();

Mainkan ketukan ganda cepat saat aksi berhasil, dan laporkan bila tidak bisa diputar:

async function successBuzz() {
  const AH = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.AppwrightHaptics;
  if (!AH) return;
  const r = await AH.play({ events: [{ at: 0, duration: 40, intensity: 1 }, { at: 120, duration: 40, intensity: 0.6 }] });
  if (!r.ok && r.error === 'unsupported') console.log('this phone has no vibrator');
}

Catatan: Kekuatan hanya berfungsi di ponsel dengan kontrol amplitudo; ponsel lain mempertahankan pewaktuan pada satu kekuatan tetap. Jika sistem menolak getaran, play menjawab { ok: false, error: '<the system message>' }. Di aplikasi buatan AI gunakan hapticPlay dari @/lib/appmintNative, yang juga punya pola bernama.

Capacitor.AppwrightLiveProgress Capacitor#

Capacitor.Plugins.AppwrightLiveProgress β€” start / update / end

Contoh

Plugin Android milik AppMint sendiri (nama JS-nya AppwrightLiveProgress) untuk notifikasi status yang menetap, senyap, dan diperbarui secara langsung (bilah progres, spinner, atau jam berjalan) dan membuka suatu rute saat diketuk.

Mengembalikan: start(opts) / update(opts) β†’ Promise<{ ok: true, id }>, atau { ok: false, error } tanpa yang diposting - 'permission' bila notifikasi tidak diizinkan (Android 13+: belum diberi izin, atau dimatikan untuk aplikasi), 'channel_disabled' bila pengguna mematikan kategori "Live status"; end({ id }) β†’ Promise<void>. Memerlukan: aplikasi Android dan izin notifikasi (Android 13+). Tidak tersedia di web.

Di aplikasi buatan AI gunakan wrapper liveProgress dari @/lib/appmintNative:

import { liveProgress } from '@/lib/appmintNative';
await liveProgress.start({ id: 'order', title: 'Order #42', text: 'Being prepared', indeterminate: true });
await liveProgress.update({ id: 'order', title: 'Order #42', text: 'On the way', progress: 0.6, route: '/orders/42' });
await liveProgress.end('order');

Di halaman yang ditulis manual:

async function showDelivery(step, total) {
  const P = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.AppwrightLiveProgress;
  if (!P) return;                                   // not in the Android app
  if (window.Notification && Notification.permission !== 'granted') {
    if (await Notification.requestPermission() !== 'granted') return;
  }
  const r = await P.update({
    id: 'delivery',
    title: 'Your delivery',
    text: 'Stop ' + step + ' of ' + total,
    progress: step / total,                         // 0–1; or indeterminate: true
    route: '/track'                                 // opened when the card is tapped
  });
  if (!r.ok) console.warn('live card not posted:', r.error);
}

async function deliveryDone() {
  const P = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.AppwrightLiveProgress;
  if (P) await P.end({ id: 'delivery' });
}

Timer olahraga: startedAt membuat kartu menghitung naik sendiri, jadi diposting sekali dan diakhiri saat olahraga berhenti:

const Live = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.AppwrightLiveProgress;
let workoutStart = 0;

async function startWorkout(name) {
  workoutStart = Date.now();
  if (!Live) return;
  const r = await Live.start({ id: 'workout', title: name, text: 'Workout in progress', startedAt: workoutStart, route: '/workout' });
  if (!r.ok && r.error === 'channel_disabled') {
    showHint('Turn on "Live status" in this app\'s notification settings to see the timer.');
  }
}

async function stopWorkout() {
  if (Live) await Live.end({ id: 'workout' });
  saveWorkout({ durationMs: Date.now() - workoutStart });
}

Opsi: id (default 'live'), title, text, progress (0-1, hilangkan agar tanpa bilah), indeterminate, startedAt (epoch ms, menampilkan jam berjalan), route.

Catatan: start dan update melakukan hal yang sama (memposting atau mengganti kartu dengan id itu). Kartu tidak bisa digeser untuk dihapus - selalu panggil end. Minta izin terlebih dahulu: di Android 13+ tanpa izin itu start menjawab error: 'permission' dan tidak memposting apa pun.

Capacitor.AppwrightSystemPalette Capacitor#

Capacitor.Plugins.AppwrightSystemPalette β€” get()

Contoh

Mengembalikan warna Material You ponsel (palet yang dibangun Android 12+ dari wallpaper), sehingga aplikasi bisa menyesuaikan dengan aplikasi sistem. Plugin milik AppMint sendiri (AppwrightSystemPalettePlugin.kt).

Mengembalikan: Promise { available: false } di bawah Android 12, selain itu { available: true, accent1, accent2, accent3, neutral1, neutral2 } - masing-masing berupa objek dari nada ke warna hex, dengan nada '0', '10', '50', '100' … '900', '1000' (mis. accent1['600'] === '#3F5F90'). Memerlukan: tidak ada yang perlu diaktifkan - setiap aplikasi sudah memuat plugin ini. window.Capacitor ada di halaman yang disajikan aplikasi sendiri (aplikasi HTML, ZIP, dan buatan AI) dan, pada aplikasi mode Situs web, di situs Anda sendiri (domain dan subdomainnya) - tidak pernah di situs lain yang dibuka aplikasi. Deteksi fitur terlebih dahulu.

var Palette = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.AppwrightSystemPalette;

async function useWallpaperColours() {
  if (!Palette) return;
  var p = await Palette.get();
  if (!p.available) return;                 // keep the app's own colours
  var root = document.documentElement.style;
  root.setProperty('--accent', p.accent1['600']);
  root.setProperty('--surface', p.neutral1['50']);
}
useWallpaperColours();

Di aplikasi buatan AI:

import { systemPalette } from '@/lib/appmintNative';

const p = await systemPalette();
if (p.available && p.accent1) document.documentElement.style.setProperty('--accent', p.accent1['600']);

Pilih nada terang atau gelap agar sesuai tema sistem, dan baca palet lagi saat pengguna kembali setelah mengganti wallpaper:

var Palette = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.AppwrightSystemPalette;
var darkQuery = window.matchMedia('(prefers-color-scheme: dark)');

async function applyPalette() {
  if (!Palette) return;
  var p = await Palette.get();
  if (!p.available) return;
  var dark = darkQuery.matches;
  var s = document.documentElement.style;
  s.setProperty('--accent', p.accent1[dark ? '200' : '600']);
  s.setProperty('--on-accent', p.accent1[dark ? '800' : '0']);
  s.setProperty('--bg', p.neutral1[dark ? '900' : '10']);
  s.setProperty('--text', p.neutral1[dark ? '100' : '900']);
}

darkQuery.addEventListener('change', applyPalette);
document.addEventListener('visibilitychange', function () {
  if (document.visibilityState === 'visible') applyPalette();
});
applyPalette();

Catatan: Periksa kontras teks sebelum menerapkan warna palet - nada wallpaper tidak dijamin terbaca baik di latar Anda. Browser tidak menyediakan warna wallpaper: di web wrapper menjawab { available: false }. Warna berubah saat pengguna mengganti wallpaper; panggil get() lagi saat dilanjutkan.

Capacitor.AppwrightWidget Capacitor#

Capacitor.Plugins.AppwrightWidget β€” set(card), clear(), placedCount(), requestPin()

Contoh

Mengisi widget layar utama aplikasi: satu kartu dengan judul, nilai besar, hingga dua belas baris, warna Anda, dan rute ketuk - kartu yang sama dengan yang diterima AppMint.widget.set(), semua key disertakan. Kartu disimpan di ponsel dan tetap tampil bahkan setelah reboot. Plugin milik AppMint sendiri (AppwrightWidgetPlugin.kt).

Mengembalikan: set({ title?, value?, caption?, lines?, route?, bg?, ink?, accent?, textSize?, align?, wrap?, … }) β†’ Promise { ok: true, placed }, ditolak dengan alasan untuk kartu yang buruk (placed = widget yang saat ini ada di layar utama). clear() β†’ void. placedCount() β†’ { value }. requestPin() β†’ { value: boolean } (true bila lembar "tambah widget" peluncur dibuka). Memerlukan: tidak ada yang perlu diaktifkan - setiap aplikasi mendeklarasikan widget. window.Capacitor ada di halaman yang disajikan aplikasi sendiri (aplikasi HTML, ZIP, dan buatan AI) dan, pada aplikasi mode Situs web, di situs Anda sendiri (domain dan subdomainnya) - tidak pernah di situs lain yang dibuka aplikasi. Deteksi fitur terlebih dahulu.

var Widget = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.AppwrightWidget;

async function updateWidget(tasks) {
  if (!Widget) return;
  await Widget.set({
    title: 'Today',
    value: tasks.length + ' tasks',
    lines: tasks.slice(0, 6).map(function (t) { return t.title; }),
    route: '/today',                 // opened when the widget is tapped
    bg: '#0B0F1A', ink: '#FFFFFF', accent: '#22D3EE'
  });
}

Tawarkan untuk menempatkannya (hanya bila belum ada yang ditempatkan):

async function offerWidget() {
  if (!Widget) return;
  var n = (await Widget.placedCount()).value;
  if (n > 0) return;
  var r = await Widget.requestPin();
  if (!r.value) alert('Long-press the home screen, tap Widgets and pick this app.');
}

Di aplikasi buatan AI:

import { widget } from '@/lib/appmintNative';

await widget.set({ title: 'Today', value: '3 tasks', lines: ['Gym', 'Call mum'], route: '/today' });
if ((await widget.placedCount()) === 0) await widget.requestPin();

Catatan: Warna berupa #RRGGBB, #AARRGGBB (alfa lebih dulu), atau rgba(); yang kosong memakai kartu gelap dengan nilai cyan. Lihat AppMint.widget untuk baris bergaya, caption, textSize, align, wrap, dan font (file .ttf/.otf Anda sendiri, diberikan sebagai path di aplikasi Anda). Ketukan membuka aplikasi di route sebagai deep link (baca dengan WebToApk.getLaunchUrl() atau event appmint:deep-link). Sebelum ada set(), widget menampilkan "Nothing to show yet"; clear() mengembalikannya ke keadaan itu. Di browser can('widget') adalah 'none'.

Capacitor.Badge Capacitor#

Capacitor.Plugins.Badge β€” the launcher-icon count

Contoh

Plugin Badge (capawesome) yang mengatur angka pada ikon peluncur aplikasi.

Mengembalikan: Promise: set({ count }), clear(), increase(), decrease() β†’ void; get() β†’ { count }; isSupported() β†’ { isSupported }. Plugin Android tidak punya metode izin. Memerlukan: tidak ada di Android. Tidak tersedia di web.

Di aplikasi buatan AI gunakan wrapper badge dari @/lib/appmintNative:

import { badge } from '@/lib/appmintNative';
await badge.set(3);
await badge.clear();

Di halaman yang ditulis manual:

async function setUnread(count) {
  const B = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.Badge;
  if (!B) return false;                       // not inside the app
  try {
    const s = await B.isSupported();
    if (!s.isSupported) return false;         // this launcher shows no badges
    if (count > 0) await B.set({ count: count });
    else await B.clear();
    return true;
  } catch (e) {
    return false;
  }
}

window.addEventListener('appmint:push', function () {
  const inbox = JSON.parse(window.WebToApk ? WebToApk.getPushInbox() : '[]');
  setUnread(inbox.filter(function (m) { return !m.read; }).length);
});

Hitung naik dan turun saat item masuk dan dibaca:

const B = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.Badge;
async function onNewMessage() { if (B) await B.increase(); }
async function onMessageRead() { if (B) await B.decrease(); }
async function showCurrent() {
  if (!B) return;
  const { count } = await B.get();
  console.log('badge shows', count);
}

Catatan: di Android tampilannya bergantung pada peluncur (angka, titik, atau tidak ada). navigator.setAppBadge(n) di aplikasi menulis ke badge yang sama (hanya ada di peluncur yang bisa menampilkan hitungan).

Capacitor.BarcodeScanner Capacitor#

Capacitor.Plugins.BarcodeScanner β€” scan, startScan, readBarcodesFromImage, isSupported

Contoh

Pemindaian QR dan barcode dengan API @capacitor-mlkit/barcode-scanning - plugin milik shell aplikasi (BarcodeScannerPlugin.kt) di atas pemindai kode Google yang sama dengan AppMint.scanCode(). Panggilan @capacitor-community/barcode-scanner yang lebih lama (startScan() yang me-resolve { hasContent, content }, checkPermission, prepare, hideBackground) memakai nama yang sama dan juga berfungsi.

Mengembalikan: scan({ formats?, autoZoom? }) β†’ { barcodes: [{ rawValue, displayValue, format, valueType, bytes?, cornerPoints?, urlBookmark?, wifi?, email?, phone?, sms?, geoPoint?, contactInfo?, calendarEvent?, driverLicense? }] } (ditolak "scan canceled." saat pengguna membatalkan); readBarcodesFromImage({ path, formats? }) β†’ { barcodes }; isSupported() β†’ { supported }; isGoogleBarcodeScannerModuleAvailable() β†’ { available }; installGoogleBarcodeScannerModule() (progres sebagai googleBarcodeScannerModuleInstallProgress); checkPermissions() / requestPermissions() β†’ { camera }; openSettings(). format adalah 'QR_CODE', 'EAN_13', 'CODE_128'… Memerlukan: tidak ada yang perlu diaktifkan dan tanpa izin kamera - pemindai Google menggambar layarnya sendiri (Play services mengunduhnya saat pertama digunakan). window.Capacitor ada di halaman yang disajikan aplikasi sendiri (aplikasi HTML, ZIP, dan buatan AI) dan, pada aplikasi mode Situs web, di situs Anda sendiri (domain dan subdomainnya) - tidak pernah di situs lain yang dibuka aplikasi. Deteksi fitur terlebih dahulu.

const Scanner = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.BarcodeScanner;

scanBtn.onclick = async () => {
  if (!Scanner) return;
  try {
    const { barcodes } = await Scanner.scan({ formats: ['QR_CODE'] });
    const code = barcodes[0];
    if (code.valueType === 'URL') location.href = code.urlBookmark.url;
    else resultBox.textContent = code.displayValue;
  } catch (e) {
    if (e.message !== 'scan canceled.') alert(e.message);
  }
};

Pencarian harga dari barcode produk, dengan gaya listener (startScan + barcodesScanned) yang sudah dipakai aplikasi ML Kit:

const Scanner = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.BarcodeScanner;

async function scanProduct() {
  const listener = await Scanner.addListener('barcodesScanned', async ({ barcodes }) => {
    await listener.remove();
    await Scanner.stopScan();
    const ean = barcodes[0].rawValue;
    const res = await fetch('https://api.example.com/products/' + encodeURIComponent(ean));
    priceBox.textContent = res.ok ? (await res.json()).price : 'Not found';
  });
  await Scanner.startScan({ formats: ['EAN_13', 'EAN_8', 'UPC_A', 'UPC_E'] });
}

Baca kode QR dari foto yang sudah dimiliki pengguna:

const Scanner = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.BarcodeScanner;
const Camera = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.Camera;

async function qrFromGallery() {
  const photo = await Camera.getPhoto({ source: 'PHOTOS', resultType: 'uri', quality: 90 });
  const { barcodes } = await Scanner.readBarcodesFromImage({ path: photo.path, formats: ['QR_CODE'] });
  return barcodes.length ? barcodes[0].rawValue : null;
}

Catatan: startScan() upstream menampilkan pratinjau kamera langsung di balik halaman transparan dan terus memindai sampai stopScan(); di sini membuka layar pemindai, kode pertama memicu barcodeScanned / barcodesScanned, dan sesi berakhir (panggilan lalu selesai dengan { hasContent, content, format } untuk kode komunitas; pemindai yang ditutup selesai dengan { hasContent: false }). Senter dan zoom milik pratinjau itu, jadi isTorchAvailable() bernilai false dan setter senter/zoom ditolak - layar pemindai punya tombol senternya sendiri. checkPermissions() menjawab granted saat aplikasi tidak punya izin kamera sama sekali (pemindai tidak membutuhkannya); aplikasi yang juga memakai kamera mendapat status sebenarnya. Aplikasi buatan AI memakai scanCode() dari @/lib/appmintNative.

Capacitor.Browser Capacitor#

Capacitor.Plugins.Browser β€” open({ url, toolbarColor }), close(), addListener('browserFinished')

Contoh

Membuka halaman web di tab browser dalam aplikasi (Chrome Custom Tabs), sehingga pengguna membaca ketentuan, dokumen, atau halaman masuk dan kembali dengan satu gestur (@capacitor/browser 8.0.3).

Mengembalikan: open() / close() β†’ Promise void. Event: browserFinished (pengguna menutup tab) dan browserPageLoaded. Memerlukan: tidak ada - setiap aplikasi sudah memuat plugin ini (browser yang mendukung Custom Tabs, seperti Chrome, harus terpasang). window.Capacitor ada di halaman yang disajikan aplikasi sendiri (aplikasi HTML, ZIP, dan buatan AI) dan, pada aplikasi mode Situs web, di situs Anda sendiri (domain dan subdomainnya) - tidak pernah di situs lain yang dibuka aplikasi. Deteksi fitur terlebih dahulu.

var Browser = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.Browser;

async function openTerms() {
  if (!Browser) return;
  var h = await Browser.addListener('browserFinished', function () {
    console.log('user closed the terms');
    h.remove();
  });
  await Browser.open({ url: 'https://example.com/terms', toolbarColor: '#0B0F1A' });
}

Di aplikasi buatan AI (tab baru di web):

import { browser } from '@/lib/appmintNative';

const off = browser.onClosed(() => refreshAccount());
await browser.open('https://example.com/terms', { toolbarColor: '#0B0F1A' });
// call off() when you no longer care

Buka tautan, dan tutup tab saat kembalian dari proses masuk sampai ke halaman:

var Browser = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.Browser;

async function openHelp() {
  if (!Browser) { window.open('https://example.com/help', '_blank'); return; }
  try {
    await Browser.open({ url: 'https://example.com/help' });
  } catch (e) {
    alert('Could not open the page: ' + e.message);
  }
}

window.addEventListener('appmint:deep-link', function () {
  if (Browser) Browser.close().catch(function () {});
});

Catatan: url tidak boleh kosong. toolbarColor adalah warna hex; yang tidak valid diabaikan. close() juga berfungsi di Android pada versi plugin ini (menyelesaikan activity host tab) - berguna setelah tautan masuk kembali ke aplikasi. Tab ini adalah browser terpisah: tidak berbagi cookie aplikasi atau localStorage.

Capacitor.Calendar Capacitor#

Capacitor.Plugins.Calendar β€” createEvent, findEvents, deleteEvent, listCalendars, openCalendar

Contoh

Menambah, mencari, dan menghapus acara di kalender bawaan ponsel (Android CalendarContract), dan membuka aplikasi kalender pada tanggal tertentu. Dibundel @capacitor/calendar (template/plugins/calendar).

Mengembalikan: createEvent() β†’ { id }; findEvents() β†’ { events: [{ id, title, location?, notes?, startDate, endDate, isAllDay, calendarId, calendarName?, attendees? }] }; listCalendars() β†’ { calendars: [{ id, name, displayName?, isPrimary }] }; deleteEvent(), openCalendar() β†’ void. Tanggal dalam milidetik epoch. Memerlukan: centang Kalender di Langkah 4 (Akses) saat build. Untuk aplikasi HTML, ZIP, dan buatan AI, build juga menambahkan izin kalender sendiri bila file Anda berisi panggilan Calendar.<method>( yang ditulis persis seperti itu (seperti di bawah) atau calendar.createEvent( milik wrapper. Plugin meminta akses kalender kepada pengguna saat pertama digunakan. window.Capacitor ada di halaman yang disajikan aplikasi sendiri (aplikasi HTML, ZIP, dan buatan AI) dan, pada aplikasi mode Situs web, di situs Anda sendiri (domain dan subdomainnya) - tidak pernah di situs lain yang dibuka aplikasi. Deteksi fitur terlebih dahulu.

var Calendar = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.Calendar;

async function addDentist() {
  if (!Calendar) return;
  var start = new Date('2026-10-02T10:00:00').getTime();
  try {
    var r = await Calendar.createEvent({
      title: 'Dentist', startDate: start, endDate: start + 60 * 60 * 1000,
      location: 'Main St 5', notes: 'Bring the card', isAllDay: false,
      firstReminderMinutes: 30
    });
    console.log('event id', r.id);
  } catch (e) {
    // e.code: OS-PLUG-CLDR-0020 permission denied, -0001 bad arguments
    alert('Could not add the event: ' + e.message);
  }
}

Baca minggu ini, hapus satu, buka kalender:

async function thisWeek() {
  if (!Calendar) return;
  var now = Date.now();
  var found = await Calendar.findEvents({ startDate: now, endDate: now + 7 * 864e5 });
  found.events.forEach(function (ev) { console.log(ev.title, new Date(ev.startDate)); });
  if (found.events.length) await Calendar.deleteEvent({ id: found.events[0].id });
  await Calendar.openCalendar({ date: now });
}

Di aplikasi buatan AI (di web createEvent mengunduh file .ics; membaca mengembalikan []):

import { calendar } from '@/lib/appmintNative';

if ((await calendar.requestPermission()) === 'granted') {
  const id = await calendar.createEvent({ title: 'Dentist', start: new Date('2026-10-02T10:00'), end: new Date('2026-10-02T11:00') });
  const week = await calendar.listEvents({ from: Date.now(), to: Date.now() + 7 * 864e5 });
  if (id) await calendar.deleteEvent(id);
  await calendar.openCalendar(new Date());
}

Catatan: Tanpa izin kalender di aplikasi, tidak ada dialog yang muncul dan setiap panggilan acara ditolak (izin tidak ada); pengguna yang menolak mendapat OS-PLUG-CLDR-0020. recurrence: { frequency: 'daily' | 'weekly' | 'monthly' | 'yearly', interval?, count?, endDate? } membuat acara berulang. createEventInteractively({ title, startDate, endDate }) membuka editor milik aplikasi kalender sendiri: me-resolve { id } dari acara yang disimpan, dan ditolak OS-PLUG-CLDR-0006 bila pengguna menutup editor tanpa menyimpan (memerlukan akses baca dan tulis untuk membedakan keduanya). deleteEvent({ id, fromDate }) mengakhiri acara berulang sebelum fromDate dan mempertahankan kejadian sebelumnya. Wrapper mengembalikan null / [] / false alih-alih melempar kesalahan.

Capacitor.Camera Capacitor#

Capacitor.Plugins.Camera

Contoh

Plugin Camera resmi Capacitor, tertanam di aplikasi: ambil foto dengan kamera atau pilih foto dari galeri.

Mengembalikan: Promise. getPhoto(opts) β†’ { dataUrl | base64String | webPath, format, saved } (kolom mana yang ada bergantung pada resultType), dan DITOLAK saat pengguna membatalkan; pickImages(opts) β†’ { photos: [{ webPath, format }] }; checkPermissions() / requestPermissions({ permissions }) β†’ { camera, photos }. Memerlukan: centang Kamera di Langkah 4 (Akses). Untuk aplikasi HTML, ZIP, dan buatan AI, build juga menambahkan izin kamera sendiri bila file Anda berisi Camera.getPhoto( yang ditulis persis seperti itu (seperti di bawah), getUserMedia dengan video, atau <input capture>. window.Capacitor ada di halaman yang disajikan aplikasi sendiri (aplikasi HTML, ZIP, dan buatan AI) dan, pada aplikasi mode Situs web, di situs Anda sendiri (domain dan subdomainnya) - tidak pernah di situs lain yang dibuka aplikasi. Deteksi fitur terlebih dahulu.

Ambil foto dan tampilkan.

async function takePhoto() {
  var Camera = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.Camera;
  if (!Camera) { showMessage('Open the app to use the camera.'); return; }
  try {
    var perm = await Camera.requestPermissions({ permissions: ['camera'] });
    if (perm.camera !== 'granted') { showMessage('Camera permission was refused.'); return; }

    var photo = await Camera.getPhoto({
      source: 'CAMERA',          // 'CAMERA' | 'PHOTOS' | 'PROMPT'
      resultType: 'dataUrl',     // 'dataUrl' | 'base64' | 'uri'
      quality: 80,
      direction: 'REAR',         // 'REAR' | 'FRONT'
      correctOrientation: true,
      saveToGallery: false
    });
    document.getElementById('photo').src = photo.dataUrl;
  } catch (err) {
    // The user closed the camera (or no camera app). Nothing to do.
  }
}

Pilih hingga 5 foto dari galeri.

async function choosePhotos() {
  var Camera = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.Camera;
  if (!Camera) return;
  try {
    var result = await Camera.pickImages({ quality: 80, limit: 5 });
    result.photos.forEach(function (p) {
      var img = document.createElement('img');
      img.src = p.webPath;       // a URL the page can load
      document.getElementById('gallery').appendChild(img);
    });
  } catch (err) { /* cancelled */ }
}

Di aplikasi buatan AI gunakan wrapper, yang juga berfungsi di web (dan mengembalikan null alih-alih melempar kesalahan saat dibatalkan):

import { camera } from '@/lib/appmintNative';
const photo = await camera.take({ source: 'camera' });

Catatan: pickImages tidak memerlukan izin kamera. Jika izin kamera tidak ada di aplikasi (kotak mati dan build tidak menemukan panggilan kamera), izin kamera ditolak tanpa prompt. <input type="file" accept="image/*" capture> juga membuka kamera. Kamera bersifat sensitif: deklarasikan di formulir Data safety Play Anda.

Capacitor.CapacitorBarcodeScanner Capacitor#

Capacitor.Plugins.CapacitorBarcodeScanner β€” scanBarcode({ hint })

Contoh

Pemindaian QR / barcode satu panggilan dengan API resmi @capacitor/barcode-scanner - plugin milik shell aplikasi (CapacitorBarcodeScannerPlugin.kt) di atas pemindai kode Google yang sama dengan AppMint.scanCode(). Kode yang ditulis untuk paket npm (CapacitorBarcodeScanner.scanBarcode({ hint: CapacitorBarcodeScannerTypeHint.ALL })) berfungsi tanpa perubahan.

Mengembalikan: scanBarcode({ hint, scanInstructions?, cameraDirection?, scanOrientation? }) β†’ { ScanResult, format }. hint / format adalah angka dari paket: 0 QR_CODE, 1 AZTEC, 2 CODABAR, 3 CODE_39, 4 CODE_93, 5 CODE_128, 6 DATA_MATRIX, 8 ITF, 9 EAN_13, 10 EAN_8, 11 PDF_417, 14 UPC_A, 15 UPC_E, 17 ALL. Ditolak dengan kode OS-PLUG-BARC-0006 saat pengguna menutup pemindai. Memerlukan: tidak ada yang perlu diaktifkan dan tanpa izin kamera - pemindai Google menggambar layarnya sendiri (Play services mengunduhnya saat pertama digunakan). window.Capacitor ada di halaman yang disajikan aplikasi sendiri (aplikasi HTML, ZIP, dan buatan AI) dan, pada aplikasi mode Situs web, di situs Anda sendiri (domain dan subdomainnya) - tidak pernah di situs lain yang dibuka aplikasi. Deteksi fitur terlebih dahulu.

const Scanner = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.CapacitorBarcodeScanner;

ticketBtn.onclick = async () => {
  if (!Scanner) return;
  try {
    const { ScanResult } = await Scanner.scanBarcode({ hint: 0 });   // QR codes only
    const ok = await fetch('/api/tickets/check?code=' + encodeURIComponent(ScanResult)).then((r) => r.ok);
    statusBox.textContent = ok ? 'Valid ticket' : 'Unknown ticket';
  } catch (e) {
    if (e.code !== 'OS-PLUG-BARC-0006') alert(e.message);
  }
};

Terima kode apa pun, dan beri tahu pengguna jenis kodenya:

const Scanner = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.CapacitorBarcodeScanner;
const NAMES = { 0: 'QR code', 5: 'Code 128', 9: 'EAN-13', 10: 'EAN-8', 14: 'UPC-A', 15: 'UPC-E' };

async function scanAnything() {
  const { ScanResult, format } = await Scanner.scanBarcode({ hint: 17 });
  return (NAMES[format] || 'Barcode') + ': ' + ScanResult;
}

Tangani penolakan yang bukan karena pengguna menutup pemindai:

const Scanner = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.CapacitorBarcodeScanner;

async function scanProduct() {
  if (!Scanner) { alert('Scanning works only inside the app'); return null; }
  try {
    const { ScanResult } = await Scanner.scanBarcode({ hint: 9 });   // EAN-13
    return ScanResult;
  } catch (e) {
    if (e.code === 'OS-PLUG-BARC-0006') return null;                 // user closed the scanner
    alert('Scan failed: ' + e.message);
    return null;
  }
}

Catatan: scanInstructions, scanButton, cameraDirection, dan scanOrientation mengatur tampilan layar kamera upstream sendiri dan tidak berpengaruh pada pemindai Google (selalu kamera belakang). MAXICODE, RSS_14, RSS_EXPANDED, dan UPC_EAN_EXTENSION tidak didukung sebagai hint (ditolak OS-PLUG-BARC-0008); 17 (ALL) memindai semua jenis yang didukung. Aplikasi buatan AI memakai scanCode() dari @/lib/appmintNative.

Capacitor.CapacitorCookies Capacitor#

Capacitor.Plugins.CapacitorCookies β€” getCookies / setCookie / deleteCookie / clearCookies / clearAllCookies

Contoh

Membaca dan menulis cookie aplikasi, termasuk milik host lain yang diakses halaman Anda (milik inti Capacitor CapacitorCookies).

Mengembalikan: getCookies({ url? }) β†’ { [name]: value } - dengan url, cookie yang akan dikirim URL itu (host dan path); tanpanya, document.cookie milik halaman sendiri. Menolak url yang bukan http(s). setCookie({ key, value, url?, path?, expires? }), deleteCookie({ key, url? }), clearCookies({ url? }), clearAllCookies() β†’ Promise void; setCookie / deleteCookie ditolak tanpa string key (dan value) dan tidak menulis apa pun. Membutuhkan: tidak ada yang perlu diaktifkan - setiap aplikasi menjalankan plugin ini. window.Capacitor ada di halaman yang disajikan aplikasi sendiri (HTML, ZIP dan aplikasi buatan AI) dan, pada aplikasi mode Website, di situs Anda sendiri (domain dan sub-domainnya) - tidak pernah di situs lain yang dibuka aplikasi. Deteksi fitur.

var Cookies = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.CapacitorCookies;

// Read the session cookie your API host set β€” not the page's own cookies.
async function apiSession() {
  if (!Cookies) return null;          // not inside the app
  var jar = await Cookies.getCookies({ url: 'https://api.example.com/' });
  return jar.session || null;
}

// Remember a choice for the API host, for 30 days, on one path only.
async function rememberRegion(region) {
  if (!Cookies) return;
  var expires = new Date(Date.now() + 30 * 864e5).toUTCString();
  await Cookies.setCookie({ url: 'https://api.example.com', path: '/v2', key: 'region', value: region, expires: expires });
}

Keluar: hapus cookie host itu, atau semua cookie yang dipegang aplikasi.

async function signOut(everything) {
  if (!Cookies) return;
  if (everything) await Cookies.clearAllCookies();
  else await Cookies.clearCookies({ url: 'https://api.example.com' });
}

Catatan: Cookie yang diatur dengan path hanya dikembalikan untuk url di bawah path itu. Nilai didekode URL saat dibaca. Cookie dibagikan oleh setiap halaman yang ditampilkan aplikasi, jadi jangan simpan rahasia di dalamnya yang bisa dibaca halaman asing - simpan di Preferences atau penyimpanan aman aplikasi.

Capacitor.CapacitorSQLite Capacitor#

Capacitor.Plugins.CapacitorSQLite β€” createConnection, open, execute, query, run, executeSet, close

Contoh

Database SQLite sungguhan di ponsel, dengan API @capacitor-community/sqlite. @capacitor-community/sqlite yang dibundel (template/plugins/sqlite), berjalan di SQLite bawaan Android. Kode yang ditulis untuk paket npm (new SQLiteConnection(CapacitorSQLite)) berfungsi tanpa perubahan; halaman yang ditulis manual memanggil objek plugin secara langsung, seperti di bawah.

Mengembalikan: createConnection({ database, version, encrypted: false, mode: 'no-encryption', readonly: false }), open({ database }), close({ database }), closeConnection({ database }) β†’ void; execute({ database, statements }) β†’ { changes: { changes } }; run({ database, statement, values }) β†’ { changes: { changes, lastId } }; query({ database, statement, values }) β†’ { values: [rows] }; executeSet({ database, set: [{ statement, values }] }) β†’ { changes }; isDBExists({ database }) / isDBOpen({ database }) β†’ { result }; beginTransaction, commitTransaction, rollbackTransaction, isTransactionActive({ database }); deleteDatabase({ database }); exportToJson / importFromJson untuk cadangan. Memerlukan: tidak ada yang perlu diaktifkan dan tanpa izin. Database berada di penyimpanan privat aplikasi dan bertahan setelah pembaruan aplikasi. window.Capacitor ada di halaman yang disajikan aplikasi sendiri (aplikasi HTML, ZIP, dan buatan AI) dan, pada aplikasi mode Situs web, di situs Anda sendiri (domain dan subdomainnya) - tidak pernah di situs lain yang dibuka aplikasi. Deteksi fitur terlebih dahulu.

const DB = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.CapacitorSQLite;
const database = 'notes';

async function openNotes() {
  if (!DB) return false;
  await DB.createConnection({ database, version: 1, encrypted: false, mode: 'no-encryption', readonly: false });
  await DB.open({ database, readonly: false });
  await DB.execute({ database, statements:
    'CREATE TABLE IF NOT EXISTS notes (id INTEGER PRIMARY KEY AUTOINCREMENT, text TEXT NOT NULL, at INTEGER);' });
  return true;
}

async function addNote(text) {
  const r = await DB.run({ database, statement: 'INSERT INTO notes (text, at) VALUES (?, ?);', values: [text, Date.now()] });
  return r.changes.lastId;
}

async function listNotes() {
  const r = await DB.query({ database, statement: 'SELECT id, text, at FROM notes ORDER BY at DESC;', values: [] });
  return r.values || [];
}

Beberapa penulisan yang harus berhasil semua atau tidak sama sekali - satu transaksi dengan executeSet:

const DB = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.CapacitorSQLite;

async function moveMoney(database, fromId, toId, amount) {
  await DB.executeSet({ database, transaction: true, set: [
    { statement: 'UPDATE accounts SET balance = balance - ? WHERE id = ?;', values: [amount, fromId] },
    { statement: 'UPDATE accounts SET balance = balance + ? WHERE id = ?;', values: [amount, toId] },
    { statement: 'INSERT INTO ledger (from_id, to_id, amount, at) VALUES (?, ?, ?, ?);', values: [fromId, toId, amount, Date.now()] },
  ] });
}

Buka database hanya sekali per start aplikasi, bahkan saat dua layar memintanya bersamaan:

const DB = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.CapacitorSQLite;
let ready = null;

function db(database) {
  if (!ready) ready = (async () => {
    try {
      await DB.createConnection({ database, version: 1, encrypted: false, mode: 'no-encryption', readonly: false });
    } catch (e) {
      if (!/already exists/i.test(e.message)) throw e;   // a page reload keeps the native connection
    }
    if (!(await DB.isDBOpen({ database, readonly: false })).result) await DB.open({ database, readonly: false });
    return database;
  })();
  return ready;
}

Catatan: Aplikasi dibuat tanpa SQLCipher, sehingga database tidak terenkripsi: encrypted: true, setEncryptionSecret, changeEncryptionSecret, isSecretStored, dan panggilan enkripsi lainnya ditolak dengan "Encryption is not available in this app". isInConfigEncryption() menjawab false. Semua yang lain (kueri, nilai terikat, transaksi, upgrade berversi dengan addUpgradeStatement, impor/ekspor JSON) adalah kode plugin itu sendiri. Penolakan membawa teks kesalahan SQLite.

Capacitor.Clipboard Capacitor#

Capacitor.Plugins.Clipboard β€” write(options), read()

Contoh

Menyalin teks (atau tautan) ke clipboard sistem dan membacanya kembali (@capacitor/clipboard 8.0.1).

Mengembalikan: write({ string?, url?, image?, label? }) β†’ Promise void. read() β†’ Promise { value, type } (type adalah 'text/plain' untuk teks). Membutuhkan: tidak ada yang perlu diaktifkan - setiap aplikasi menjalankan plugin ini. window.Capacitor ada di halaman yang disajikan aplikasi sendiri (HTML, ZIP dan aplikasi buatan AI) dan, pada aplikasi mode Website, di situs Anda sendiri (domain dan sub-domainnya) - tidak pernah di situs lain yang dibuka aplikasi. Deteksi fitur.

async function copyCode(code) {
  var Clipboard = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.Clipboard;
  if (!Clipboard) { alert('Copy is not available here'); return; }
  await Clipboard.write({ string: code, label: 'Invite code' });
}

async function pasteCode(input) {
  var Clipboard = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.Clipboard;
  if (!Clipboard) return;
  try {
    var r = await Clipboard.read();
    input.value = r.value;
  } catch (e) {
    // An EMPTY clipboard is a rejection: "There is no data on the clipboard".
    if (/no data/i.test(e.message)) input.value = '';
    else alert('Could not read the clipboard: ' + e.message);
  }
}

Di aplikasi buatan AI wrapper berbentuk Capacitor mengubah clipboard kosong menjadi '':

import { Clipboard } from '@/lib/appmintNative';

await Clipboard.write({ string: 'ABC-123' });
const { value } = await Clipboard.read();   // '' when the clipboard is empty

Salin tautan dan konfirmasikan dengan sentuhan umpan balik:

async function copyLink(url) {
  var P = window.Capacitor && window.Capacitor.Plugins;
  if (!P || !P.Clipboard) { alert('Copy is not available here'); return; }
  await P.Clipboard.write({ url: url });
  if (P.Haptics) P.Haptics.impact({ style: 'LIGHT' });
  copiedToast.hidden = false;
}

Catatan: write memerlukan salah satu dari string, url, atau image (data URL), jika tidak ditolak "No data provided". Android 12+ menampilkan pemberitahuan "pasted from…" sendiri saat membaca - itu dari OS, bukan aplikasi. write milik wrapper hanya mengirim string || url.

Capacitor.Contacts Capacitor#

Capacitor.Plugins.Contacts β€” getContacts, getContact, pickContact, createContact, deleteContact

Contoh

Buku alamat ponsel dengan API @capacitor-community/contacts. @capacitor-community/contacts yang dibundel (template/plugins/contacts). Kode yang ditulis untuk paket npm berfungsi tanpa perubahan.

Mengembalikan: checkPermissions() / requestPermissions() β†’ { contacts, contactsWrite } (masing-masing 'granted' | 'denied' | 'prompt'; contacts untuk membaca, contactsWrite untuk menambah dan menghapus); getContacts({ projection }) β†’ { contacts: [ContactPayload] }; getContact({ contactId, projection }) dan pickContact({ projection }) β†’ { contact }; createContact({ contact }) β†’ { contactId }; deleteContact({ contactId }) β†’ void. projection memilih kolom: { name, phones, emails, organization, birthday, note, urls, postalAddresses, image } (masing-masing true). Memerlukan: centang Kontak di Langkah 4 (Akses) untuk membaca, dan Edit Kontak juga untuk menambah atau menghapus. Build HTML, ZIP, dan AI-Studio mencentangnya sendiri saat kode memanggil Contacts.getContacts( / getContact( / pickContact( (membaca) atau Contacts.createContact( / deleteContact( (keduanya). Plugin meminta izin pengguna saat pertama digunakan; tanpa kotak yang dicentang, panggilan ditolak "Permission is required to access contacts." - dan di aplikasi tanpa Kontak, SMS, atau Log panggilan yang dicentang, plugin sama sekali tidak ada di aplikasi (Capacitor menolak "not implemented"). window.Capacitor ada di halaman yang disajikan aplikasi sendiri (aplikasi HTML, ZIP, dan buatan AI) dan, pada aplikasi mode Situs web, di situs Anda sendiri (domain dan subdomainnya) - tidak pernah di situs lain yang dibuka aplikasi. Deteksi fitur terlebih dahulu.

const Contacts = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.Contacts;

async function friendsWithPhones() {
  if (!Contacts) return [];
  const { contacts } = await Contacts.requestPermissions();
  if (contacts !== 'granted') return [];
  const res = await Contacts.getContacts({ projection: { name: true, phones: true } });
  return res.contacts
    .filter((c) => c.phones && c.phones.length)
    .map((c) => ({ id: c.contactId, name: (c.name && c.name.display) || '', phone: c.phones[0].number }));
}

Biarkan pengguna memilih satu orang dari pemilih sistem:

const Contacts = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.Contacts;

inviteBtn.onclick = async () => {
  if (!Contacts) return;
  try {
    const { contact } = await Contacts.pickContact({ projection: { name: true, phones: true, emails: true } });
    inviteField.value = (contact.emails && contact.emails[0] && contact.emails[0].address) || '';
  } catch (e) {
    // The user closed the picker, or refused access.
  }
};

Simpan kartu nama dari aplikasi ke buku alamat:

const Contacts = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.Contacts;

async function saveCard(card) {
  const perm = await Contacts.requestPermissions();
  if (perm.contactsWrite !== 'granted') return null;
  const { contactId } = await Contacts.createContact({ contact: {
    name: { given: card.first, family: card.last },
    organization: { company: card.company, jobTitle: card.title },
    phones: [{ type: 'work', label: 'work', number: card.phone }],
    emails: [{ type: 'work', label: 'work', address: card.email }],
  } });
  return contactId;
}

Catatan: pickContact() ditolak dengan kode CANCELLED saat pengguna keluar dari pemilih. Android hanya mengisi contactId, name, phones, emails, organization, birthday, note, urls, postalAddresses dan image saat proyeksi memintanya - mintalah hanya apa yang Anda tampilkan. Membaca kontak adalah izin sensitif di Google Play: jelaskan alasannya di formulir keamanan data listing. Aplikasi buatan AI memakai listContacts(), pickContact() dan addContact() dari @/lib/appmintNative.

Capacitor.Device Capacitor#

Capacitor.Plugins.Device

Contoh

Plugin Device resmi Capacitor, tertanam di aplikasi: model ponsel, versi OS, baterai, ID yang stabil, dan bahasa.

Mengembalikan: Promise. getInfo() β†’ { model, platform, operatingSystem, osVersion, androidSDKVersion, manufacturer, isVirtual, webViewVersion, … }; getId() β†’ { identifier }; getBatteryInfo() β†’ { batteryLevel (0–1), isCharging }; getLanguageCode() β†’ { value }. Memerlukan: tidak ada yang perlu diaktifkan. window.Capacitor ada di halaman yang disajikan aplikasi sendiri (aplikasi HTML, ZIP, dan buatan AI) dan, pada aplikasi mode Situs web, di situs Anda sendiri (domain dan subdomainnya) - tidak pernah di situs lain yang dibuka aplikasi. Deteksi fitur terlebih dahulu.

Tampilkan ponsel dan baterai.

async function showDevice() {
  var cap = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.Device;
  if (!cap) { document.getElementById('out').textContent = navigator.userAgent; return; }
  try {
    var info = await cap.getInfo();
    var battery = await cap.getBatteryInfo();
    document.getElementById('out').textContent =
      info.manufacturer + ' ' + info.model + ' - ' + info.operatingSystem + ' ' + info.osVersion +
      ' - battery ' + Math.round(battery.batteryLevel * 100) + '%' + (battery.isCharging ? ' (charging)' : '');
  } catch (err) {
    document.getElementById('out').textContent = 'Could not read device info';
  }
}

ID yang stabil dan bahasa.

async function helloServer() {
  var cap = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.Device;
  if (!cap) return;
  var id = (await cap.getId()).identifier;
  var lang = (await cap.getLanguageCode()).value;     // e.g. "en"
  await fetch('https://api.example.com/hello?lang=' + encodeURIComponent(lang), {
    method: 'POST', body: JSON.stringify({ device: id })
  });
}

Di aplikasi buatan AI gunakan wrapper, yang juga berfungsi di web:

import { Device } from '@/lib/appmintNative';
const info = await Device.getInfo();

Catatan: Untuk ID build Android, patch keamanan, layar, memori, dan jaringan, WebToApk.getDeviceInfo() milik shell memberi detail lebih lengkap. ID plugin bukan ID perangkat keras; bisa berubah setelah reset pabrik.

Capacitor.Dialog Capacitor#

Capacitor.Plugins.Dialog β€” alert, confirm, prompt

Contoh

Menampilkan dialog sistem Android sungguhan: pesan, pertanyaan ya/tidak, atau pertanyaan teks satu baris (@capacitor/dialog 8.0.1).

Mengembalikan: alert({ title?, message, buttonTitle? }) β†’ Promise void. confirm({ title?, message, okButtonTitle?, cancelButtonTitle? }) β†’ { value: boolean }. prompt({ title?, message, okButtonTitle?, cancelButtonTitle?, inputPlaceholder?, inputText? }) β†’ { value: string, cancelled: boolean }. Memerlukan: tidak ada yang perlu diaktifkan - setiap aplikasi sudah memuat plugin ini. window.Capacitor ada di halaman yang disajikan aplikasi sendiri (aplikasi HTML, ZIP, dan buatan AI) dan, pada aplikasi mode Situs web, di situs Anda sendiri (domain dan subdomainnya) - tidak pernah di situs lain yang dibuka aplikasi. Deteksi fitur terlebih dahulu.

var Dialog = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.Dialog;

async function deleteNote(id) {
  if (!Dialog) return;
  var r = await Dialog.confirm({
    title: 'Delete note?',
    message: 'This cannot be undone.',
    okButtonTitle: 'Delete',
    cancelButtonTitle: 'Keep'
  });
  if (r.value) removeNote(id);
}

Alert dan prompt:

async function renameFlow() {
  if (!Dialog) return;
  await Dialog.alert({ title: 'Saved', message: 'Your changes are stored.', buttonTitle: 'OK' });

  var p = await Dialog.prompt({ title: 'Rename', message: 'New name', inputText: 'Groceries', inputPlaceholder: 'List name' });
  if (!p.cancelled && p.value.trim()) renameList(p.value.trim());
}

Di aplikasi buatan AI wrapper tidak pernah menolak: penutupan berupa { value: false } / { cancelled: true }, dan di web memakai dialog browser sendiri:

import { Dialog } from '@/lib/appmintNative';

const { value } = await Dialog.confirm({ title: 'Delete note?', message: 'This cannot be undone.' });
if (value) removeNote(id);

Catatan: message wajib diisi - tanpanya plugin menolak "Please provide a message for the dialog". Dialog bersifat modal; gunakan hanya untuk keputusan yang harus memblokir.

Capacitor.Filesystem Capacitor#

Capacitor.Plugins.Filesystem

Contoh

Plugin Filesystem Capacitor standar: membaca dan menulis file di penyimpanan aplikasi SENDIRI (bukan folder yang dipilih pengguna - untuk itu gunakan WebToApkFS).

Mengembalikan: setiap metode mengembalikan Promise dan ditolak saat gagal (misalnya membaca file yang tidak ada). readFile β†’ { data }, writeFile β†’ { uri }, readdir β†’ { files: [{ name, type, size, mtime, uri }] }, mkdir / deleteFile β†’ tidak ada. Memerlukan: tidak ada yang perlu diaktifkan; 'DATA' dan 'CACHE' tidak memerlukan izin.

Halaman tidak punya impor Directory / Encoding, jadi berikan string biasa 'DATA' (file aplikasi privat, disimpan sampai dicopot) atau 'CACHE' (sistem boleh menghapusnya), dan 'utf8' untuk teks:

async function saveAndReadBack() {
  var Fs = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.Filesystem;
  if (!Fs) { console.log('Filesystem plugin not available (not inside the app)'); return; }

  try {
    await Fs.mkdir({ path: 'notes', directory: 'DATA', recursive: true });
    await Fs.writeFile({ path: 'notes/today.txt', data: 'Hello', directory: 'DATA', encoding: 'utf8', recursive: true });

    var r = await Fs.readFile({ path: 'notes/today.txt', directory: 'DATA', encoding: 'utf8' });
    console.log('text:', r.data);

    var dir = await Fs.readdir({ path: 'notes', directory: 'DATA' });
    dir.files.forEach(function (f) { console.log(f.type, f.name, f.size); });   // type: 'file' | 'directory'

    await Fs.deleteFile({ path: 'notes/today.txt', directory: 'DATA' });
  } catch (e) {
    console.log('File error:', e.message);   // e.g. the file does not exist
  }
}

Hilangkan encoding untuk menulis atau membaca data biner sebagai base64:

var Fs = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.Filesystem;
var base64Data = btoa('raw bytes here');   // any base64 string, e.g. from a canvas or FileReader
if (Fs) {
  Fs.writeFile({ path: 'blobs/data.bin', data: base64Data, directory: 'CACHE', recursive: true })
    .then(function (w) { console.log('written to', w.uri); })
    .catch(function (e) { console.log('write failed:', e.message); });
}

Di aplikasi buatan AI, wrapper @/lib/appmintNative yang memakai plugin ini adalah fileTransfer (menyiapkan unduhan dan unggahan di 'CACHE'):

import { fileTransfer } from '@/lib/appmintNative';

const r = await fileTransfer.download('https://example.com/report.pdf', 'report.pdf', {
  onProgress: (p) => console.log(Math.round(p.fraction * 100) + '%'),
});
if (r.path) console.log('saved in the app at', r.path);   // on the web the browser saves it instead

Catatan: window.Capacitor hanya ada di dalam aplikasi - selalu deteksi fitur. File di 'DATA' bersifat privat bagi aplikasi dan dihapus saat dicopot; untuk menaruh file di tempat yang bisa dilihat pengguna, gunakan WebToApkFS (folder yang diberi izin pengguna) atau unduhan.

Capacitor.FileTransfer Capacitor#

Capacitor.Plugins.FileTransfer

Contoh

Plugin File Transfer resmi Capacitor: mengunduh URL ke file di ponsel, atau mengunggah file dari ponsel, secara native, dengan event progres.

Mengembalikan: downloadFile({url, path, headers?, progress?}) β†’ Promise<{path}>; uploadFile({url, path, fileKey?, mimeType?, method?, headers?, progress?}) β†’ Promise<{bytesSent, responseCode, response, headers}>. Progres tiba sebagai event listener 'progress' {type, url, bytes, contentLength, lengthComputable}. Kegagalan ditolak dengan {message, code}. Memerlukan: tidak ada yang perlu diaktifkan. window.Capacitor ada di halaman yang disajikan aplikasi sendiri dan, pada aplikasi mode Situs web, di situs Anda sendiri (domain dan subdomainnya) - tidak pernah di situs lain. Selalu deteksi fitur terlebih dahulu.

Unduh ke cache aplikasi dengan progres:

async function download(url, name, onPct) {
  const P = window.Capacitor && window.Capacitor.Plugins;
  if (!P || !P.FileTransfer || !P.Filesystem) return null;          // not in the app
  const target = await P.Filesystem.getUri({ path: name, directory: 'CACHE' });
  const listener = await P.FileTransfer.addListener('progress', function (p) {
    if (p.url === url && p.lengthComputable) onPct(Math.round(p.bytes / p.contentLength * 100));
  });
  try {
    const r = await P.FileTransfer.downloadFile({ url: url, path: target.uri, progress: true });
    return r.path;
  } catch (e) {
    alert('Download failed: ' + e.message);
    return null;
  } finally {
    listener.remove();
  }
}

Unggah file yang sudah ada di ponsel:

const P = window.Capacitor && window.Capacitor.Plugins;
if (P && P.FileTransfer) {
  P.FileTransfer.uploadFile({
    url: 'https://example.com/api/upload', path: localFileUri,
    fileKey: 'file', mimeType: 'image/jpeg', headers: { Authorization: 'Bearer ' + token }
  }).then(function (r) { console.log('server said', r.responseCode, r.response); })
    .catch(function (e) { alert('Upload failed: ' + e.message); });
}

Laporkan transfer yang gagal berdasarkan kodenya:

async function safeDownload(url, target) {
  const P = window.Capacitor && window.Capacitor.Plugins;
  if (!P || !P.FileTransfer) { alert('Downloads need the app'); return null; }
  try {
    const r = await P.FileTransfer.downloadFile({ url: url, path: target });
    return r.path;
  } catch (e) {
    console.log('transfer failed', e.code, e.message);
    alert('Could not download the file.');
    return null;
  }
}

Catatan: Path harus berupa path file atau URI file://, bukan Blob - tulis Blob ke cache dengan Filesystem.writeFile terlebih dahulu. Di Android 10 ke bawah, path di penyimpanan publik meminta izin penyimpanan. Di aplikasi buatan AI utamakan fileTransfer dari @/lib/appmintNative, yang melakukan semua ini dan juga berfungsi di web.

Capacitor.FileViewer Capacitor#

Capacitor.Plugins.FileViewer

Contoh

Plugin File Viewer resmi Capacitor: membuka dokumen atau file media di aplikasi penampil ponsel, dari alamat web, path file lokal, atau file yang dibundel di aplikasi.

Mengembalikan: setiap metode mengembalikan Promise<void> yang ditolak dengan {message, code} bila tidak ada yang bisa membuka file. Memerlukan: tidak ada yang perlu diaktifkan. window.Capacitor ada di halaman yang disajikan aplikasi sendiri dan, pada aplikasi mode Situs web, di situs Anda sendiri (domain dan subdomainnya) - tidak pernah di situs lain. Selalu deteksi fitur terlebih dahulu.

async function openPdf(url) {
  const FV = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.FileViewer;
  if (!FV) { window.open(url, '_blank'); return; }          // a normal browser: open a tab
  try {
    await FV.openDocumentFromUrl({ url: url });
  } catch (e) {
    alert('No app on this phone can open this file.');
  }
}

File di ponsel, misalnya yang ditulis dengan Capacitor.Plugins.Filesystem:

async function openSaved(name) {
  const P = window.Capacitor && window.Capacitor.Plugins;
  if (!P || !P.FileViewer || !P.Filesystem) return;
  const f = await P.Filesystem.getUri({ path: name, directory: 'CACHE' });
  try {
    await P.FileViewer.openDocumentFromLocalPath({ path: f.uri.replace(/^file:\/\//, '') });
  } catch (e) {
    alert('Cannot open ' + name + ': ' + e.message);
  }
}

openDocumentFromResources({path}) membuka file yang dikemas dalam folder assets APK sendiri. Tiga metode yang sama juga ada sebagai previewMediaContentFromUrl, previewMediaContentFromLocalPath, dan previewMediaContentFromResources untuk video dan audio.

Unduh file dan buka saat sudah tiba:

async function downloadAndOpen(url, name) {
  const P = window.Capacitor && window.Capacitor.Plugins;
  if (!P || !P.FileTransfer || !P.Filesystem || !P.FileViewer) return;
  const f = await P.Filesystem.getUri({ path: name, directory: 'CACHE' });
  const r = await P.FileTransfer.downloadFile({ url: url, path: f.uri });
  await P.FileViewer.openDocumentFromLocalPath({ path: r.path.replace(/^file:\/\//, '') });
}

Catatan: Di aplikasi buatan AI, utamakan fileViewer.open(target) dari @/lib/appmintNative, yang memilih metode yang tepat dan juga berfungsi di web. Path lokal adalah path biasa (tanpa file://).

Capacitor.Geolocation Capacitor#

Capacitor.Plugins.Geolocation

Contoh

Plugin Geolocation resmi Capacitor, tertanam di aplikasi: posisi ponsel sekali, atau pembaruan berkelanjutan.

Mengembalikan: Promise. getCurrentPosition(opts) β†’ { timestamp, coords: { latitude, longitude, accuracy, altitude, speed, heading, … } }; watchPosition(opts, callback) β†’ id pengawasan (string); clearWatch({ id }); checkPermissions() / requestPermissions() β†’ { location, coarseLocation } ('granted' | 'denied' | 'prompt' | …). Memerlukan: GPS dan/atau Lokasi di Langkah 4 (Akses) - untuk aplikasi HTML, ZIP, dan buatan AI, build juga mengaktifkannya sendiri bila file Anda memanggil getCurrentPosition atau watchPosition. window.Capacitor ada di halaman yang disajikan aplikasi sendiri (aplikasi HTML, ZIP, dan buatan AI) dan, pada aplikasi mode Situs web, di situs Anda sendiri (domain dan subdomainnya) - tidak pernah di situs lain yang dibuka aplikasi. Deteksi fitur terlebih dahulu.

Posisi sekali, tanyakan dulu.

async function whereAmI() {
  var geo = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.Geolocation;
  if (!geo) { showMessage('Open the app to use location.'); return; }
  try {
    var perm = await geo.checkPermissions();
    if (perm.location !== 'granted' && perm.coarseLocation !== 'granted') {
      perm = await geo.requestPermissions();
      if (perm.location !== 'granted' && perm.coarseLocation !== 'granted') {
        showMessage('Location is off for this app.');
        return;
      }
    }
    var pos = await geo.getCurrentPosition({ enableHighAccuracy: true, timeout: 15000 });
    showMessage(pos.coords.latitude.toFixed(5) + ', ' + pos.coords.longitude.toFixed(5));
  } catch (err) {
    showMessage('No location: ' + err.message);   // location off in settings, timeout, …
  }
}

Pembaruan berkelanjutan. Callback menerima (position, error).

var watchId = null;

async function startTracking() {
  var geo = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.Geolocation;
  if (!geo) return;
  watchId = await geo.watchPosition({ enableHighAccuracy: true }, function (pos, err) {
    if (err || !pos) return;
    addPointToMap(pos.coords.latitude, pos.coords.longitude);
  });
}

async function stopTracking() {
  var geo = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.Geolocation;
  if (geo && watchId) { await geo.clearWatch({ id: watchId }); watchId = null; }
}

Di aplikasi buatan AI gunakan wrapper, yang juga berfungsi di web:

import { Geolocation } from '@/lib/appmintNative';
const pos = await Geolocation.getCurrentPosition({ enableHighAccuracy: true });

Catatan: navigator.geolocation biasa juga berfungsi di aplikasi. Bila saklar lokasi mati saat build, izin ditolak tanpa prompt. Di Android 12+ pengguna bisa mengizinkan lokasi perkiraan saja (coarseLocation diberikan). Lokasi adalah data pribadi: deklarasikan di formulir Data safety Play Anda.

Capacitor.Haptics Capacitor#

Capacitor.Plugins.Haptics

Contoh

Plugin Haptics resmi Capacitor (@capacitor/haptics), tertanam di aplikasi: ketukan ringan/sedang/berat, umpan balik berhasil/peringatan/kesalahan, tik pemilihan, dan getaran biasa.

Mengembalikan: setiap metode mengembalikan Promise yang selesai tanpa nilai. Membutuhkan: tidak ada yang perlu diaktifkan - setiap aplikasi mendeklarasikan izin getar, baik Vibrate dicentang di Langkah 4 (Access) maupun tidak. window.Capacitor ada di halaman yang disajikan aplikasi sendiri (HTML, ZIP dan aplikasi buatan AI) dan, pada aplikasi mode Website, di situs Anda sendiri (domain dan sub-domainnya) - tidak pernah di situs lain yang dibuka aplikasi. Deteksi fitur.

function haptics() {
  return window.Capacitor && window.Capacitor.Plugins ? window.Capacitor.Plugins.Haptics : null;
}

async function tap(style) {            // 'LIGHT' | 'MEDIUM' | 'HEAVY'
  var h = haptics();
  if (!h) return;
  try { await h.impact({ style: style }); } catch (e) { console.log('haptics failed', e); }
}

async function result(type) {          // 'SUCCESS' | 'WARNING' | 'ERROR'
  var h = haptics();
  if (h) { try { await h.notification({ type: type }); } catch (e) {} }
}

document.getElementById('add').addEventListener('click', function () { tap('LIGHT'); });
document.getElementById('pay').addEventListener('click', function () { result('SUCCESS'); });

Tik pemilihan untuk picker atau penggeser, dan getaran biasa:

var h = window.Capacitor && window.Capacitor.Plugins ? window.Capacitor.Plugins.Haptics : null;
var wheel = document.getElementById('wheel');

wheel.addEventListener('pointerdown', function () { if (h) h.selectionStart(); });
wheel.addEventListener('change', function () { if (h) h.selectionChanged(); });
wheel.addEventListener('pointerup', function () { if (h) h.selectionEnd(); });

document.getElementById('buzz').addEventListener('click', function () {
  if (h) h.vibrate({ duration: 300 });   // milliseconds
});

Getarkan saat terjadi kesalahan dan pasangkan dengan pesan yang terlihat:

var h = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.Haptics;

function rejectInput(field) {
  field.classList.add('invalid');
  if (h) h.notification({ type: 'ERROR' }).catch(function () {});
}

Catatan: String ditulis huruf besar ('HEAVY', bukan 'heavy'). Di aplikasi buatan AI, import { Haptics } from '@/lib/appmintNative' memberi nama yang sama. Untuk ritme kustom dengan kekuatan per ketukan, gunakan Capacitor.Plugins.AppwrightHaptics.

Capacitor.InAppReview Capacitor#

Capacitor.Plugins.InAppReview β€” requestReview()

Contoh

Meminta Google Play menampilkan lembar "beri nilai aplikasi ini" miliknya sendiri di dalam aplikasi. Dibundel @capacitor-community/in-app-review (template/plugins/in-app-review).

Mengembalikan: Promise void - di-resolve saat alur Play berakhir, dan Play tidak pernah memberi tahu apakah lembar ditampilkan atau apa yang dilakukan pengguna. Ditolak bila Play tidak bisa memulai alur. Memerlukan: tidak ada yang perlu diaktifkan; aplikasi harus dipasang dari Google Play agar lembar muncul. window.Capacitor ada di halaman yang disajikan aplikasi sendiri (aplikasi HTML, ZIP, dan buatan AI) dan, pada aplikasi mode Situs web, di situs Anda sendiri (domain dan subdomainnya) - tidak pernah di situs lain yang dibuka aplikasi. Deteksi fitur terlebih dahulu.

var Review = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.InAppReview;

async function afterThirdOrder() {
  if (!Review) return;
  try {
    await Review.requestReview();
  } catch (e) {
    console.log('review flow not available:', e.message);
  }
  // continue the app flow either way β€” you cannot know if the user rated
}

Di aplikasi buatan AI:

import { requestReview } from '@/lib/appmintNative';

// after a success moment, not on launch
const asked = await requestReview();   // false where nothing could be asked (web)

Minta sekali, setelah momen berhasil, dan ingat bahwa Anda sudah meminta:

var Review = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.InAppReview;

async function maybeAskForReview() {
  if (!Review || localStorage.getItem('review_asked')) return;
  localStorage.setItem('review_asked', '1');
  try { await Review.requestReview(); } catch (e) { console.log('review not shown:', e.message); }
}

Catatan: Play membatasi seberapa sering lembar muncul dan tidak menampilkannya untuk setiap panggilan - jangan kaitkan hadiah dengannya dan jangan meminta dari tombol "Beri kami nilai" sambil berharap lembar terbuka (buka halaman toko untuk itu). Minta setelah momen berhasil, bukan saat startup. Pemasangan sideload atau debug biasanya tidak menampilkan apa pun.

Capacitor.KeepAwake Capacitor#

Capacitor.Plugins.KeepAwake β€” keepAwake(), allowSleep(), isKeptAwake(), isSupported()

Contoh

Mencegah layar meredup dan terkunci saat sesuatu harus tetap terlihat - resep, rute, kode QR, timer. Dibundel @capacitor-community/keep-awake (template/plugins/keep-awake).

Mengembalikan: keepAwake() / allowSleep() β†’ Promise void. isKeptAwake() β†’ { isKeptAwake: boolean }. isSupported() β†’ { isSupported: true }. Memerlukan: tidak ada - setiap aplikasi sudah memuat plugin ini; tanpa izin. window.Capacitor ada di halaman yang disajikan aplikasi sendiri (aplikasi HTML, ZIP, dan buatan AI) dan, pada aplikasi mode Situs web, di situs Anda sendiri (domain dan subdomainnya) - tidak pernah di situs lain yang dibuka aplikasi. Deteksi fitur terlebih dahulu.

var KA = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.KeepAwake;

async function startCooking() {
  if (KA) await KA.keepAwake();
  showSteps();
}

async function stopCooking() {
  if (KA) await KA.allowSleep();      // always release when the view closes
}

if (KA) KA.isKeptAwake().then(function (r) { console.log('awake?', r.isKeptAwake); });

Di aplikasi buatan AI (Screen Wake Lock API di web):

import { keepAwake } from '@/lib/appmintNative';

useEffect(() => {
  void keepAwake(true);
  return () => { void keepAwake(false); };
}, []);

Biarkan layar tetap menyala hanya saat timer berjalan:

var KA = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.KeepAwake;

async function runTimer(seconds) {
  if (KA) await KA.keepAwake();
  await new Promise(function (done) { setTimeout(done, seconds * 1000); });
  if (KA) await KA.allowSleep();
  alert('Time is up');
}

Catatan: Flag ini milik jendela aplikasi: hanya berfungsi saat aplikasi di depan, dan tetap aktif sampai allowSleep() - lepaskan di setiap jalan keluar dari layar. keepAwake() mengembalikan false bila tidak ada yang bisa menjaga layar tetap menyala.

Capacitor.Keyboard Capacitor#

Capacitor.Plugins.Keyboard β€” show(), hide(), addListener('keyboardDidShow' | ...)

Contoh

Membuka atau menutup keyboard layar dan memberi tahu halaman kapan muncul dan berapa tingginya (@capacitor/keyboard 8.0.5).

Mengembalikan: show() / hide() β†’ Promise void. addListener(event, fn) β†’ Promise berisi handle dengan remove(), seperti di API Capacitor sendiri - await atau rangkai .then(); nilai yang dikembalikan juga punya remove() sendiri; event show meneruskan { keyboardHeight } dalam piksel CSS. Event: keyboardWillShow, keyboardDidShow, keyboardWillHide, keyboardDidHide. Memerlukan: tidak ada yang perlu diaktifkan - setiap aplikasi sudah memuat plugin ini. window.Capacitor ada di halaman yang disajikan aplikasi sendiri (aplikasi HTML, ZIP, dan buatan AI) dan, pada aplikasi mode Situs web, di situs Anda sendiri (domain dan subdomainnya) - tidak pernah di situs lain yang dibuka aplikasi. Deteksi fitur terlebih dahulu.

var Keyboard = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.Keyboard;

if (Keyboard) {
  Keyboard.addListener('keyboardDidShow', function (info) {
    console.log('keyboard height', info.keyboardHeight);
    document.body.classList.add('typing');       // e.g. hide the bottom tab bar
  });
  Keyboard.addListener('keyboardDidHide', function () {
    document.body.classList.remove('typing');
  });
}

function onSend() {
  if (Keyboard) Keyboard.hide().catch(function () {});   // rejects if no field is focused
}

Di aplikasi buatan AI gunakan onKeyboard() untuk tata letak - ini hanya melaporkan bagian keyboard yang belum dikosongkan oleh halaman yang diubah ukurannya - dan hideKeyboard() untuk menutupnya:

import { onKeyboard, hideKeyboard, Keyboard } from '@/lib/appmintNative';

const off = onKeyboard((px) => { composer.style.paddingBottom = `${px}px`; });  // call off() on unmount
hideKeyboard();

const h = Keyboard.addListener('keyboardWillShow', ({ keyboardHeight }) => console.log(keyboardHeight));
h.remove();

Tampilkan keyboard untuk sebuah kolom setelah tombol diketuk:

var Keyboard = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.Keyboard;

searchBtn.addEventListener('click', function () {
  searchInput.focus();
  if (Keyboard) Keyboard.show().catch(function () {});
});

Catatan: Shell sudah mengubah ukuran halaman untuk keyboard, jadi JANGAN tambahkan keyboardHeight penuh sebagai padding - bilah bawah sudah berada di atas tombol. setAccessoryBarVisible, setStyle, setResizeMode, dan setScroll tidak diimplementasikan di Android - jangan panggil. hide() menolak "Can't close keyboard, not currently focused" bila tidak ada yang berfokus.

Capacitor.LocalNotifications Capacitor#

Capacitor.Plugins.LocalNotifications β€” schedule, cancel, getPending, requestPermissions, events

Contoh

Notifikasi yang diposting aplikasi sendiri - sekarang, atau pada waktu tertentu - dengan API resmi @capacitor/local-notifications (com.capacitorjs:local-notifications). Kode yang ditulis untuk paket npm berfungsi tanpa perubahan.

Mengembalikan: requestPermissions() / checkPermissions() β†’ { display: 'granted' | 'denied' | 'prompt' }; schedule({ notifications: [{ id, title, body, schedule?: { at | on | every }, extra?, actionTypeId?, channelId? }] }) β†’ { notifications: [{ id }] }; getPending() β†’ { notifications }; cancel({ notifications: [{ id }] }); registerActionTypes({ types }); createChannel / listChannels / deleteChannel; checkExactNotificationSetting() β†’ { exact_alarm }. Event: localNotificationReceived, localNotificationActionPerformed (actionId adalah 'tap' untuk ketukan pada notifikasi itu sendiri). Memerlukan: centang Notifikasi di Langkah 4 (Akses) - tanpa itu plugin tidak ada di aplikasi dan setiap panggilan ditolak "not implemented". Untuk notifikasi terjadwal centang juga ⏰ Pengingat (waktu tepat dan bertahan setelah reboot). Build HTML, ZIP, dan AI-Studio mencentang keduanya sendiri saat kode mengimpor @capacitor/local-notifications dan memanggil LocalNotifications.schedule(. window.Capacitor ada di halaman yang disajikan aplikasi sendiri (aplikasi HTML, ZIP, dan buatan AI) dan, pada aplikasi mode Situs web, di situs Anda sendiri (domain dan subdomainnya) - tidak pernah di situs lain yang dibuka aplikasi. Deteksi fitur terlebih dahulu.

const LN = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.LocalNotifications;

async function remindIn(minutes, text) {
  if (!LN) return false;
  const { display } = await LN.requestPermissions();
  if (display !== 'granted') return false;
  await LN.schedule({ notifications: [{
    id: Date.now() % 2147483647,
    title: 'Reminder',
    body: text,
    schedule: { at: new Date(Date.now() + minutes * 60000), allowWhileIdle: true },
    extra: { screen: 'tasks' },
  }] });
  return true;
}

Buka layar yang tepat saat pengguna mengetuk notifikasi - juga bila ketukan itu yang memulai aplikasi, karena event menunggu listener:

const LN = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.LocalNotifications;

if (LN) {
  LN.addListener('localNotificationActionPerformed', ({ actionId, notification }) => {
    if (actionId === 'tap' && notification.extra && notification.extra.screen) {
      location.hash = '#/' + notification.extra.screen;
    }
  });
}

Pengingat kebiasaan harian dengan tombol Selesai / Tunda:

const LN = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.LocalNotifications;

async function dailyWaterReminder() {
  await LN.registerActionTypes({ types: [{ id: 'water', actions: [
    { id: 'done', title: 'Done' },
    { id: 'snooze', title: 'In 30 min' },
  ] }] });
  await LN.schedule({ notifications: [{
    id: 42, title: 'Drink water', body: 'Time for a glass of water.',
    actionTypeId: 'water', schedule: { on: { hour: 10, minute: 0 }, repeats: true },
  }] });
  LN.addListener('localNotificationActionPerformed', ({ actionId }) => {
    if (actionId === 'snooze') {
      LN.schedule({ notifications: [{ id: 43, title: 'Drink water', body: 'Snoozed reminder.',
        schedule: { at: new Date(Date.now() + 30 * 60000) } }] });
    }
  });
}

Catatan: Di Android 12+ notifikasi terjadwal memerlukan izin alarm tepat waktu: schedule() pertama bisa membuka halaman sistem "Alarms & reminders"; bila pengguna membiarkannya mati, notifikasi tetap muncul, sedikit lebih lambat (hasilnya membawa warning). Notifikasi plugin memakai channel "Default" sendiri, terpisah dari notifikasi lain aplikasi. sound dari file web tidak didukung (Android memutar suara default channel). Ketukan sampai ke halaman melalui layar kunci saat aplikasi memiliki PIN. Aplikasi buatan AI memakai notify() / LocalNotifications.schedule dari @/lib/appmintNative, yang memposting lewat stack notifikasi aplikasi sendiri.

Capacitor.Network Capacitor#

Capacitor.Plugins.Network β€” getStatus(), addListener('networkStatusChange')

Contoh

Memberi tahu halaman apakah ponsel online dan lewat jenis koneksi apa, dan saat itu berubah (@capacitor/network 8.0.1).

Mengembalikan: getStatus() β†’ Promise { connected: boolean, connectionType: 'wifi' | 'cellular' | 'none' | 'unknown' }. Event networkStatusChange meneruskan bentuk yang sama. Memerlukan: tidak ada yang perlu diaktifkan - setiap aplikasi sudah memuat plugin ini. window.Capacitor ada di halaman yang disajikan aplikasi sendiri (aplikasi HTML, ZIP, dan buatan AI) dan, pada aplikasi mode Situs web, di situs Anda sendiri (domain dan subdomainnya) - tidak pernah di situs lain yang dibuka aplikasi. Deteksi fitur terlebih dahulu.

var Network = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.Network;

function showBanner(s) {
  document.getElementById('offline').hidden = s.connected;
}

if (Network) {
  Network.getStatus().then(showBanner);
  Network.addListener('networkStatusChange', function (s) {
    showBanner(s);
    if (s.connected) retryQueuedWrites();
    if (s.connectionType === 'cellular') console.log('on mobile data');
  });
}

Di aplikasi buatan AI:

import { Network, networkStatus, onNetworkChange } from '@/lib/appmintNative';

const { connected, connectionType } = await Network.getStatus();
const now = networkStatus();                        // sync: { connected, type }
const off = onNetworkChange((s) => setOnline(s.connected));   // call off() on unmount

Jeda unggahan besar saat memakai data seluler:

var Network = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.Network;

async function canUploadVideo() {
  if (!Network) return navigator.onLine;
  var s = await Network.getStatus();
  if (!s.connected) return false;
  return s.connectionType === 'wifi' || confirm('Upload over mobile data?');
}

Catatan: connected berarti ponsel punya jaringan, bukan berarti server Anda menjawab - tetap tangani permintaan yang gagal. Network.getStatus() dan networkStatus() milik wrapper membaca navigator.onLine / navigator.connection, bukan plugin, sehingga tipenya bisa 'unknown' atau kelas kecepatan seperti '4g'; onNetworkChange() memang memakai event plugin di aplikasi.

Capacitor.Preferences Capacitor#

Capacitor.Plugins.Preferences β€” get / set / remove / keys / clear

Contoh

Penyimpanan key-value native kecil (Android SharedPreferences) untuk string (@capacitor/preferences 8.0.1).

Mengembalikan: set({ key, value }), remove({ key }), clear() β†’ Promise void; get({ key }) β†’ { value } (null bila key tidak ada); keys() β†’ { keys: string[] }. Memerlukan: tidak ada yang perlu diaktifkan - setiap aplikasi sudah memuat plugin ini. window.Capacitor ada di halaman yang disajikan aplikasi sendiri (aplikasi HTML, ZIP, dan buatan AI) dan, pada aplikasi mode Situs web, di situs Anda sendiri (domain dan subdomainnya) - tidak pernah di situs lain yang dibuka aplikasi. Deteksi fitur terlebih dahulu.

var Prefs = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.Preferences;

async function saveTheme(name) {
  if (!Prefs) return false;          // not inside the app
  await Prefs.set({ key: 'theme', value: name });
  return true;
}

async function loadTheme() {
  if (!Prefs) return null;
  var r = await Prefs.get({ key: 'theme' });
  return r.value;            // null if never saved
}

Objek harus diubah menjadi string terlebih dahulu:

async function saveUser() {
  if (!Prefs) return;
  await Prefs.set({ key: 'user', value: JSON.stringify({ id: 7, name: 'Asha' }) });
  var u = JSON.parse((await Prefs.get({ key: 'user' })).value || 'null');
  var all = (await Prefs.keys()).keys;
  await Prefs.remove({ key: 'user' });
}

Tampilkan dan hapus kunci tersimpan dari layar pengaturan:

async function resetSettings() {
  if (!Prefs) return;
  var k = (await Prefs.keys()).keys;
  console.log('clearing', k.length, 'saved values');
  await Prefs.clear();
}

Catatan: @/lib/appmintNative TIDAK punya wrapper Preferences, dengan sengaja: localStorage sudah nyata dan persisten di aplikasi, dan penyimpanan kedua akan memecah data satu aplikasi ke dua tempat. Aplikasi buatan AI sebaiknya tetap memakai localStorage (atau data runtime). Gunakan Preferences di halaman yang ditulis manual hanya bila Anda ingin semua pengaturan di sana, dan pilih satu penyimpanan per nilai. configure({ group }) mengubah nama penyimpanan (default CapacitorStorage).

Capacitor.PrivacyScreen Capacitor#

Capacitor.Plugins.PrivacyScreen β€” enable(), disable(), isEnabled()

Contoh

Plugin resmi @capacitor/privacy-screen: memblokir tangkapan layar dan perekaman layar dan menyembunyikan konten aplikasi di tampilan aplikasi terbaru. Sudah tertanam agar proyek Capacitor yang diimpor dan memanggilnya tetap berfungsi.

Mengembalikan: enable({android}) β†’ {success}; disable() β†’ {success}; isEnabled() β†’ {enabled}. Memerlukan: tidak ada yang perlu diaktifkan.

const Privacy = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.PrivacyScreen;

async function openVault() {
  if (Privacy) await Privacy.enable({ android: { privacyModeOnActivityHidden: 'dim' } });
  showVault();
}
async function closeVault() {
  if (Privacy) await Privacy.disable();
}

Periksa status saat ini sebelum mengalihkan:

async function toggleProtection() {
  if (!Privacy) return;
  var s = await Privacy.isEnabled();
  if (s.enabled) await Privacy.disable();
  else await Privacy.enable();
}

Lindungi layar hanya saat tampilan sensitif terbuka:

async function showCardNumber() {
  if (Privacy) await Privacy.enable({ android: { privacyModeOnActivityHidden: 'splash' } });
  cardBox.hidden = false;
}
async function hideCardNumber() {
  cardBox.hidden = true;
  if (Privacy) await Privacy.disable();
}

Catatan: privacyModeOnActivityHidden: 'none', 'dim', atau 'splash'. Kode yang ditulis untuk aplikasi itu sendiri sebaiknya memakai WebToApk.setSecureScreen(true) / privacyScreen.enable() dari @/lib/appmintNative, yang mengikuti halaman (dilepas saat aplikasi meninggalkannya); bila keduanya dicampur, panggilan terakhir yang berlaku.

Capacitor.PushNotifications Capacitor#

Capacitor.Plugins.PushNotifications β€” register, requestPermissions, registration, pushNotificationReceived

Contoh

Notifikasi push dari server ANDA sendiri melalui project Firebase ANDA, dengan API resmi @capacitor/push-notifications (com.capacitorjs:push-notifications, didaftarkan oleh PushNotificationsPlugin.kt milik shell). Kode yang ditulis untuk paket npm berfungsi tanpa perubahan: register(), lalu kirim ke token dari event registration dengan Firebase Admin SDK atau FCM HTTP v1 API.

Mengembalikan: requestPermissions() / checkPermissions() β†’ { receive: 'granted' | 'denied' | 'prompt' }; register() / unregister() β†’ void (token tiba sebagai event registration { value }, kegagalan sebagai registrationError { error }); getDeliveredNotifications() β†’ { notifications }; removeDeliveredNotifications({ notifications }), removeAllDeliveredNotifications(); createChannel({ id, name, importance? }), listChannels(), deleteChannel({ id }). Event: pushNotificationReceived (pesan saat aplikasi terbuka: { id, title?, body?, data }) dan pushNotificationActionPerformed ({ actionId: 'tap', notification: { id, data } }). Memerlukan: build dengan AppMint Push diaktifkan dan google-services.json Anda diunggah (langkah Notifikasi) - itulah project Firebase tempat token berada. Tanpa itu register() ditolak dengan kode PUSH_NOT_CONFIGURED ("Push is not set up in this app"). Build HTML, ZIP, dan AI-Studio mencentang Notifikasi sendiri saat kode memanggil PushNotifications.register( / requestPermissions( / addListener(. window.Capacitor ada di halaman yang disajikan aplikasi sendiri (aplikasi HTML, ZIP, dan buatan AI) dan, pada aplikasi mode Situs web, di situs Anda sendiri (domain dan subdomainnya) - tidak pernah di situs lain yang dibuka aplikasi. Deteksi fitur terlebih dahulu.

const Push = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.PushNotifications;

async function enablePush(userId) {
  if (!Push) return;
  await Push.addListener('registration', ({ value }) => {
    // Your server stores the token and sends to it later.
    fetch('https://api.example.com/push-tokens', {
      method: 'POST', headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ userId, token: value, platform: 'android' }),
    });
  });
  await Push.addListener('registrationError', ({ error }) => console.warn('push:', error));
  const { receive } = await Push.requestPermissions();
  if (receive !== 'granted') return;
  try { await Push.register(); }
  catch (e) { if (e.code === 'PUSH_NOT_CONFIGURED') alert('Push is not set up in this build.'); }
}

Tanggapi pesan saat aplikasi terbuka, dan ketukan pada pesan yang masuk saat aplikasi tertutup (event ketukan menunggu listener Anda, sehingga start dingin tidak terlewat):

const Push = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.PushNotifications;

if (Push) {
  Push.addListener('pushNotificationReceived', (msg) => {
    alert((msg.title || 'New message') + (msg.body ? ': ' + msg.body : ''));
  });
  Push.addListener('pushNotificationActionPerformed', ({ notification }) => {
    const orderId = notification.data && notification.data.orderId;
    if (orderId) location.hash = '#/orders/' + orderId;
  });
}

Channel untuk peringatan penting (Android 8+), dipakai oleh pesan yang menyebutnya di android.notification.channel_id:

const Push = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.PushNotifications;

async function setupChannels() {
  if (!Push) return;
  await Push.createChannel({ id: 'orders', name: 'Order updates', description: 'Your order status', importance: 4, vibration: true });
}

Catatan: Pesan yang dikirim dengan blok notification ditampilkan oleh Android sendiri saat aplikasi di latar belakang; ketukannya membuka aplikasi (melalui layar kunci saat aplikasi memiliki PIN) dan memicu pushNotificationActionPerformed. Saat aplikasi terbuka, pesan datang sebagai pushNotificationReceived dan tidak digambar di baki. Pesan data-only hanya sampai ke halaman saat halaman terbuka. Pesan AppMint Push tetap berfungsi berdampingan - tidak pernah sampai ke plugin ini. Pada aplikasi yang dibangun dengan OneSignal alih-alih AppMint Push, pesan dikirim oleh OneSignal dan tidak pernah sampai ke plugin ini. Aplikasi buatan AI menerima push kreator melalui pushInbox() dari @/lib/appmintNative.

Capacitor.ScreenBrightness Capacitor#

Capacitor.Plugins.ScreenBrightness β€” getBrightness(), setBrightness({ brightness })

Contoh

Mengatur kecerahan layar jendela aplikasi - kecerahan penuh untuk boarding pass atau kode QR, lalu dikembalikan. Dibundel @capacitor-community/screen-brightness (template/plugins/screen-brightness).

Mengembalikan: getBrightness() β†’ Promise { brightness } (0-1, atau -1 bila aplikasi belum menimpanya dan layar mengikuti sistem). setBrightness({ brightness }) β†’ Promise void. Memerlukan: tidak ada - setiap aplikasi sudah memuat plugin ini; tanpa izin (hanya mengubah jendela aplikasi ini, bukan pengaturan sistem). window.Capacitor ada di halaman yang disajikan aplikasi sendiri (aplikasi HTML, ZIP, dan buatan AI) dan, pada aplikasi mode Situs web, di situs Anda sendiri (domain dan subdomainnya) - tidak pernah di situs lain yang dibuka aplikasi. Deteksi fitur terlebih dahulu.

var SB = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.ScreenBrightness;

async function showTicket() {
  if (SB) await SB.setBrightness({ brightness: 1 });     // full brightness
  document.getElementById('qr').hidden = false;
}

async function hideTicket() {
  if (SB) await SB.setBrightness({ brightness: -1 });    // -1 = follow the system again
  document.getElementById('qr').hidden = true;
}

Di aplikasi buatan AI:

import { brightness } from '@/lib/appmintNative';

await brightness.set(1);        // clamped to 0–1; false where not available (web)
// ... on leaving the screen
await brightness.restore();
const level = await brightness.get();   // -1 = following the system / not available

Baca level saat ini terlebih dahulu, lalu pulihkan persis ke level itu:

var SB = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.ScreenBrightness;
var before = -1;

async function boost() {
  if (!SB) return;
  before = (await SB.getBrightness()).brightness;
  await SB.setBrightness({ brightness: 1 });
}
async function undo() {
  if (SB) await SB.setBrightness({ brightness: before });
}

Catatan: Selalu berikan angka - setBrightness({}) tidak punya nilai untuk diterapkan. Pulihkan dengan -1 saat tampilan ditutup; penimpaan juga berakhir saat aplikasi ditutup. Halaman web tidak bisa mengendalikan lampu latar, sehingga can('brightness') adalah 'none' di browser.

Capacitor.ScreenOrientation Capacitor#

Capacitor.Plugins.ScreenOrientation β€” orientation(), lock({ orientation }), unlock()

Contoh

Membaca orientasi layar, mengunciknya untuk satu tampilan (game, grafik, kolom tanda tangan) lalu melepasnya (@capacitor/screen-orientation 8.0.1).

Mengembalikan: orientation() β†’ Promise { type } (mis. 'portrait-primary'). lock() / unlock() β†’ Promise void. Event screenOrientationChange meneruskan { type }. Memerlukan: tidak ada yang perlu diaktifkan - setiap aplikasi sudah memuat plugin ini. window.Capacitor ada di halaman yang disajikan aplikasi sendiri (aplikasi HTML, ZIP, dan buatan AI) dan, pada aplikasi mode Situs web, di situs Anda sendiri (domain dan subdomainnya) - tidak pernah di situs lain yang dibuka aplikasi. Deteksi fitur terlebih dahulu.

orientation nilai: 'portrait', 'landscape', 'portrait-primary', 'portrait-secondary', 'landscape-primary', 'landscape-secondary', 'natural', 'any'.

var SO = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.ScreenOrientation;

async function openChart() {
  if (SO) await SO.lock({ orientation: 'landscape' });
  showChart();
}

async function closeChart() {
  if (SO) await SO.unlock();          // always release when leaving the view
  hideChart();
}

if (SO) {
  SO.orientation().then(function (o) { console.log('now', o.type); });
  SO.addListener('screenOrientationChange', function (o) { console.log('rotated to', o.type); });
}

Di aplikasi buatan AI:

import { lockOrientation, ScreenOrientation } from '@/lib/appmintNative';

const ok = await lockOrientation('landscape');   // false when refused (always on desktop)
await lockOrientation('any');                    // release

await ScreenOrientation.lock({ orientation: 'portrait' });
await ScreenOrientation.unlock();

Tangani penguncian yang ditolak dan beri tahu pengguna:

var SO = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.ScreenOrientation;
var Toast = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.Toast;

async function tryLandscape() {
  if (!SO) { document.getElementById('rotate-hint').hidden = false; return; }   // ask the user to rotate by hand
  try {
    await SO.lock({ orientation: 'landscape' });
  } catch (e) {
    if (Toast) Toast.show({ text: 'Could not rotate the screen', duration: 'short' });
  }
}

Catatan: Wrapper hanya mengenal portrait / landscape / any: ScreenOrientation.lock({ orientation: 'landscape-secondary' }) mengunci ke landscape biasa. Beri pengguna jalan keluar dari tampilan yang terkunci.

Capacitor.ScreenReader Capacitor#

Capacitor.Plugins.ScreenReader β€” isEnabled(), speak({ value, language }), addListener('stateChange')

Contoh

Memberi tahu halaman apakah TalkBack aktif, dan mengucapkan pengumuman (@capacitor/screen-reader 8.0.1).

Mengembalikan: isEnabled() β†’ Promise { value: boolean }. speak() β†’ Promise void. Event stateChange meneruskan { value: boolean } saat TalkBack dihidupkan atau dimatikan. Memerlukan: tidak ada yang perlu diaktifkan - setiap aplikasi sudah memuat plugin ini. window.Capacitor ada di halaman yang disajikan aplikasi sendiri (aplikasi HTML, ZIP, dan buatan AI) dan, pada aplikasi mode Situs web, di situs Anda sendiri (domain dan subdomainnya) - tidak pernah di situs lain yang dibuka aplikasi. Deteksi fitur terlebih dahulu.

var SR = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.ScreenReader;

function setCalmMode(on) {
  document.documentElement.classList.toggle('no-motion', on);   // shorten animations
}

if (SR) {
  SR.isEnabled().then(function (r) { setCalmMode(r.value); });
  SR.addListener('stateChange', function (s) { setCalmMode(s.value); });
}

async function announceSaved() {
  if (SR) await SR.speak({ value: 'Order placed', language: 'en' });
}

Di aplikasi buatan AI (speak memakai text-to-speech di web; isEnabled() adalah false di sana):

import { screenReader } from '@/lib/appmintNative';

const on = await screenReader.isEnabled();
const off = screenReader.onChange((enabled) => setCalmMode(enabled));
await screenReader.speak('Order placed', 'en');

Deteksi fitur dan jaga halaman tetap bisa dipakai tanpa plugin:

var SR = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.ScreenReader;

async function say(message) {
  if (SR) { await SR.speak({ value: message }); return; }
  document.getElementById('live-region').textContent = message;   // an aria-live="polite" element
}

Catatan: language default-nya 'en'. Utamakan markup yang aksesibel biasa (label, wilayah aria-live) untuk sebagian besar pengumuman; gunakan speak untuk perubahan status yang singkat dan penting. Tidak ada API web untuk mendeteksi pembaca layar, sehingga can('screenReader') adalah 'none' di browser.

Capacitor.Share Capacitor#

Capacitor.Plugins.Share β€” share(options), canShare()

Contoh

Membuka lembar berbagi Android dengan judul, teks, dan/atau tautan (@capacitor/share 8.0.1).

Mengembalikan: share() β†’ Promise { activityType } (nama komponen aplikasi yang dipilih, bisa ''); DITOLAK saat pengguna menutup lembar. canShare() β†’ Promise { value: boolean }. Memerlukan: tidak ada yang perlu diaktifkan - setiap aplikasi sudah memuat plugin ini. window.Capacitor ada di halaman yang disajikan aplikasi sendiri (aplikasi HTML, ZIP, dan buatan AI) dan, pada aplikasi mode Situs web, di situs Anda sendiri (domain dan subdomainnya) - tidak pernah di situs lain yang dibuka aplikasi. Deteksi fitur terlebih dahulu.

async function shareLink() {
  var Share = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.Share;
  if (!Share) { alert('Sharing is not available here'); return; }
  // Only pass the fields you have. A present but empty `url` is rejected ("Unsupported url").
  var opts = { title: 'My list', text: 'Milk, eggs, bread' };
  var link = 'https://example.com/list/42';
  if (link) opts.url = link;
  try {
    var r = await Share.share(opts);
    console.log('shared to', r.activityType);
  } catch (e) {
    console.log('share cancelled or failed:', e.message);   // "Share canceled" on dismiss
  }
}

Dalam aplikasi buatan AI pembungkusnya memiliki bentuk yang sama dan juga menolak saat dibatalkan:

import { Share, can } from '@/lib/appmintNative';

if (can('share') !== 'none') {
  try {
    await Share.share({ title: 'My list', text: 'Milk, eggs, bread', url: 'https://example.com/list/42' });
  } catch {
    // the user closed the sheet β€” not an error to show
  }
}

Periksa canShare() terlebih dahulu dan sembunyikan tombol bila berbagi tidak tersedia:

var Share = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.Share;
var btn = document.getElementById('share');

btn.hidden = true;
if (Share) {
  Share.canShare().then(function (r) { btn.hidden = !r.value; });
}

Catatan: url harus berupa http(s):// atau file://. dialogTitle mengatur judul pemilih. Berbagi file memerlukan path file:// yang dimiliki aplikasi; dari halaman, bagikan file dengan navigator.share({ files }) sebagai gantinya. Hanya satu berbagi yang bisa terbuka sekaligus ("Can't share while sharing is in progress").

Capacitor.SpeechRecognition Capacitor#

Capacitor.Plugins.SpeechRecognition

Contoh

Mengubah ucapan pengguna menjadi teks dengan pengenal suara Android (plugin komunitas @capacitor-community/speech-recognition, tertanam di aplikasi). Android WebView tidak punya pengenalan Web Speech sendiri, jadi inilah cara untuk dikte.

Mengembalikan: Promise. available() β†’ { available }. checkPermissions() / requestPermissions() β†’ { speechRecognition: 'granted' | 'denied' | 'prompt' }. start({ partialResults: false }) β†’ { status: 'success', matches: [...] } setelah pengguna berhenti berbicara; ditolak pada kesalahan seperti tidak ada ucapan atau tidak cocok. Memerlukan: centang Mikrofon di Langkah 4 (Akses) saat build (untuk aplikasi HTML, ZIP, dan buatan AI, build juga menambahkan izin mikrofon sendiri bila file Anda menyebut SpeechRecognition), dan pengguna harus mengizinkan mikrofon. window.Capacitor ada di halaman yang disajikan aplikasi sendiri (aplikasi HTML, ZIP, dan buatan AI) dan, pada aplikasi mode Situs web, di situs Anda sendiri (domain dan subdomainnya) - tidak pernah di situs lain yang dibuka aplikasi. Deteksi fitur terlebih dahulu.

Dikte sekali jalan (cara yang sama @/lib/appmintNative speech menggunakannya):

var SR = window.Capacitor && window.Capacitor.Plugins ? window.Capacitor.Plugins.SpeechRecognition : null;

async function dictate() {
  var out = document.getElementById('text');
  if (!SR || !(await SR.available()).available) { out.textContent = 'Voice input is not available on this phone.'; return; }

  var p = (await SR.checkPermissions()).speechRecognition;
  if (p !== 'granted') p = (await SR.requestPermissions()).speechRecognition;
  if (p !== 'granted') { out.textContent = 'Microphone permission was not given.'; return; }

  try {
    var r = await SR.start({ language: 'en-US', maxResults: 3, partialResults: false, popup: false });
    out.textContent = r.matches && r.matches.length ? r.matches[0] : '';
  } catch (e) {
    out.textContent = 'Did not catch that. Try again.';
  }
}

document.getElementById('mic').addEventListener('click', dictate);

Teks langsung saat pengguna berbicara (partialResults: true), dan status mendengarkan:

// Add the listeners ONCE, when the page starts.
if (SR) {
  SR.addListener('partialResults', function (d) {
    // Words as they come, and then the final text, all arrive here.
    if (d.matches && d.matches.length) document.getElementById('text').textContent = d.matches[0];
  });
  SR.addListener('listeningState', function (d) {
    // 'started' = the user began speaking, 'stopped' = the user stopped speaking
    document.body.classList.toggle('listening', d.status === 'started');
  });
}

document.getElementById('mic-live').addEventListener('click', async function () {
  if (!SR) return;
  try {
    await SR.start({ language: 'en-US', partialResults: true, popup: false });   // resolves at once, no matches
  } catch (e) {
    document.getElementById('text').textContent = 'Could not start: ' + e.message;
  }
});

document.getElementById('stop').addEventListener('click', function () { if (SR) SR.stop(); });

Tampilkan tombol mikrofon hanya saat dikte bisa berfungsi, dan berhenti mendengarkan saat halaman disembunyikan:

var SR = window.Capacitor && window.Capacitor.Plugins ? window.Capacitor.Plugins.SpeechRecognition : null;
var mic = document.getElementById('mic');

mic.hidden = true;
if (SR) {
  SR.available().then(function (r) { mic.hidden = !r.available; });
}

document.addEventListener('visibilitychange', function () {
  if (document.hidden && SR) SR.stop();
});

Catatan:

  • Dalam mode langsung (partialResults: true), teks akhir tiba setelah status 'stopped', jadi jangan hapus listener partialResults pada 'stopped'. Kesalahan setelah mulai (tanpa ucapan, tidak cocok) tidak dilaporkan dalam mode ini.
  • language adalah tag seperti 'en-US' atau 'ta-IN' (default: bahasa ponsel). popup: true menampilkan dialog mendengarkan milik Google sebagai gantinya. getSupportedLanguages() β†’ { languages } dan isListening() β†’ { listening } juga tersedia.
  • start() ditolak dengan 'Missing permission' bila Anda tidak meminta izin terlebih dahulu. Mendengarkan berhenti sendiri setelah jeda bicara.

Capacitor.SplashScreen Capacitor#

Capacitor.Plugins.SplashScreen β€” show(), hide()

Contoh

API @capacitor/splash-screen di atas splash peluncuran aplikasi sendiri yang bermerek, sehingga proyek Capacitor / AI Studio yang diimpor dan memanggil SplashScreen.hide() begitu layar pertamanya siap tetap berfungsi di aplikasi Android.

Mengembalikan: hide() β†’ Promise (splash hilang setelah waktu splash minimum dari pembuat terlewati); show({showDuration, autoHide}) β†’ Promise (splash kembali di atas halaman dan, dengan autoHide - default - hilang setelah showDuration ms, default 3000). Memerlukan: tidak ada yang perlu diaktifkan.

const Splash = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.SplashScreen;

async function boot() {
  await loadFirstScreen();
  if (Splash) await Splash.hide();     // otherwise the shell hides it at first paint
}
boot();

Tutupi pergantian akun yang lambat dengan splash, dipertahankan sampai data baru tampil di layar:

const Splash = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.SplashScreen;

async function switchAccount(accountId) {
  if (Splash) await Splash.show({ autoHide: false });   // stays until hide()
  try {
    await loadAccount(accountId);
    renderHome();
  } finally {
    if (Splash) await Splash.hide();
  }
}

Tampilkan splash bermerek sejenak setelah keluar; hilang dengan sendirinya setelah showDuration:

const Splash = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.SplashScreen;

async function signOut() {
  await clearSession();
  showSignInScreen();
  if (Splash) {
    try {
      await Splash.show({ showDuration: 1200 });
    } catch (e) {
      console.warn('splash not shown:', e.code);
    }
  }
}

Catatan: tanpa panggilan hide(), splash tetap hilang pada render pertama, seperti setiap aplikasi. Aplikasi buatan AI memakai splash.hold() / splash.ready() dari @/lib/appmintNative.

Capacitor.StatusBar Capacitor#

Capacitor.Plugins.StatusBar β€” setStyle, setBackgroundColor, show, hide, getInfo

Contoh

Mengubah gaya ikon, warna, dan visibilitas status bar (@capacitor/status-bar 8.0.2).

Mengembalikan: setiap metode β†’ Promise void, kecuali getInfo() β†’ { visible, style, color, overlays, height }. Memerlukan: tidak ada yang perlu diaktifkan - setiap aplikasi sudah memuat plugin ini. window.Capacitor ada di halaman yang disajikan aplikasi sendiri (aplikasi HTML, ZIP, dan buatan AI) dan, pada aplikasi mode Situs web, di situs Anda sendiri (domain dan subdomainnya) - tidak pernah di situs lain yang dibuka aplikasi. Deteksi fitur terlebih dahulu.

style menyebut LATAR BELAKANG yang cocok: 'DARK' = ikon terang (untuk bilah gelap), 'LIGHT' = ikon gelap, 'DEFAULT' = ikuti sistem.

var StatusBar = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.StatusBar;
if (StatusBar) {
  StatusBar.setStyle({ style: 'DARK' });          // light icons
  StatusBar.hide();                               // e.g. while a video plays
  // later
  StatusBar.show();
}

Warnai bilah dengan jembatan shell, bukan plugin. Di Android 15+ setBackgroundColor milik plugin tidak berpengaruh (edge-to-edge mengabaikannya). Shell mengecat strip itu sendiri dan menerima gaya ikon dalam panggilan yang sama:

if (window.WebToApk && window.WebToApk.setStatusBarColor) {
  window.WebToApk.setStatusBarColor('#0B0F1A', 'light');   // dark bar, light icons
} else if (StatusBar) {
  StatusBar.setBackgroundColor({ color: '#0B0F1A' });      // hex only, e.g. #RRGGBB
}

Di aplikasi buatan AI gunakan setStatusBar(color, contentStyle); ini mengutamakan jembatan shell dan mengatur warna serta ikon dalam satu panggilan:

import { setStatusBar, StatusBar } from '@/lib/appmintNative';

setStatusBar('#0B0F1A', 'light');                       // dark bar, light icons
await StatusBar.setBackgroundColor({ color: '#FFFFFF' }); // colour only; icons picked from luminance

Catatan: setBackgroundColor menolak warna yang bukan string hex. Pada build layar penuh / kiosk, bilah disembunyikan oleh shell. Di aplikasi Android StatusBar.setStyle() milik wrapper saja tidak mengubah apa pun (jembatan memerlukan warna untuk dicat) - berikan gaya ke setStatusBar() bersama warna.

Capacitor.TextToSpeech Capacitor#

Capacitor.Plugins.TextToSpeech β€” speak(), stop(), getSupportedLanguages(), getSupportedVoices()

Contoh

Plugin komunitas @capacitor-community/text-to-speech di atas mesin text-to-speech ponsel. Sudah disertakan agar proyek Capacitor impor yang memanggilnya berfungsi.

Mengembalikan: speak({text, lang, rate, pitch, volume, voice}) β†’ Promise yang resolve saat kalimat selesai diucapkan; stop(); getSupportedLanguages() β†’ {languages}; getSupportedVoices() β†’ {voices}; isLanguageSupported({lang}) β†’ {supported}. Memerlukan: tidak ada yang perlu diaktifkan.

const Tts = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.TextToSpeech;

async function readAloud(text) {
  if (!Tts) { speechSynthesis.speak(new SpeechSynthesisUtterance(text)); return; }
  await Tts.speak({ text: text, lang: 'en-US', rate: 1.0, pitch: 1.0, volume: 1.0 });
}
document.getElementById('stop').onclick = () => Tts && Tts.stop();

Periksa bahasa sebelum berbicara dan tampilkan pesan bila belum terpasang:

const Tts = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.TextToSpeech;

async function speakIn(lang, text) {
  if (!Tts) return false;
  const { supported } = await Tts.isLanguageSupported({ lang: lang });
  if (!supported) { showMessage('This phone has no ' + lang + ' voice installed.'); return false; }
  await Tts.speak({ text: text, lang: lang });
  return true;
}

Bacakan sebuah paragraf dengan tombol berhenti, dan tangani kesalahan saat berbicara:

const Tts = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.TextToSpeech;

async function readParagraph(el, btn) {
  if (!Tts) return;
  btn.textContent = 'Stop';
  btn.onclick = () => Tts.stop();
  try {
    await Tts.speak({ text: el.textContent, lang: 'en-US', rate: 0.9 });   // resolves when finished
  } catch (e) {
    console.warn('could not speak:', e.message);
  } finally {
    btn.textContent = 'Listen';
    btn.onclick = () => readParagraph(el, btn);
  }
}

Catatan: window.speechSynthesis juga berfungsi di aplikasi (engine milik shell) dan itulah yang dipakai aplikasi buatan AI lewat speak(); plugin ini adalah jalur berbentuk Capacitor.

Capacitor.TextZoom Capacitor#

Capacitor.Plugins.TextZoom β€” get(), getPreferred(), set({ value })

Contoh

Membaca dan mengubah ukuran teks halaman aplikasi, untuk kontrol "ukuran teks" di dalam aplikasi (@capacitor/text-zoom 8.0.1).

Mengembalikan: get() β†’ Promise { value } (zoom saat ini, 1 = 100%). getPreferred() β†’ { value } (ukuran yang dipilih pengguna di pengaturan Android). set({ value }) β†’ Promise void. Memerlukan: tidak ada yang perlu diaktifkan - setiap aplikasi sudah memuat plugin ini. window.Capacitor ada di halaman yang disajikan aplikasi sendiri (aplikasi HTML, ZIP, dan buatan AI) dan, pada aplikasi mode Situs web, di situs Anda sendiri (domain dan subdomainnya) - tidak pernah di situs lain yang dibuka aplikasi. Deteksi fitur terlebih dahulu.

var TZ = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.TextZoom;

async function biggerText() {
  if (!TZ) return;
  var now = (await TZ.get()).value;
  await TZ.set({ value: Math.min(2, now + 0.1) });
}

async function resetText() {
  if (!TZ) return;
  var pref = (await TZ.getPreferred()).value;   // e.g. 1.15 when the phone uses large text
  await TZ.set({ value: pref });
}

Di aplikasi buatan AI (di web ini menskalakan ukuran font root sebagai gantinya):

import { textZoom } from '@/lib/appmintNative';

const size = await textZoom.get();
await textZoom.set(size + 0.1);                     // clamped to 0.5–3
await textZoom.set(await textZoom.getPreferred());  // back to the system size

Penggeser ukuran teks yang mengingat pilihan:

var TZ = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.TextZoom;
var slider = document.getElementById('text-size');   // <input type="range" min="0.8" max="1.6" step="0.1">

if (TZ) {
  var saved = parseFloat(localStorage.getItem('textZoom'));
  if (saved) TZ.set({ value: saved });
  slider.addEventListener('change', function () {
    TZ.set({ value: parseFloat(slider.value) });
    localStorage.setItem('textZoom', slider.value);
  });
} else {
  slider.hidden = true;
}

Catatan: Aplikasi sudah mengikuti ukuran teks sistem; ini untuk kontrol tambahan di dalam aplikasi. Uji tata letak Anda pada ukuran besar - tinggi tetap pada kontrol teks akan terpotong.

Capacitor.Toast Capacitor#

Capacitor.Plugins.Toast β€” show({ text, duration, position })

Contoh

Menampilkan toast sistem Android singkat seperti "Saved" atau "Copied" (@capacitor/toast 8.0.1).

Mengembalikan: Promise void. Memerlukan: tidak ada yang perlu diaktifkan - setiap aplikasi sudah memuat plugin ini. window.Capacitor ada di halaman yang disajikan aplikasi sendiri (aplikasi HTML, ZIP, dan buatan AI) dan, pada aplikasi mode Situs web, di situs Anda sendiri (domain dan subdomainnya) - tidak pernah di situs lain yang dibuka aplikasi. Deteksi fitur terlebih dahulu.

var Toast = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.Toast;

function saved() {
  if (Toast) Toast.show({ text: 'Saved', duration: 'short', position: 'bottom' });
}

duration adalah 'short' (sekitar 2 d) atau 'long' (sekitar 3,5 d). position adalah 'top', 'center' atau 'bottom'.

Di aplikasi buatan AI gunakan toast() atau Toast berbentuk Capacitor; di web keduanya menggambar snackbar dengan warna aplikasi:

import { Toast, toast } from '@/lib/appmintNative';

await Toast.show({ text: 'Added to list', duration: 'long' });
toast('Copied');   // short form, same result

Deteksi fitur dan tampilkan pesan di halaman saat plugin tidak ada:

function notify(message) {
  var Toast = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.Toast;
  if (Toast) { Toast.show({ text: message, duration: 'short' }); return; }
  var el = document.getElementById('snackbar');   // a plain in-page message
  el.textContent = message;
  el.hidden = false;
  setTimeout(function () { el.hidden = true; }, 2000);
}

Catatan: text wajib diisi ("Must provide text"). Sistem menggambar toast dengan gaya pembuat ponsel, dan versi Android yang lebih baru mengabaikan position untuk toast teks. Toast mudah terlewat - jangan pernah memakainya untuk kesalahan yang harus ditindaklanjuti pengguna; gunakan Dialog.alert untuk itu.

Capacitor.Torch Capacitor#

Capacitor.Plugins.Torch β€” enable(), disable(), toggle(), isEnabled(), isAvailable()

Contoh

Senter ponsel, dengan API @capawesome/capacitor-torch. Plugin milik shell aplikasi sendiri (TorchPlugin.kt).

Mengembalikan: enable() / disable() / toggle() β†’ Promise (ditolak CAMERA_IN_USE saat aliran kamera aplikasi sendiri terbuka, UNAVAILABLE bila tanpa flash); isEnabled() β†’ {enabled}; isAvailable() β†’ {available}. Memerlukan: tidak ada yang perlu diaktifkan dan tanpa izin.

const Torch = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.Torch;

async function setupLightButton() {
  if (!Torch || !(await Torch.isAvailable()).available) { lightBtn.hidden = true; return; }
  lightBtn.onclick = async () => {
    try {
      await Torch.toggle();
      lightBtn.classList.toggle('on', (await Torch.isEnabled()).enabled);
    } catch (e) {
      alert(e.message);
    }
  };
}

Kedipkan sinyal SOS dari sebuah tombol, dan matikan lampu jika kamera mengambil alih lampu kilat di tengah jalan:

const Torch = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.Torch;
const wait = (ms) => new Promise((r) => setTimeout(r, ms));

sosBtn.onclick = async () => {
  if (!Torch || !(await Torch.isAvailable()).available) return;
  const flashes = [200, 200, 200, 600, 600, 600, 200, 200, 200];   // S O S, in ms
  try {
    for (const ms of flashes) {
      await Torch.enable();  await wait(ms);
      await Torch.disable(); await wait(200);
    }
  } catch (e) {
    await Torch.disable().catch(() => {});
    alert(e.code === 'CAMERA_IN_USE' ? 'Close the camera first.' : e.message);
  }
};

Jaga tombol senter tetap selaras dengan sistem, karena pengguna bisa mengganti senter dari tile pengaturan cepat saat aplikasi di latar belakang:

const Torch = window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.Torch;

async function syncLightButton() {
  if (!Torch) return;
  const { enabled } = await Torch.isEnabled();
  lightBtn.classList.toggle('on', enabled);
  lightBtn.setAttribute('aria-pressed', String(enabled));
}

document.addEventListener('visibilitychange', () => {
  if (document.visibilityState === 'visible') syncLightButton();
});
syncLightButton();

Catatan: lampu mengikuti status sistem (mematikannya dari tile pengaturan cepat terbaca sebagai mati) dan dimatikan saat aplikasi ditutup. Saat aliran getUserMedia terbuka, nyalakan lewat track: track.applyConstraints({ advanced: [{ torch: true }] }). Aplikasi buatan AI memakai torch dari @/lib/appmintNative.

Dibuat dari runtime aplikasi dan file contohnya pada setiap build dokumentasi. Baca sebagai Markdown Β· Semua keluarga.

Diperiksa terhadap jembatan yang dirilis pada 2026-10-22.