commit c97a49cad708bcc80c4720cb554429da172af6ad Author: allebonvi Date: Fri Jun 12 15:11:26 2026 +0200 Register alpha.0 B4A prototype diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..bccc77f --- /dev/null +++ b/.gitignore @@ -0,0 +1,21 @@ +# B4A generated output +Objects/ +AutoBackups/ + +# Local diagnostic output +logs/ + +# Android build artifacts +*.apk +*.aab +*.ap_ +*.dex +*.class + +# Local/editor noise +.vs/ +.vscode/ +*.tmp +*.bak +Thumbs.db +Desktop.ini diff --git a/Files/drp.bal b/Files/drp.bal new file mode 100644 index 0000000..e8e10d5 Binary files /dev/null and b/Files/drp.bal differ diff --git a/Files/drpimg.png b/Files/drpimg.png new file mode 100644 index 0000000..c51d897 Binary files /dev/null and b/Files/drpimg.png differ diff --git a/Files/drpimgp.png b/Files/drpimgp.png new file mode 100644 index 0000000..56bcc97 Binary files /dev/null and b/Files/drpimgp.png differ diff --git a/Files/swarm.bal b/Files/swarm.bal new file mode 100644 index 0000000..cdaf854 Binary files /dev/null and b/Files/swarm.bal differ diff --git a/droplist.b4a.meta b/droplist.b4a.meta new file mode 100644 index 0000000..3afe682 --- /dev/null +++ b/droplist.b4a.meta @@ -0,0 +1,9 @@ +ModuleBookmarks0= +ModuleBookmarks1= +ModuleBreakpoints0=198 +ModuleBreakpoints1= +ModuleClosedNodes0= +ModuleClosedNodes1= +NavigationStack=Main,CronoClock_Tick,35,0,Main,DropSelect,108,0,Main,Activity_Create,63,6,Designer Visuale,swarm.bal,-100,6,droplist,dlst_ItemClick,119,0,droplist,Initialize,37,0,Main,VRImp_Result,161,3,Main,BtnSend_Click,166,6,Main,GetAllTexts,191,6,Main,Globals,38,0,Main,Process_Globals,19,0 +SelectedBuild=0 +VisibleModules=1 diff --git a/droplist.bas b/droplist.bas new file mode 100644 index 0000000..0d618c3 --- /dev/null +++ b/droplist.bas @@ -0,0 +1,137 @@ +Group=Default Group +ModulesStructureVersion=1 +Type=Class +Version=2.02 +@EndOfDesignText@ +'Class module +Sub Class_Globals + Dim pnlMn As Panel + Dim lblMn As Label + Dim btnMn As ImageView + Dim dpnl As Panel + Dim dlst As ListView + Dim dlItems As List + Dim isOpen As Boolean + Dim selPos As Int + Dim selVal As String + Dim selEvent As String +End Sub + +'Initializes the object. You can add parameters to this method if needed. +Public Sub Initialize(pnl As Panel, txt As String, evn As String) + Dim i, j, k As Int + Dim spc As String + Dim bp As Panel + Dim v As Panel + + i = pnl.Height + j = pnl.Width + pnlMn = pnl + dlItems.Initialize + + pnl.Color = Colors.Gray + + spc = " " + + Dim gd1 As GradientDrawable + Dim cl1(2) As Int + cl1(0) = Colors.ARGB(255, 220, 220, 220) + cl1(1) = Colors.ARGB(255, 160, 160, 160) + gd1.Initialize("TOP_BOTTOM", cl1) + + lblMn.Initialize("") ' control main label + pnl.AddView(lblMn, 0, 0, j-i-1, i) + lblMn.Background = gd1 + lblMn.Gravity = Gravity.LEFT + Gravity.CENTER_VERTICAL + lblMn.TextColor = Colors.Black + lblMn.TextSize = 18 + lblMn.Text = spc & txt + + Dim gd2 As GradientDrawable + Dim cl2(2) As Int + cl2(0) = Colors.ARGB(255, 220, 220, 220) + cl2(1) = Colors.ARGB(255, 160, 160, 160) + gd2.Initialize("TOP_BOTTOM", cl2) + + bp.Initialize("") ' button panel for drop button image + pnl.AddView(bp, j-i, 0, i, i) + bp.Background = gd2 + + btnMn.Initialize("btnMn") + bp.AddView(btnMn, 0, 0, i, i) + + Dim sld1 As StateListDrawable + Dim enb, psd As BitmapDrawable + + enb.Initialize(LoadBitmap(File.DirAssets, "drpimg.png")) + psd.Initialize(LoadBitmap(File.DirAssets, "drpimgp.png")) + + sld1.Initialize + sld1.AddState(sld1.State_Pressed, psd) + sld1.AddState(sld1.State_Enabled, enb) + + btnMn.Gravity = Gravity.FILL + btnMn.Background = sld1 + + Dim cd3 As ColorDrawable + cd3.Initialize(Colors.Gray, 5dip) + + dpnl.Initialize("") ' the drop panel + dpnl.Background = cd3 + v = GetParent(pnl) + v.AddView(dpnl, pnl.Left+j*0.03, pnl.Top+i, j, 5*i) + + Dim cd4 As ColorDrawable + cd4.Initialize(Colors.LightGray, 5dip) + + dlst.Initialize("dlst") ' the drop panel listview + dpnl.AddView(dlst, 0, 0, dpnl.Width, dpnl.Height) + dlst.SingleLineLayout.Background = cd4 + dlst.SingleLineLayout.ItemHeight = pnl.Height + dlst.SingleLineLayout.Label.TextColor = Colors.Black + dlst.SingleLineLayout.Label.TextSize = 18 + dlst.SingleLineLayout.Label.Gravity = Gravity.CENTER_HORIZONTAL + Gravity.CENTER_VERTICAL + + dpnl.Enabled = False + dpnl.Visible = False + + isOpen = False + selPos = -1 + selVal = "" + selEvent = evn +End Sub + +Sub btnMn_Click + If (isOpen = True) Then + isOpen = False + dpnl.Enabled = False + dpnl.Visible = False + Else + isOpen = True + + dlst.Clear + For i=0 To dlItems.Size-1 + dlst.AddSingleLine(dlItems.Get(i)) + Next + + dpnl.Enabled = True + dpnl.Visible = True + End If +End Sub + +Sub dlst_ItemClick (pos As Int, val As Object) + selPos = pos + selVal = val + lblMn.Text = " " & val + + If (isOpen = False) Then Return + + CallSubDelayed(Main, selEvent) + btnMn_Click +End Sub + +Sub GetParent(v As View) As View + Dim r As Reflector + r.Target = v + Return r.RunMethod("getParent") +End Sub \ No newline at end of file diff --git a/swarm.b4a b/swarm.b4a new file mode 100644 index 0000000..7cb23ab --- /dev/null +++ b/swarm.b4a @@ -0,0 +1,470 @@ +Build1=Default,anywheresoftware.b4a.swarm +File1=drp.bal +File2=swarm.bal +FileGroup1=Default Group +FileGroup2=Default Group +Group=Default Group +Library1=core +Library2=phone +Library3=reflection +Library4=tts +Library5=json +Library6=okhttputils2 +ManifestCode='This code will be applied to the manifest file during compilation.~\n~'You do not need to modify it in most cases.~\n~'See this link for for more information: https://www.b4x.com/forum/showthread.php?p=78136~\n~AddManifestText(~\n~~\n~)~\n~SetApplicationAttribute(android:icon, "@drawable/icon")~\n~SetApplicationAttribute(android:label, "$LABEL$")~\n~CreateResourceFromFile(Macro, Themes.LightTheme)~\n~'End of default text.~\n~ +Module1=droplist +NumberOfFiles=2 +NumberOfLibraries=6 +NumberOfModules=1 +Version=13 +@EndOfDesignText@ +#Region Module Attributes + #FullScreen: True + #IncludeTitle: False + #ApplicationLabel: Swarm + #VersionCode: 1 + #VersionName: 1.0 + #SupportedOrientations: unspecified + #CanInstallToExternalStorage: False + +#End Region + +'#AdditionalJar: jtds-1.3.1.jar + +'Activity module +Sub Process_Globals + 'These global variables will be declared once when the application starts. + 'These variables can be accessed from all modules. + Dim VRStd As VoiceRecognition + Dim TTSStd As TTS + + Dim VRImp As VoiceRecognition + Dim TTSImp As TTS + + Private Const API_ENDPOINT As String = "https://example.com/api/processes" + Private Const EVENT_TYPE_STANDARD As String = "standard" + Private Const EVENT_TYPE_UNEXPECTED As String = "unexpected" + + Private CurrentProcessId As String + Private ProcessStartTime As Long + Private ProcessStartedAt As String + Private Events As List + Private ProcessActive As Boolean + + Private crono As Timer + crono.Initialize("CronoClock", 1000) + + +End Sub + + +Sub CronoClock_Tick + 'Handle tick events + tempoTrascorso = tempoTrascorso +1 + TimeElapsed.Text= "Secondi trascorsi " & tempoTrascorso & " sec" + +End Sub + + + + + +Sub Globals + 'These global variables will be redeclared each time the activity is created. + 'These variables can only be accessed from this module. + + Dim pnl1 As Panel + Dim dlist As droplist + Dim tempoTrascorso As Long + Private BtnRecImp As Button + Private BtnRecStd As Button + Private BtnSend As Button + Private InputImp As EditText + Private InputStd As EditText + Private LblEvnt As Label + Private StartStopTog As ToggleButton + Private TimeElapsed As Label + Private pressed As Long + Private IgnoreToggleEvent As Boolean + Private EventList As ListView + Private SelectedEventIndex As Int + Private RerecordEventIndex As Int + + tempoTrascorso=0 + SelectedEventIndex = -1 + RerecordEventIndex = -1 + +End Sub + +Sub Activity_Create(FirstTime As Boolean) + + If FirstTime Then + VRStd.Initialize("VRStd") + TTSStd.Initialize("TTSStd") + + VRImp.Initialize("VRImp") + TTSImp.Initialize("TTSImp") + Events.Initialize + + End If + + + Activity.LoadLayout("swarm") + dlist.Initialize(pnl1, "Operatore:", "DropSelect") + + dlist.dlItems.Add("Beppe") + dlist.dlItems.Add("George") + dlist.dlItems.Add("Cristina") + dlist.dlItems.Add("Erica") + dlist.dlItems.Add("Alfonso") + +' If VR.IsSupported Then +' ToastMessageShow("Voice recognition is supported.", False) +' Else +' ToastMessageShow("Voice recognition is not supported.", True) +' End If + + BtnRecImp.SetTextColorAnimated(0, Colors.Black) + BtnRecImp.Text="Rec imp" + + BtnRecStd.SetTextColorAnimated(0, Colors.Black) + BtnRecStd.Text="Rec std" + + BtnSend.SetTextColorAnimated(0, Colors.Black) + BtnSend.Text="Invia" + + SetupEventList + +End Sub + +Sub Activity_Resume + +End Sub + +Sub Activity_Pause (UserClosed As Boolean) + +End Sub + +Sub DropSelect + Log("** You Selected " & dlist.selVal & ", at " & dlist.selPos & " **") +End Sub + + + + +Private Sub StartStopTog_CheckedChange(Checked As Boolean) + If IgnoreToggleEvent Then Return + + Log("** You Selected: " & StartStopTog.Checked) + + If StartStopTog.Checked Then + Log("** Start counting " & StartStopTog.Checked) + StartProcess + + + Else + Log("** Stop counting " & StartStopTog.Checked) + StopProcess(False) + End If + + 'Dim pressedTime As Long = DateTime.Now - pressed + 'TimeElapsed.Text = pressedTime & "s" + + +End Sub + +Private Sub BtnRecStd_Click + If ProcessActive = False Then + ToastMessageShow("Avvia prima il processo.", False) + Return + End If + VRStd.Prompt = "Fai il tuo sproloquio per un evento standard!" + VRStd.Listen 'calls the voice recognition external activity +End Sub + +Private Sub BtnRecImp_Click + If ProcessActive = False Then + ToastMessageShow("Avvia prima il processo.", False) + Return + End If + VRImp.Prompt = "Descrivi l'evento imprevisto!" + VRImp.Listen 'calls the voice recognition external activity +End Sub + + +Sub VRStd_Result (Success As Boolean, Texts As List) + If Success = False Then + RerecordEventIndex = -1 + Return + End If + If Texts.IsInitialized = False Then + RerecordEventIndex = -1 + Return + End If + If Texts.Size = 0 Then + RerecordEventIndex = -1 + Return + End If + + Dim description As String = Texts.Get(0) + Log("** You said: " & description) + InputStd.Text=description + TTSStd.Speak(description, True) + SaveVoiceDescription(EVENT_TYPE_STANDARD, description) +End Sub + + +Sub VRImp_Result (Success As Boolean, Texts As List) + If Success = False Then + RerecordEventIndex = -1 + Return + End If + If Texts.IsInitialized = False Then + RerecordEventIndex = -1 + Return + End If + If Texts.Size = 0 Then + RerecordEventIndex = -1 + Return + End If + + Dim description As String = Texts.Get(0) + Log("** You said: " & description) + InputImp.Text=description + TTSImp.Speak(description, True) + SaveVoiceDescription(EVENT_TYPE_UNEXPECTED, description) +End Sub + + + +Private Sub BtnSend_Click + Log("** You clicked: " & " INVIATO" ) + SendProcess +End Sub + +Private Sub StartProcess + If dlist.selPos < 0 Then + ToastMessageShow("Seleziona prima l'operatore.", True) + IgnoreToggleEvent = True + StartStopTog.Checked = False + IgnoreToggleEvent = False + Return + End If + + CurrentProcessId = "SWARM-" & DateTime.Now + ProcessStartTime = DateTime.Now + ProcessStartedAt = FormatApiDate(ProcessStartTime) + tempoTrascorso = 0 + Events.Initialize + SelectedEventIndex = -1 + RerecordEventIndex = -1 + ProcessActive = True + crono.Enabled = True + TimeElapsed.Text= "Secondi trascorsi 0 sec" + LblEvnt.Text = "Processo avviato" + RefreshEventList +End Sub + +Private Sub StopProcess(ClearData As Boolean) + crono.Enabled = False + ProcessActive = False + + If ClearData Then + CurrentProcessId = "" + ProcessStartTime = 0 + ProcessStartedAt = "" + tempoTrascorso = 0 + Events.Initialize + SelectedEventIndex = -1 + RerecordEventIndex = -1 + TimeElapsed.Text= " 0" + LblEvnt.Text = "" + RefreshEventList + Else + LblEvnt.Text = "Processo fermato - eventi: " & Events.Size + End If +End Sub + +Private Sub SaveVoiceDescription(EventType As String, Description As String) + If RerecordEventIndex >= 0 Then + UpdateEventDescription(RerecordEventIndex, Description) + RerecordEventIndex = -1 + Else + RegisterEvent(EventType, Description) + End If +End Sub + +Private Sub RegisterEvent(EventType As String, Description As String) + If Events.IsInitialized = False Then Events.Initialize + + Dim evt As Map + evt.Initialize + evt.Put("sequence", Events.Size + 1) + evt.Put("type", EventType) + evt.Put("description", Description) + evt.Put("elapsedSeconds", tempoTrascorso) + evt.Put("timestamp", FormatApiDate(DateTime.Now)) + + Events.Add(evt) + SelectedEventIndex = -1 + LblEvnt.Text = "Eventi registrati: " & Events.Size + RefreshEventList +End Sub + +Private Sub UpdateEventDescription(Index As Int, Description As String) + If Events.IsInitialized = False Then Return + If Index < 0 Or Index >= Events.Size Then Return + + Dim evt As Map = Events.Get(Index) + evt.Put("description", Description) + evt.Put("updatedAt", FormatApiDate(DateTime.Now)) + Events.Set(Index, evt) + + SelectedEventIndex = -1 + LblEvnt.Text = "Record aggiornato: " & (Index + 1) + RefreshEventList +End Sub + +Private Sub SendProcess + If CurrentProcessId = "" Then + ToastMessageShow("Nessun processo da inviare.", True) + Return + End If + + If Events.IsInitialized = False Then + ToastMessageShow("Registra almeno un evento prima di inviare.", True) + Return + End If + + If Events.Size = 0 Then + ToastMessageShow("Registra almeno un evento prima di inviare.", True) + Return + End If + + crono.Enabled = False + ProcessActive = False + + Dim payload As Map + payload.Initialize + payload.Put("processId", CurrentProcessId) + payload.Put("operator", dlist.selVal) + payload.Put("startedAt", ProcessStartedAt) + payload.Put("endedAt", FormatApiDate(DateTime.Now)) + payload.Put("durationSeconds", tempoTrascorso) + payload.Put("events", Events) + + Dim json As JSONGenerator + json.Initialize(payload) + + Dim job As HttpJob + job.Initialize("SendProcess", Me) + job.PostString(API_ENDPOINT, json.ToString) + job.GetRequest.SetContentType("application/json") + LblEvnt.Text = "Invio in corso..." +End Sub + +Sub JobDone(Job As HttpJob) + If Job.JobName = "SendProcess" Then + If Job.Success Then + Log("** API response: " & Job.GetString) + ToastMessageShow("Processo inviato.", False) + IgnoreToggleEvent = True + StartStopTog.Checked = False + IgnoreToggleEvent = False + StopProcess(True) + Else + Log("** API error: " & Job.ErrorMessage) + ToastMessageShow("Errore invio: " & Job.ErrorMessage, True) + LblEvnt.Text = "Invio non riuscito - eventi: " & Events.Size + End If + End If + Job.Release +End Sub + +Private Sub FormatApiDate(Ticks As Long) As String + Return DateTime.GetYear(Ticks) & "-" & TwoDigits(DateTime.GetMonth(Ticks)) & "-" & TwoDigits(DateTime.GetDayOfMonth(Ticks)) & "T" & TwoDigits(DateTime.GetHour(Ticks)) & ":" & TwoDigits(DateTime.GetMinute(Ticks)) & ":" & TwoDigits(DateTime.GetSecond(Ticks)) +End Sub + +Private Sub TwoDigits(Value As Int) As String + If Value < 10 Then Return "0" & Value + Return "" & Value +End Sub + +Private Sub SetupEventList + EventList.Initialize("EventList") + Activity.AddView(EventList, 8dip, Activity.Height - 170dip, Activity.Width - 16dip, 160dip) + EventList.SingleLineLayout.Label.TextSize = 14 + EventList.SingleLineLayout.Label.TextColor = Colors.Black + EventList.SingleLineLayout.ItemHeight = 48dip + RefreshEventList +End Sub + +Private Sub RefreshEventList + If EventList.IsInitialized = False Then Return + EventList.Clear + If Events.IsInitialized = False Then Return + + For i = 0 To Events.Size - 1 + Dim evt As Map = Events.Get(i) + Dim description As String = evt.Get("description") + If description.Length > 45 Then description = description.SubString2(0, 45) & "..." + EventList.AddSingleLine((i + 1) & ". [" & evt.Get("elapsedSeconds") & "s] " & evt.Get("type") & ": " & description) + Next +End Sub + +Private Sub EventList_ItemClick (Position As Int, Value As Object) + If Events.IsInitialized = False Then Return + If Position < 0 Or Position >= Events.Size Then Return + + SelectedEventIndex = Position + RerecordEventIndex = Position + + Dim evt As Map = Events.Get(Position) + Dim eventType As String = evt.Get("type") + LblEvnt.Text = "Riregistra record " & (Position + 1) + + If eventType = EVENT_TYPE_UNEXPECTED Then + VRImp.Prompt = "Riregistra la descrizione dell'evento imprevisto." + VRImp.Listen + Else + VRStd.Prompt = "Riregistra la descrizione dell'evento standard." + VRStd.Listen + End If +End Sub + +Sub GetAllTexts (Act As Activity) + Dim lbl As Label + Dim txt As EditText + + For i = 0 To Act.NumberOfViews - 1 + + + If Act.GetView(i) Is Label Then + lbl = Act.GetView(i) + Log(lbl.Text) + + End If +' If Activity.GetView(i) Is EditText Then +' txt= Activity.GetView(i) +' Log(lbl.Text) +' End If + If Act.GetView(i) Is Panel Then + Dim pan As Panel + pan = Act.GetView(i) + 'lbl = Act.GetView(i) + 'GetAllTexts(pan) + For j = 0 To pan.NumberOfViews - 1 + Dim lbl As Label + Dim txt As EditText + + If pan.GetView(j) Is Label Then + lbl = pan.GetView(j) + Log(lbl.Text) + + End If + + Next + + End If + + Next +End Sub diff --git a/swarm.b4a.meta b/swarm.b4a.meta new file mode 100644 index 0000000..cbdd6b2 --- /dev/null +++ b/swarm.b4a.meta @@ -0,0 +1,9 @@ +ModuleBookmarks0= +ModuleBookmarks1= +ModuleBreakpoints0= +ModuleBreakpoints1= +ModuleClosedNodes0= +ModuleClosedNodes1= +NavigationStack=droplist,Class_Globals,6,0,Main,DropSelect,108,0,droplist,Initialize,16,3,Main,Activity_Create,63,2,Main,BtnRecImp_Click,143,1,Main,BtnSend_Click,176,1,Main,GetAllTexts,181,1,Main,CronoClock_Tick,30,0,Designer Visuale,swarm.bal,-100,1,Main,Globals,45,1 +SelectedBuild=0 +VisibleModules=1 diff --git a/tools/build-b4a.ps1 b/tools/build-b4a.ps1 new file mode 100644 index 0000000..3bb531a --- /dev/null +++ b/tools/build-b4a.ps1 @@ -0,0 +1,51 @@ +param( + [string]$ProjectRoot = (Resolve-Path "$PSScriptRoot\..").Path, + [string]$ProjectFile = "swarm.b4a", + [string]$BuilderPath = "C:\Program Files\Anywhere Software\B4A\B4ABuilder.exe", + [ValidateSet("Build", "BuildBundle", "BuildLibrary")] + [string]$Task = "Build", + [switch]$NoSign, + [switch]$Obfuscate, + [switch]$NoClean, + [string]$Configuration = "", + [string]$Output = "" +) + +$ErrorActionPreference = "Stop" + +if (-not (Test-Path -LiteralPath $BuilderPath)) { + throw "B4ABuilder.exe non trovato: $BuilderPath" +} + +if (-not (Test-Path -LiteralPath (Join-Path $ProjectRoot $ProjectFile))) { + throw "Progetto B4A non trovato: $(Join-Path $ProjectRoot $ProjectFile)" +} + +$arguments = @( + "-Task=$Task", + "-BaseFolder=$ProjectRoot", + "-Project=$ProjectFile", + "-Obfuscate=$($Obfuscate.IsPresent)", + "-ShowWarnings=True", + "-NoSign=$($NoSign.IsPresent)", + "-NoClean=$($NoClean.IsPresent)" +) + +if ($Configuration.Trim().Length -gt 0) { + $arguments += "-Configuration=$Configuration" +} + +if ($Output.Trim().Length -gt 0) { + $arguments += "-Output=$Output" +} + +Write-Host "B4A build: $ProjectFile" +Write-Host "Root: $ProjectRoot" +Write-Host "" + +& $BuilderPath @arguments +$exitCode = $LASTEXITCODE + +if ($exitCode -ne 0) { + throw "Build B4A fallita. Exit code: $exitCode" +} diff --git a/tools/deploy-emulator.ps1 b/tools/deploy-emulator.ps1 new file mode 100644 index 0000000..e5eb413 --- /dev/null +++ b/tools/deploy-emulator.ps1 @@ -0,0 +1,40 @@ +param( + [string]$ProjectRoot = (Resolve-Path "$PSScriptRoot\..").Path, + [string]$AdbPath = "C:\android\platform-tools\adb.exe", + [string]$PackageName = "anywheresoftware.b4a.swarm", + [string]$MainActivity = ".main", + [switch]$NoBuild, + [switch]$NoLaunch, + [switch]$KeepLogcat +) + +$ErrorActionPreference = "Stop" + +if (-not (Test-Path -LiteralPath $AdbPath)) { + throw "adb.exe non trovato: $AdbPath" +} + +if (-not $NoBuild) { + & "$PSScriptRoot\build-b4a.ps1" -ProjectRoot $ProjectRoot +} + +$apkPath = Join-Path $ProjectRoot "Objects\swarm.apk" +if (-not (Test-Path -LiteralPath $apkPath)) { + throw "APK non trovato: $apkPath" +} + +& $AdbPath wait-for-device + +if (-not $KeepLogcat) { + & $AdbPath logcat -c +} + +Write-Host "" +Write-Host "Installo APK: $apkPath" +& $AdbPath install -r -d $apkPath + +if (-not $NoLaunch) { + Write-Host "" + Write-Host "Avvio app: $PackageName/$MainActivity" + & $AdbPath shell am start -n "$PackageName/$MainActivity" +} diff --git a/tools/watch-logcat.ps1 b/tools/watch-logcat.ps1 new file mode 100644 index 0000000..85a8cc1 --- /dev/null +++ b/tools/watch-logcat.ps1 @@ -0,0 +1,31 @@ +param( + [string]$ProjectRoot = (Resolve-Path "$PSScriptRoot\..").Path, + [string]$AdbPath = "C:\android\platform-tools\adb.exe", + [string]$PackageName = "anywheresoftware.b4a.swarm", + [switch]$KeepExisting +) + +$ErrorActionPreference = "Stop" + +if (-not (Test-Path -LiteralPath $AdbPath)) { + throw "adb.exe non trovato: $AdbPath" +} + +$logDir = Join-Path $ProjectRoot "logs" +New-Item -ItemType Directory -Force -Path $logDir | Out-Null + +$stamp = Get-Date -Format "yyyyMMdd-HHmmss" +$logFile = Join-Path $logDir "logcat-$stamp.txt" + +& $AdbPath wait-for-device + +if (-not $KeepExisting) { + & $AdbPath logcat -c +} + +Write-Host "Logcat live. Premi Ctrl+C per fermare." +Write-Host "File: $logFile" +Write-Host "Filtro mentale utile: cerca '$PackageName', 'AndroidRuntime', 'FATAL EXCEPTION', 'System.err', 'B4A'." +Write-Host "" + +& $AdbPath logcat -v time | Tee-Object -FilePath $logFile