Android Tutorial Custom WebSocket Based Push Framework

The online example is currently disabled due to spam :(

Now that both B4A and B4J support WebSockets it is possible to implement a full push framework solution.
The solution is made of two components. The client app (B4A) and the server WebApp (B4J).

The client opens and maintains a WebSocket connection with the server.

SS-2014-04-24_17.31.41.png


In the browser you can see the number of active connections and the total number of users (which includes inactive users). You can send a message to all users.

The message is queued in a database and will be delivered to the devices when they connect.

A similar process happens on the device. If the activity is paused then the message is stored with the help of KeyValueStore and a notification is shown. Later when the activity becomes visible the messages are listed on the device.

SS-2014-04-24_17.35.08.png


SS-2014-04-24_17.35.29.png


Note that the device can also send messages to the server (it is not implemented in the demo interface).
It is also possible to send messages to specific ids.

Please give it a try. You need to first download WebSocket library (v1.01+): http://www.b4x.com/android/forum/threads/40221/#content
Run the program and then go to the online console to send a message: http://basic4ppc.com:51042/push/index.html

You can also download the compiled apk and install it.

The server code is available here: http://www.b4x.com/android/forum/threads/webapp-web-apps-overview.39811

B4J client implementation: http://www.b4x.com/android/forum/threads/jwebsocketclient-library.40985/

Edit: Both the server code and device code were updated.
This example can be the base for many types of solutions that require a persistent server connection.
 

Attachments

  • Push_Client.zip
    11.5 KB · Views: 4,531
  • WebSocketPush.apk
    143.7 KB · Views: 2,926
Last edited:

vfafou

Well-Known Member
Licensed User
Longtime User
Happy New Year!
~300 tablets and still having rapid data transfer!!!
I'm very happy!

I would like to ask you something for the browser section:
Instead of this:
SS-2014-04-24_17.31.41.png


is it possible to have a Google (or whatever) Map, to show the locations of the users realtime?
Is there any example or does anyone know the libraries/classes needed to do this?

Thank you in advance!
 

vfafou

Well-Known Member
Licensed User
Longtime User
Hi Erel!
Thank you for your reply!
I have already implemented the locations storing to the server.
I'm just searching for the appropriate libraries/classes/APIs to show the map on the browser and place the markers on it!
 

vfafou

Well-Known Member
Licensed User
Longtime User
One more question, please:
which Google Maps JavaScript API should I use? V2 or V3?
 

vfafou

Well-Known Member
Licensed User
Longtime User
OK, Erel!
Thank you for your advices!
I'll try to implement it!
 

vfafou

Well-Known Member
Licensed User
Longtime User
Hello!
I've found that every connection does not free resources after disconnect!
This caused a memory leak to the push web server and crashing!
I searched the code and I haven't found anything that closes the connections at the web server!
Which is the best way to close the connections?

Thank you in advance!
 

vfafou

Well-Known Member
Licensed User
Longtime User
Hello Erel!
Thank you for your reply! :)
You mean that one connection may be released after some minutes or hours or when garbage collector decide that?
 

vfafou

Well-Known Member
Licensed User
Longtime User
OK, Erel!
I'll check again the code, with your advice considered! :)
By the way, ~400 devices and still is rapid!!! ;)
 

vfafou

Well-Known Member
Licensed User
Longtime User
Hi!
I have a strange problem:
Some times there is an unexpected condition. If the tablet user pause my application, when Activity_Resume the websocket connection stops sending and receiving messages. I start the service on Activity_Resume.
Is there any way to keep websocket connection alive? I have the service set to start every 180 seconds and ping the server every 10 seconds.

Thank you in advance!
 

vfafou

Well-Known Member
Licensed User
Longtime User
Thank you Erel!

By the way, the following code is from B4J PushServer as I have changed it. Is it OK, so I will not have any memory leaks and disconnections anymore? (MINS_TO_REMOVE_CONN = 5)

B4X:
Public Sub UpdateBrowsers
    Dim sb As StringBuilder

    sb.Initialize
 
    For Each id As String In ActiveConnections.Keys
     
        Dim pb As PushB4A = ActiveConnections.Get(id)
     
        Dim p As Period
 
        p.Initialize
        p.Minutes = -MINS_TO_REMOVE_CONN
        Dim old As Long = DateUtils.AddPeriod(DateTime.Now, p)
     
        If pb.lastPingTime < old  Then
            RemoveConnection(id, pb)
        End If
     
        sb.Append(WebUtils.ReplaceMap("<li>$ID$, Last Ping: $TIME$</li>", _
            CreateMap("ID": id, "TIME": DateTime.Time(pb.lastPingTime))))
     
    Next
 
    Dim total As Int = PushDB.ExecQuerySingleResult("SELECT Count(*) FROM rmmusers")
 
    sb.Append(WebUtils.ReplaceMap("<li>Total number of users: $TOTAL$</li>", CreateMap("TOTAL": total)))
 
    For Each pbr As PushBrowser In ConnectedBrowsers
        CallSubDelayed2(pbr, "UpdateConnectedIds", sb.ToString)
    Next
 
