Criar APK grátis

API da ponte JavaScript

Vibração e som

Feedback tátil, o som de clique do próprio app disparado nos seus eventos semânticos em vez de em cada toque perdido, e a trilha de música de fundo que o criador escolheu na compilação - getMusicVolume retorna -1 quando o app não traz nenhuma, para que uma tela de configurações possa ocultar o controle deslizante em vez de mostrar um sem função.

navigator.vibrate padrão web#

navigator.vibrate(pattern)

Exemplo

Faz o celular vibrar, usando a Vibration API normal da web. O navigator.vibrate do próprio WebView do Android nunca move o motor; o app o substitui ao iniciar o documento para que ele realmente vibre.

Retorna: true quando a solicitação foi aceita, false para entrada inválida (uma duração negativa ou que não seja número). Requer: ative Vibrar na Etapa 4 (Acesso) ao compilar. Apps criados por IA já recebem isso ativado quando o código vibra.

function buzz(pattern) {
  if ('vibrate' in navigator) navigator.vibrate(pattern);
}

document.getElementById('save').addEventListener('click', function () {
  buzz(30);                    // one short buzz, 30 ms
});

document.getElementById('wrong').addEventListener('click', function () {
  buzz([80, 40, 80]);          // buzz 80, pause 40, buzz 80
});

document.getElementById('alarm-off').addEventListener('click', function () {
  buzz(0);                     // 0 or [] stops a running vibration
});

Use o valor de retorno para detectar uma duração inválida, por exemplo uma digitada pelo usuário:

document.getElementById('test-buzz').addEventListener('click', function () {
  var ms = parseInt(document.getElementById('buzz-ms').value, 10);   // '' gives NaN
  if (!('vibrate' in navigator)) return;
  if (!navigator.vibrate(ms)) {
    showError('Enter a duration of 0 ms or more.');
  }
});

Um tique curto quando um puxar para atualizar passa do ponto em que soltar vai atualizar:

var armed = false;
var list = document.getElementById('feed');

list.addEventListener('touchmove', function () {
  var ready = list.scrollTop <= 0 && pullDistance() > 80;
  if (ready && !armed && 'vibrate' in navigator) navigator.vibrate(15);
  armed = ready;
}, { passive: true });

list.addEventListener('touchend', function () {
  if (armed) refreshFeed();
  armed = false;
});

Observaçþes:

  • O padrão é o da web: o primeiro número é uma vibração, depois pausa, vibração, pausa ... (o app converte para o Android).
  • Se Vibrar não foi ativado ao compilar, a chamada ainda retorna true, mas o celular não vibra.
  • Decimais são arredondados para baixo. Em uma lista, números negativos contam como 0.
  • Em um navegador de computador, navigator.vibrate pode não existir, então mantenha a verificação 'vibrate' in navigator.

cancelVibrate ponte#

window.WebToApk.cancelVibrate()

Vibração simples para a página (navigator.vibrate e uma forma com padrão). Ambas são ignoradas, a menos que o build tenha ativado a permissão de Vibrar.

Descrito pelo seu grupo, Vibração, e não isoladamente.

Exemplo

Interrompe uma vibração que ainda está em andamento. A maioria das páginas usa o navigator.vibrate(0) padrão, que chama isto para você.

Retorna: nada. Requer: ative Vibrar na Etapa 4 (Acesso) ao compilar.

A forma padrão:

if ('vibrate' in navigator) navigator.vibrate(0);   // or navigator.vibrate([])

A chamada direta, por exemplo para parar um padrão de alarme longo quando o usuário toca em "Dispensar":

if (window.WebToApk && window.WebToApk.vibratePattern) {
  window.WebToApk.vibratePattern(JSON.stringify([1000, 500, 1000, 500, 1000]));
}

document.getElementById('dismiss').addEventListener('click', function () {
  if (window.WebToApk && typeof window.WebToApk.cancelVibrate === 'function') {
    window.WebToApk.cancelVibrate();
  }
});

Pare uma vibração em andamento quando o usuário sair da tela, para o celular não ficar vibrando no bolso dele:

document.addEventListener('visibilitychange', function () {
  if (!document.hidden) return;
  if (window.WebToApk && typeof window.WebToApk.cancelVibrate === 'function') {
    window.WebToApk.cancelVibrate();
  }
});

Observações: É seguro chamar quando nada está vibrando.

getMusicVolume ponte#

window.WebToApk.getMusicVolume(): Int

