Register alpha.0 B4A prototype

This commit is contained in:
2026-06-12 15:11:26 +02:00
commit c97a49cad7
12 changed files with 768 additions and 0 deletions

21
.gitignore vendored Normal file
View File

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

BIN
Files/drp.bal Normal file

Binary file not shown.

BIN
Files/drpimg.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

BIN
Files/drpimgp.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

BIN
Files/swarm.bal Normal file

Binary file not shown.

9
droplist.b4a.meta Normal file
View File

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

137
droplist.bas Normal file
View File

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

470
swarm.b4a Normal file
View File

@@ -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~<uses-sdk android:minSdkVersion="4" android:targetSdkVersion="28"/>~\n~<supports-screens android:largeScreens="true" ~\n~ android:normalScreens="true" ~\n~ android:smallScreens="true" ~\n~ android:anyDensity="true"/>)~\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

9
swarm.b4a.meta Normal file
View File

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

51
tools/build-b4a.ps1 Normal file
View File

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

40
tools/deploy-emulator.ps1 Normal file
View File

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

31
tools/watch-logcat.ps1 Normal file
View File

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