feat(ble): breadcrumb persistente sobrevive crash WebView v1.10.18
Some checks are pending
Build Android (APK + AAB) / build-android (push) Waiting to run
Some checks are pending
Build Android (APK + AAB) / build-android (push) Waiting to run
Karlão reportou: APK fecha 'em seguida' ao mandar parear. v1.10.17 removeu wake-up do path Capacitor mas crash ainda persiste — agora é em ble.requestDevice ou ble.connect/getServices. Sem alert popup = crash nativo lado Java do plugin BLE. Try/catch JS não captura. Solução: breadcrumb em localStorage ANTES de cada chamada nativa. bleCrumb(step) grava 'shivao_ble_last_step' no disco antes de: - ensureBleNativeReady - requestDevice - selected:<name> - ble.connect - ble.getServices Se app crashar, próxima abertura lê o breadcrumb e mostra alert '⚠ Crash detectado · Última ação: ble.connect @ 2026...' — daí descobrimos exatamente onde o plugin Java explode. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
70b123735e
commit
0c0b2d2825
6 changed files with 51 additions and 13 deletions
|
|
@ -3749,6 +3749,16 @@ async function updateStorageInfo(){
|
|||
(async()=>{
|
||||
// Wrapper try/catch pra capturar crash no boot (Capacitor WebView pode fechar silenciosamente)
|
||||
try{
|
||||
// Detecta crash BLE da sessão anterior via breadcrumb
|
||||
try{
|
||||
const lastStep=localStorage.getItem('shivao_ble_last_step');
|
||||
if(lastStep){
|
||||
setTimeout(()=>{
|
||||
try{alert('⚠ Crash detectado na sessão anterior!\nÚltima ação BLE: '+lastStep+'\n\nMe envie esta mensagem.')}catch{}
|
||||
},2000);
|
||||
localStorage.removeItem('shivao_ble_last_step');
|
||||
}
|
||||
}catch{}
|
||||
await openDB();
|
||||
try{loadState()}catch(e){console.error('[boot] loadState',e);try{localStorage.removeItem(STORAGE_KEY)}catch{}/* corrupt state — reset */}
|
||||
// Migration defensiva: limpa entries inválidas em state.btDevices
|
||||
|
|
@ -5885,6 +5895,12 @@ function setBleDiag(msg,type){
|
|||
console.log('[ble]',msg);
|
||||
}
|
||||
|
||||
// Breadcrumb persistente: grava ANTES de cada chamada nativa pra sobreviver crash do WebView
|
||||
function bleCrumb(step){
|
||||
try{localStorage.setItem('shivao_ble_last_step',step+' @ '+new Date().toISOString())}catch{}
|
||||
}
|
||||
function bleCrumbClear(){try{localStorage.removeItem('shivao_ble_last_step')}catch{}}
|
||||
|
||||
async function pairBluetoothDevice(){
|
||||
const backend=bleBackend();
|
||||
setBleDiag('Backend: '+(backend||'NENHUM'),backend?'info':'err');
|
||||
|
|
@ -5892,8 +5908,10 @@ async function pairBluetoothDevice(){
|
|||
try{
|
||||
let deviceId,deviceName;
|
||||
if(backend==='capacitor'){
|
||||
bleCrumb('ensureBleNativeReady');
|
||||
setBleDiag('Inicializando plugin nativo...');
|
||||
await ensureBleNativeReady();
|
||||
bleCrumb('requestDevice');
|
||||
setBleDiag('Plugin OK · abrindo picker...');
|
||||
const ble=window.Capacitor.Plugins.BluetoothLe;
|
||||
const result=await ble.requestDevice({
|
||||
|
|
@ -5901,9 +5919,10 @@ async function pairBluetoothDevice(){
|
|||
optionalServices:[BLE_BATTERY_SERVICE,BLE_DEVICE_INFO],
|
||||
allowDuplicates:false,
|
||||
});
|
||||
if(!result?.deviceId){setBleDiag('Picker cancelado','warn');return}
|
||||
if(!result?.deviceId){bleCrumbClear();setBleDiag('Picker cancelado','warn');return}
|
||||
deviceId=result.deviceId;
|
||||
deviceName=result.name||'Dispositivo BLE';
|
||||
bleCrumb('selected:'+deviceName);
|
||||
setBleDiag('Selecionado: '+deviceName+' ('+deviceId+')','ok');
|
||||
}else{
|
||||
setBleDiag('Abrindo picker do navegador...');
|
||||
|
|
@ -5963,6 +5982,7 @@ async function connectAndRead(deviceId,deviceName){
|
|||
if(backend==='capacitor'){
|
||||
const ble=window.Capacitor.Plugins.BluetoothLe;
|
||||
try{
|
||||
bleCrumb('ble.connect');
|
||||
await ble.connect({deviceId,timeout:30000});
|
||||
setBleDiag('GATT conectado','ok');
|
||||
}catch(e){
|
||||
|
|
@ -5972,13 +5992,12 @@ async function connectAndRead(deviceId,deviceName){
|
|||
const conn=_bleConnections.get(deviceId)||{};
|
||||
conn.backend='capacitor';conn.deviceId=deviceId;conn.connected=true;
|
||||
_bleConnections.set(deviceId,conn);
|
||||
// Discover all services pra diagnóstico + auto-detect protocols
|
||||
try{
|
||||
bleCrumb('ble.getServices');
|
||||
const r=await ble.getServices({deviceId});
|
||||
const svcs=(r.services||r||[]).map(s=>s.uuid||s).slice(0,8);
|
||||
setBleDiag('Serviços encontrados: '+svcs.length+' ('+svcs.map(u=>u.slice(4,8)).join(', ')+')','info');
|
||||
info.services=svcs;
|
||||
// Auto-detect: service ff00 = JBD/LLT Power BMS
|
||||
const hasJbd=svcs.some(u=>u.toLowerCase().startsWith('0000ff00'));
|
||||
if(hasJbd){
|
||||
setBleDiag('🔋 JBD BMS protocol detectado!','ok');
|
||||
|
|
@ -6461,7 +6480,7 @@ async function removeBluetoothDevice(id){
|
|||
renderBluetoothCard();
|
||||
}
|
||||
|
||||
const APP_VERSION='1.10.17';
|
||||
const APP_VERSION='1.10.18';
|
||||
function renderBluetoothCard(){
|
||||
const el=document.getElementById('bt-list');
|
||||
const supportEl=document.getElementById('bt-support');
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@ android {
|
|||
applicationId "br.com.pontualtech.shivao"
|
||||
minSdkVersion rootProject.ext.minSdkVersion
|
||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||
versionCode 30
|
||||
versionName "1.10.17"
|
||||
versionCode 31
|
||||
versionName "1.10.18"
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
aaptOptions {
|
||||
// Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps.
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "shivao-mobile",
|
||||
"version": "1.10.17",
|
||||
"version": "1.10.18",
|
||||
"description": "Shivao app nativo (Capacitor wrapper Android/iOS)",
|
||||
"main": "index.js",
|
||||
"type": "module",
|
||||
|
|
|
|||
|
|
@ -3749,6 +3749,16 @@ async function updateStorageInfo(){
|
|||
(async()=>{
|
||||
// Wrapper try/catch pra capturar crash no boot (Capacitor WebView pode fechar silenciosamente)
|
||||
try{
|
||||
// Detecta crash BLE da sessão anterior via breadcrumb
|
||||
try{
|
||||
const lastStep=localStorage.getItem('shivao_ble_last_step');
|
||||
if(lastStep){
|
||||
setTimeout(()=>{
|
||||
try{alert('⚠ Crash detectado na sessão anterior!\nÚltima ação BLE: '+lastStep+'\n\nMe envie esta mensagem.')}catch{}
|
||||
},2000);
|
||||
localStorage.removeItem('shivao_ble_last_step');
|
||||
}
|
||||
}catch{}
|
||||
await openDB();
|
||||
try{loadState()}catch(e){console.error('[boot] loadState',e);try{localStorage.removeItem(STORAGE_KEY)}catch{}/* corrupt state — reset */}
|
||||
// Migration defensiva: limpa entries inválidas em state.btDevices
|
||||
|
|
@ -5885,6 +5895,12 @@ function setBleDiag(msg,type){
|
|||
console.log('[ble]',msg);
|
||||
}
|
||||
|
||||
// Breadcrumb persistente: grava ANTES de cada chamada nativa pra sobreviver crash do WebView
|
||||
function bleCrumb(step){
|
||||
try{localStorage.setItem('shivao_ble_last_step',step+' @ '+new Date().toISOString())}catch{}
|
||||
}
|
||||
function bleCrumbClear(){try{localStorage.removeItem('shivao_ble_last_step')}catch{}}
|
||||
|
||||
async function pairBluetoothDevice(){
|
||||
const backend=bleBackend();
|
||||
setBleDiag('Backend: '+(backend||'NENHUM'),backend?'info':'err');
|
||||
|
|
@ -5892,8 +5908,10 @@ async function pairBluetoothDevice(){
|
|||
try{
|
||||
let deviceId,deviceName;
|
||||
if(backend==='capacitor'){
|
||||
bleCrumb('ensureBleNativeReady');
|
||||
setBleDiag('Inicializando plugin nativo...');
|
||||
await ensureBleNativeReady();
|
||||
bleCrumb('requestDevice');
|
||||
setBleDiag('Plugin OK · abrindo picker...');
|
||||
const ble=window.Capacitor.Plugins.BluetoothLe;
|
||||
const result=await ble.requestDevice({
|
||||
|
|
@ -5901,9 +5919,10 @@ async function pairBluetoothDevice(){
|
|||
optionalServices:[BLE_BATTERY_SERVICE,BLE_DEVICE_INFO],
|
||||
allowDuplicates:false,
|
||||
});
|
||||
if(!result?.deviceId){setBleDiag('Picker cancelado','warn');return}
|
||||
if(!result?.deviceId){bleCrumbClear();setBleDiag('Picker cancelado','warn');return}
|
||||
deviceId=result.deviceId;
|
||||
deviceName=result.name||'Dispositivo BLE';
|
||||
bleCrumb('selected:'+deviceName);
|
||||
setBleDiag('Selecionado: '+deviceName+' ('+deviceId+')','ok');
|
||||
}else{
|
||||
setBleDiag('Abrindo picker do navegador...');
|
||||
|
|
@ -5963,6 +5982,7 @@ async function connectAndRead(deviceId,deviceName){
|
|||
if(backend==='capacitor'){
|
||||
const ble=window.Capacitor.Plugins.BluetoothLe;
|
||||
try{
|
||||
bleCrumb('ble.connect');
|
||||
await ble.connect({deviceId,timeout:30000});
|
||||
setBleDiag('GATT conectado','ok');
|
||||
}catch(e){
|
||||
|
|
@ -5972,13 +5992,12 @@ async function connectAndRead(deviceId,deviceName){
|
|||
const conn=_bleConnections.get(deviceId)||{};
|
||||
conn.backend='capacitor';conn.deviceId=deviceId;conn.connected=true;
|
||||
_bleConnections.set(deviceId,conn);
|
||||
// Discover all services pra diagnóstico + auto-detect protocols
|
||||
try{
|
||||
bleCrumb('ble.getServices');
|
||||
const r=await ble.getServices({deviceId});
|
||||
const svcs=(r.services||r||[]).map(s=>s.uuid||s).slice(0,8);
|
||||
setBleDiag('Serviços encontrados: '+svcs.length+' ('+svcs.map(u=>u.slice(4,8)).join(', ')+')','info');
|
||||
info.services=svcs;
|
||||
// Auto-detect: service ff00 = JBD/LLT Power BMS
|
||||
const hasJbd=svcs.some(u=>u.toLowerCase().startsWith('0000ff00'));
|
||||
if(hasJbd){
|
||||
setBleDiag('🔋 JBD BMS protocol detectado!','ok');
|
||||
|
|
@ -6461,7 +6480,7 @@ async function removeBluetoothDevice(id){
|
|||
renderBluetoothCard();
|
||||
}
|
||||
|
||||
const APP_VERSION='1.10.17';
|
||||
const APP_VERSION='1.10.18';
|
||||
function renderBluetoothCard(){
|
||||
const el=document.getElementById('bt-list');
|
||||
const supportEl=document.getElementById('bt-support');
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// Shivao Service Worker — offline real
|
||||
// Estratégia: shell precachado, tiles cache-first, windy network-first, /api passa direto.
|
||||
// Versão usada nos cache names — bumpa essa string pra invalidar caches antigos em deploys.
|
||||
const VERSION = 'shivao-v1.10.17';
|
||||
const VERSION = 'shivao-v1.10.18';
|
||||
const SHELL_CACHE = `shivao-shell-${VERSION}`;
|
||||
const TILES_CACHE = 'shivao-tiles-v1'; // separado pra não invalidar tiles em update do shell
|
||||
const WINDY_CACHE = `shivao-windy-${VERSION}`;
|
||||
|
|
|
|||
|
|
@ -413,7 +413,7 @@ app.get('/.well-known/assetlinks.json', (req, res) => {
|
|||
});
|
||||
|
||||
// Atalho: /apk redireciona pra última APK release no Forgejo
|
||||
const LATEST_APK_URL = 'https://git.pontualtech.work/karlao/shivao-projeto/releases/download/v1.10.17/Shivao-v1.10.17.apk';
|
||||
const LATEST_APK_URL = 'https://git.pontualtech.work/karlao/shivao-projeto/releases/download/v1.10.18/Shivao-v1.10.18.apk';
|
||||
app.get('/apk', (req, res) => res.redirect(302, LATEST_APK_URL));
|
||||
|
||||
// Página A4 imprimível com QR Code + instruções (cola no barco/marina)
|
||||
|
|
|
|||
Loading…
Reference in a new issue