Android Question Play Sound Multiple Times between time intervals

RishiKumar2210

Active Member
Hi. I want to Play the Alarm Sound after some time(multiple times) from the current time. Here I am using the Flexgrid table to store when the alarm needs to play. Suppose I have 2 rows(the first row is 10 seconds and 2nd row is 15 seconds). I want to play an alarm sound after 10 seconds from the current time and then play an alarm sound again after 15 seconds from the first alarm sound. But My code plays the Alarm sound Only 1 time. what's wrong with this code?Here is my code
B4X:
Private Sub btn_startalarm_Click
    timer1.Enabled = True
   
    For i = 0 To if_flexgridtabledetailslist.RowCount - 1
        Dim rowdata As List = if_flexgridtabledetailslist.GetCellRow(i)
       
        Dim ls_time As String = rowdata.Get(1)
        Dim ls_minsec As String = rowdata.Get(2)
       
        Log(ls_time)
       
        Dim ls_totaltime As String = ls_time & " " & ls_minsec
        Log("totaltime : " & ls_totaltime)
       
        Dim p As Period
        If ls_minsec == "Minutes" Then
            p.Minutes = ls_time
        Else If ls_minsec == "Seconds" Then
            p.Seconds = ls_time
        End If
       
        is_currenttime = DateTime.Now
        is_nexttime = DateUtils.AddPeriod(DateTime.Now, p)
       
        Log("currenttime : " & DateTime.Time(is_currenttime))
        Log("nexttime : " & DateTime.Time(is_nexttime))
        Sleep(is_nexttime)
        Timer1_Tick
       
    Next

End Sub

Sub Timer1_Tick
    ' Check if the current time has reached or passed the next time
    If DateTime.Now >= is_nexttime Then
        timer1.Enabled = False ' Disable the timer
'        MsgboxAsync("Success", "Time Alert")
        imedia_player.Load(File.DirAssets, "beepsound.mp3")
        imedia_player.Play
    End If
   
End Sub
 

RishiKumar2210

Active Member
Hi. I want to Play the Alarm Sound after some time(multiple times) from the current time. Here I am using the Flexgrid table to store when the alarm needs to play. Suppose I have 2 rows(the first row is 10 seconds and 2nd row is 15 seconds). I want to play an alarm sound after 10 seconds from the current time and then play an alarm sound again after 15 seconds from the first alarm sound. But My code plays the Alarm sound Only 1 time. what's wrong with this code?Here is my code
B4X:
Private Sub btn_startalarm_Click
    timer1.Enabled = True
  
    For i = 0 To if_flexgridtabledetailslist.RowCount - 1
        Dim rowdata As List = if_flexgridtabledetailslist.GetCellRow(i)
      
        Dim ls_time As String = rowdata.Get(1)
        Dim ls_minsec As String = rowdata.Get(2)
      
        Log(ls_time)
      
        Dim ls_totaltime As String = ls_time & " " & ls_minsec
        Log("totaltime : " & ls_totaltime)
      
        Dim p As Period
        If ls_minsec == "Minutes" Then
            p.Minutes = ls_time
        Else If ls_minsec == "Seconds" Then
            p.Seconds = ls_time
        End If
      
        is_currenttime = DateTime.Now
        is_nexttime = DateUtils.AddPeriod(DateTime.Now, p)
      
        Log("currenttime : " & DateTime.Time(is_currenttime))
        Log("nexttime : " & DateTime.Time(is_nexttime))
        Sleep(is_nexttime)
        Timer1_Tick
      
    Next

End Sub

Sub Timer1_Tick
    ' Check if the current time has reached or passed the next time
    If DateTime.Now >= is_nexttime Then
        timer1.Enabled = False ' Disable the timer
'        MsgboxAsync("Success", "Time Alert")
        imedia_player.Load(File.DirAssets, "beepsound.mp3")
        imedia_player.Play
    End If
  
End Sub
Here is my project attached.
 

Attachments

  • AlarmSound.zip
    24.1 KB · Views: 32
Upvote 0

walt61

Active Member
Licensed User
Longtime User
I'd do something like this:

B4X:
Sub Globals
    'These global variables will be redeclared each time the activity is created.
    'These variables can only be accessed from this module.

    Private timer1 As Timer
    Private currentIndex As Int = -1

End Sub

Private Sub btn_startalarm_Click

    Timer1_Tick

End Sub

Sub Timer1_Tick

    timer1.Enabled = False ' Disable the timer

    If currentIndex >= 0 Then ' The timer has ticked over, this isn't the first Timer1_Tick that was called by btn_startalarm_Click
        imedia_player.Load(File.DirAssets, "beepsound.mp3")
        imedia_player.Play
    End If

    currentIndex = currentIndex + 1

    Dim msecs As Long = 1000 ' <------ Here, calculate the number of msecs until the next time at which you need the timer to tick

    timer1.Interval = msecs
    timer1.Enabled = True

