B4J Question StartMessageLoop and StopMessageLoop

aeric

Expert
Licensed User
Longtime User
When I should put StartMessageLoop and StopMessageLoop if I am using a For loop to send push message?

B4X:
For Each s1 As String In Subscriber1
    SendData(strTopic1, s1)
    StartMessageLoop     ' <-- Is this correct?
Next
'StartMessageLoop

B4X:
Private Sub SendData(Topic As String, ID As String)
    Dim Job As HttpJob
    Job.Initialize("fcm", Me)
    
    DateTime.DateFormat = "yyyy-MM-dd hh:mm:ss"
    Dim strDate As String = DateTime.Date(DateTime.Now)
    
    Dim msg As Map = CreateMap("to": $"/topics/${Topic&ID}"$)
    ' Android / iOS
    Dim data As Map = CreateMap("title": strTitle, "body": strBody, "content": strContent, "date": strDate)
    ' iOS
    'Dim alert As Map = CreateMap("title": strTitle, "body": strBody, "sound": "default", "badge": 1)
    
    If Topic.StartsWith("ios_") Then
        msg.Put("priority", 10)
        msg.Put("content_available", True) ' <--- silent push notification
        'msg.Put("notification", alert)
    End If
    msg.Put("data", data)
    
    Dim JG As JSONGenerator
    JG.Initialize(msg)
    Job.PostString("https://fcm.googleapis.com/fcm/send", JG.ToString)
    Job.GetRequest.SetContentType("application/json;charset=UTF-8")
    Job.GetRequest.SetHeader("Authorization", "key=" & API_KEY)
    
    Wait For(Job) JobDone(Job As HttpJob)
    If Job.Success Then
        Log(" (" & ID & ")" & Job.GetString)
    Else
        Log(" [Error:" & Job.ErrorMessage & "]")
    End If
    Job.Release
    intSend = intSend + 1
    If intSend = Subscriber1.Size Then
        Log(" Sent:" & intSend)
        SQL1.Close
        'Sleep(3000)
        StopMessageLoop     ' <-- Is this correct?
        ExitApplication2(0)
    End If
    StopMessageLoop     ' <-- Is this correct?
End Sub
 

DonManfred

Expert
Licensed User
Longtime User
- move the StartMessageLoop before the for each line. [striked out because wrong; thanks @OliverA]
- Make SendData a resumeable sub and wait for the sub to finish.
- put the StopMessageLoop after the for each loop.
 
Last edited:
Upvote 0

OliverA

Expert
Licensed User
Longtime User
When I should put StartMessageLoop and StopMessageLoop if I am using a For loop to send push message?
- move the StartMessageLoop before the for each line.
If you do that, the For Each will never be reached. You need to place the For Each loop into another sub
Make SendData a resumeable sub and wait for the sub to finish.
Yes.
put the StopMessageLoop after the for each loop.
Yes

B4X:
ProcessMessages(strTopic1,Subscriber1)
StartMessageLoop
'Anything below here will execute after StopMessageLoop has been called.
'This will never be reached if ExitApplication is called

Sub ProcessMessages(topic as Text, messages as list)
    For Each s1 As String In messages
        Wait For (SendData(topic, s1)) Complete (Result as Boolean)
    Next
    StopMessageLoop
End Sub

Private Sub SendData(Topic As String, ID As String) As ResumableSub
    'Everything above this ok
    If intSend = Subscriber1.Size Then
        Log(" Sent:" & intSend)
        SQL1.Close
        'Sleep(3000)
        'StopMessageLoop     ' <-- Is this correct?  <---- Not needed
        ExitApplication2(0) '<- this exits the application right here and then. Nothing below this or after the StartMessageLoop is executed
    End If
    Return True '<-New
End Sub
 
Upvote 0

aeric

Expert
Licensed User
Longtime User
Here is my code. I hope this is correct.
B4X:
'Non-UI application (console / server application)
#Region Project Attributes
    #CommandLineArgs:
    #MergeLibraries: True
    #AdditionalJar: jtds-1.3.1.jar
#End Region

