Criar APK grátis

API da ponte JavaScript

Plugins do Capacitor

Os plugins do Capacitor que o app hospeda. Uma pĂĄgina escrita Ă mĂŁo os acessa como window.Capacitor.Plugins.<Name>; um app criado com IA usa o wrapper @/lib/appmintNative citado em cada exemplo.

Capacitor.ActionSheet Capacitor#

Capacitor.Plugins.ActionSheet — showActions({ title, message, options })

Exemplo

Mostra uma folha inferior nativa com uma lista de opçÔes e informa qual foi tocada (@capacitor/action-sheet 8.1.1).

Retorna: Promise { index, canceled } - index Ă© a opção tocada; quando a folha Ă© dispensada canceled Ă© true e index fica fora da lista (-1). Requer: nada para ativar - todo app hospeda o plugin. window.Capacitor existe nas pĂĄginas que o prĂłprio app serve (apps HTML, ZIP e criados com IA) e, em um app no modo Website, no seu prĂłprio site (seu domĂ­nio e subdomĂ­nios) - nunca em outros sites que o app abre. Detecte o recurso antes de usar.

Cada opção Ă© { title, style? } com style 'DEFAULT', 'DESTRUCTIVE' ou '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();
}

Em um app criado com IA o wrapper no formato Capacitor retorna { index: -1 } ao dispensar; a forma curta actionSheet() retorna 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

ConfirmaçÔes de exclusĂŁo que tambĂ©m funcionam em um navegador comum:

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;
}

Observaçþes: Sempre verifique o limite do Ă­ndice - nunca trate qualquer Ă­ndice como uma escolha real. O formato de opção do wrapper Ă© { title, destructive? }; ele mapeia destructive para o estilo 'DESTRUCTIVE' do plugin.

Capacitor.App Capacitor#

Capacitor.Plugins.App — getInfo(), getState(), exitApp(), minimizeApp(), addListener(...)

Exemplo

Identidade e ciclo de vida do app: nome, id do pacote, versĂŁo, se o app estĂĄ em primeiro plano e eventos de pausa/retomada (@capacitor/app 8.1.0).

Retorna: getInfo() → { name, id, build, version }; getState() → { isActive }; getLaunchUrl() → { url } ou nada; getAppLanguage() → { value }; exitApp() / minimizeApp() → void. addListener() → uma Promise de um handle com remove(), como na própria API do Capacitor - use await nele ou encadeie .then(); o valor retornado também tem remove(). Requer: nada para ativar - todo app hospeda o plugin. window.Capacitor existe em páginas que o próprio app serve (apps HTML, ZIP e criados com IA) e, em um app no modo Site, no seu próprio site (seu domínio e subdomínios) - nunca em outros sites que o app abre. Detecte o recurso.

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 + ')';
  });
}

Pausar e retomar - salve um rascunho quando o usuĂĄrio sair e atualize quando ele voltar:

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'); });
}

Em um app criado com IA:

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

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

Observaçþes: O evento backButton nunca dispara: o shell mantĂ©m o botĂŁo voltar (o plugin roda com disableBackButtonHandler). Trate o voltar com AppMint.setBackHandler(fn) ou o wrapper onBackGesture. Para links diretos (deep links) use WebToApk.getLaunchUrl() / o evento appmint:deep-link (ou launchUrl() / onDeepLink() em apps criados com IA). minimizeApp() Ă© sĂł para Android. Nunca faça de um botĂŁo Sair o Ășnico caminho adiante.

Capacitor.AppLauncher Capacitor#

Capacitor.Plugins.AppLauncher — canOpenUrl({ url }), openUrl({ url })

Exemplo

Abre outro app por link (whatsapp://send?text=…, tel:, geo:, um link https) e pergunta se algum app consegue tratĂĄ-lo (@capacitor/app-launcher 8.0.1).

Retorna: canOpenUrl() → Promise { value: boolean }. openUrl() → Promise { completed: boolean } (false quando nenhum app aceitou o link). Requer: nada para ativar - todo app hospeda o plugin. window.Capacitor existe nas pĂĄginas que o prĂłprio app serve (apps HTML, ZIP e criados com IA) e, em um app no modo Website, no seu prĂłprio site (seu domĂ­nio e subdomĂ­nios) - nunca em outros sites que o app abre. Detecte o recurso antes de usar.

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');
}

Em um app criado com IA:

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

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

Abra um link de mapa sem perguntar antes:

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');
}

Observaçþes: No Android 11+ um app sĂł consegue "ver" outros apps que ele declara. Os apps gerados declaram links https, geo, google.navigation, tel, mailto, sms, whatsapp, intent e upi, entĂŁo canOpenUrl responde false para outros esquemas (por exemplo spotify:) mesmo com o app instalado. openUrl ainda funciona para eles - chame-o e verifique completed. No Android canOpenUrl tambĂ©m aceita um nome de pacote ('com.whatsapp'), com o mesmo limite de visibilidade.

Capacitor.AppUpdate Capacitor#

Capacitor.Plugins.AppUpdate — getAppUpdateInfo(), performImmediateUpdate(), startFlexibleUpdate(), completeFlexibleUpdate(), openAppStore()

Exemplo

Verifica no Google Play se hĂĄ uma versĂŁo mais nova do app e inicia a atualização no app do Play. Incluso @capawesome/capacitor-app-update (template/plugins/app-update).

Retorna: getAppUpdateInfo() → { currentVersionName, currentVersionCode, availableVersionCode, updateAvailability, updatePriority, immediateUpdateAllowed, flexibleUpdateAllowed, clientVersionStalenessDays?, installStatus } (cĂłdigos de versĂŁo sĂŁo strings; updateAvailability 2 = hĂĄ uma atualização disponĂ­vel). performImmediateUpdate() / startFlexibleUpdate() → { code }: 0 OK, 1 cancelado, 2 falhou, 3 indisponĂ­vel, 4 nĂŁo permitido, 5 chame getAppUpdateInfo() primeiro. openAppStore() → void. Requer: nada para ativar; o app precisa estar instalado pelo Google Play. window.Capacitor existe nas pĂĄginas que o prĂłprio app serve (apps HTML, ZIP e criados com IA) e, em um app no modo Website, no seu prĂłprio site (seu domĂ­nio e subdomĂ­nios) - nunca em outros sites que o app abre. Detecte o recurso antes de usar.

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
  }
}

Atualização flexĂ­vel - baixe em segundo plano e reinicie quando o usuĂĄrio concordar:

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(); }

Em um app criado com IA:

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

Observaçþes: Use updateAvailability === 2 como Ășnico teste de "atualização disponĂ­vel". O check() do wrapper compara currentVersionName com availableVersionCode, que nunca sĂŁo iguais no Android, entĂŁo seu updateAvailable nĂŁo Ă© confiĂĄvel ali - teste inPlace em vez disso. start() resolve true mesmo quando o usuĂĄrio cancela.

Capacitor.AppwrightDocScanner Capacitor#

Capacitor.Plugins.AppwrightDocScanner — scan({ pageLimit, pdf, quality }), isSupported()

Exemplo

Abre o scanner de documentos do Google ML Kit: o usuĂĄrio fotografa uma ou mais pĂĄginas (ou as importa), as bordas sĂŁo encontradas e endireitadas, e as pĂĄginas voltam como imagens JPEG. Plugin prĂłprio do Appwright (AppwrightDocScannerPlugin.kt).

Retorna: scan() → Promise que sempre Ă© RESOLVIDA: { ok: true, pages: string[] (JPEG data URLs), pdfDataUrl?, pdfPath?, pdfError? } em caso de sucesso, { ok: false, cancelled: true } quando o usuĂĄrio desiste, { ok: false, error } quando o scanner nĂŁo consegue iniciar. isSupported() → { value: boolean } (Google Play services presente). Requer: nada para ativar e nenhuma permissĂŁo de cĂąmera (o scanner roda dentro do Play services, que baixa o modelo no primeiro uso).

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 = sem limite. quality Ă© de 0,1 a 1 para o JPEG. Com pdf: true o scanner tambĂ©m grava um PDF: pdfDataUrl Ă© ele como uma URL data:application/pdf;base64,… que a pĂĄgina pode baixar, enviar ou exibir, e pdfPath Ă© a cĂłpia dele na pasta de cache do app. Se o PDF nĂŁo pĂŽde ser lido, as pĂĄginas ainda voltam e pdfError diz o motivo.

Em um app criado com IA (null ao cancelar, em erro ou na 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
}

Escaneie vĂĄrias pĂĄginas e ofereça o 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');
}

Observaçþes: As pĂĄginas sĂŁo data URLs completos e podem ser grandes - reduza-as antes de salvar muitas em localStorage. Use pdfDataUrl, nĂŁo pdfPath - o caminho de um arquivo do dispositivo nĂŁo Ă© uma URL que a pĂĄgina consiga carregar. Uma pĂĄgina que nĂŁo puder ser lida Ă© ignorada; as demais ainda voltam.

Capacitor.AppwrightGallery Capacitor#

Capacitor.Plugins.AppwrightGallery — save({ source, fileName, album, kind })

Exemplo

Salva uma foto ou um vĂ­deo na galeria do celular (Pictures/<album> ou Movies/<album>). Plugin prĂłprio do shell do app (AppwrightGalleryPlugin.kt).

Retorna: Promise de { uri } do item salvo. Ă rejeitada com um code: bad-source, download-failed, permission-denied (Android 7-9, armazenamento recusado) ou failed. Requer: nada para ativar; nenhuma permissĂŁo no Android 10+ (o Android 7-9 pede armazenamento na primeira vez).

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);
  }
}