End Sub
 
Upvote 0

RishiKumar2210

Active Member
I'd do something like this:

B4X:
Sub Globals
    'These global variables will be redeclared each time the activity is created.
    'These variables can only be accessed from this module.

    Private timer1 As Timer
    Private currentIndex As Int = -1

End Sub

Private Sub btn_startalarm_Click

    Timer1_Tick

End Sub

Sub Timer1_Tick

    timer1.Enabled = False ' Disable the timer

    If currentIndex >= 0 Then ' The timer has ticked over, this isn't the first Timer1_Tick that was called by btn_startalarm_Click
        imedia_player.Load(File.DirAssets, "beepsound.mp3")
        imedia_player.Play
    End If

    currentIndex = currentIndex + 1

    Dim msecs As Long = 1000 ' <------ Here, calculate the number of msecs until the next time at which you need the timer to tick

    timer1.Interval = msecs
    timer1.Enabled = True

End Sub
It is not working. I have stored time intervals such as 20 seconds, 2 minutes, and 5 minutes in the Flexgrid table. is it necessary to write for loop for the flexgrid table to play music each time?
 
Last edited:
Upvote 0

walt61

Active Member
Licensed User
Longtime User
No, the idea is that 'currentIndex' points to the row in the Flexgrid table that contains the time for the next occurrence. In line 27, where 'msecs' is calculated, you use that value to get the timer started again, which will then tick, play the sound, and set the timer so that it will tick at the appropriate time. Did you calculate 'msecs' correctly?
 
Upvote 0

RishiKumar2210

Active Member
No, the idea is that 'currentIndex' points to the row in the Flexgrid table that contains the time for the next occurrence. In line 27, where 'msecs' is calculated, you use that value to get the timer started again, which will then tick, play the sound, and set the timer so that it will tick at the appropriate time. Did you calculate 'msecs' correctly?
It means I need to call the function "Timer1_Tick" and I need to declare currentIndex = currentIndex + 1 inside the for loop . I don't know how to rewrite the code. here is my code
B4X:
Private Sub btn_startalarm_Click
    timer1.Enabled = False
    For i = 0 To if_flexgridtabledetailslist.RowCount - 1
        Dim rowdata As List = if_flexgridtabledetailslist.GetCellRow(i)
      
        Dim ls_time As String = rowdata.Get(1)
        Dim ls_minsec As String = rowdata.Get(2)
      
        Log("Row " & i & " Time: " & ls_time & " " & ls_minsec)
      
        Dim p As Period
        If ls_minsec == "Minutes" Then
            p.Minutes = ls_time
        Else If ls_minsec == "Seconds" Then
            p.Seconds = ls_time
        End If
    
        is_currenttime = DateTime.Now
        is_nexttime = DateUtils.AddPeriod(DateTime.Now, p)
      
        Log("Current time: " & DateTime.Time(is_currenttime))
        Log("Next alarm time: " & DateTime.Time(is_nexttime))
      
        WaitForTimeAndPlayAlarm
      
    Next
  
End Sub

Sub WaitForTimeAndPlayAlarm
    Do While DateTime.Now < is_nexttime
        DoEvents
    Loop
  
    ' When the time has elapsed, play the alarm
    Timer1_Tick
End Sub

Sub Timer1_Tick
    ' Play the alarm sound
    imedia_player.Load(File.DirAssets, "beepsound.mp3")
    imedia_player.Play
    Log("Alarm played!")
End Sub
 
Upvote 0

walt61

Active Member
Licensed User
Longtime User
You only call Timer_Tick the first time. Subsequent iterations will be initiated in Timer_Tick itself, which will be called when the timer expires. Use my code instead:

B4X:
Sub Globals
    'These global variables will be redeclared each time the activity is created.
    'These variables can only be accessed from this module.

    Private timer1 As Timer
    Private currentIndex As Int = -1

End Sub

Private Sub btn_startalarm_Click

    Timer1_Tick

End Sub

Sub Timer1_Tick

    timer1.Enabled = False ' Disable the timer

    If currentIndex >= 0 Then ' The timer has ticked over, this isn't the first Timer1_Tick that was called by btn_startalarm_Click
        imedia_player.Load(File.DirAssets, "beepsound.mp3")
        imedia_player.Play
    End If

    currentIndex = currentIndex + 1
    if currentIndex > if_flexgridtabledetailslist.RowCount - 1 Then Return ' End of rows reached

    Dim rowdata As List = if_flexgridtabledetailslist.GetCellRow(currentIndex)
    Dim ls_time As String = rowdata.Get(1)
    Dim ls_minsec As String = rowdata.Get(2)

    If ls_minsec = "Minutes" Then
       msecs = ls_time * DateTime.TicksPerMinute
    Else If ls_minsec = "Seconds" Then
       msecs = ls_time * DateTime.TicksPerSecond
    End If

    timer1.Interval = msecs
    timer1.Enabled = True

