Other B4X Push Server

Erel

Administrator
Staff member
Licensed User
B4X Push Server is a B4J written back-end server for B4i and B4A apps that use push notifications (Android - GCM, iOS - APN).

Its two main features are:
- Collect device tokens - DeviceToken class.
- Send messages to the devices - Send servlet (which calls iOSPush and AndroidPush modules).

Configuration

There are several settings which you need to configure. The configuration file is located under the Objects folder:



You must set the following properties:
iPushKeyStore / iPushKeystorePassword - Path and password of the push keystore created with B4i (see this tutorial: http://www.b4x.com/android/forum/threads/push-notifications.48562/).

AndroidApiKey - The GCM key from Google developer console (see this tutorial: http://www.b4x.com/android/forum/threads/19226/#content).

PushServerPassword - This value is required when sending messages.

B4A / B4i Apps

The B4A / B4i apps that receive push notifications (client apps) need to register to the push notifications service when they start and send the received token to the B4X push server. You need to configure the push server url in each of the apps.

For the B4A app you need to set the SenderId and to add the required text to the manifest editor.

For the B4i app you need to set the #ProvisionFile attribute to point to the push provision profile.

Server Code

The server code is quite simple and can be customized as needed. It depends on jNetwork library v1.10+ (for the SSLSocket).
The tokens are stored in a SQLite database.

To send a message to all devices (that were updated in the last 3 days) you need to call the Send servlet:
http://<server url>/send?password=<PushServerPassword>&text=Message to send

Apple remote notifications documentation: https://developer.apple.com/library...icationsPG/Chapters/CommunicatingWIthAPS.html
Google GCM documentation: http://developer.android.com/google/gcm/index.html


V0.96 - Fixes an issue with the feedback timer being disabled.
V0.95 - It adds support for iOS feedback service. These lines should be added to existing config files:

#change to: feedback.push.apple.com for production
iFeedback=feedback.sandbox.push.apple.com
iFeedbackPort=2196

The feedback service holds a list of rejected tokens. The server will call it once an hour to find rejected tokens which will then be deleted from the database.

Note that the feedback service isn't working properly in sandbox mode (the problem is in Apple servers).
 

Attachments

Last edited:

NJDude

Expert
Licensed User
I tried the sample on Lollipop and it crashes, this is the log:
B4X:
** Activity (main) Create, isFirst = true **


** Activity (main) Resume **


** Service (pushservice) Create **


** Service (pushservice) Start **


java.lang.IllegalArgumentException: Service Intent must be explicit: Intent { act=com.google.android.c2dm.intent.REGISTER (has extras) }


	at android.app.ContextImpl.validateServiceIntent(ContextImpl.java:1674)
	at android.app.ContextImpl.startServiceCommon(ContextImpl.java:1703)
	at android.app.ContextImpl.startService(ContextImpl.java:1687)
	at android.content.ContextWrapper.startService(ContextWrapper.java:515)
	at anywheresoftware.b4a.keywords.Common.StartService(Common.java:726)
	at anywheresoftware.b4a.samples.push.pushservice._registerdevice(pushservice.java:204)
	at java.lang.reflect.Method.invoke(Native Method)
	at java.lang.reflect.Method.invoke(Method.java:372)
	at anywheresoftware.b4a.BA.raiseEvent2(BA.java:175)
	at anywheresoftware.b4a.keywords.Common$5.run(Common.java:962)
	at android.os.Handler.handleCallback(Handler.java:739)
	at android.os.Handler.dispatchMessage(Handler.java:95)
	at android.os.Looper.loop(Looper.java:135)
~e:	at android.app.ActivityThread.main(ActivityThread.java:5221)


	at java.lang.reflect.Method.invoke(Native Method)
	at java.lang.reflect.Method.invoke(Method.java:372)
	at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)
java.lang.RuntimeException: java.lang.RuntimeException: java.lang.IllegalArgumentException: Service Intent must be explicit: Intent { act=com.google.android.c2dm.intent.REGISTER (has extras) }
	at anywheresoftware.b4a.keywords.Common$5.run(Common.java:965)
	at android.os.Handler.handleCallback(Handler.java:739)
	at android.os.Handler.dispatchMessage(Handler.java:95)
	at android.os.Looper.loop(Looper.java:135)
	at android.app.ActivityThread.main(ActivityThread.java:5221)
	at java.lang.reflect.Method.invoke(Native Method)
	at java.lang.reflect.Method.invoke(Method.java:372)
	at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)
Caused by: java.lang.RuntimeException: java.lang.IllegalArgumentException: Service Intent must be explicit: Intent { act=com.google.android.c2dm.intent.REGISTER (has extras) }
	at anywheresoftware.b4a.BA.raiseEvent2(BA.java:201)
	at anywheresoftware.b4a.keywords.Common$5.run(Common.java:962)
	... 8 more
Caused by: java.lang.IllegalArgumentException: Service Intent must be explicit: Intent { act=com.google.android.c2dm.intent.REGISTER (has extras) }
	at android.app.ContextImpl.validateServiceIntent(ContextImpl.java:1674)
	at android.app.ContextImpl.startServiceCommon(ContextImpl.java:1703)
	at android.app.ContextImpl.startService(ContextImpl.java:1687)
	at android.content.ContextWrapper.startService(ContextWrapper.java:515)
	at anywheresoftware.b4a.keywords.Common.StartService(Common.java:726)
	at anywheresoftware.b4a.samples.push.pushservice._registerdevice(pushservice.java:204)
	at java.lang.reflect.Method.invoke(Native Method)
	at java.lang.reflect.Method.invoke(Method.java:372)
	at anywheresoftware.b4a.BA.raiseEvent2(BA.java:175)
	... 9 more