Salve um vĂ­deo do seu servidor em um ĂĄlbum prĂłprio, com uma mensagem para cada cĂłdigo de falha:

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);
  }
}

Salve uma foto que o usuĂĄrio editou como Blob (por exemplo de canvas.toBlob) convertendo-a antes em uma URL data::

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);
}

Observaçþes: source Ă© uma URL data:, uma URL http(s) ou uma URI content:///file://; kind ('image'/'video') Ă© lido do tipo MIME quando omitido. Apps criados com IA usam saveToGallery() de @/lib/appmintNative.

Capacitor.AppwrightHaptics Capacitor#

Capacitor.Plugins.AppwrightHaptics

Exemplo

Plugin prĂłprio do AppMint para padrĂ”es de vibração ricos: uma lista de batidas, cada uma com seu prĂłprio inĂ­cio, duração e intensidade.

Retorna: play({ events }) resolve { ok: true } ou { ok: false, error } ('unsupported' = sem vibrador, 'empty' = sem eventos, ou a mensagem do sistema). Nunca Ă© rejeitada. isSupported() resolve { value: true/false }. Requer: nada para ativar - todo app declara a permissĂŁo de vibração, estando ou nĂŁo Vibrar marcado na Etapa 4 (Acesso). window.Capacitor existe nas pĂĄginas que o prĂłprio app serve (apps HTML, ZIP e criados com IA) e, em um app no modo Website, no seu prĂłprio site (seu domĂ­nio e subdomĂ­nios) - nunca em outros sites que o app abre. Detecte o recurso antes de usar.

Cada evento Ă© { at, duration, intensity, sharpness }: at = inĂ­cio em ms, duration = duração em ms (abaixo de 20 vira um toque de 30 ms), intensity = 0-1 (padrĂŁo 0,8). sharpness Ă© aceito mas ignorado no 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);

Esconda o botĂŁo em celulares sem vibrador:

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

Toque duas vezes rapidamente em uma ação bem-sucedida e avise quando nĂŁo for possĂ­vel tocar:

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');
}

Observaçþes: A intensidade sĂł funciona em celulares com controle de amplitude; os outros mantĂȘm o ritmo com uma intensidade fixa. Se o sistema recusar a vibração, play responde { ok: false, error: '<the system message>' }. Em apps criados com IA use hapticPlay de @/lib/appmintNative, que tambĂ©m tem padrĂ”es nomeados.

Capacitor.AppwrightLiveProgress Capacitor#

Capacitor.Plugins.AppwrightLiveProgress — start / update / end

Exemplo

O plugin Android prĂłprio do AppMint (seu nome em JS Ă© AppwrightLiveProgress) para uma notificação de status fixa, silenciosa e atualizada em tempo real (barra de progresso, indicador de carregamento ou relĂłgio em contagem) que abre uma rota quando tocada.

Retorna: start(opts) / update(opts) → Promise<{ ok: true, id }>, ou { ok: false, error } sem nada publicado - 'permission' quando as notificaçÔes nĂŁo sĂŁo permitidas (Android 13+: ainda nĂŁo concedidas, ou desativadas para o app), 'channel_disabled' quando o usuĂĄrio desativou a categoria "Live status"; end({ id }) → Promise<void>. Requer: o app Android e a permissĂŁo de notificação (Android 13+). NĂŁo disponĂ­vel na web.

Em um app criado com IA use o wrapper liveProgress de @/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');

Em uma pĂĄgina escrita Ă mĂŁo:

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' });
}

Um cronĂŽmetro de treino: startedAt faz o cartĂŁo contar para cima sozinho, entĂŁo ele Ă© publicado uma vez e encerrado quando o treino para:

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 });
}

OpçÔes: id (padrĂŁo 'live'), title, text, progress (0-1, omita para nĂŁo ter barra), indeterminate, startedAt (epoch em ms, mostra um relĂłgio em contagem), route.

Observaçþes: start e update fazem a mesma coisa (publicam ou substituem o cartĂŁo com esse id). O cartĂŁo nĂŁo pode ser dispensado com um gesto - chame sempre end. Peça a permissĂŁo antes: no Android 13+ sem ela start responde error: 'permission' e nĂŁo publica nada.

Capacitor.AppwrightSystemPalette Capacitor#

Capacitor.Plugins.AppwrightSystemPalette — get()

Exemplo

Retorna as cores Material You do celular (a paleta que o Android 12+ gera a partir do papel de parede), para que o app combine com os apps do sistema. Plugin prĂłprio do AppMint (AppwrightSystemPalettePlugin.kt).

Retorna: Promise { available: false } abaixo do Android 12, senĂŁo { available: true, accent1, accent2, accent3, neutral1, neutral2 } - cada um um objeto de tom para cor hexadecimal, com tons '0', '10', '50', '100' … '900', '1000' (por exemplo accent1['600'] === '#3F5F90'). Requer: nada para ativar - todo app hospeda o plugin. window.Capacitor existe nas pĂĄginas que o prĂłprio app serve (apps HTML, ZIP e criados com IA) e, em um app no modo Website, no seu prĂłprio site (seu domĂ­nio e subdomĂ­nios) - nunca em outros sites que o app abre. Detecte o recurso antes de usar.

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();

Em um app criado com IA:

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

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

Escolha tons claros ou escuros para combinar com o tema do sistema e leia a paleta de novo quando o usuĂĄrio voltar de trocar o papel de parede:

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();

Observaçþes: Verifique o contraste do texto antes de aplicar as cores da paleta - nĂŁo hĂĄ garantia de que um tom do papel de parede seja legĂ­vel sobre o seu fundo. Os navegadores nĂŁo expĂ”em cores do papel de parede: na web o wrapper responde { available: false }. As cores mudam quando o usuĂĄrio troca o papel de parede; chame get() de novo ao retomar.

Capacitor.AppwrightWidget Capacitor#

Capacitor.Plugins.AppwrightWidget — set(card), clear(), placedCount(), requestPin()

Exemplo

Preenche o widget da tela inicial do app: um cartão com título, um valor grande, até doze linhas, suas cores e uma rota ao tocar - o mesmo cartão que AppMint.widget.set() aceita, com todas as chaves. O cartão é salvo no celular e continua aparecendo mesmo depois de reiniciar. Plugin próprio do AppMint (AppwrightWidgetPlugin.kt).

Retorna: set({ title?, value?, caption?, lines?, route?, bg?, ink?, accent?, textSize?, align?, wrap?, … }) → Promise { ok: true, placed }, rejeitada com o motivo de um cartĂŁo invĂĄlido (placed = widgets atualmente na tela inicial). clear() → void. placedCount() → { value }. requestPin() → { value: boolean } (true quando a folha "adicionar widget" do launcher foi aberta). Requer: nada para ativar - todo app declara o widget. window.Capacitor existe nas pĂĄginas que o prĂłprio app serve (apps HTML, ZIP e criados com IA) e, em um app no modo Website, no seu prĂłprio site (seu domĂ­nio e subdomĂ­nios) - nunca em outros sites que o app abre. Detecte o recurso antes de usar.

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'
  });
}

Ofereça adicionå-lo (somente quando nenhum estiver adicionado ainda):

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.');
}

Em um app criado com IA:

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();

Observaçþes: As cores sĂŁo #RRGGBB, #AARRGGBB (alfa primeiro) ou rgba(); as vazias usam um cartĂŁo escuro com um valor ciano. Veja AppMint.widget para linhas estilizadas, caption, textSize, align, wrap e font (seu prĂłprio arquivo .ttf/.otf, informado como um caminho no seu app). O toque abre o app em route como um deep link (leia com WebToApk.getLaunchUrl() ou o evento appmint:deep-link). Antes de qualquer set() o widget diz "Nothing to show yet"; clear() o devolve a esse estado. Em um navegador can('widget') Ă© 'none'.

Capacitor.Badge Capacitor#

Capacitor.Plugins.Badge — the launcher-icon count

Exemplo

O plugin Badge (capawesome) que define o nĂșmero no Ă­cone do app no launcher.

Retorna: Promises: set({ count }), clear(), increase(), decrease() → void; get() → { count }; isSupported() → { isSupported }. O plugin Android nĂŁo tem mĂ©todos de permissĂŁo. Requer: nada no Android. NĂŁo disponĂ­vel na web.

Em um app criado com IA use o wrapper badge de @/lib/appmintNative:

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

Em uma pĂĄgina escrita Ă mĂŁo:

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);
});

Conte para cima e para baixo conforme os itens chegam e sĂŁo lidos:

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);
}

Observaçþes: no Android a aparĂȘncia depende do launcher (um nĂșmero, um ponto ou nada). navigator.setAppBadge(n) no app grava no mesmo badge (sĂł existe em launchers que conseguem mostrar uma contagem).

Capacitor.BarcodeScanner Capacitor#

Capacitor.Plugins.BarcodeScanner — scan, startScan, readBarcodesFromImage, isSupported

Exemplo

Leitura de QR e códigos de barras com a API @capacitor-mlkit/barcode-scanning - o plugin próprio do app (BarcodeScannerPlugin.kt) sobre o mesmo scanner de códigos do Google que AppMint.scanCode(). As chamadas mais antigas de @capacitor-community/barcode-scanner (startScan() resolvendo { hasContent, content }, checkPermission, prepare, hideBackground) compartilham este nome e também funcionam.

