iOS Question b4i - Push server to specific user

IamTrying

Active Member
Licensed User
1. I have User1 on iPhone, User2 on iPad, User3 on iPhone running following code as app minimised.

B4X:
Sub Process_Globals
    Public App As Application
    Public NavControl As NavigationController
    Private Page1 As Page


    Private Const ServerUrl As String = "http://192.168.1.32:51044"
   
End Sub

Private Sub Application_Start (Nav As NavigationController)
    NavControl = Nav
    Page1.Initialize("Page1")
    Page1.Title = "Page 1"
    Page1.RootPanel.Color = Colors.White
    NavControl.ShowPage(Page1)
    App.RegisterUserNotifications(True, True, True)
    App.RegisterForRemoteNotifications
End Sub

Private Sub Application_PushToken (Success As Boolean, Token() As Byte)
    If Success Then
        Dim bc As ByteConverter
        Dim j As HttpJob
        j.Initialize("j", Me)
        j.PostString(ServerUrl & "/devicetoken", "token=" & bc.HexFromBytes(Token) & "&type=1")
    Else
        Log("Error getting token: " & LastException)
    End If
End Sub

Private Sub JobDone(j As HttpJob)
    If j.Success Then
        Log("Token uploaded successfully.")
    Else
        Log("Error uploading token")
    End If
    j.Release
End Sub

Private Sub Application_RemoteNotification (Message As Map)
    Log("Remote notification: " & Message)
    Dim m As Map = Message.Get("aps")
    Log(m)
    Log(m.Get("alert"))
End Sub

Private Sub Page1_Resize(Width As Int, Height As Int)
   
End Sub

Private Sub Application_Background
   
End Sub


2. Now i want to send notification to only user: User3 on iPhone

B4X:
    http://192.168.1.32:51044/send?password=123&text=wakeup_User3

3. Why does all User1, User2, User3 is getting notification?


My goal is to send it to only the target user.
I just want to send to User3 not to all.
 

Erel

B4X founder
Staff member
Licensed User
Longtime User
If this is a new app then you are doing a mistake not using Firebase.

The B4i code has nothing to do with this question.
The relevant code is in the Send class in the B4J code. It sends the message to all devices. Go over the code. It shouldn't be difficult to change it to send to a specific device instead.
However as I started it will be simpler to use Firebase.
 
Upvote 0

IamTrying

Active Member
Licensed User
But Firebase is not free right? You have to pay for Firebase service? (i want absolute independent service, so that i can run on intranet big buildings local servers, local intranet)



EDIT: For your information. I am writing WhatsAPP app in my own style.
Its like i want to call from Android to iPhone/iPad. Peer to Peer call, when the call signal arrives B4i app has to start notification or UI.
 
Last edited:
Upvote 0

Grant Fullen

Member
Licensed User
Firebase is simply using Google's servers in the cloud to handle these tasks. Surely you see that big FREE package to the left of the two you drew arrows to. I mean you've literally answered your own question with your screenshot if you would just bother to read what you've posted. It lays out the clear differences between what you get if you want free. Which like in life..... isn't much.

EDIT: I can vouch that their free package really is free and you won't be getting charged for using it. (If that's what you were asking) However, read the limits and what comes with it.
 
Upvote 0

IamTrying

Active Member
Licensed User
I am scared with Google services. I used to made Chromium sources, Google extensions for serial, desktop share. Now in 2018 they stopped it, many feature i wrote in C++11 is removed in Google chrome and i became alone to survive with Chromium code of mine. It was disaster with Google products in my previous experience.

Therefore i want to be independent and try as much as possible to avoid using "Google now closed source products" because later they on the fly remove things without caring i/or you existed.
 
Upvote 0

Grant Fullen

Member
Licensed User
Your past experience is unfortunate. However, I'm a huge fan of Firebase. The product is new, modern, and they're updating the database to work as efficient as something like MongoDB. They're not going anywhere with this product anytime soon. Chromium was awfully non-mainstream anyways. It's not surprising they nixed that.
 
Upvote 0

Grant Fullen

Member
Licensed User
I'll put it to you this way. Becoming your own independent cloud introduces yourself to a whole lot more problems. You become the only support you have. Are you well versed in preventing DDoS attacks? Can you mitigate traffic across multiple servers? Can you have data redundancy easily? If you're willing to take over what people get paid salaries to do, that doesn't leave much time for coding the actual app.
 