Nível atual de 0 a 100, ou -1 quando este app não inclui música de fundo.

Exemplo

Lê o nível da música de fundo em loop do app, de 0 a 100.

Retorna: um número, de forma síncrona: 0-100, ou -1 quando este app foi compilado sem um arquivo de música. Requer: um arquivo escolhido em Música de fundo na Etapa 3 (Integrar), em Opções de exibição, ao compilar.

Mostre um controle deslizante de música somente quando houver música:

var slider = document.getElementById('music-slider');
var level = -1;
if (window.WebToApk && typeof window.WebToApk.getMusicVolume === 'function') {
  level = window.WebToApk.getMusicVolume();
}

if (level < 0) {
  slider.parentNode.hidden = true;          // no music in this app: hide the setting
} else {
  slider.value = level;
  slider.addEventListener('input', function () {
    window.WebToApk.setMusicVolume(parseInt(slider.value, 10));
  });
}

Um botão de silenciar que volta ao nível do próprio usuário ao reativar o som (o app lembra 0 também, então guarde você mesmo o nível anterior):

function musicLevel() {
  return window.WebToApk && typeof window.WebToApk.getMusicVolume === 'function'
    ? window.WebToApk.getMusicVolume() : -1;
}
var muteBtn = document.getElementById('mute');

function paint() {
  var v = musicLevel();
  muteBtn.hidden = v < 0;
  muteBtn.textContent = v === 0 ? 'Unmute' : 'Mute';
}

muteBtn.addEventListener('click', function () {
  var v = musicLevel();
  if (v < 0) return;
  if (v > 0) {
    try { localStorage.setItem('musicBefore', String(v)); } catch (e) {}
    window.WebToApk.setMusicVolume(0);
  } else {
    var back = 40;
    try { back = parseInt(localStorage.getItem('musicBefore') || '40', 10); } catch (e) {}
    window.WebToApk.setMusicVolume(back);
  }
  paint();
});
paint();

Faça a música passar gradualmente do nível atual para um novo, por exemplo sob uma cena de diálogo:

function fadeMusicTo(target, ms) {
  if (!window.WebToApk || typeof window.WebToApk.getMusicVolume !== 'function') return;
  var start = window.WebToApk.getMusicVolume();
  if (start < 0 || start === target) return;
  var steps = 10, i = 0;
  var t = setInterval(function () {
    i++;
    window.WebToApk.setMusicVolume(Math.round(start + (target - start) * i / steps));
    if (i === steps) clearInterval(t);
  }, ms / steps);
}

fadeMusicTo(10, 800);     // dim under the dialogue
// later: fadeMusicTo(60, 800);  the last level set is the one kept for the next launch

Observações: Retorna o nível definido pelo controle deslizante do build ou pela sua última chamada de setMusicVolume. Quando outro app ou uma ligação assume o áudio, a música abaixa ou pausa sozinha; o número que você lê não muda.

getVolume ponte#

window.WebToApk.getVolume(stream: String): String

O nível de um stream: `{stream, current, max, percent, muted}` como string JSON. stream: 'media' | 'alarm' | 'ring' | 'notification' | 'call'.

Exemplo

Lê um dos níveis de volume do próprio celular.

Retorna: uma string JSON, de forma síncrona: {"stream":"alarm","current":5,"max":7,"percent":71,"muted":false} - current/max são os passos do próprio celular (diferem entre celulares), percent vai de 0 a 100. stream é 'media', 'alarm', 'ring', 'notification' ou 'call'; qualquer outro nome dá {"error":"unknown_stream"}. Requer: nada.

function warnIfAlarmSilent() {
  if (!(window.WebToApk && window.WebToApk.getVolume)) return;
  const v = JSON.parse(WebToApk.getVolume('alarm'));
  if (!v.error && v.percent === 0) {
    showMessage('Your alarm volume is off, so the alarm will not be heard.');
  }
}
warnIfAlarmSilent();

Mostre todos os níveis em uma tela de configurações:

['media', 'alarm', 'ring', 'notification'].forEach(function (s) {
  const v = JSON.parse(WebToApk.getVolume(s));
  document.getElementById('vol-' + s).value = v.percent;
});

Defina um volume e leia o resultado. setVolume(stream, percent, showUi) responde com uma string JSON.

function setAlarmVolume(percent) {
  if (!(window.WebToApk && WebToApk.setVolume)) return;
  const r = JSON.parse(WebToApk.setVolume('alarm', percent, true));
  if (!r.ok) showMessage('Could not change the volume: ' + r.error);   // fixed_volume, muted, ...
  else document.getElementById('vol-alarm').value = r.percent;
}