Retorna: scan({ formats?, autoZoom? }) → { barcodes: [{ rawValue, displayValue, format, valueType, bytes?, cornerPoints?, urlBookmark?, wifi?, email?, phone?, sms?, geoPoint?, contactInfo?, calendarEvent?, driverLicense? }] } (rejeita "scan canceled." quando o usuĂĄrio desiste); readBarcodesFromImage({ path, formats? }) → { barcodes }; isSupported() → { supported }; isGoogleBarcodeScannerModuleAvailable() → { available }; installGoogleBarcodeScannerModule() (progresso como googleBarcodeScannerModuleInstallProgress); checkPermissions() / requestPermissions() → { camera }; openSettings(). format Ă© 'QR_CODE', 'EAN_13', 'CODE_128'… Requer: nada para ativar e nenhuma permissĂŁo de cĂąmera - o scanner do Google desenha a prĂłpria tela (o Play services o baixa no primeiro uso). window.Capacitor existe nas pĂĄginas que o prĂłprio app serve (apps HTML, ZIP e criados com IA) e, em um app no modo Website, no seu prĂłprio site (seu domĂ­nio e subdomĂ­nios) - nunca em outros sites que o app abre. Detecte o recurso antes de usar.

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);
  }
};

Consulta de preço a partir do cĂłdigo de barras de um produto, com o estilo de listener (startScan + barcodesScanned) que os apps ML Kit jĂĄ usam:

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'] });
}

Leia um QR code de uma foto que o usuĂĄrio jĂĄ tem:

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;
}

Observações: O startScan() original mostra uma prévia ao vivo da câmera atrás de uma página transparente e continua escaneando até stopScan(); aqui ele abre a tela do scanner, o primeiro código dispara barcodeScanned / barcodesScanned e a sessão termina (a chamada então resolve { hasContent, content, format } para código da comunidade; um scanner fechado resolve { hasContent: false }). A lanterna e o zoom pertencem a essa prévia, então isTorchAvailable() é false e os setters de lanterna/zoom rejeitam - a tela do scanner tem seu próprio botão de lanterna. checkPermissions() responde granted quando o app não tem nenhuma permissão de câmera (o scanner não precisa de nenhuma); um app que também usa a câmera recebe o estado real. Apps criados com IA usam scanCode() de @/lib/appmintNative.

Capacitor.Browser Capacitor#

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

Exemplo

Abre uma pĂĄgina web em uma aba de navegador dentro do app (Chrome Custom Tabs), para que o usuĂĄrio leia termos, documentação ou uma pĂĄgina de login e volte com um Ășnico gesto (@capacitor/browser 8.0.3).

Retorna: open() / close() → Promise void. Eventos: browserFinished (o usuĂĄrio fechou a aba) e browserPageLoaded. Requer: nada - todo app hospeda o plugin (um navegador que suporte Custom Tabs, como o Chrome, precisa estar instalado). window.Capacitor existe nas pĂĄginas que o prĂłprio app serve (apps HTML, ZIP e criados com IA) e, em um app no modo Website, no seu prĂłprio site (seu domĂ­nio e subdomĂ­nios) - nunca em outros sites que o app abre. Detecte o recurso antes de usar.

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' });
}

Em um app criado com IA (uma nova aba na 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

Abra um link e feche a aba quando o retorno de um login chegar Ă pĂĄgina:

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 () {});
});

Observaçþes: url nĂŁo pode estar vazio. toolbarColor Ă© uma cor hexadecimal; uma invĂĄlida Ă© ignorada. close() tambĂ©m funciona no Android nesta versĂŁo do plugin (ele encerra a activity host da aba) - Ăștil depois que um link de login volta para o app. A aba Ă© um navegador separado: ela nĂŁo compartilha os cookies do app nem localStorage.

Capacitor.Calendar Capacitor#

Capacitor.Plugins.Calendar — createEvent, findEvents, deleteEvent, listCalendars, openCalendar

Exemplo

Adiciona, encontra e exclui eventos na agenda do prĂłprio celular (Android CalendarContract) e abre o app de agenda em uma data. Incluso @capacitor/calendar (template/plugins/calendar).

Retorna: createEvent() → { id }; findEvents() → { events: [{ id, title, location?, notes?, startDate, endDate, isAllDay, calendarId, calendarName?, attendees? }] }; listCalendars() → { calendars: [{ id, name, displayName?, isPrimary }] }; deleteEvent(), openCalendar() → void. As datas sĂŁo em milissegundos desde a Ă©poca (epoch). Requer: marque Agenda na Etapa 4 (Acesso) ao compilar. Em apps HTML, ZIP e criados com IA, o build tambĂ©m adiciona a permissĂŁo de agenda sozinho quando seus arquivos contĂȘm uma chamada Calendar.<method>( escrita exatamente assim (como abaixo) ou o calendar.createEvent( do wrapper. O plugin pede ao usuĂĄrio acesso Ă agenda no primeiro uso. window.Capacitor existe nas pĂĄginas que o prĂłprio app serve (apps HTML, ZIP e criados com IA) e, em um app no modo Website, no seu prĂłprio site (seu domĂ­nio e subdomĂ­nios) - nunca em outros sites que o app abre. Detecte o recurso antes de usar.

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);
  }
}

Leia esta semana, exclua um evento, abra a agenda:

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 });
}

Em um app criado com IA (na web createEvent baixa um arquivo .ics; ler retorna []):

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());
}

Observaçþes: Sem a permissĂŁo de agenda no app, nenhum diĂĄlogo aparece e toda chamada de evento Ă© rejeitada (missing permission); um usuĂĄrio que diz nĂŁo recebe OS-PLUG-CLDR-0020. recurrence: { frequency: 'daily' | 'weekly' | 'monthly' | 'yearly', interval?, count?, endDate? } cria um evento recorrente. createEventInteractively({ title, startDate, endDate }) abre o prĂłprio editor do app de agenda: resolve { id } do evento salvo e Ă© rejeitada com OS-PLUG-CLDR-0006 quando o usuĂĄrio fecha o editor sem salvar (precisa de acesso de leitura e de escrita para distinguir os dois casos). deleteEvent({ id, fromDate }) encerra um evento recorrente antes de fromDate e mantĂ©m as ocorrĂȘncias anteriores. O wrapper retorna null / [] / false em vez de gerar erro.

Capacitor.Camera Capacitor#

Capacitor.Plugins.Camera

Exemplo

O plugin oficial Capacitor Camera, incluĂ­do no app: tire uma foto com a cĂąmera ou escolha fotos da galeria.

Retorna: Promises. getPhoto(opts) → { dataUrl | base64String | webPath, format, saved } (qual campo depende de resultType), e Ă© REJEITADA quando o usuĂĄrio cancela; pickImages(opts) → { photos: [{ webPath, format }] }; checkPermissions() / requestPermissions({ permissions }) → { camera, photos }. Requer: marque CĂąmera na Etapa 4 (Acesso). Em apps HTML, ZIP e criados com IA, o build tambĂ©m adiciona a permissĂŁo de cĂąmera sozinho quando seus arquivos contĂȘm Camera.getPhoto( escrito exatamente assim (como abaixo), getUserMedia com vĂ­deo, ou <input capture>. window.Capacitor existe nas pĂĄginas que o prĂłprio app serve (apps HTML, ZIP e criados com IA) e, em um app no modo Website, no seu prĂłprio site (seu domĂ­nio e subdomĂ­nios) - nunca em outros sites que o app abre. Detecte o recurso antes de usar.

Tire uma foto e mostre-a.

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.
  }
}

Escolha até 5 fotos da galeria.

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 */ }
}

Em um app criado com IA use o wrapper, que também funciona na web (e retorna null em vez de gerar erro ao cancelar):

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

Observaçþes: pickImages nĂŁo precisa de permissĂŁo de cĂąmera. Se a permissĂŁo de cĂąmera nĂŁo estĂĄ no app (a opção estava desligada e o build nĂŁo achou nenhuma chamada de cĂąmera), a permissĂŁo Ă© recusada sem nenhum aviso. Um <input type="file" accept="image/*" capture> tambĂ©m abre a cĂąmera. A cĂąmera Ă© sensĂ­vel: declare-a no seu formulĂĄrio de Segurança dos dados do Play.

Capacitor.CapacitorBarcodeScanner Capacitor#

Capacitor.Plugins.CapacitorBarcodeScanner — scanBarcode({ hint })

Exemplo

Leitura de QR / cĂłdigo de barras em uma chamada com a API oficial @capacitor/barcode-scanner - o plugin prĂłprio do app (CapacitorBarcodeScannerPlugin.kt) sobre o mesmo scanner de cĂłdigos do Google que AppMint.scanCode(). O cĂłdigo escrito para o pacote npm (CapacitorBarcodeScanner.scanBarcode({ hint: CapacitorBarcodeScannerTypeHint.ALL })) funciona sem alteraçÔes.

Retorna: scanBarcode({ hint, scanInstructions?, cameraDirection?, scanOrientation? }) → { ScanResult, format }. hint / format sĂŁo os nĂșmeros do pacote: 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. Ă rejeitada com o cĂłdigo OS-PLUG-BARC-0006 quando o usuĂĄrio fecha o scanner. Requer: nada para ativar e nenhuma permissĂŁo de cĂąmera - o scanner do Google desenha a prĂłpria tela (o Play services o baixa no primeiro uso). window.Capacitor existe nas pĂĄginas que o prĂłprio app serve (apps HTML, ZIP e criados com IA) e, em um app no modo Website, no seu prĂłprio site (seu domĂ­nio e subdomĂ­nios) - nunca em outros sites que o app abre. Detecte o recurso antes de usar.

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);
  }
};

Aceite qualquer cĂłdigo e diga ao usuĂĄrio de que tipo ele era:

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;
}

Trate uma rejeição que nĂŁo seja o usuĂĄrio fechando o scanner:

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;
  }
}