End Sub
 

vfafou

Well-Known Member
Licensed User
Longtime User
Hello again, Erel.
I've tested the code from my previous post and when the time to remove a connection is coming, I get the following error (that has the impact of stopping - I think - the MessageLoop) resulting to partially not working application. I mean that I can receive messages from client Web Sockets but AsyncStreams do not work:

B4X:
main.main (java line: 29)
java.lang.RuntimeException: java.lang.RuntimeException: java.lang.RuntimeException: java.util.NoSuchElementException
    at anywheresoftware.b4a.BA.raiseEvent2(BA.java:114)
    at anywheresoftware.b4a.BA.raiseEvent(BA.java:84)
    at rm.rmtunnel.main.main(main.java:29)
Caused by: java.lang.RuntimeException: java.lang.RuntimeException: java.util.NoSuchElementException
    at anywheresoftware.b4a.keywords.Common.CallSub4(Common.java:455)
    at anywheresoftware.b4a.keywords.Common.access$0(Common.java:426)
    at anywheresoftware.b4a.keywords.Common$CallSubDelayedHelper.run(Common.java:500)
    at anywheresoftware.b4a.keywords.SimpleMessageLoop.runMessageLoop(SimpleMessageLoop.java:30)
    at anywheresoftware.b4a.StandardBA.startMessageLoop(StandardBA.java:26)
    at anywheresoftware.b4a.keywords.Common.StartMessageLoop(Common.java:131)
    at rm.rmtunnel.main._appstart(main.java:85)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at anywheresoftware.b4a.BA.raiseEvent2(BA.java:93)
    ... 2 more
Caused by: java.lang.RuntimeException: java.util.NoSuchElementException
    at anywheresoftware.b4a.BA.raiseEvent2(BA.java:114)
    at anywheresoftware.b4a.keywords.Common.CallSub4(Common.java:446)
    ... 13 more
Caused by: java.util.NoSuchElementException
    at java.util.LinkedHashMap$LinkedHashIterator.nextEntry(LinkedHashMap.java:396)
    at java.util.LinkedHashMap$EntryIterator.next(LinkedHashMap.java:413)
    at java.util.LinkedHashMap$EntryIterator.next(LinkedHashMap.java:412)
    at anywheresoftware.b4a.objects.collections.Map$MyMap.getEntry(Map.java:210)
    at anywheresoftware.b4a.objects.collections.Map$MyMap.getKey(Map.java:196)
    at anywheresoftware.b4a.objects.collections.Map.GetKeyAt(Map.java:95)
    at anywheresoftware.b4a.objects.collections.Map$IterableMap.Get(Map.java:160)
    at rm.rmtunnel.pushshared._updatebrowsers(pushshared.java:366)
    at sun.reflect.GeneratedMethodAccessor14.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at anywheresoftware.b4a.BA.raiseEvent2(BA.java:93)

Is there any way to solve this error?

I would like to ask you if it is possible to send you my whole project to see if I misuse some libraries, techniques or any other portion of code...

Thank you in advance! :)
 
Last edited:

Erel

B4X founder
Staff member
Licensed User
Longtime User
What was the problem with the original code? I don't think that there is a memory leak in the original code.

I would like to ask you if it is possible to send you my whole project to see if I misuse some libraries, techniques or any other portion of code..
I'm sorry but it is not possible.
 

vfafou

Well-Known Member
Licensed User
Longtime User
Hello Erel!
Thank you for your reply!
There is not any problem with the original code. I'm afraid of problems created after my additions to it. Problems that I can't figure out how and why happen...
Is it possible to post 2-3 little suspected portions added from me, to see if there is any problem I can't see?
I have implemented a socket server into the websocket server to make a communication tunnel between my old desktop application and tablet devices.

:)
 

vfafou

Well-Known Member
Licensed User
Longtime User
Erel, please tell me:
Should I pool.Close after a DB transaction?
I ask you because I've read that I have to, but tutorials I've seen doesn't close the pool.
If I close the DB pool, will the connection with the database be lost?
Then BeginTransaction will automatically call and connect the pool?
I'm confused!
Maybe my problems exist because of not closing the DB connections!

Thank you one more time!!!
 
Top