End Sub
 
Upvote 0

RishiKumar2210

Active Member
You only call Timer_Tick the first time. Subsequent iterations will be initiated in Timer_Tick itself, which will be called when the timer expires. Use my code instead:

B4X:
Sub Globals
    'These global variables will be redeclared each time the activity is created.
    'These variables can only be accessed from this module.

    Private timer1 As Timer
    Private currentIndex As Int = -1

End Sub

Private Sub btn_startalarm_Click

    Timer1_Tick

End Sub

Sub Timer1_Tick

    timer1.Enabled = False ' Disable the timer

    If currentIndex >= 0 Then ' The timer has ticked over, this isn't the first Timer1_Tick that was called by btn_startalarm_Click
        imedia_player.Load(File.DirAssets, "beepsound.mp3")
        imedia_player.Play
    End If

    currentIndex = currentIndex + 1
    if currentIndex > if_flexgridtabledetailslist.RowCount - 1 Then Return ' End of rows reached

    Dim rowdata As List = if_flexgridtabledetailslist.GetCellRow(currentIndex)
    Dim ls_time As String = rowdata.Get(1)
    Dim ls_minsec As String = rowdata.Get(2)

    If ls_minsec = "Minutes" Then
       msecs = ls_time * DateTime.TicksPerMinute
    Else If ls_minsec = "Seconds" Then
       msecs = ls_time * DateTime.TicksPerSecond
    End If

    timer1.Interval = msecs
    timer1.Enabled = True

End Sub
Thanks @walt61. It worked. But I have Another Question. If the user minimizes or closes the app, it is not working. I saw some examples suggesting to use service module. But when i use the service module, the music plays only 1 time(First time Only). how to overcome this?
 
Upvote 0

walt61

Active Member
Licensed User
Longtime User
These days better use a Receiver instead of a Service. But first, change your app to a B4XPages app - see examples on the forum, start by looking at https://www.b4x.com/android/forum/t...framework-for-managing-multiple-pages.118901/ where @Erel states:

B4XPages is a library that serves two purposes:

1. Make it simple to develop B4A apps by solving almost all of the challenges involved with Android complex activities life cycle.
B4XPages makes B4A behave more similar to B4J and B4i where the new "B4XPage" element is a regular object that is never paused, never destroyed, can be accessed from anywhere and easy to work with.
2. Provide a cross platform layer above the navigation related APIs.

I'm not 100% certain if just using B4XPages would cater for what you need, or if a Receiver (that restarts itself at a certain time) would be required. In the latter case, check the forum and/or start a new thread as I don't want to provide a half-baked solution (I haven't had a need for that facility yet so can't be sure if my solution will be the best one) :)
 
Upvote 0

RishiKumar2210

Active Member
These days better use a Receiver instead of a Service. But first, change your app to a B4XPages app - see examples on the forum, start by looking at https://www.b4x.com/android/forum/t...framework-for-managing-multiple-pages.118901/ where @Erel states:



I'm not 100% certain if just using B4XPages would cater for what you need, or if a Receiver (that restarts itself at a certain time) would be required. In the latter case, check the forum and/or start a new thread as I don't want to provide a half-baked solution (I haven't had a need for that facility yet so can't be sure if my solution will be the best one) :)
1. This is the same project I have created with B4XPages. I attached the project below
2. I have already created a new thread 2 days before, still I didn't get any answer, here is the link to the thread I created 2 days before https://www.b4x.com/android/forum/threads/make-app-run-in-background.163558/
 

Attachments

  • Notification.zip
    78.8 KB · Views: 25
Upvote 0

walt61

Active Member
Licensed User
Longtime User
I can only give some pointers to things to look at:
- https://www.b4x.com/android/forum/threads/receivers-and-services-in-2023.145370/
- https://www.b4x.com/android/forum/threads/background-location-tracking.99873/
- https://www.b4x.com/android/forum/pages/results/?query=startreceiverat
- last but not least, make sure the device's battery optimisation settings don't interfere with what you want to do; through these, you may need to allow your app to continue running in the background

Good luck!
 
Upvote 0

RishiKumar2210

Active Member
I can only give some pointers to things to look at:
- https://www.b4x.com/android/forum/threads/receivers-and-services-in-2023.145370/
- https://www.b4x.com/android/forum/threads/background-location-tracking.99873/
- https://www.b4x.com/android/forum/pages/results/?query=startreceiverat
- last but not least, make sure the device's battery optimisation settings don't interfere with what you want to do; through these, you may need to allow your app to continue running in the background

Good luck!
I just read about receivers and services, but I don't know how to incorporate this into my code. Is there a small example available that fits my case? Thanks in advance.
 
Upvote 0
Top