Observaçþes: scanInstructions, scanButton, cameraDirection e scanOrientation estilizam a tela de cĂąmera do projeto original e nĂŁo tĂȘm efeito no scanner do Google (sempre a cĂąmera traseira). MAXICODE, RSS_14, RSS_EXPANDED e UPC_EAN_EXTENSION nĂŁo sĂŁo suportados como hint (rejeita OS-PLUG-BARC-0008); 17 (ALL) lĂȘ todos os tipos suportados. Apps criados com IA usam scanCode() de @/lib/appmintNative.

Capacitor.CapacitorCookies Capacitor#

Capacitor.Plugins.CapacitorCookies — getCookies / setCookie / deleteCookie / clearCookies / clearAllCookies

Exemplo

LĂȘ e grava os cookies do app, incluindo os de outro host com o qual sua pĂĄgina conversa (do nĂșcleo do Capacitor, CapacitorCookies).

Retorna: getCookies({ url? }) → { [name]: value } - com um url, os cookies que essa URL (host e caminho) enviaria; sem ele, o document.cookie da própria página. Rejeita uma url que não seja http(s). setCookie({ key, value, url?, path?, expires? }), deleteCookie({ key, url? }), clearCookies({ url? }), clearAllCookies() → Promise void; setCookie / deleteCookie rejeitam sem uma key string (e value) e então não gravam nada. Requer: nada para ativar - todo app hospeda o plugin. window.Capacitor existe em páginas que o próprio app serve (apps HTML, ZIP e criados com IA) e, em um app no modo Site, no seu próprio site (seu domínio e subdomínios) - nunca em outros sites que o app abre. Detecte o recurso.

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 });
}

Sair da conta: apague os cookies desse host, ou todos os cookies que o app guarda.

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

Observaçþes: Um cookie definido com um path sĂł Ă© devolvido para um url sob esse caminho. Os valores sĂŁo decodificados de URL ao ler. Os cookies sĂŁo compartilhados por todas as pĂĄginas que o app mostra, entĂŁo nunca guarde segredos em um que uma pĂĄgina externa possa ler - eles pertencem a Preferences ou ao armazenamento seguro do app.

Capacitor.CapacitorSQLite Capacitor#

Capacitor.Plugins.CapacitorSQLite — createConnection, open, execute, query, run, executeSet, close

Exemplo

Um banco de dados SQLite de verdade no celular, com a API @capacitor-community/sqlite. Incluso @capacitor-community/sqlite (template/plugins/sqlite), rodando no SQLite do prĂłprio Android. O cĂłdigo escrito para o pacote npm (new SQLiteConnection(CapacitorSQLite)) funciona sem alteraçÔes; uma pĂĄgina escrita Ă mĂŁo chama o objeto do plugin diretamente, como abaixo.

Retorna: 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 para backups. Requer: nada para ativar e nenhuma permissĂŁo. O banco de dados fica no armazenamento privado do app e sobrevive Ă s atualizaçÔes do app. window.Capacitor existe nas pĂĄginas que o prĂłprio app serve (apps HTML, ZIP e criados com IA) e, em um app no modo Website, no seu prĂłprio site (seu domĂ­nio e subdomĂ­nios) - nunca em outros sites que o app abre. Detecte o recurso antes de usar.

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 || [];
}

VĂĄrias gravaçÔes que devem ser todas concluĂ­das ou nenhuma - uma transação com 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()] },
  ] });
}

Abra o banco de dados apenas uma vez por inicialização do app, mesmo quando duas telas pedem ao mesmo tempo:

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;
}

Observaçþes: O app Ă© compilado sem SQLCipher, entĂŁo os bancos de dados nĂŁo sĂŁo criptografados: encrypted: true, setEncryptionSecret, changeEncryptionSecret, isSecretStored e as demais chamadas de criptografia sĂŁo rejeitadas com "Encryption is not available in this app". isInConfigEncryption() responde false. Todo o resto (consultas, valores vinculados, transaçÔes, atualizaçÔes versionadas com addUpgradeStatement, importação/exportação JSON) Ă© cĂłdigo do prĂłprio plugin. As rejeiçÔes trazem o texto de erro do SQLite.

Capacitor.Clipboard Capacitor#

Capacitor.Plugins.Clipboard — write(options), read()

Exemplo

Copia texto (ou um link) para a ĂĄrea de transferĂȘncia do sistema e o lĂȘ de volta (@capacitor/clipboard 8.0.1).

Retorna: write({ string?, url?, image?, label? }) → Promise void. read() → Promise { value, type } (type é 'text/plain' para texto). Requer: nada para ativar - todo app hospeda o plugin. window.Capacitor existe em páginas que o próprio app serve (apps HTML, ZIP e criados com IA) e, em um app no modo Site, no seu próprio site (seu domínio e subdomínios) - nunca em outros sites que o app abre. Detecte o recurso.

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);
  }
}

Em um app criado com IA o wrapper no formato Capacitor transforma uma ĂĄrea de transferĂȘncia vazia em '':

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

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

Copie um link e confirme com um toque de feedback:

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;
}

Observaçþes: write precisa de um entre string, url ou image (um data URL), senĂŁo Ă© rejeitado com "No data provided". O Android 12+ mostra o prĂłprio aviso "pasted from…" ao ler - isso Ă© do sistema, nĂŁo do app. O write do wrapper envia apenas string || url.

Capacitor.Contacts Capacitor#

Capacitor.Plugins.Contacts — getContacts, getContact, pickContact, createContact, deleteContact

Exemplo

A agenda de contatos do celular com a API @capacitor-community/contacts. Incluso @capacitor-community/contacts (template/plugins/contacts). O cĂłdigo escrito para o pacote npm funciona sem alteraçÔes.

Retorna: checkPermissions() / requestPermissions() → { contacts, contactsWrite } (cada 'granted' | 'denied' | 'prompt'; contacts Ă© leitura, contactsWrite Ă© adicionar e excluir); getContacts({ projection }) → { contacts: [ContactPayload] }; getContact({ contactId, projection }) e pickContact({ projection }) → { contact }; createContact({ contact }) → { contactId }; deleteContact({ contactId }) → void. projection escolhe os campos: { name, phones, emails, organization, birthday, note, urls, postalAddresses, image } (cada true). Requer: marque Contatos na Etapa 4 (Acesso) para ler, e tambĂ©m Editar contatos para adicionar ou excluir. Builds HTML, ZIP e AI-Studio marcam essas opçÔes sozinhos quando o cĂłdigo chama Contacts.getContacts( / getContact( / pickContact( (leitura) ou Contacts.createContact( / deleteContact( (ambos). O plugin pergunta ao usuĂĄrio no primeiro uso; sem a opção marcada a chamada Ă© rejeitada com "Permission is required to access contacts." - e em um app sem Contatos, SMS ou Registro de chamadas marcados o plugin nem estĂĄ no app (o Capacitor rejeita com "not implemented"). window.Capacitor existe nas pĂĄginas que o prĂłprio app serve (apps HTML, ZIP e criados com IA) e, em um app no modo Website, no seu prĂłprio site (seu domĂ­nio e subdomĂ­nios) - nunca em outros sites que o app abre. Detecte o recurso antes de usar.

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 }));
}

Deixe o usuário escolher uma pessoa no seletor do sistema:

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.
  }
};

Salve um cartĂŁo de visita do app na agenda de contatos:

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;
}

Observações: pickContact() rejeita com o código CANCELLED quando o usuário sai do seletor. O Android só preenche contactId, name, phones, emails, organization, birthday, note, urls, postalAddresses e image quando a projeção os pede - peça apenas o que você mostra. Ler contatos é uma permissão sensível no Google Play: descreva o motivo no formulário de segurança de dados da ficha. Apps criados com IA usam listContacts(), pickContact() e addContact() de @/lib/appmintNative.

Capacitor.Device Capacitor#

Capacitor.Plugins.Device

Exemplo

O plugin oficial Capacitor Device, incluĂ­do no app: modelo do celular, versĂŁo do sistema, bateria, um ID estĂĄvel e o idioma.

Retorna: Promises. getInfo() → { model, platform, operatingSystem, osVersion, androidSDKVersion, manufacturer, isVirtual, webViewVersion, … }; getId() → { identifier }; getBatteryInfo() → { batteryLevel (0–1), isCharging }; getLanguageCode() → { value }. Requer: nada para ativar. window.Capacitor existe nas pĂĄginas que o prĂłprio app serve (apps HTML, ZIP e criados com IA) e, em um app no modo Website, no seu prĂłprio site (seu domĂ­nio e subdomĂ­nios) - nunca em outros sites que o app abre. Detecte o recurso antes de usar.

Mostre o celular e a bateria.

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';
  }
}

Um ID estĂĄvel e o idioma.

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 })
  });
}

Em um app criado com IA use o wrapper, que também funciona na web:

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

Observaçþes: Para o ID de build do Android, patch de segurança, tela, memĂłria e rede, o WebToApk.getDeviceInfo() do shell dĂĄ mais detalhes. Os ids do plugin nĂŁo sĂŁo ids de hardware; eles podem mudar depois de uma restauração de fĂĄbrica.

Capacitor.Dialog Capacitor#

Capacitor.Plugins.Dialog — alert, confirm, prompt

Exemplo

Mostra um diĂĄlogo real do sistema Android: uma mensagem, uma pergunta de sim/nĂŁo ou uma pergunta de texto de uma linha (@capacitor/dialog 8.0.1).

