API del bridge JavaScript
Vibrazione e suono
Feedback aptico, il clic sonoro proprio dell'app attivato sui tuoi eventi semantici invece che su ogni tocco casuale, e il brano di musica di sottofondo scelto dal creatore al momento della build: getMusicVolume restituisce -1 quando l'app non ne include nessuno, così una schermata delle impostazioni può nascondere il cursore invece di mostrarne uno inutile.
cancelVibrate bridge#
window.WebToApk.cancelVibrate()
Feedback aptico semplice per la pagina (navigator.vibrate e la forma con uno schema). Entrambi vengono ignorati a meno che la build non abbia abilitato l'autorizzazione Vibrazione.
Descritta insieme al suo gruppo, Vibrazione, e non da sola.
Esempio
Interrompe una vibrazione ancora in corso. La maggior parte delle pagine usa lo standard navigator.vibrate(0), che chiama questo per te.
Restituisce: niente. Richiede: attiva Vibrazione nel Passaggio 4 (Accesso) quando crei l'app.
Il metodo standard:
if ('vibrate' in navigator) navigator.vibrate(0); // or navigator.vibrate([])La chiamata grezza, per esempio per fermare un lungo schema di allarme quando l'utente tocca «Ignora»:
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();
}
});Interrompi una vibrazione in corso quando l'utente lascia la schermata, così il telefono non continua a vibrare in tasca:
document.addEventListener('visibilitychange', function () {
if (!document.hidden) return;
if (window.WebToApk && typeof window.WebToApk.cancelVibrate === 'function') {
window.WebToApk.cancelVibrate();
}
});Note: si può chiamare in sicurezza anche quando nulla sta vibrando.
getMusicVolume bridge#
window.WebToApk.getMusicVolume(): Int
Livello attuale 0..100, oppure -1 quando questa app non include musica di sottofondo.
Esempio
Legge il livello della musica di sottofondo in loop dell'app, da 0 a 100.
Restituisce: un numero, in modo sincrono: 0-100, oppure -1 quando questa app è stata creata senza un file musicale. Richiede: un file scelto in Musica di sottofondo nel passaggio 3 (Integrazione), sotto Opzioni di visualizzazione, quando crei l'app.
Mostra un cursore della musica solo quando c'è musica:
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));
});
}Un pulsante muto che torna al livello dell'utente quando si riattiva l'audio (l'app ricorda anche 0, quindi conserva tu il vecchio livello):
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();Sfuma la musica dal livello attuale a uno nuovo, per esempio sotto una scena di dialogo:
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 launchNote: restituisce il livello impostato dal cursore della build o dalla tua ultima chiamata a setMusicVolume. Quando un'altra app o una chiamata prende l'audio, la musica si abbassa o va in pausa da sola; il numero che leggi non cambia.
getVolume bridge#
window.WebToApk.getVolume(stream: String): String
Il livello di un flusso: `{stream, current, max, percent, muted}` come stringa JSON. stream: 'media' | 'alarm' | 'ring' | 'notification' | 'call'.
Esempio
Legge uno dei livelli di volume del telefono.
Restituisce: una stringa JSON, in modo sincrono: {"stream":"alarm","current":5,"max":7,"percent":71,"muted":false}; current/max sono i passi del telefono (variano da telefono a telefono), percent va da 0 a 100. stream è 'media', 'alarm', 'ring', 'notification' o 'call'; qualsiasi altro nome dà {"error":"unknown_stream"}. Richiede: niente.
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();Mostra tutti i livelli in una schermata delle impostazioni:
['media', 'alarm', 'ring', 'notification'].forEach(function (s) {
const v = JSON.parse(WebToApk.getVolume(s));
document.getElementById('vol-' + s).value = v.percent;
});Imposta un volume e leggi il risultato. setVolume(stream, percent, showUi) risponde con una stringa 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 bridge#
window.WebToApk.playClick()
Riproduce su richiesta il suono del tocco dell'app, così una pagina può attivarlo sui PROPRI eventi semantici (la pressione di un pulsante) invece che a ogni tocco casuale - che è ciò che fa davvero un'app nativa, e il motivo per cui clickSoundMode può essere "off" e questa funzione continuare a funzionare. Non fa nulla solo quando l'app è stata creata SENZA suono del tocco (enableClickSound disattivato). In clickSoundMode "off" - nessun suono automatico a ogni tocco - una chiamata esplicita suona comunque: quella modalità esiste per le app che emettono suoni sui propri eventi. Altrimenti riproduce il feedback configurato dal creatore.
Esempio
Riproduce una volta il suono del tocco dell'app, così i tuoi pulsanti possono fare clic come in un'app nativa.
Restituisce: niente. Richiede: l'interruttore Suono al tocco nel passaggio 3 (Integrazione), sotto Opzioni di visualizzazione, quando crei l'app (attivo per impostazione predefinita). Con l'interruttore spento, non fa nulla.
function clickSound() {
if (window.WebToApk && typeof window.WebToApk.playClick === 'function') {
window.WebToApk.playClick();
}
}
document.querySelectorAll('button, .tab').forEach(function (el) {
el.addEventListener('click', clickSound);
});Un unico listener per un'intera plancia di gioco, che emette il clic solo su un tocco che fa qualcosa:
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);
});Dai ai tuoi utenti un interruttore «Suoni» tutto loro, oltre all'impostazione della 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();
}
}Note: ciò che senti dipende dalla scelta Suono del tocco:
- Segui l'impostazione del telefono (consigliato): il clic di sistema. È silenzioso quando l'utente ha disattivato «Suoni al tocco» nelle impostazioni del telefono. È voluto.
- Riproduci sempre a ogni tocco: il clic proprio dell'app, sempre udibile. Anche ogni tocco sulla pagina produce il clic, quindi in questa modalità di solito non ti serve
playClick().
Chiamala dalla pressione reale di un pulsante, non da un timer.
requestDndAccess bridge#
window.WebToApk.requestDndAccess(): String
Accesso a Non disturbare, necessario per cambiare il livello di suoneria / notifica mentre DND è attivo. "granted" | "opened" (è stata aperta la schermata delle impostazioni) | "not_declared".
Esempio
Chiede l'accesso a Non disturbare, che Android richiede prima che un'app possa cambiare il volume della suoneria o delle notifiche mentre Non disturbare è attivo (setVolume risponde dnd_access_required in quel caso).
Restituisce: una stringa: 'granted' (già consentito), 'opened' (è stata aperta la schermata di sistema in cui l'utente lo consente: ricontrolla quando torna) oppure 'not_declared' (questa build non include l'autorizzazione, quindi Android non elencherebbe l'app lì). Richiede: chiamare requestDndAccess nel codice della tua app: la build dichiara allora automaticamente ACCESS_NOTIFICATION_POLICY.
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.');
}Riprova a cambiare il volume una volta che l'utente ha consentito l'accesso:
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;
}Silenzia la suoneria con un interruttore «modalità riunione» e spiega perché quando non può funzionare:
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 bridge#
window.WebToApk.setMusicVolume(percent: Int)
Imposta dalla pagina il livello della musica di sottofondo, 0..100. Il cursore della procedura guidata decide come l'app PARTE; questo è il modo in cui un'app offre ai propri utenti un controllo della musica, cosa che ci si aspetta da qualsiasi gioco con una schermata delle impostazioni. Limitato in [BackgroundMusic.setVolume], così una pagina che passa 500 o -1 non può dare a MediaPlayer un guadagno fuori dall'intervallo accettato. Il livello viene MEMORIZZATO: il prossimo avvio parte da lì, non dal livello della procedura guidata. Non fa nulla quando l'app è stata creata senza una traccia: non c'è niente da impostare, e la risposta onesta è [getMusicVolume] che restituisce -1, così la pagina può nascondere il suo cursore invece di mostrarne uno che non fa nulla.
Esempio
Cambia il livello della musica di sottofondo in loop dell'app, da 0 a 100, per esempio dalla schermata delle impostazioni del tuo gioco.
Restituisce: niente. Richiede: un file scelto in Musica di sottofondo nel Passaggio 3 (Integrazione), sotto Opzioni di visualizzazione, quando crei l'app. Senza musica non fa nulla (controlla getMusicVolume() per -1).
Un pulsante muto: l'app ricorda il livello per il prossimo avvio:
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);
});Pulsanti Off / Basso / Alto in una schermata delle impostazioni:
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);
});
});Abbassa la musica mentre si riproduce un tuo video, poi rimettila (il livello viene memorizzato, quindi ripristinalo sempre):
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);Note: il livello impostato viene salvato: il prossimo avvio parte da quello invece che dal livello del cursore della build (finché l'utente non cancella i dati dell'app). 0 rende la musica silenziosa ma continua a riprodursi.
setVolume bridge#
window.WebToApk.setVolume(stream: String, percent: Double, showUi: Boolean): String
Imposta un flusso a [percent] (0-100); [showUi] mostra il cursore del volume del telefono. `{ok:true, stream, current, max, percent}` oppure `{ok:false, error}` - error è unknown_stream | bad_percent | fixed_volume | dnd_access_required | muted | not_applied | failed | foreign_origin (una pagina esterna al sito dell'app).
Esempio
Imposta uno dei livelli di volume del telefono, da 0 a 100: per esempio alzare il flusso della sveglia per una sveglia, o un cursore multimediale in un'app musicale.
Restituisce: una stringa JSON: {"ok":true,"stream":"alarm","current":6,"max":7,"percent":86}, oppure {"ok":false,"error":"…"} dove error è unknown_stream, bad_percent, fixed_volume (questo dispositivo non ha un volume regolabile), dnd_access_required (Non disturbare è attivo e blocca il livello di suoneria / notifiche - vedi requestDndAccess()), foreign_origin (una pagina esterna al sito della tua app) oppure failed. showUi: true mostra il cursore del volume del telefono mentre si muove. Richiede: niente per media, sveglia e chiamata; suoneria e notifiche possono richiedere l'accesso a Non disturbare mentre DND è attivo.
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.');
}
};Leggi un livello, poi imposta un cursore del volume multimediale:
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
};
}Mostra il livello attuale della suoneria e reagisci quando cambia:
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;
});
}Note: il valore viene arrotondato al passo più vicino del telefono e la risposta riporta il livello effettivamente impostato. Il flusso delle chiamate non scende mai sotto il suo minimo (di solito 1).
vibrate bridge#
window.WebToApk.vibrate(durationMs: Long)
Feedback aptico semplice per la pagina (navigator.vibrate e la forma con uno schema). Entrambi vengono ignorati a meno che la build non abbia abilitato l'autorizzazione Vibrazione.
Descritta insieme al suo gruppo, Vibrazione, e non da sola.
Esempio
Fa vibrare il telefono una volta per il numero di millisecondi indicato. La maggior parte delle pagine usa lo standard navigator.vibrate(ms), che chiama questa funzione per te.
Restituisce: niente. Richiede: attiva Vibrazione nel Passaggio 4 (Accesso) quando crei l'app. Senza, la chiamata non fa nulla.
Il modo standard (funziona allo stesso modo in un browser):
if ('vibrate' in navigator) navigator.vibrate(50);La chiamata grezza:
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);Un piccolo «tic» ogni volta che un cursore scatta su un nuovo passo, come un selettore 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
}
});Una vibrazione più lunga quando un modulo non può essere inviato, così l'utente sente l'errore:
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();
});Note: passa un numero intero. L'intensità è quella predefinita del telefono; per tocchi più forti/deboli usa Capacitor.Plugins.Haptics.impact o Capacitor.Plugins.AppwrightHaptics.play. Per uno schema vibra-pausa-vibra usa vibratePattern.
vibratePattern bridge#
window.WebToApk.vibratePattern(patternJson: String)
Fa vibrare con uno schema on/off, ad es. "[100,50,100]" = vibra 100 ms, pausa 50, vibra 100. È alla base di navigator.vibrate(array); preferisci l'API standard. Non fa nulla a meno che il creatore abbia attivato l'autorizzazione Vibrazione.
Esempio
Fa vibrare uno schema on/off, dato come stringa JSON. La maggior parte delle pagine usa lo standard navigator.vibrate([...]), che chiama questa funzione per te.
Restituisce: niente. Richiede: attiva Vibrazione nel Passaggio 4 (Accesso) quando crei l'app. Senza, la chiamata non fa nulla.
Il metodo standard:
if ('vibrate' in navigator) navigator.vibrate([100, 50, 100]); // buzz, pause, buzzLa chiamata grezza accetta lo stesso schema in stile web come stringa 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 vibrationLo schema viene riprodotto una volta, quindi una sveglia lo ripete da sé finché l'utente non la ferma:
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
}Note: il primo numero è una vibrazione, poi pausa, vibrazione, pausa ... (ordine web). L'app aggiunge per te l'«attesa» iniziale di Android, quindi non mettere tu uno 0 all'inizio: [0, 100] significa «vibra 0 ms, pausa 100 ms» e non senti nulla. I numeri negativi valgono 0. Lo schema viene riprodotto una volta.
watchVolume bridge#
window.WebToApk.watchVolume(on: Boolean): Boolean
Attiva (true) o disattiva (false) gli eventi `appmint:volume`.
Esempio
Attiva o disattiva gli eventi di variazione del volume in tempo reale: quando sono attivi, ogni cambiamento di un livello di volume (i tasti hardware, il cursore di sistema, un'altra app) raggiunge la pagina come appmint:volume.
Restituisce: true quando la modifica ha avuto effetto. Richiede: niente.
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); });
}Lo stesso oggetto è raggiungibile anche da un hook della pagina, se preferisci:
window.onAppMintVolume = function (level) {
if (level.stream === 'alarm' && level.percent === 0) showMessage('Alarm volume is now off.');
};
WebToApk.watchVolume(true);Mostra il livello una volta con getVolume, poi tienilo aggiornato solo mentre la schermata è visibile:
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); }
});
}Note: un evento per ogni flusso che è cambiato (media, alarm, ring, notification, call). Disattivalo quando si chiude la schermata che mostra i livelli.