Upvote 0

IamTrying

Active Member
Licensed User
How do i get the "userid" : msg.userID, "username": msg.userName in class iOSPush? its giving me empty value for userid, username, but badge is received.

URL : http://192.168.1.32:51044/send?password=123&text=iamfrom_browser&userid=1&username=iamtest&badge=111

B4X:
Public Sub SendMessageTo(Devices As List, msg As Message)
    Log(">>> Send message to userID: " & msg.userID  & ", userName: " & msg.userName & ", Badge: " & msg.Badge)
  
    Dim out As OutputStream
    out.InitializeToBytesArray(0)
    For Each device As String In Devices
        Dim FrameData As OutputStream
        FrameData.InitializeToBytesArray(0)
        WriteItem(FrameData, 1, bc.HexToBytes(device))
        Dim jg As JSONGenerator
      
        Dim m As Map =  CreateMap("alert": CreateMap("title": "___TITLE___", _
        "body": msg.Text), "badge": msg.Badge , "userid" : msg.userID, "username": msg.userName)

      
        If msg.Sound Then m.Put("sound", "default")
        jg.Initialize(CreateMap("aps":m))
        'jg.Initialize(CreateMap("aps":CreateMap("content-available": 1)))
        WriteItem(FrameData,2, jg.ToString.GetBytes("UTF8"))
        WriteItem(FrameData,3, bc.IntsToBytes(Array As Int(Rnd(0, 9999999))))
        WriteItem(FrameData,4, bc.IntsToBytes(Array As Int(msg.ExpirationDate / 1000)))
        Dim p As Byte
        If msg.HighPriority Then p = 10 Else p = 5
        WriteItem(FrameData,5, Array As Byte(p))
        Dim payload() As Byte = FrameData.ToBytesArray
        out.WriteBytes(Array As Byte(2), 0, 1)
        out.WriteBytes(bc.IntsToBytes(Array As Int(payload.Length)), 0, 4)
        out.WriteBytes(payload, 0, payload.Length)
    Next
    astream.Write(out.ToBytesArray)
End Sub

Complete update: https://github.com/shamun/android-sample/tree/master/PushServer-p2p
 
Last edited:
Upvote 0

IamTrying

Active Member
Licensed User
1. It is empty in: SendMessageTo(Devices As List, msg As Message)
2. Posted Log:

B4X:
Waiting for debugger to connect...
Program started.
2017-12-18 09:05:14.234:INFO::main: Logging initialized @1112ms to org.eclipse.jetty.util.log.StdErrLog
2017-12-18 09:05:14.578:INFO:oejs.Server:main: jetty-9.4.z-SNAPSHOT
2017-12-18 09:05:14.683:INFO:oejs.session:main: DefaultSessionIdManager workerName=node0
2017-12-18 09:05:14.683:INFO:oejs.session:main: No SessionScavenger set, using defaults
2017-12-18 09:05:14.689:INFO:oejs.session:main: Scavenging every 660000ms
2017-12-18 09:05:14.705:INFO:oejsh.ContextHandler:main: Started o.e.j.s.ServletContextHandler@4cc0edeb{/,file:///C:/Users/tpt/Desktop/github/b4a-notification-route/PushServer/Objects/www,AVAILABLE}
2017-12-18 09:05:14.733:INFO:oejs.AbstractNCSARequestLog:main: Opened C:\Users\tpt\Desktop\github\b4a-notification-route\PushServer\Objects\logs\b4j-2017_12_18.request.log
2017-12-18 09:05:14.911:INFO:oejs.AbstractConnector:main: Started ServerConnector@39c0f4a{HTTP/1.1,[http/1.1]}{0.0.0.0:51044}
2017-12-18 09:05:14.913:INFO:oejs.Server:main: Started @1794ms
Emulated network latency: 100ms
server version: 0.97
server is listening on port: 51044
>>> iOSPush: connect
Table: tokens
>>> iOSPush: Socket connected.
Feedback Socket connected.
feedback terminated
>>> Username: 1
>>> Username: iamtest
Token added: 49D9C71ABF5C3A714FAEA90D01F4E81D5C06A5962FF285686D124C13BB104C1E
>>> iOSPush: Send message to userID: , userName: , Badge: 1

3. When i call `http://192.168.1.32:51044/send?password=123&text=iamfrom_browser&userid=1&username=iamtest&badge=1` .
then iGateway trigger the SendMessageTo where msg as Message do not have userid, username but all the rest well.

config.txt:
iGateway=gateway.sandbox.push.apple.com
iGateWayPort=2195


B4X:
Sub Process_Globals
    Private sock As Socket
    Private astream As AsyncStreams
    Private bc As ByteConverter
    Private timer1 As Timer
    Type Message(Text As String, Sound As Boolean, Badge As Int, ExpirationDate As Long, _
    HighPriority As Boolean, _
    userID As String, _
    userName As String)
   
End Sub

Public Sub Start
    bc.LittleEndian = False
    timer1.Initialize("timer1", 3000) 'this timer is used when trying to reconnect
    Connect
End Sub

Private Sub Connect
    If sock.IsInitialized Then sock.Close
    Dim sock As Socket
    sock.InitializeSSL("sock", File.OpenInput(Main.config.Get("iPushKeystore"), ""), Main.config.Get("iPushKeystorePassword"))
    sock.Connect(Main.config.Get("iGateway"), Main.config.Get("iGateWayPort"), 30000)
   
    Log(">>> iOSPush: connect")
End Sub

Private Sub sock_Connected (Successful As Boolean)
    If Successful Then
        timer1.Enabled = False
        Log(">>> iOSPush: Socket connected.")
        If astream.IsInitialized Then astream.Close
        astream.Initialize(sock.InputStream, sock.OutputStream, "astream")
    Else
        Log(">>> iOSPush: Error connecting socket: " & LastException)
        Reconnect
    End If
End Sub
Private Sub Reconnect
    Log(">>> iOSPush: Trying to reconnect...")
    timer1.Enabled = True
End Sub
Private Sub Timer1_Tick
    timer1.Enabled = False
    Connect
End Sub

Private Sub astream_NewData (Buffer() As Byte)
    If Buffer.Length >=6 Then
        Log(">>> iOSPush: status=" & Buffer(1))
    Else
        Log(">>> iOSPush: Invalid response")
    End If
End Sub
Private Sub astream_Error
    Log(">>> iOSPush: error: " & LastException)
    Reconnect
End Sub
Private Sub astream_Terminated
    Log(">>> iOSPush: terminated")
    Reconnect
End Sub

Public Sub SendMessageTo(Devices As List, msg As Message)
    Log(">>> iOSPush: Send message to userID: " & msg.userID  & ", userName: " & msg.userName & ", Badge: " & msg.Badge)
   
    Dim out As OutputStream
    out.InitializeToBytesArray(0)
    For Each device As String In Devices
        Dim FrameData As OutputStream
        FrameData.InitializeToBytesArray(0)
        WriteItem(FrameData, 1, bc.HexToBytes(device))
        Dim jg As JSONGenerator
       
        Dim m As Map =  CreateMap("alert": CreateMap("title": "___TITLE___", _
        "body": msg.Text), "badge": msg.Badge , "userid" : msg.userID, "username": msg.userName)

       
        If msg.Sound Then m.Put("sound", "default")
        jg.Initialize(CreateMap("aps":m))
        'jg.Initialize(CreateMap("aps":CreateMap("content-available": 1)))
        WriteItem(FrameData,2, jg.ToString.GetBytes("UTF8"))
        WriteItem(FrameData,3, bc.IntsToBytes(Array As Int(Rnd(0, 9999999))))
        WriteItem(FrameData,4, bc.IntsToBytes(Array As Int(msg.ExpirationDate / 1000)))
        Dim p As Byte
        If msg.HighPriority Then p = 10 Else p = 5
        WriteItem(FrameData,5, Array As Byte(p))
        Dim payload() As Byte = FrameData.ToBytesArray
        out.WriteBytes(Array As Byte(2), 0, 1)
        out.WriteBytes(bc.IntsToBytes(Array As Int(payload.Length)), 0, 4)
        out.WriteBytes(payload, 0, payload.Length)
    Next
    astream.Write(out.ToBytesArray)
End Sub

Private Sub WriteItem(out As OutputStream, id As Byte, data() As Byte)
    out.WriteBytes(Array As Byte(id), 0, 1)
    out.WriteBytes(bc.ShortsToBytes(Array As Short(data.Length)), 0, 2)
    out.WriteBytes(data, 0, data.Length)
End Sub
 
Upvote 0
Cookies are required to use this site. You must accept them to continue using the site. Learn more…