Retorna: alert({ title?, message, buttonTitle? }) → Promise void. confirm({ title?, message, okButtonTitle?, cancelButtonTitle? }) → { value: boolean }. prompt({ title?, message, okButtonTitle?, cancelButtonTitle?, inputPlaceholder?, inputText? }) → { value: string, cancelled: boolean }. Requer: nada para ativar - todo app hospeda o plugin. window.Capacitor existe nas pĂĄginas que o prĂłprio app serve (apps HTML, ZIP e criados com IA) e, em um app no modo Website, no seu prĂłprio site (seu domĂ­nio e subdomĂ­nios) - nunca em outros sites que o app abre. Detecte o recurso antes de usar.

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);
}

Alerta e 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());
}

Em um app criado com IA o wrapper nunca rejeita: dispensar Ă© { value: false } / { cancelled: true }, e na web ele usa as prĂłprias caixas de diĂĄlogo do navegador:

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

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

Observaçþes: message Ă© obrigatĂłrio - sem ele o plugin rejeita com "Please provide a message for the dialog". Os diĂĄlogos sĂŁo modais; use-os apenas para decisĂ”es que precisam bloquear.

Capacitor.Filesystem Capacitor#

Capacitor.Plugins.Filesystem

Exemplo

O plugin Filesystem padrĂŁo do Capacitor: lĂȘ e grava arquivos no armazenamento PRĂPRIO do app (nĂŁo em uma pasta escolhida pelo usuĂĄrio - para isso use WebToApkFS).

Retorna: todo mĂ©todo retorna uma Promise e Ă© rejeitado em caso de falha (por exemplo, ler um arquivo que nĂŁo existe). readFile → { data }, writeFile → { uri }, readdir → { files: [{ name, type, size, mtime, uri }] }, mkdir / deleteFile → nada. Requer: nada para ativar; 'DATA' e 'CACHE' nĂŁo precisam de permissĂŁo.

Uma pågina não tem imports de Directory / Encoding, então passe as strings simples 'DATA' (arquivos privados do app, mantidos até desinstalar) ou 'CACHE' (o sistema pode limpar) e 'utf8' para texto:

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
  }
}

Omita encoding para gravar ou ler dados binĂĄrios em 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); });
}

Em apps criados com IA, o wrapper @/lib/appmintNative que usa este plugin Ă© fileTransfer (ele prepara downloads e uploads em '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

Observações: window.Capacitor existe apenas dentro do app - sempre detecte o recurso. Os arquivos em 'DATA' são privados do app e apagados ao desinstalar; para colocar arquivos onde o usuário possa vê-los, use WebToApkFS (uma pasta que o usuário concede) ou um download.

Capacitor.FileTransfer Capacitor#

Capacitor.Plugins.FileTransfer

Exemplo

O plugin oficial Capacitor File Transfer: baixa uma URL para um arquivo no celular, ou envia um arquivo do celular, de forma nativa, com eventos de progresso.

Retorna: downloadFile({url, path, headers?, progress?}) → Promise<{path}>; uploadFile({url, path, fileKey?, mimeType?, method?, headers?, progress?}) → Promise<{bytesSent, responseCode, response, headers}>. O progresso chega como eventos de listener 'progress' {type, url, bytes, contentLength, lengthComputable}. As falhas sĂŁo rejeitadas com {message, code}. Requer: nada para ativar. window.Capacitor existe nas pĂĄginas que o prĂłprio app serve e, em um app no modo Website, no seu prĂłprio site (seu domĂ­nio e subdomĂ­nios) - nunca em outros sites. Sempre detecte o recurso antes de usar.

Baixe para o cache do app com progresso:

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();
  }
}

Envie um arquivo que jĂĄ estĂĄ no celular:

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); });
}

Informe uma transferĂȘncia que falhou pelo cĂłdigo:

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;
  }
}

Observaçþes: O caminho deve ser um caminho de arquivo ou uma URI file://, nĂŁo um Blob - grave antes o Blob no cache com Filesystem.writeFile. No Android 10 e anteriores, um caminho no armazenamento pĂșblico pede permissĂŁo de armazenamento. Em apps criados com IA prefira fileTransfer de @/lib/appmintNative, que faz tudo isso e tambĂ©m funciona na web.

Capacitor.FileViewer Capacitor#

Capacitor.Plugins.FileViewer

Exemplo

O plugin oficial Capacitor File Viewer: abre um documento ou arquivo de mĂ­dia no app visualizador do celular, a partir de um endereço web, de um caminho de arquivo local ou de um arquivo incluĂ­do no app.

Retorna: cada método retorna uma Promise<void> que é rejeitada com {message, code} quando nada consegue abrir o arquivo. Requer: nada para ativar. window.Capacitor existe nas påginas que o próprio app serve e, em um app no modo Website, no seu próprio site (seu domínio e subdomínios) - nunca em outros sites. Sempre detecte o recurso antes de usar.

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.');
  }
}

Um arquivo no celular, por exemplo um escrito com 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}) abre um arquivo empacotado na pasta de assets do prĂłprio APK. Os mesmos trĂȘs mĂ©todos tambĂ©m existem como previewMediaContentFromUrl, previewMediaContentFromLocalPath e previewMediaContentFromResources para vĂ­deo e ĂĄudio.

Baixe um arquivo e abra-o quando chegar:

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:\/\//, '') });
}

Observaçþes: Em apps criados com IA prefira fileViewer.open(target) de @/lib/appmintNative, que escolhe o mĂ©todo certo e tambĂ©m funciona na web. Um caminho local Ă© um caminho simples (sem file://).

Capacitor.Geolocation Capacitor#

Capacitor.Plugins.Geolocation

Exemplo

O plugin oficial Capacitor Geolocation, incluĂ­do no app: a posição do celular uma vez, ou atualizaçÔes contĂ­nuas.

Retorna: Promises. getCurrentPosition(opts) → { timestamp, coords: { latitude, longitude, accuracy, altitude, speed, heading, … } }; watchPosition(opts, callback) → o id da observação (uma string); clearWatch({ id }); checkPermissions() / requestPermissions() → { location, coarseLocation } ('granted' | 'denied' | 'prompt' | …). Requer: GPS e/ou Localização na Etapa 4 (Acesso) - em apps HTML, ZIP e criados com IA o build tambĂ©m os ativa sozinho quando seus arquivos chamam getCurrentPosition ou watchPosition. window.Capacitor existe nas pĂĄginas que o prĂłprio app serve (apps HTML, ZIP e criados com IA) e, em um app no modo Website, no seu prĂłprio site (seu domĂ­nio e subdomĂ­nios) - nunca em outros sites que o app abre. Detecte o recurso antes de usar.

Posição uma vez, pedindo permissĂŁo antes.

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, …
  }
}

Atualizaçðes contĂ­nuas. O callback recebe (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; }
}

Em um app criado com IA use o wrapper, que também funciona na web:

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

Observaçþes: O navigator.geolocation simples tambĂ©m funciona no app. Se os interruptores de localização estavam desligados na hora da compilação, a permissĂŁo Ă© recusada sem nenhum aviso. No Android 12+ o usuĂĄrio pode permitir apenas a localização aproximada (coarseLocation concedida). A localização Ă© um dado pessoal: declare-a no seu formulĂĄrio de Segurança dos dados do Play.

Capacitor.Haptics Capacitor#

Capacitor.Plugins.Haptics

Exemplo

O plugin oficial Capacitor Haptics (@capacitor/haptics), incluĂ­do no app: toques leves/mĂ©dios/fortes, feedback de sucesso/aviso/erro, tiques de seleção e vibração simples.

Retorna: todo método retorna uma Promise que resolve sem valor. Requer: nada para ativar - todo app declara a permissão de vibração, esteja ou não Vibrar marcado na Etapa 4 (Acesso). window.Capacitor existe em páginas que o próprio app serve (apps HTML, ZIP e criados com IA) e, em um app no modo Site, no seu próprio site (seu domínio e subdomínios) - nunca em outros sites que o app abre. Detecte o recurso.

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'); });

Tiques de seleção para um seletor ou controle deslizante, e uma vibração simples:

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
});

Vibre em um erro e combine com uma mensagem visĂ­vel:

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 () {});
}

Observaçþes: As strings sĂŁo em maiĂșsculas ('HEAVY', nĂŁo 'heavy'). Em apps criados com IA, import { Haptics } from '@/lib/appmintNative' oferece os mesmos nomes. Para ritmos personalizados com intensidade por batida, use Capacitor.Plugins.AppwrightHaptics.

Capacitor.InAppReview Capacitor#

Capacitor.Plugins.InAppReview — requestReview()

Exemplo

Pede ao Google Play que mostre a prĂłpria folha "avalie este app" dentro do app. Incluso @capacitor-community/in-app-review (template/plugins/in-app-review).

Retorna: Promise void - ela resolve quando o fluxo do Play termina, e o Play nunca diz se a folha foi exibida nem o que o usuĂĄrio fez. Ă rejeitada quando o Play nĂŁo conseguiu iniciar o fluxo. Requer: nada para ativar; o app precisa estar instalado pelo Google Play para a folha aparecer. window.Capacitor existe nas pĂĄginas que o prĂłprio app serve (apps HTML, ZIP e criados com IA) e, em um app no modo Website, no seu prĂłprio site (seu domĂ­nio e subdomĂ­nios) - nunca em outros sites que o app abre. Detecte o recurso antes de usar.

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
}

Em um app criado com IA:

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

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

Pergunte uma vez, depois de um momento de sucesso, e lembre-se de que jĂĄ perguntou:

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); }
}