Sub Process_Globals
    Private SQL1 As SQL
    Private SQL2 As SQL
    Private const API_KEY As String = "AAAAZ..."    ' Actual API key redacted
    Dim strTopic1 As String    = "and_topic-"       ' Android topic prefix
    Dim strTopic2 As String = "ios_topic-"          ' iOS topic prefix
    Dim Subscriber1 As List                         ' Android user ID
    Dim Subscriber2 As List                         ' iOS user ID
    Dim strTitle As String
    Dim strBody As String
    Dim strContent As String
    Dim strDate As String
    Dim intSent As Int
End Sub

Sub AppStart (Args() As String)
    Try
        SQL1.Initialize2("net.sourceforge.jtds.jdbc.Driver", "jdbc:jtds:sqlserver://10.0.0.1/MY_Database1", "sa", "P@ssw0rD1")
        SQL2.Initialize2("net.sourceforge.jtds.jdbc.Driver", "jdbc:jtds:sqlserver://10.0.0.2/MY_Database2", "sa", "P@ssw0rD2")
        Subscriber1.Initialize
        Subscriber2.Initialize
        GetUsers
        strTitle = "Demo"
        strBody = "Push Notification"
        strContent = "Testing Push Notification"
        DateTime.DateFormat = "yyyy-MM-dd hh:mm:ss"
        strDate = DateTime.Date(DateTime.Now)      
        intSent = 0
        ProcessMessages
        StartMessageLoop
    Catch
        Log(LastException)
    End Try
End Sub

'Return true to allow the default exceptions handler to handle the uncaught exception.
Sub Application_Error (Error As Exception, StackTrace As String) As Boolean
    Return True
End Sub

Sub ProcessMessages
    For Each id As String In Subscriber1
        Wait For (SendData(strTopic1, id)) Complete (Result As Boolean)
    Next
    For Each id As String In Subscriber2
        Wait For (SendData(strTopic2, id)) Complete (Result As Boolean)
    Next
    StopMessageLoop
End Sub

Private Sub SendData(Topic As String, ID As String) As ResumableSub
    Dim Job As HttpJob
    Job.Initialize("fcm", Me)
    ' Android / iOS
    Dim msg As Map = CreateMap("to": $"/topics/${Topic&ID}"$)  
    Dim data As Map = CreateMap("title": strTitle, "body": strBody, "content": strContent, "date": strDate)
    ' iOS
    Dim alert As Map = CreateMap("title": strTitle, "body": strBody, "sound": "default", "badge": 1)
   
    If Topic.StartsWith("ios_") Then
        msg.Put("priority", 10)
        msg.Put("content_available", True) ' <--- silent push notification
        msg.Put("notification", alert)
    End If
    msg.Put("data", data)
   
    Dim JG As JSONGenerator
    JG.Initialize(msg)
    Job.PostString("https://fcm.googleapis.com/fcm/send", JG.ToString)
    Job.GetRequest.SetContentType("application/json;charset=UTF-8")
    Job.GetRequest.SetHeader("Authorization", "key=" & API_KEY)
   
    Wait For(Job) JobDone(Job As HttpJob)
    If Job.Success Then
        Log(" (" & ID & ")" & Job.GetString)
    Else
        Log(" [Error:" & Job.ErrorMessage & "]")
    End If
    Job.Release
    intSent = intSent + 1
    If intSent = Subscriber1.Size + Subscriber2.Size Then
        Log(" Sent:" & intSent)
        SQL1.Close
        SQL2.Close
        'Sleep(3000)       
        ExitApplication2(0)
    End If
    Return True
End Sub

Private Sub GetUsers
    Dim strSQL As String
    strSQL = "SELECT android_user FROM tbl_users WHERE active = 1 AND android_user IS NOT NULL ORDER BY id"
    Dim RS As ResultSet = SQL1.ExecQuery(strSQL)
    Do While RS.NextRow
        Subscriber1.Add(RS.GetString2(0))
    Loop
    RS.Close
    strSQL = "SELECT ios_user FROM tbl_users WHERE active = 1 AND ios_user IS NOT NULL ORDER BY id"
    Dim RS As ResultSet = SQL1.ExecQuery(strSQL)
    Do While RS.NextRow
        Subscriber2.Add(RS.GetString2(0))
    Loop
    RS.Close
    If Subscriber1.Size + Subscriber2.Size < 1 Then
        Log("Subscribers: 0")
        SQL1.Close
        SQL2.Close
        ExitApplication2(0)
    End If
End Sub

* SQL2 is used to get some values from database2 using another Sub
 
Last edited:
Upvote 0
Top