From c97a49cad708bcc80c4720cb554429da172af6ad Mon Sep 17 00:00:00 2001 From: allebonvi Date: Fri, 12 Jun 2026 15:11:26 +0200 Subject: [PATCH] Register alpha.0 B4A prototype --- .gitignore | 21 ++ Files/drp.bal | Bin 0 -> 4958 bytes Files/drpimg.png | Bin 0 -> 1050 bytes Files/drpimgp.png | Bin 0 -> 1038 bytes Files/swarm.bal | Bin 0 -> 5379 bytes droplist.b4a.meta | 9 + droplist.bas | 137 +++++++++++ swarm.b4a | 470 ++++++++++++++++++++++++++++++++++++++ swarm.b4a.meta | 9 + tools/build-b4a.ps1 | 51 +++++ tools/deploy-emulator.ps1 | 40 ++++ tools/watch-logcat.ps1 | 31 +++ 12 files changed, 768 insertions(+) create mode 100644 .gitignore create mode 100644 Files/drp.bal create mode 100644 Files/drpimg.png create mode 100644 Files/drpimgp.png create mode 100644 Files/swarm.bal create mode 100644 droplist.b4a.meta create mode 100644 droplist.bas create mode 100644 swarm.b4a create mode 100644 swarm.b4a.meta create mode 100644 tools/build-b4a.ps1 create mode 100644 tools/deploy-emulator.ps1 create mode 100644 tools/watch-logcat.ps1 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 0000000000000000000000000000000000000000..e8e10d5f0db2402fdf11867538962be260c288e6 GIT binary patch literal 4958 zcmcIm&65*V5TC$iA&Q8y$nv3}!m`ZFrB`fM- z_2NMfUaayDpgef?k5G!gz>`&$mPd}3m-YAS$xITHz(PT)-kW~i{rYwPx?jH}4Z~Qs z#xS12cL-xWM!KZ!hOKXJ0zDBe=6tJGQ+^7(v)V1H(#&FQBNfipwf5Ymc#vXYv=nD` znO0}qT3ut4Sk0DgZK_Xoa~tImE7rxnb>QdboovI^&w-rCS@X(i?nzR{^#F*P>r9Hq zCCly5ko5*=%xcTmv)Zef-ok#`n(`KFUfnHs_`e6z1xI!8xVxSGEZ6p;$~smpP-O2S*cK?ysbnB}Tkni4{HR8zwp)J{;Dc`L9>6B!lQ3$F4fE-GzB zHNg-y^m-KvUAJ6&(bBf(X6n9t>2cY&maKV4jr1^{Y08is$Md7rR%lK{+d4%AxI|r| zSMq##ShUJ^Js?`1Z!1^J!2~&%oi=Y2XU?5B3B7XZgk(=Opq95572S(sam1%27G(WK#7EvM!E_M^Qn&rb52uZuP7U-bn4%!n!LZb%_JFwvb4{cb! zZMpg&O*yKfSu-eAZeFs>x=PbkWiM1UH&!jTRP}tZ5t39qdCM*bEW(4^F!f5C+=Z@N zGTB2rLOuk0&eqi_!8V8lgm>Qa%gUEx_L@n+P{j%va%M`N8!%xtD+rblKeHMjB1h$HS1}ENzU@dU73-; zR{`22OBk;PG}+vmnpd+$b7m@?V{nK2m8~>+Dckn;Pt(n(fn=6<*gi=^M_PX2xoMsY zin61GK6;5rOS+rFW4poV1#f%z-w&Nfdpp`+9=c`+Q&m;ErQ~&EO%y5>Cc7{_O=pGU z@)arM>GE+FdfR(Lo?$GXJ_F+SaABnQ<(5?R+9bXMi}gr`k)mOd6D!6&xI#9DSYYL) zcn*I9Y<9^65l=;rQBt0xWP(|iGx#crluuKN{~WeN#7mKgeS2^PzhMx`1oOL=6`Uwz z+7S`#1HySZB3>bZVeEjC~(C+$qm-6NFJLW1qy!L*NJ$JX=Dd6~TncV;CC*7~&TLBOw#2IIa*FL0}`? zYav8)qK>a2@^Q%Hvtw^!OVs1NGzRu#3K2R0N)Q?c(U#OVu$;hy`% zFM$$7FN0_yx+h}uR_?{2yFNpO2SV{FeKVeHZ`-L(WN#PO+jS4Ow$Jgla> r(%{20K&|c!JR;sS(!$%tN(}H-*ol$&1(S4F`u(7~g}8}4DZ}^=tY)b# literal 0 HcmV?d00001 diff --git a/Files/drpimg.png b/Files/drpimg.png new file mode 100644 index 0000000000000000000000000000000000000000..c51d897a7572a821d1e75230e76dbed95f6a5332 GIT binary patch literal 1050 zcmV+#1m*jQP)N2bPDNB8 zb~7$DE-^4L^m3s900WjuL_t(&L+zT&YZ_4$#*ME?V-TXnM~F(Tie!<9kzh#kQV52S zUAk;G2Ba237lDwMBxKP-z(+{`fYMF7DR$99p_@QyTAD)Wwu?qc>88*{A2bN|+!9MM zv3_wf<3z7;nNh!c&-u+cbLL!8Q7je}%`}<{mIamrH+p*W2=fRxSQY0f%~QHrQ(7VO z7n+&yJuGuxoCCfxGAD*PU?B&V*A;*R2MguJcfuQ(0~T^%d0hcGaIjEbd_1M$z`??@ zYr49+s@UAzG^W#OS1OfqZEbB`Wn+DP-LbN=VqaWbw6o*V(vp37dHL@seO7*?_5Nu8 z{hZBPTU&FGoh#XF)|JU*m>nyfE6YO+bHKtf3*Ft_cAL$1-(s=su|enW*f5z)uZ>3I zZbwJQZt2L*OQZa|YVX;4X0!RN)oR^iqpPdyXoDWa`XsfwXcD4omY43YyggY<~ddA;6;YPDMQ)MgiyD)h@_GHE)k2ZEnA zu&_d>6_3YlZnyif*s0yw+4*X6a?)F=;e$C~VFgS3`}+!l_R%x)vslo2z5YAZjB7hP zJ0}{Bl3OqbEUeN?M{(;B-3QE0xNc(wjCKdD?AxP}sUgxa8#Y^mLRQ|9I9&v+j** zLF_EBvH)gIP<4$^<^G03Q`>k%MJk@p=hYVym{MCoMeL4Fr~6e6npJm?$Mb+T_u8|< z$|l0hk%fhYOSECnus-;I&@Pwj(cIjewH8=e0W)VdHa5%-hvQA94F*-@PqA3cb9i`I zD{psl0SkqCB=UTi0~U(x zu+ZgU4p=DEBa!FB9H_8SbZ`&KfiLJ^5_yChC3P!t@Cfq=U(n*jQ~Ee?O?MCf2D!|3 UgVgGhRR91007*qoM6N<$g3HV9;{X5v literal 0 HcmV?d00001 diff --git a/Files/drpimgp.png b/Files/drpimgp.png new file mode 100644 index 0000000000000000000000000000000000000000..56bcc975367f24a831f2ff6011012c1e05c67322 GIT binary patch literal 1038 zcmV+p1o8WcP)N2bPDNB8 zb~7$DE-^4L^m3s900W9iL_t(&L+zU1OIl$V$4@OIDky4YwJlq%#n{E@Dw4?UX0l!M zC+un)V=iJ1A=HGTOG#6T?V_6?sEZg~1yMrHHq&gJnK|mBX;_S0+q#%V{@DAPj%JCE zp3d>4ukdp8_@H49nv`_5mNdol z7ql|L*D%j{;T+(Z;W;sw11u!K{F(u9;=n?F@ttu4<^T%`Fu!I1oH($MUwovb!HEM4 zW9C$?R#O^{rd+4fHE6Zk27|$H3%CCMeo=34Z>>V1sKrO6Qdz4~ss6R-x!5BbFRVR% z9{20(>l2|k^<$%|rt#74hbTt1Ua!xMO);1QER2Z|`bxF_w3W9q%sJk4#Tbmv9b@1EM9OU~8dzD!^fB8wNWo&)Wlm zR~xV}&Q1$2PpECPeH|a!bGHvx3tHoC_`n=sVVp=bO;dr5N(r05$Bvw!+a!`ME-s$g za71l^Il#gMduf;D?qi=lZ}+0Xf7|l+P46Yo6K&CdT zZMvaP1id+5`k||0|Ns>^VBuV@ml-`jo_wG;_-M=$h7NJ&Q$mvz_hUvnOAyNIH&L;wH)07*qo IM6N<$f|f_)%K!iX literal 0 HcmV?d00001 diff --git a/Files/swarm.bal b/Files/swarm.bal new file mode 100644 index 0000000000000000000000000000000000000000..cdaf85490a944785a868f7471a62863a5b8c4b22 GIT binary patch literal 5379 zcmcImOLG%P5MBq#M7;8VB#;*lPXormn3tUpEG!uWLNcT$9RyP#jW~N-95tV{&r7uUEU0YzfO1BGrt(>FMd|`KG5^QBBkO zp3}5-_qX$fU@-0Im5Op=ke&AIoGPT|Dx0Wqy6SmlyFT5^X%RFO zr#xe=ziLX^1~*9Am8ysJvO&@?y}bI&t6SiFAPRNsCekxjvSxc5p)#1(XOvZ66NNy= z5rB$q4T;92ZntR2cmp)1Jl*l8ymBR9p50Gd&_(1-9V$;1vh`IqTU2b z%;>IJ7)&VFoVArRctLr35G*{f2fcO?!~^KIIj4JO*-lg)`K8Z>qtELzmfF+Cc%nXs ztFp>YFnSG|gTb=aDbih_F8L{x9e9}24YTT!*Ro?O+mnq+c{(|fzm`j#Ih*HYD4R|g zybo1_T1KB!bT2p?R}`z3HC1qwvT5G53s%)odDF8*^M+p2$r4$xv6{S9bO*KopH-70b34pI2_#XN5!8{9KW)V%aIEMA?=jmEsoS zVh)F<@1&T&CDZn(%3nDz2PV@&Kv+I`CC`{gd?=jVN)^hs%M(>}!!YexvQp7qcfRb% zdvhVPRNAx^&+2-&Ea5wo&0UD6xuu8P!d>_)Thao9v#1vo4JVQl@k{AE@1YhtO``MJ zNg9|(<|BPW+t9U(dPywHQqE8t?I3XdSe-V#(zt}C8%&Vl8JtWx;%Z|!&D-WNl%;AC zxpa-Wj;=)T;xYaD=G(s)Bx(+xDErRw((>ppUhpmoXq7@rJ*AYe^7MlP5?0w;Kastz|=cRK~S5BB{1ug$NC^>M{#pK*bkl6Rg>mgL^n-$ zyrc>@m6S||Y_?crEM_Mr=(tF1)|G6AE+1!vG*uwVPVo4kpVgMhwodKYY%X;*o5{!1 zd?+cqX6n?|w1rb+01GsVPmDt1SWuyQ?n1;h6lgKJA@kgZEcGr@j3(yzjAHbPp9s@q zw1;;U3yN4&%2>3AuE`#(W-`l?7Gq809}xks22;%Ry^Hv41&H=AGS)EWdkl1M1c3QX zByR=aZ2~lHdjL3y^r2hx4m&h0wga6UX(vFF%eye#O$9o&2MtHQ9^VTP)%q#lhc4Vg zHhmuwMu99j0MNVm@6_w4MOSF~0!_ z4<6csQ2y&^k@tXnZb^u6dlH}#MIQuWM$suWiJ~z8xh_Ah78VvHuDGl3IGX&-rM%p5_BT|nnY9)J+Sty&{514%nZso93nFCi92d5OX(BPqP!&=Q1o zMzcUZqmw{F-9>-~qg};Zp4s;W&L_5)_EDiI=$(@It{k6J_O0qmrgC= zdkSEsm%d8ANwe_H$1Z%6>!wD-X%hKS=H$bf=H-JB$tK_@2s@X6p2Er`+5R$I4Y!Qk+-w7az+ay3V6!T_9 z{M7#mv(Va&*8D%=o?o#_5X+6@*Y~NLEK7r}Tz1Z~)D=ce06!l9JR3%N?~)0~u`o*S QTO$}jE}sbdC7q`I3n~\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