qualcuno sa dirmi cosa non va nel mio codice sento il suono solo 1 volta anzichè 10 come mi aspettavo, grazie.
B4X:
Sub EseguiSuono
Dim i As Int
Dim b As Beeper
Dim p As Phone
p.SetVolume(p.VOLUME_RING, p.GetMaxVolume(p.VOLUME_RING), False)
For i = 1 To 10
b.Initialize(100, 100) '300 milliseconds, 500 hz
b.Beep
Next
End Sub
Per come hai scritto il codice, il beeper viene inizializzato 10 volte (senza mai rilasciare le risorse e quindi creando i presupposti di un memory leak) per produrre un suono a 100Hz di durata 100ms, ma il loop fa sì che il successivo venga avviato mentre il precedente ancora non iniziava nemmeno. Alla fine senti solo l'ultimo.
Prova con un timer. Prima inizializzi (una sola volta) il beeper, poi setti un timer in modo opportuno affinchè il suono abbia tempo di essere eseguito ed anche seguito da una breve pausa. Tramite un contatore, quando arrivi a 10 (o al numero max di ripetizioni), disabiliti il timer e rilasci il beeper (b.release se non sbaglio).
Un altro modo sarebbe tramite sub richiamata da un wait for. Anche questa sarebbe da sperimentare per comprendere bene come funziona questo tipo di meccanismo.
Sub EseguiSuono
Dim i As Int
Dim b As Beeper
Dim p As Phone
p.SetVolume(p.VOLUME_RING, p.GetMaxVolume(p.VOLUME_RING), False)
b.Initialize(300, 500) '300 milliseconds, 500 hz
For i = 1 To 10
b.Beep
Sleep(450)
Next
b.Release
End Sub
E come ti ha appena mostrato @Star-Dust sleep è ancora un'altra possibilità. Attenzione che all'esecuzione di sleep, il flusso torna alla sub che ha lancianciato Eseguisuono (o comunque alla UI), per poi ritornare in essa ogni 450ms, avviare un beep etc; dopo l'ultimo beep Eseguisuono viene completata con il rilascio delle risorse del beeper (e si torna definitivamente al flusso principale.
Attenzione che all'esecuzione di sleep, il flusso torna alla sub che ha lanciato Eseguisuono (o comunque alla UI), per poi ritornare in essa ogni 450ms
Sì, esatto, infatti l'uso di Sleep deve essere ben ponderato e valutato, a me sta dando un sacco di problemi proprio per questo motivo, che ritorna alla sub di livello superiore e lì il casino è totale.
Se si usa ancora il DoEvents controllando con DateTime.Now che siano passati i 450 ms è proprio brutto ???
A quel punto, proverei con il timer..
Invece di controllare un orario in un loop (cosa che Android comunque non gradisce perchè blocca la UI), aspetti che la tua beep-routine venga richiamata dal timer. Facile, semplice e pulito.
Per risolvere i problemi dello Sleep che ritorna al livello superiore
B4X:
Sub Principale
Wait For (EseguiSuono) Complete (Result As Boolean)
End Sub
Sub EseguiSuono As ResumableSub
Dim i As Int, b As Beeper, p As Phone
p.SetVolume(p.VOLUME_RING, p.GetMaxVolume(p.VOLUME_RING), False)
b.Initialize(300, 500) '300 milliseconds, 500 hz
For i = 1 To 10
b.Beep
Sleep(450)
Next
b.Release
Return True
End Sub
Chiaramente l'uso di sleep dipende dall'intera struttura dell'Algoritmo. DoEvent lo userei con parsimonia perchè in effetti qualche volta genera Crash. C'è uno Sleep in Java che ferma il dispositivo per un Tot (ms), che può essere richiamato da Java, però l'effetto che "congela" il dispositivo in quel lasso di tempo stabilito.
Il timer che è stato suggerito, è una buona alternativa.
Per far sentire i 10 beep bisogna intervallare dai 100ms ai 200ms di silenzio altrimenti sembrerebbe un suono unico ecco perchè ho messo uno Sleep(450) e non di 300ms.
Se, da qualunque punto del progetto, si deve richiamare una Sub che contiene uno Sleep e si ha necessità di attendere il suo completamento và per forza implementato subito anche un WAIT FOR che attenda il completamento della SUB.
Personalmente utilizzo molto il waitfor, mi piace. Però capisco anche chi non si sente a suo agio e preferisce altre strade.
Direi che, in generale, siamo fortunati ad avere un ventaglio di scelte
Ciao, grazie a tutti per gli esempi, ho provato il codice postato da Star-Dust oggi alle 10.12 ma eseguendolo mi da il seguente errore:
Errore di sintassi
Routine EseguiSuono non utilizzata (warning #12)
qualcuno da il motivo?
io eseguo la routine Principale su click di un Button1 qui sotto riporto codice
B4X:
Sub Button1_Click
Principale
End Sub
Sub Principale
Wait For EseguiSuono Complete (Result As Boolean)
End Sub
Sub EseguiSuono As ResumableSub
Dim i As Int, b As Beeper, p As Phone
p.SetVolume(p.VOLUME_RING, p.GetMaxVolume(p.VOLUME_RING), False)
b.Initialize(300, 500) '300 milliseconds, 500 hz
For i = 1 To 10
b.Beep
Sleep(450)
Next
b.Release
Return True
End Sub
Remember that that a call to Sleep or Wait For in a resumable sub causes the code flow to return to the parent. Example: Sub Button1_Click Sum(1, 2) Log("after sum") End Sub Sub Sum(a As Int, b As Int) Sleep(100) 'this will cause the code flow to return to the parent Log(a + b) End Sub...