Observaçþes: O Play limita a frequĂȘncia com que a folha aparece e nĂŁo a mostra a cada chamada - nunca vincule uma recompensa a ela e nunca peça a partir de um botĂŁo "Avalie-nos" esperando que ela abra (para isso abra a pĂĄgina do app na loja). Peça depois de um momento de sucesso, nĂŁo na inicialização. Uma instalação por sideload ou de debug geralmente nĂŁo mostra nada.

Capacitor.KeepAwake Capacitor#

Capacitor.Plugins.KeepAwake — keepAwake(), allowSleep(), isKeptAwake(), isSupported()

Exemplo

Impede que a tela escureça e bloqueie enquanto algo precisa continuar visĂ­vel - uma receita, uma rota, um QR code, um cronĂŽmetro. Incluso @capacitor-community/keep-awake (template/plugins/keep-awake).

Retorna: keepAwake() / allowSleep() → Promise void. isKeptAwake() → { isKeptAwake: boolean }. isSupported() → { isSupported: true }. Requer: nada - todo app hospeda o plugin; nenhuma permissĂŁo. window.Capacitor existe nas pĂĄginas que o prĂłprio app serve (apps HTML, ZIP e criados com IA) e, em um app no modo Website, no seu prĂłprio site (seu domĂ­nio e subdomĂ­nios) - nunca em outros sites que o app abre. Detecte o recurso antes de usar.

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); });

Em um app criado com IA (a Screen Wake Lock API na web):

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

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

Mantenha a tela ligada apenas enquanto um cronĂŽmetro estiver rodando:

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');
}

Observaçþes: O sinalizador pertence Ă janela do app: sĂł funciona enquanto o app estĂĄ em primeiro plano e continua atĂ© allowSleep() - libere-o em toda saĂ­da da tela. keepAwake() retorna false quando nada conseguiu manter a tela ligada.

Capacitor.Keyboard Capacitor#

Capacitor.Plugins.Keyboard — show(), hide(), addListener('keyboardDidShow' | ...)

Exemplo

Abre ou fecha o teclado virtual e avisa a pĂĄgina quando ele aparece e qual Ă© a altura (@capacitor/keyboard 8.0.5).

Retorna: show() / hide() → Promise void. addListener(event, fn) → uma Promise de um handle com remove(), como na API do prĂłprio Capacitor - use await nele ou encadeie .then(); o valor retornado tambĂ©m tem remove() por si sĂł; os eventos de exibição passam { keyboardHeight } em pixels CSS. Eventos: keyboardWillShow, keyboardDidShow, keyboardWillHide, keyboardDidHide. Requer: nada para ativar - todo app hospeda o plugin. window.Capacitor existe nas pĂĄginas que o prĂłprio app serve (apps HTML, ZIP e criados com IA) e, em um app no modo Website, no seu prĂłprio site (seu domĂ­nio e subdomĂ­nios) - nunca em outros sites que o app abre. Detecte o recurso antes de usar.

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
}

Em um app criado com IA use onKeyboard() para o layout - ele informa apenas a parte do teclado que a pĂĄgina redimensionada ainda nĂŁo liberou - e hideKeyboard() para fechĂĄ-lo:

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();

Mostre o teclado para um campo depois de tocar em um botĂŁo:

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

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

Observaçþes: O shell jĂĄ redimensiona a pĂĄgina para o teclado, entĂŁo NĂO adicione o keyboardHeight inteiro como preenchimento - uma barra inferior jĂĄ fica acima das teclas. setAccessoryBarVisible, setStyle, setResizeMode e setScroll nĂŁo estĂŁo implementados no Android - nĂŁo os chame. hide() rejeita com "Can't close keyboard, not currently focused" quando nada tem o foco.

Capacitor.LocalNotifications Capacitor#

Capacitor.Plugins.LocalNotifications — schedule, cancel, getPending, requestPermissions, events

Exemplo

NotificaçÔes que o prĂłprio app publica - agora ou em um horĂĄrio - com a API oficial @capacitor/local-notifications (com.capacitorjs:local-notifications). O cĂłdigo escrito para o pacote npm funciona sem alteraçÔes.

Retorna: 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 }. Eventos: localNotificationReceived, localNotificationActionPerformed (actionId Ă© 'tap' para um toque na prĂłpria notificação). Requer: marque NotificaçÔes na Etapa 4 (Acesso) - sem isso o plugin nĂŁo estĂĄ no app e toda chamada Ă© rejeitada com "not implemented". Para notificaçÔes agendadas marque tambĂ©m â° Lembretes (horĂĄrio exato e sobreviver a uma reinicialização). Builds HTML, ZIP e AI-Studio marcam as duas sozinhos quando o cĂłdigo importa @capacitor/local-notifications e chama LocalNotifications.schedule(. window.Capacitor existe nas pĂĄginas que o prĂłprio app serve (apps HTML, ZIP e criados com IA) e, em um app no modo Website, no seu prĂłprio site (seu domĂ­nio e subdomĂ­nios) - nunca em outros sites que o app abre. Detecte o recurso antes de usar.

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;
}

Abra a tela certa quando o usuĂĄrio tocar em uma notificação - tambĂ©m quando o toque iniciou o app, jĂĄ que o evento espera pelo 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;
    }
  });
}

Um lembrete diårio de håbito com botÔes Concluir / Adiar:

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) } }] });
    }
  });
}

Observaçþes: No Android 12+ uma notificação agendada precisa da concessĂŁo de alarme exato: o primeiro schedule() pode abrir a pĂĄgina "Alarmes e lembretes" do sistema; se o usuĂĄrio deixar desativado, a notificação ainda dispara, um pouco depois (o resultado traz um warning). As notificaçÔes do plugin usam o prĂłprio canal "Default", separado das outras notificaçÔes do app. Um sound vindo dos arquivos web nĂŁo Ă© suportado (o Android toca o som padrĂŁo do canal). Os toques chegam Ă pĂĄgina pela tela de desbloqueio quando o app tem PIN. Apps criados com IA usam notify() / LocalNotifications.schedule de @/lib/appmintNative, que publica pela pilha de notificaçÔes do prĂłprio app.

Capacitor.Network Capacitor#

Capacitor.Plugins.Network — getStatus(), addListener('networkStatusChange')

Exemplo

Informa Ă pĂĄgina se o celular estĂĄ online e em que tipo de conexĂŁo, e quando isso muda (@capacitor/network 8.0.1).

Retorna: getStatus() → Promise { connected: boolean, connectionType: 'wifi' | 'cellular' | 'none' | 'unknown' }. O evento networkStatusChange passa o mesmo formato. Requer: nada para ativar - todo app hospeda o plugin. window.Capacitor existe nas pĂĄginas que o prĂłprio app serve (apps HTML, ZIP e criados com IA) e, em um app no modo Website, no seu prĂłprio site (seu domĂ­nio e subdomĂ­nios) - nunca em outros sites que o app abre. Detecte o recurso antes de usar.

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');
  });
}

Em um app criado com IA:

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

Pause um envio grande quando estiver em dados mĂłveis:

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?');
}

Observaçþes: connected significa que o celular tem rede, nĂŁo que seu servidor responde - continue tratando requisiçÔes que falham. O Network.getStatus() e o networkStatus() do wrapper leem navigator.onLine / navigator.connection, nĂŁo o plugin, entĂŁo o tipo pode ser 'unknown' ou uma classe de velocidade como '4g'; onNetworkChange() usa o evento do plugin no app.

Capacitor.Preferences Capacitor#

Capacitor.Plugins.Preferences — get / set / remove / keys / clear

Exemplo

Um pequeno armazenamento nativo de chave-valor (Android SharedPreferences) para strings (@capacitor/preferences 8.0.1).

Retorna: set({ key, value }), remove({ key }), clear() → Promise void; get({ key }) → { value } (null quando a chave nĂŁo existe); keys() → { keys: string[] }. Requer: nada para ativar - todo app hospeda o plugin. window.Capacitor existe nas pĂĄginas que o prĂłprio app serve (apps HTML, ZIP e criados com IA) e, em um app no modo Website, no seu prĂłprio site (seu domĂ­nio e subdomĂ­nios) - nunca em outros sites que o app abre. Detecte o recurso antes de usar.

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
}

Objetos precisam ser convertidos em string antes:

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' });
}

Liste e apague as chaves salvas a partir de uma tela de configurações:

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

Observaçþes: @/lib/appmintNative NĂO tem wrapper de Preferences, de propĂłsito: localStorage jĂĄ Ă© real e persistente no app, e um segundo armazenamento dividiria os dados de um app em dois lugares. Apps criados com IA devem continuar usando localStorage (ou o runtime de dados). Use Preferences em uma pĂĄgina escrita Ă mĂŁo apenas se quiser todas as suas configuraçÔes ali, e escolha um armazenamento por valor. configure({ group }) muda o nome do armazenamento (padrĂŁo CapacitorStorage).

Capacitor.PrivacyScreen Capacitor#

Capacitor.Plugins.PrivacyScreen — enable(), disable(), isEnabled()

Exemplo

O plugin oficial @capacitor/privacy-screen: bloqueia capturas e gravaçÔes de tela e esconde o conteĂșdo do app na visualização de apps recentes. IncluĂ­do para que projetos Capacitor importados que o chamam funcionem.

Retorna: enable({android}) → {success}; disable() → {success}; isEnabled() → {enabled}. Requer: nada para ativar.

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();
}

Verifique o estado atual antes de alternar:

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

Proteja a tela apenas enquanto uma visualização sensĂ­vel estiver aberta:

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();
}

Observaçþes: privacyModeOnActivityHidden: 'none', 'dim' ou 'splash'. O cĂłdigo escrito para o prĂłprio app deve usar WebToApk.setSecureScreen(true) / privacyScreen.enable() de @/lib/appmintNative, que acompanha a pĂĄgina (liberado quando o app sai dela); se misturar os dois, vale a Ășltima chamada.