playClick ponte#

window.WebToApk.playClick()

Toca o som de toque do app sob demanda, para que uma página possa disparar nos SEUS próprios eventos semânticos (um toque em botão) em vez de em cada toque aleatório - que é o que um app nativo realmente faz, e o motivo de clickSoundMode poder ser "off" e isto ainda funcionar. Não faz nada apenas quando o app foi compilado SEM som de toque (enableClickSound desligado). Em clickSoundMode "off" - sem som automático a cada toque - uma chamada explícita ainda toca: esse modo existe para apps que tocam som nos próprios eventos. Caso contrário, toca o feedback configurado pelo criador.

Exemplo

Toca o som de toque do app uma vez, para que seus próprios botões façam clique como um app nativo.

Retorna: nada. Requer: a chave Som de toque na Etapa 3 (Integrar), em Opções de exibição, ao compilar (ativada por padrão). Com a chave desligada, isto não faz nada.

function clickSound() {
  if (window.WebToApk && typeof window.WebToApk.playClick === 'function') {
    window.WebToApk.playClick();
  }
}

document.querySelectorAll('button, .tab').forEach(function (el) {
  el.addEventListener('click', clickSound);
});

Um único listener para um tabuleiro de jogo inteiro, clicando só em um toque que faz alguma coisa:

document.getElementById('board').addEventListener('click', function (e) {
  var cell = e.target.closest('.cell');
  if (!cell || cell.classList.contains('taken')) return;   // a dead tap stays silent
  if (window.WebToApk && typeof window.WebToApk.playClick === 'function') {
    window.WebToApk.playClick();
  }
  placeMark(cell);
});

Dê aos seus usuários a própria chave de "Sons" além da configuração do build:

var toggle = document.getElementById('sounds-toggle');
var soundsOn = true;
try { soundsOn = localStorage.getItem('sounds') !== 'off'; } catch (e) {}
toggle.checked = soundsOn;

toggle.addEventListener('change', function () {
  soundsOn = toggle.checked;
  try { localStorage.setItem('sounds', soundsOn ? 'on' : 'off'); } catch (e) {}
});

function tapSound() {
  if (soundsOn && window.WebToApk && typeof window.WebToApk.playClick === 'function') {
    window.WebToApk.playClick();
  }
}

Observações: O que você ouve depende da escolha em Som de toque:

  • Seguir a configuração do celular (recomendado): o clique do sistema. Fica em silêncio quando o usuário desligou "Sons de toque" nas configurações do celular. Isso é intencional.
  • Sempre tocar em cada toque: o clique do próprio app, sempre audível. Cada toque na página também faz um clique, então você normalmente não precisa de playClick() neste modo.

Chame a partir de um toque real em um botão, não de um temporizador.

requestDndAccess ponte#

window.WebToApk.requestDndAccess(): String

Acesso a Não perturbe, necessário para mudar o nível de toque / notificação enquanto o Não perturbe está ativo. "granted" | "opened" (a tela de configurações foi aberta) | "not_declared".

Exemplo

Pede acesso ao Não perturbe, que o Android exige antes de um app poder mudar o volume do toque ou das notificações enquanto o Não perturbe está ligado (setVolume responde dnd_access_required nesse caso).

Retorna: uma string: 'granted' (já permitido), 'opened' (a tela do sistema onde o usuário permite foi aberta - confira de novo quando ele voltar) ou 'not_declared' (esta compilação não inclui a permissão, então o Android não listaria o app lá). Requer: chamar requestDndAccess no código do seu app: a compilação então declara ACCESS_NOTIFICATION_POLICY automaticamente.

function allowRingVolume() {
  if (!(window.WebToApk && window.WebToApk.requestDndAccess)) return;
  const r = WebToApk.requestDndAccess();
  if (r === 'opened') showMessage('Allow Do Not Disturb access for this app, then come back.');
  if (r === 'not_declared') showMessage('Turn off Do Not Disturb to change the ring volume.');
}

Tente de novo a mudança de volume depois que o usuário permitir o acesso:

function setRing(percent) {
  const r = JSON.parse(WebToApk.setVolume('ring', percent, true));
  if (r.ok || r.error !== 'dnd_access_required') return r;
  const a = WebToApk.requestDndAccess();     // 'granted' | 'opened' | 'not_declared'
  if (a === 'granted') return JSON.parse(WebToApk.setVolume('ring', percent, true));
  showMessage(a === 'opened' ? 'Allow access, then press the button again.' : 'Turn off Do Not Disturb first.');
  return r;
}