No problems on KitKat or JellyBean
 

Erel

Administrator
Staff member
Licensed User
Hi , Compile error
jWebSocketClient and WebSocketClient libraries should NOT be referenced.

@NJDude change the RegisterDevice code to:
B4X:
Sub RegisterDevice (Unregister As Boolean)
   Dim i As Intent
   If Unregister Then     
     i.Initialize("com.google.android.c2dm.intent.UNREGISTER", "")
   Else
     i.Initialize("com.google.android.c2dm.intent.REGISTER", "")
     i.PutExtra("sender", Main.SenderId)
   End If
   Dim jo As JavaObject = i
   jo.RunMethod("setPackage", Array("com.google.android.gms"))
   Dim r As Reflector
   Dim i2 As Intent
   i2 = r.CreateObject("android.content.Intent")
   Dim pi As Object
   pi = r.RunStaticMethod("android.app.PendingIntent", "getBroadcast", _
     Array As Object(r.GetContext, 0, i2, 0), _
     Array As String("android.content.Context", "java.lang.int", "android.content.Intent", "java.lang.int"))
   i.PutExtra("app", pi)
   StartService(i)
End Sub
Does it work?
 

ivanomonti

Well-Known Member
Licensed User
Compiler error line 19 InitializeSSL module iOSPhus project b4j

B4X:
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)
End Sub
Screen Shot 2014-12-26 at 21.15.12.png


Screen Shot 2014-12-26 at 21.17.05.png
 

DKnowles

Member
Licensed User
Compiler error line 19 InitializeSSL module iOSPhus project b4j

B4X:
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)
End Sub
View attachment 30647

View attachment 30648
Ivan, download the jNetwork library v1.10+ from the top post, under server, I just spent an hour trying to work out what was wrong.

David
 

Shay

Well-Known Member
Licensed User
Where do I get the iPushKeystorePassword
I don't recall asking & giving any password
 

Shay

Well-Known Member
Licensed User
I manage to install all, b.t.w my tip is to open incoming port (51044) on firewall
and on the URL for sending the message you need to add IP: port

I see that both devices are registered, and once I send message from browser I am getting
Message sent to 2 device(s).
and on server:
"send message to
Message was sent successfully"
and nothing arrive to both phones (IOS/Android)
What am I missing?
 

Shay

Well-Known Member
Licensed User
I fixed the clock on my server, and not IOS is working
still Android is not
 

roddy

Member
Licensed User
B4X-PushServer is server
B4i-PushClient and B4A-PushClient are Device's APP. Receive messages.

If the above is correct,and my question is:
Send a message from there?
From PC(windows)? Cell phone(iphone or Android)?
How to do?
 

DKnowles

Member
Licensed User
UPDATE : Just tried via Mobile Internet (Different IP Address), works fine.
On further investigation, Cable speed just been upgraded to a nice 150+MBit
and the lovely VirginMedia IT guys reset my router, inc deleting all the firewall settings.... Added the push Server port back in, and hey presto it works again. 2 hours wasted Grrr

Push Server Just stopped working? getting 'Remote host closed connection during handshake'.

This is what is show in the Log, not changed anything since last week?
This also happened the first time I tried to run so its not like apple think its a DOS attack (or shouldn't) which I see on the web forums as the main thing that rejects the connection.

Help anyone?
ps note the warnings and info lines before the 'server is listening on port: 51044' line have always popped up.

Program started.
2015-02-09 15:49:19.140:INFO::main: Logging initialized @671ms
2015-02-09 15:49:19.203:INFO:eek:ejs.Server:main: jetty-9.1.z-SNAPSHOT
2015-02-09 15:49:19.234:WARN:eek:ejh.MimeTypes:main: java.util.MissingResourceException: Can't find bundle for base name org/eclipse/jetty/http/encoding, locale en_GB
2015-02-09 15:49:19.234:INFO:eek:ejsh.ContextHandler:main: Started o.e.j.s.ServletContextHandler@15669ae{/,file:/C:/Users/David%20Knowles/Documents/B4i/PushServer/Objects/www,AVAILABLE}
2015-02-09 15:49:19.234:INFO:eek:ejs.AbstractNCSARequestLog:main: Opened C:\Users\David Knowles\Documents\B4i\PushServer\Objects\logs\b4j-2015_02_09.request.log
2015-02-09 15:49:19.250:INFO:eek:ejs.ServerConnector:main: Started ServerConnector@1b2668f{HTTP/1.1}{0.0.0.0:51044}
2015-02-09 15:49:19.250:INFO:eek:ejs.Server:main: Started @796ms
Emulated network latency: 100ms
server version: 0.9
server is listening on port: 51044
javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:946)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1312)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1339)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1323)
at anywheresoftware.b4a.objects.SocketWrapper$1.run(SocketWrapper.java:141)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
at java.util.concurrent.FutureTask.run(FutureTask.java:262)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.io.EOFException: SSL peer shut down incorrectly
at sun.security.ssl.InputRecord.read(InputRecord.java:482)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:927)
... 9 more
Error connecting socket: (EOFException) java.io.EOFException: SSL peer shut down incorrectly
Trying to reconnect...
[/CODE]
 
Last edited:
Top