Capacitor.PushNotifications Capacitor#

Capacitor.Plugins.PushNotifications — register, requestPermissions, registration, pushNotificationReceived

Exemplo

NotificaçÔes push do SEU prĂłprio servidor pelo SEU projeto Firebase, com a API oficial @capacitor/push-notifications (com.capacitorjs:push-notifications, registrada pelo PushNotificationsPlugin.kt do shell). O cĂłdigo escrito para o pacote npm funciona sem alteraçÔes: register() e depois envie para o token do evento registration com o Firebase Admin SDK ou a API FCM HTTP v1.

Retorna: requestPermissions() / checkPermissions() → { receive: 'granted' | 'denied' | 'prompt' }; register() / unregister() → void (o token chega como o evento registration { value }, uma falha como registrationError { error }); getDeliveredNotifications() → { notifications }; removeDeliveredNotifications({ notifications }), removeAllDeliveredNotifications(); createChannel({ id, name, importance? }), listChannels(), deleteChannel({ id }). Eventos: pushNotificationReceived (uma mensagem com o app aberto: { id, title?, body?, data }) e pushNotificationActionPerformed ({ actionId: 'tap', notification: { id, data } }). Requer: compile com AppMint Push ativado e seu google-services.json enviado (etapa Notificaçþes) - esse Ă© o projeto Firebase ao qual o token pertence. Sem isso register() Ă© rejeitado com o cĂłdigo PUSH_NOT_CONFIGURED ("Push is not set up in this app"). Builds HTML, ZIP e AI-Studio marcam Notificaçþes sozinhos quando o cĂłdigo chama PushNotifications.register( / requestPermissions( / addListener(. window.Capacitor existe nas pĂĄginas que o prĂłprio app serve (apps HTML, ZIP e criados com IA) e, em um app no modo Website, no seu prĂłprio site (seu domĂ­nio e subdomĂ­nios) - nunca em outros sites que o app abre. Detecte o recurso antes de usar.

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.'); }
}

Reaja a uma mensagem enquanto o app estĂĄ aberto e ao toque em uma que chegou com o app fechado (o evento de toque espera pelo seu listener, entĂŁo uma inicialização a frio nĂŁo se perde):

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;
  });
}

Um canal para alertas importantes (Android 8+), usado por mensagens que o nomeiam em 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 });
}

Observações: Uma mensagem enviada com um bloco notification é exibida pelo próprio Android enquanto o app está em segundo plano; o toque nela abre o app (pela tela de desbloqueio quando o app tem PIN) e dispara pushNotificationActionPerformed. Com o app aberto, as mensagens chegam como pushNotificationReceived e não são desenhadas na bandeja. Mensagens somente de dados chegam à página apenas enquanto ela está aberta. As mensagens do AppMint Push continuam funcionando lado a lado - elas nunca chegam a este plugin. Em um app criado com OneSignal em vez de AppMint Push, as mensagens são entregues pelo OneSignal e nunca chegam a este plugin. Apps criados com IA recebem pushes do criador por meio de pushInbox() de @/lib/appmintNative.

Capacitor.ScreenBrightness Capacitor#

Capacitor.Plugins.ScreenBrightness — getBrightness(), setBrightness({ brightness })

Exemplo

Define o brilho da tela da janela do app - brilho mĂĄximo para um cartĂŁo de embarque ou QR code e depois de volta ao normal. Incluso @capacitor-community/screen-brightness (template/plugins/screen-brightness).

Retorna: getBrightness() → Promise { brightness } (0-1, ou -1 quando o app nĂŁo o alterou e a tela segue o sistema). setBrightness({ brightness }) → Promise void. Requer: nada - todo app hospeda o plugin; nenhuma permissĂŁo (ele altera sĂł a janela deste app, nĂŁo a configuração do sistema). window.Capacitor existe nas pĂĄginas que o prĂłprio app serve (apps HTML, ZIP e criados com IA) e, em um app no modo Website, no seu prĂłprio site (seu domĂ­nio e subdomĂ­nios) - nunca em outros sites que o app abre. Detecte o recurso antes de usar.

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;
}

Em um app criado com IA:

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

Leia primeiro o nĂ­vel atual e restaure exatamente esse:

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 });
}

Observaçþes: Passe sempre um nĂșmero - setBrightness({}) nĂŁo tem valor a aplicar. Restaure com -1 quando a visualização fechar; a substituição tambĂ©m termina quando o app fecha. Uma pĂĄgina web nĂŁo controla a luz de fundo, entĂŁo can('brightness') Ă© 'none' em um navegador.

Capacitor.ScreenOrientation Capacitor#

Capacitor.Plugins.ScreenOrientation — orientation(), lock({ orientation }), unlock()

Exemplo

LĂȘ a orientação da tela, a fixa para uma visualização (um jogo, um grĂĄfico, um campo de assinatura) e a libera (@capacitor/screen-orientation 8.0.1).

Retorna: orientation() → Promise { type } (por exemplo 'portrait-primary'). lock() / unlock() → Promise void. O evento screenOrientationChange passa { type }. Requer: nada para ativar - todo app hospeda o plugin. window.Capacitor existe nas pĂĄginas que o prĂłprio app serve (apps HTML, ZIP e criados com IA) e, em um app no modo Website, no seu prĂłprio site (seu domĂ­nio e subdomĂ­nios) - nunca em outros sites que o app abre. Detecte o recurso antes de usar.

orientation valores: '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); });
}

Em um app criado com IA:

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();

Trate um bloqueio recusado e avise o usuĂĄrio:

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' });
  }
}

Observaçþes: Os wrappers sĂł conhecem portrait / landscape / any: ScreenOrientation.lock({ orientation: 'landscape-secondary' }) trava em landscape simples. DĂȘ ao usuĂĄrio uma saĂ­da de uma visualização travada.

Capacitor.ScreenReader Capacitor#

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

Exemplo

Informa Ă pĂĄgina se o TalkBack estĂĄ ligado e fala um anĂșncio (@capacitor/screen-reader 8.0.1).

Retorna: isEnabled() → Promise { value: boolean }. speak() → Promise void. O evento stateChange passa { value: boolean } quando o TalkBack Ă© ligado ou desligado. Requer: nada para ativar - todo app hospeda o plugin. window.Capacitor existe nas pĂĄginas que o prĂłprio app serve (apps HTML, ZIP e criados com IA) e, em um app no modo Website, no seu prĂłprio site (seu domĂ­nio e subdomĂ­nios) - nunca em outros sites que o app abre. Detecte o recurso antes de usar.

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' });
}

Em um app criado com IA (speak usa texto para fala na web; isEnabled() Ă© false lĂĄ):

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

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

Detecte o recurso e mantenha a pĂĄgina utilizĂĄvel sem o 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
}

Observaçþes: language tem como padrĂŁo 'en'. Prefira marcação acessĂ­vel normal (rĂłtulos, regiĂ”es aria-live) para a maioria dos anĂșncios; use speak para mudanças de estado curtas e importantes. NĂŁo existe API web para detectar um leitor de tela, entĂŁo can('screenReader') Ă© 'none' em um navegador.

Capacitor.Share Capacitor#

Capacitor.Plugins.Share — share(options), canShare()

Exemplo

Abre a folha de compartilhamento do Android com um tĂ­tulo, texto e/ou um link (@capacitor/share 8.0.1).

Retorna: share() → Promise { activityType } (o nome do componente do app escolhido, pode ser ''); ela Ă© REJEITADA quando o usuĂĄrio fecha a folha. canShare() → Promise { value: boolean }. Requer: nada para ativar - todo app hospeda o plugin. window.Capacitor existe nas pĂĄginas que o prĂłprio app serve (apps HTML, ZIP e criados com IA) e, em um app no modo Website, no seu prĂłprio site (seu domĂ­nio e subdomĂ­nios) - nunca em outros sites que o app abre. Detecte o recurso antes de usar.

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
  }
}

Em um app criado com IA o wrapper tem o mesmo formato e também rejeita ao cancelar:

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
  }
}

Verifique canShare() primeiro e esconda o botĂŁo quando o compartilhamento nĂŁo estiver disponĂ­vel:

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; });
}

Observaçþes: url deve ser http(s):// ou file://. dialogTitle define o tĂ­tulo do seletor. Compartilhar arquivos exige caminhos file:// que pertencem ao app; a partir de uma pĂĄgina, compartilhe arquivos com navigator.share({ files }). SĂł um compartilhamento pode estar aberto por vez ("Can't share while sharing is in progress").

Capacitor.SpeechRecognition Capacitor#

Capacitor.Plugins.SpeechRecognition

Exemplo

Transforma a fala do usuĂĄrio em texto com o reconhecedor de voz do Android (o plugin da comunidade @capacitor-community/speech-recognition, incluĂ­do no app). O WebView do Android nĂŁo tem reconhecimento de voz Web Speech prĂłprio, entĂŁo este Ă© o caminho para ditado.

Retorna: Promises. available() → { available }. checkPermissions() / requestPermissions() → { speechRecognition: 'granted' | 'denied' | 'prompt' }. start({ partialResults: false }) → { status: 'success', matches: [...] } depois que o usuĂĄrio para de falar; Ă© rejeitada em erros como nenhuma fala ou nenhuma correspondĂȘncia. Requer: marque Microfone na Etapa 4 (Acesso) ao compilar (em apps HTML, ZIP e criados com IA o build tambĂ©m adiciona a permissĂŁo de microfone sozinho quando seus arquivos mencionam SpeechRecognition), e o usuĂĄrio precisa permitir o microfone. window.Capacitor existe nas pĂĄginas que o prĂłprio app serve (apps HTML, ZIP e criados com IA) e, em um app no modo Website, no seu prĂłprio site (seu domĂ­nio e subdomĂ­nios) - nunca em outros sites que o app abre. Detecte o recurso antes de usar.