Silencie o toque com uma chave de "modo reunião" e diga o motivo quando não for possível:

function meetingMode(on) {
  if (!(window.WebToApk && WebToApk.setVolume)) return;
  const r = JSON.parse(WebToApk.setVolume('ring', on ? 0 : 70, false));
  if (!r.ok && r.error === 'dnd_access_required') {
    const a = WebToApk.requestDndAccess();
    if (a === 'not_declared') showMessage('This build cannot change the ring volume while Do Not Disturb is on.');
  }
}

setMusicVolume ponte#

window.WebToApk.setMusicVolume(percent: Int)

Define o nível da música de fundo a partir da página, de 0 a 100. O controle deslizante do assistente decide como o app COMEÇA; é assim que um app dá aos próprios usuários um controle de música, algo que qualquer jogo com tela de configurações deve ter. Limitado em [BackgroundMusic.setVolume], então uma página que passe 500 ou -1 não consegue dar ao MediaPlayer um ganho fora da faixa aceita. O nível é LEMBRADO: a próxima abertura começa nele, não no nível do assistente. Não faz nada quando o app foi compilado sem faixa - não há o que definir, e a resposta honesta é [getMusicVolume] retornar -1, para a página poder esconder o controle em vez de mostrar um que não faz nada.

Exemplo

Muda o nível da música de fundo em repetição do app, de 0 a 100, por exemplo na tela de configurações do seu jogo.

Retorna: nada. Requer: um arquivo escolhido em Música de fundo na Etapa 3 (Integrar), em Opções de exibição, ao compilar. Sem música isto não faz nada (verifique getMusicVolume() para -1).

Um botão de silenciar - o app lembra o nível para a próxima abertura:

function hasMusic() {
  return !!(window.WebToApk && window.WebToApk.getMusicVolume) && window.WebToApk.getMusicVolume() >= 0;
}

if (!hasMusic()) document.getElementById('mute').hidden = true;

document.getElementById('mute').addEventListener('click', function () {
  if (!hasMusic()) return;
  // clamped to 0..100 by the app, and kept for the next launch
  window.WebToApk.setMusicVolume(window.WebToApk.getMusicVolume() > 0 ? 0 : 40);
});

Botões Desligado / Baixa / Alta em uma tela de configurações:

var LEVELS = { off: 0, low: 25, high: 70 };

document.querySelectorAll('[data-music]').forEach(function (btn) {
  btn.addEventListener('click', function () {
    if (!window.WebToApk || typeof window.WebToApk.setMusicVolume !== 'function') return;
    if (window.WebToApk.getMusicVolume() < 0) return;       // built without music
    window.WebToApk.setMusicVolume(LEVELS[btn.dataset.music]);
    markSelected(btn);
  });
});

Abaixe a música enquanto seu próprio vídeo toca e depois coloque-a de volta (o nível é lembrado, então sempre restaure):

var video = document.getElementById('intro-video');
var before = -1;

video.addEventListener('play', function () {
  if (!window.WebToApk || typeof window.WebToApk.getMusicVolume !== 'function') return;
  before = window.WebToApk.getMusicVolume();
  if (before > 0) window.WebToApk.setMusicVolume(Math.round(before / 4));
});

function restoreMusic() {
  if (before > 0) window.WebToApk.setMusicVolume(before);
  before = -1;
}
video.addEventListener('pause', restoreMusic);
video.addEventListener('ended', restoreMusic);

Observações: O nível definido é salvo: a próxima abertura começa nele, em vez do nível do controle deslizante do build (até o usuário limpar os dados do app). 0 deixa a música em silêncio, mas ela continua tocando.

setVolume ponte#

window.WebToApk.setVolume(stream: String, percent: Double, showUi: Boolean): String

Define um fluxo em [percent] (0-100); [showUi] mostra o controle deslizante de volume do celular. `{ok:true, stream, current, max, percent}` ou `{ok:false, error}` - error é unknown_stream | bad_percent | fixed_volume | dnd_access_required | muted | not_applied | failed | foreign_origin (uma página fora do site do próprio app).

Exemplo

Define um dos níveis de volume do próprio celular, de 0 a 100 - por exemplo aumentando o volume do alarme para um despertador, ou um controle deslizante de mídia em um app de música.

Retorna: uma string JSON: {"ok":true,"stream":"alarm","current":6,"max":7,"percent":86}, ou {"ok":false,"error":"…"} em que error é unknown_stream, bad_percent, fixed_volume (este dispositivo não tem volume ajustável), dnd_access_required (o Não perturbe está ligado e bloqueia o nível do toque / notificação - veja requestDndAccess()), foreign_origin (uma página fora do site do seu próprio app) ou failed. showUi: true mostra o controle de volume do próprio celular enquanto ele se move. Requer: nada para mídia, alarme e chamada; toque e notificação podem precisar de acesso ao Não perturbe enquanto ele estiver ligado.

function setAlarmLoud() {
  if (!(window.WebToApk && window.WebToApk.setVolume)) return;
  const r = JSON.parse(WebToApk.setVolume('alarm', 80, true));
  if (!r.ok) showMessage('Could not change the alarm volume: ' + r.error);
}

document.getElementById('ring-slider').oninput = function (e) {
  const r = JSON.parse(WebToApk.setVolume('ring', Number(e.target.value), false));
  if (r.error === 'dnd_access_required' && WebToApk.requestDndAccess() === 'not_declared') {
    showMessage('Turn off Do Not Disturb to change the ring volume.');
  }
};

Leia um nível e depois ajuste um controle deslizante de mídia:

if (window.WebToApk && WebToApk.setVolume) {
  const now = JSON.parse(WebToApk.getVolume('media'));   // {stream, current, max, percent, muted}
  slider.value = now.percent;
  slider.oninput = () => {
    const r = JSON.parse(WebToApk.setVolume('media', Number(slider.value), false));
    if (r.ok) label.textContent = r.percent + '%';
    else if (r.error === 'fixed_volume') slider.disabled = true;   // this phone has no adjustable volume
  };
}

Mostre o nível atual do toque e reaja quando ele mudar:

if (window.WebToApk && WebToApk.getVolume) {
  const ring = JSON.parse(WebToApk.getVolume('ring'));   // {stream, current, max, percent, muted}
  document.getElementById('ring-slider').value = ring.percent;
  WebToApk.watchVolume(true);
  window.addEventListener('appmint:volume', (e) => {
    if (e.detail.stream === 'ring') document.getElementById('ring-slider').value = e.detail.percent;
  });
}

Observações: o valor é arredondado para o passo mais próximo do celular, e a resposta traz o nível realmente definido. O fluxo de chamadas nunca fica abaixo do mínimo (geralmente 1).

vibrate ponte#

window.WebToApk.vibrate(durationMs: Long)

Vibração simples para a página (navigator.vibrate e uma forma com padrão). Ambas são ignoradas, a menos que o build tenha ativado a permissão de Vibrar.

Descrito pelo seu grupo, Vibração, e não isoladamente.

Exemplo

Vibra o celular uma vez pelo número de milissegundos informado. A maioria das páginas usa o navigator.vibrate(ms) padrão, que chama isto para você.

Retorna: nada. Requer: ative Vibrar na Etapa 4 (Acesso) ao compilar. Sem isso a chamada não faz nada.

O jeito padrão (funciona igual em um navegador):

if ('vibrate' in navigator) navigator.vibrate(50);

A chamada bruta:

document.getElementById('like').addEventListener('click', function () {
  if (window.WebToApk && typeof window.WebToApk.vibrate === 'function') {
    window.WebToApk.vibrate(40);      // 40 ms
  }
});

// 0 (or any value <= 0) stops a running vibration
if (window.WebToApk && window.WebToApk.vibrate) window.WebToApk.vibrate(0);

Um pequeno toque cada vez que um controle deslizante encaixa em um novo passo, como um seletor nativo:

var slider = document.getElementById('size');
var last = slider.value;
slider.addEventListener('input', function () {
  if (slider.value === last) return;          // same step, no tick
  last = slider.value;
  if (window.WebToApk && typeof window.WebToApk.vibrate === 'function') {
    window.WebToApk.vibrate(10);              // 10 ms: a light tick
  }
});

Uma vibração mais longa quando um formulário não pode ser enviado, para o usuário sentir o erro:

document.getElementById('signup').addEventListener('submit', function (e) {
  if (this.checkValidity()) return;
  e.preventDefault();
  if (window.WebToApk && typeof window.WebToApk.vibrate === 'function') {
    window.WebToApk.vibrate(250);
  }
  this.reportValidity();
});