Ditado de uma vez (do mesmo jeito que @/lib/appmintNative speech o usa):

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);

Texto ao vivo enquanto o usuĂĄrio fala (partialResults: true) e o estado de escuta:

// 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(); });

Mostre o botão de microfone apenas quando o ditado puder funcionar e pare de ouvir quando a página for ocultada:

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();
});

Observaçþes:

  • No modo ao vivo (partialResults: true), o texto final chega depois do estado 'stopped', entĂŁo nĂŁo remova o listener partialResults em 'stopped'. Um erro apĂłs o inĂ­cio (nenhuma fala, nenhuma correspondĂȘncia) nĂŁo Ă© informado neste modo.
  • language Ă© uma tag como 'en-US' ou 'ta-IN' (padrĂŁo: o idioma do celular). popup: true mostra a prĂłpria caixa de escuta do Google. getSupportedLanguages() → { languages } e isListening() → { listening } tambĂ©m existem.
  • start() rejeita com 'Missing permission' se vocĂȘ nĂŁo pediu a permissĂŁo antes. A escuta para sozinha depois de uma pausa na fala.

Capacitor.SplashScreen Capacitor#

Capacitor.Plugins.SplashScreen — show(), hide()

Exemplo

A API @capacitor/splash-screen sobre a tela de abertura personalizada do prĂłprio app, para que projetos Capacitor / AI Studio importados que chamam SplashScreen.hide() quando a primeira tela estĂĄ pronta funcionem no app Android.

Retorna: hide() → Promise (a tela de abertura sai depois que o tempo mĂ­nimo definido pelo criador passou); show({showDuration, autoHide}) → Promise (a tela de abertura volta sobre a pĂĄgina e, com autoHide - o padrĂŁo - sai depois de showDuration ms, padrĂŁo 3000). Requer: nada para ativar.

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();

Cubra uma troca lenta de conta com a tela de abertura, mantida até os novos dados aparecerem na tela:

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();
  }
}

Mostre a tela de abertura personalizada por um instante depois de sair da conta; ela some sozinha depois de 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);
    }
  }
}

Observaçþes: sem uma chamada hide() a tela de abertura ainda sai na primeira renderização, como em todo app. Apps criados com IA usam splash.hold() / splash.ready() de @/lib/appmintNative.

Capacitor.StatusBar Capacitor#

Capacitor.Plugins.StatusBar — setStyle, setBackgroundColor, show, hide, getInfo

Exemplo

Altera o estilo dos Ă­cones, a cor e a visibilidade da barra de status (@capacitor/status-bar 8.0.2).

Retorna: todo mĂ©todo → Promise void, exceto getInfo() → { visible, style, color, overlays, height }. Requer: nada para ativar - todo app hospeda o plugin. window.Capacitor existe nas pĂĄginas que o prĂłprio app serve (apps HTML, ZIP e criados com IA) e, em um app no modo Website, no seu prĂłprio site (seu domĂ­nio e subdomĂ­nios) - nunca em outros sites que o app abre. Detecte o recurso antes de usar.

style indica o FUNDO que combina: 'DARK' = ícones claros (para uma barra escura), 'LIGHT' = ícones escuros, 'DEFAULT' = seguir o sistema.

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();
}

Pinte a barra com a ponte do shell, nĂŁo com o plugin. No Android 15+ o setBackgroundColor do plugin nĂŁo faz nada (o modo edge-to-edge o ignora). O shell pinta a faixa por conta prĂłpria e recebe o estilo dos Ă­cones na mesma chamada:

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
}

Em um app criado com IA use setStatusBar(color, contentStyle); ele prefere a ponte do shell e define cor e Ă­cones em uma sĂł chamada:

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

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

Observaçþes: setBackgroundColor rejeita uma cor que nĂŁo seja uma string hexadecimal. Em builds de tela cheia / quiosque as barras sĂŁo ocultadas pelo shell. No app Android o StatusBar.setStyle() do wrapper sozinho nĂŁo muda nada (a ponte precisa de uma cor para pintar) - passe o estilo para setStatusBar() junto com uma cor.

Capacitor.TextToSpeech Capacitor#

Capacitor.Plugins.TextToSpeech — speak(), stop(), getSupportedLanguages(), getSupportedVoices()

Exemplo

O plugin da comunidade @capacitor-community/text-to-speech sobre o mecanismo de texto para fala do telefone. Incluído para que projetos Capacitor importados que o chamam funcionem.

Retorna: speak({text, lang, rate, pitch, volume, voice}) → Promise que resolve quando a frase foi falada; stop(); getSupportedLanguages() → {languages}; getSupportedVoices() → {voices}; isLanguageSupported({lang}) → {supported}. Requer: nada para ativar.

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();

Verifique o idioma antes de falar e mostre uma mensagem quando ele nĂŁo estiver instalado:

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;
}

Leia um parĂĄgrafo em voz alta com um botĂŁo de parar e trate um erro de fala:

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);
  }
}

Observaçþes: window.speechSynthesis tambĂ©m funciona no app (o motor do prĂłprio shell) e Ă© o que os apps criados com IA usam por meio de speak(); este plugin Ă© o caminho no formato Capacitor.

Capacitor.TextZoom Capacitor#

Capacitor.Plugins.TextZoom — get(), getPreferred(), set({ value })

Exemplo

LĂȘ e altera o tamanho do texto da pĂĄgina do app, para um controle de "tamanho do texto" dentro do app (@capacitor/text-zoom 8.0.1).

Retorna: get() → Promise { value } (zoom atual, 1 = 100%). getPreferred() → { value } (o tamanho que o usuĂĄrio escolheu nas configuraçÔes do Android). set({ value }) → Promise void. Requer: nada para ativar - todo app hospeda o plugin. window.Capacitor existe nas pĂĄginas que o prĂłprio app serve (apps HTML, ZIP e criados com IA) e, em um app no modo Website, no seu prĂłprio site (seu domĂ­nio e subdomĂ­nios) - nunca em outros sites que o app abre. Detecte o recurso antes de usar.

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 });
}

Em um app criado com IA (na web ele escala o tamanho da fonte da raiz):

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

Um controle deslizante de tamanho de texto que lembra a escolha:

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;
}

Observaçþes: O app jĂĄ segue o tamanho de texto do sistema; isto Ă© para um controle extra dentro do app. Teste seu layout em tamanhos grandes - alturas fixas em controles de texto vĂŁo cortar o conteĂșdo.

Capacitor.Toast Capacitor#

Capacitor.Plugins.Toast — show({ text, duration, position })

Exemplo

Mostra um toast curto do sistema Android como "Salvo" ou "Copiado" (@capacitor/toast 8.0.1).

Retorna: Promise void. Requer: nada para ativar - todo app hospeda o plugin. window.Capacitor existe nas pĂĄginas que o prĂłprio app serve (apps HTML, ZIP e criados com IA) e, em um app no modo Website, no seu prĂłprio site (seu domĂ­nio e subdomĂ­nios) - nunca em outros sites que o app abre. Detecte o recurso antes de usar.

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

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

duration Ă 'short' (cerca de 2 s) ou 'long' (cerca de 3,5 s). position Ă© 'top', 'center' ou 'bottom'.

Em um app criado com IA use toast() ou o Toast no formato Capacitor; na web eles desenham uma snackbar nas cores do app:

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

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

Detecte o recurso e mostre uma mensagem na pĂĄgina quando o plugin nĂŁo existir:

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);
}

Observações: text é obrigatório ("Must provide text"). O sistema desenha o toast no estilo do fabricante do telefone, e versões mais novas do Android ignoram position em toasts de texto. Um toast é fácil de perder - nunca o use para um erro que o usuário precise tratar; use Dialog.alert para isso.

Capacitor.Torch Capacitor#

Capacitor.Plugins.Torch — enable(), disable(), toggle(), isEnabled(), isAvailable()

Exemplo

A lanterna do celular, com a API @capawesome/capacitor-torch. Plugin prĂłprio do shell do app (TorchPlugin.kt).

Retorna: enable() / disable() / toggle() → Promise (rejeita CAMERA_IN_USE enquanto o fluxo da cĂąmera do prĂłprio app estĂĄ aberto, UNAVAILABLE sem flash); isEnabled() → {enabled}; isAvailable() → {available}. Requer: nada para ativar e nenhuma permissĂŁo.

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);
    }
  };
}

Pisque um sinal de SOS a partir de um botão e desligue a luz se a câmera tomar o flash no meio:

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);
  }
};

Mantenha um botĂŁo de lanterna em sincronia com o sistema, jĂĄ que o usuĂĄrio pode ligar a lanterna pelo bloco de configuraçÔes rĂĄpidas enquanto o app estĂĄ em segundo plano:

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();

Observaçþes: a luz segue o estado do sistema (desligĂĄ-la pelo bloco de configuraçÔes rĂĄpidas aparece como desligada) e Ă© apagada quando o app fecha. Enquanto um fluxo getUserMedia estiver aberto, acenda-a pela faixa: track.applyConstraints({ advanced: [{ torch: true }] }). Apps criados com IA usam torch de @/lib/appmintNative.

Gerado a partir do runtime do app e de seus arquivos de exemplo a cada build da documentação. Leia em Markdown · Todas as famílias.

Conferido com a ponte atual em 22/10/2026.