Observações: Passe um número inteiro. A intensidade é a padrão do celular; para toques mais fortes/fracos use Capacitor.Plugins.Haptics.impact ou Capacitor.Plugins.AppwrightHaptics.play. Para um padrão vibra-pausa-vibra use vibratePattern.

vibratePattern ponte#

window.WebToApk.vibratePattern(patternJson: String)

Vibra um padrão de liga/desliga, por ex. "[100,50,100]" = vibra 100 ms, pausa 50, vibra 100. Sustenta navigator.vibrate(array); prefira a API padrão. Sem efeito a menos que o criador tenha ativado a permissão Vibrar.

Exemplo

Vibra um padrão de liga/desliga, informado como string JSON. A maioria das páginas usa o navigator.vibrate([...]) padrão, que chama isto para você.

Retorna: nada. Requer: ative Vibrar na Etapa 4 (Acesso) ao compilar. Sem isso a chamada não faz nada.

A forma padrão:

if ('vibrate' in navigator) navigator.vibrate([100, 50, 100]);   // buzz, pause, buzz

A chamada bruta recebe o mesmo padrão estilo web como uma string JSON:

function pattern(list) {
  if (window.WebToApk && typeof window.WebToApk.vibratePattern === 'function') {
    window.WebToApk.vibratePattern(JSON.stringify(list));
  }
}

pattern([200]);                     // one 200 ms buzz
pattern([100, 50, 100, 50, 300]);   // short, short, long
pattern([]);                        // empty list stops a running vibration

O padrão toca uma vez, então um alarme o repete por conta própria até o usuário parar:

var alarm = null;
var ALARM = JSON.stringify([500, 300, 500, 300, 500]);   // about 2.1 s

function startAlarm() {
  if (!window.WebToApk || typeof window.WebToApk.vibratePattern !== 'function') return;
  window.WebToApk.vibratePattern(ALARM);
  alarm = setInterval(function () { window.WebToApk.vibratePattern(ALARM); }, 3000);
}

function stopAlarm() {
  if (alarm === null) return;
  clearInterval(alarm);
  alarm = null;
  window.WebToApk.vibratePattern('[]');                 // stop the buzz that is still running
}

Observações: O primeiro número é uma vibração, depois pausa, vibração, pausa ... (ordem da web). O app adiciona por você a "espera" inicial do Android, então não coloque um 0 no começo: [0, 100] significa "vibrar 0 ms, pausar 100 ms" e você não sente nada. Números negativos contam como 0. O padrão toca uma vez.

watchVolume ponte#

window.WebToApk.watchVolume(on: Boolean): Boolean

Liga (true) ou desliga (false) os eventos `appmint:volume`.

Exemplo

Liga ou desliga os eventos de mudança de volume ao vivo: enquanto ligado, toda mudança em um nível de volume (as teclas físicas, o controle deslizante do sistema, outro app) chega à página como appmint:volume.

Retorna: true quando a mudança surtiu efeito. Requer: nada.

if (window.WebToApk && window.WebToApk.watchVolume) {
  window.addEventListener('appmint:volume', function (e) {
    // e.detail = { stream: 'media', current: 9, max: 15, percent: 60, muted: false }
    document.getElementById('vol-' + e.detail.stream).value = e.detail.percent;
  });
  WebToApk.watchVolume(true);
  window.addEventListener('pagehide', function () { WebToApk.watchVolume(false); });
}

O mesmo objeto também alcança um gancho de página, se você preferir:

window.onAppMintVolume = function (level) {
  if (level.stream === 'alarm' && level.percent === 0) showMessage('Alarm volume is now off.');
};
WebToApk.watchVolume(true);

Mostre o nível uma vez com getVolume e depois mantenha-o atualizado só enquanto a tela estiver visível:

if (window.WebToApk && WebToApk.watchVolume && WebToApk.getVolume) {
  const meter = document.getElementById('media-meter');
  meter.value = JSON.parse(WebToApk.getVolume('media')).percent;
  const onVol = function (e) { if (e.detail.stream === 'media') meter.value = e.detail.percent; };
  document.addEventListener('visibilitychange', function () {
    if (document.hidden) { WebToApk.watchVolume(false); window.removeEventListener('appmint:volume', onVol); }
    else { window.addEventListener('appmint:volume', onVol); WebToApk.watchVolume(true); }
  });
}

Observações: um evento para cada stream que mudou (media, alarm, ring, notification, call). Desligue quando a tela que mostra os níveis for fechada.

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.