Android Tutorial Custom "push" notifications (server included)

[Reworked] Custom "push" notifications (server included)

So I have come up with a better(?) way of doing push notifications.

This time I will provide a usable server executable.
Download the server here: Filebeam - Beam up that File Scottie!
If you get an error from the server then please post it here and I will fix it.

Note: Scroll to the bottom to get the full code if you do not wish to read the tutorial.
Note2: The data cost for using this on the 3G network is really low, it would take around 162 days for it to use 1MB data, which makes this almost free to use.
I did not count the data used to receive packets tho, because those packets are always different in size, but they are virtually free to use aswell.

We start up by doing the layout.
You will need a layout named "main" with these controls:
*TextEdit; Name="txtIP"
*Button; Name="btnChange"

Next you need to add a service module with the name "getnotif".

Now let's start the coding!

Add these lines to Process_Globals:
B4X:
Dim HttpReq As HttpRequest
Dim hc As HttpClient
Dim tmrIP As Timer
Dim IP As String
Dim OldIP As String
Dim ConIP As String
Dim local As Boolean : local = True
Dim res As String
Dim Packet As UDPPacket
Dim data() As Byte
Dim str As String

HttpReq and hc is used to get the external IP address from whatismyip.com, the result is saved in res.
tmrIP adds a timer to the application, this will be used to send your IP to the server when the IP is updated.
Packet is the object you send to the server, you add data() to the packet to send something.
Change local to true if you wish to test this on a local network.

Use the designer to generate the code in Globals.

In Activity_Create you will need to add the following:
B4X:
Activity.LoadLayout("main")
tmrIP.Initialize("tmrIP", 6000)
tmrIP.Enabled = True
Activity.LoadLayout("main") will load the layout you have created in the Designer called "main".
tmrIP.Initialize("tmrIP", 6000) initializes the timer and sets the interval to 6 seconds, change to 600000 for a 10minute interval when you know that the code is working.

B4X:
If FirstTime Then
      hc.Initialize("http")
      ConIP = "10.54.12.248"
      StartService(getnotif)
hc.Initialize("http") initializes the HttpClient.
ConIP = "10.54.12.248" adds the IP "10.54.12.248" to the ConIP variable that is used to direct the packet to a specific IP Address.
(this is not vital, and you can change it to your servers IP if you wish, makes it easier to debug)
StartService(getnotif) starts the service, the service is what we use to show the notification.

B4X:
   If local = False Then
         HttpReq.InitializeGet("http://automation.whatismyip.com/n09230945.asp")
         hc.Execute(HttpReq, 1)
If local is false we will poll the whatismyip.com site for our external IP.

B4X:
   Else
         IP = "10.54.12.201"
         str = "IP:" & IP
          data = str.GetBytes("UTF8")
         Packet.Initialize(data, ConIP, 4444)
          getnotif.Socket1.Send(Packet)
      End If
   End If
if local is true then we will send a packet to the server with our local IP, there is a way to get this IP automatically but my device does not like that way of doing it so I will not include that in this tutorial.
Change "10.54.12.201" to the local IP of your server.
data = str.GetBytes("UTF8") converts the string str to bytes and adds it to the data() byte variable.
Packet.Initialize(data, ConIP, 4444) adds the data() to the packet and points the packet to the IP located in ConIP and the port 4444
getnotif.Socket1.Send(Packet) sends the Packet we created.

Add this line to btnChange_Click:
B4X:
ConIP = txtIP.Text
This code changes the IP you use to send packets to the IP you write in the TextEdit object.

Add these lines to tmrIP_Tick:
B4X:
If local = False Then 
      HttpReq.InitializeGet("http://automation.whatismyip.com/n09230945.asp")
      hc.Execute(HttpReq, 1)
   Else 
      IP = "10.54.12.201"
      str = "IP:" & IP
       data = str.GetBytes("UTF8")
      Packet.Initialize(data,   ConIP, 4444)
       getnotif.Socket1.Send(Packet)
   End If
This code is the same as the code above, thus I won't explain it again.

Last, add this to http_responsesuccess(Response As HttpResponse, TaskId As Int):
B4X:
res = Response.GetString("UTF8")
   IP = res
   If IP <> OldIP Then
      OldIP = IP
      str = "IP:" & IP
       data = str.GetBytes("UTF8")
       Packet.Initialize(data,   ConIP, 4444)
       getnotif.Socket1.Send(Packet)
   End If
res = Response.GetString("UTF8") converts the response we got from whatismyip.com to the res variable.
IP = res changes the IP variable to the value of the res variable. This could be done differently, I chose to do it this way so that I can use res for other purposes later if I wish.
If IP <> OldIP Then if IP is not the same as OldIP then do the code below.
The code below has already been explained before, thus I will not do it again.

Now we will code the service module.

First add this in Process_Globals:
B4X:
Dim n As Notification
Dim Socket1 As UDPSocket
Dim FirstTime As Boolean : FirstTime = True
n is the notification object we will use to display the messages from the server.
Socket1 is the UDPSocket object we use to send and receive packets from and to the server.

Add this to Service_Create:
B4X:
n.Initialize
n.Icon = "icon"
n.Vibrate = False
This is pretty self explanatory.

Add this to Service_Start (StartingIntent as Intent):
B4X:
Dim Packet As UDPPacket
Dim data() As Byte
Dim str As String
If FirstTime = True Then
   Socket1.Initialize("Socket1", 4444, 8000)
   n.SetInfo("Network Test", "Waiting for server...", Main)
   n.Sound = False
End If
Service.StartForeground(1, n)
FirstTime = False
If it's the first time the service is started then initialize Socket1.
n.SetInfo("Network Test", "Waiting for server...", Main) set the title of the notification to "Network Test" and the message to "Waiting for server...".
Service.StartForeground(1, n) start the service in the foreground making the app stay alive and always show the notification.

Add this to Socket1_PacketArrived (Packet As UDPPacket):
B4X:
Dim msg As String
msg = BytesToString(Packet.Data, Packet.Offset, Packet.Length, "UTF8")
n.SetInfo("Network Test", msg, Main)
n.Notify(1)
msg = BytesToString(Packet.Data, Packet.Offset, Packet.Length, "UTF8") convert the bytes received in the packet from the server to string and add that to the msg variable.
n.SetInfo("Network Test", msg, Main) change the notification to include the message from the server.
n.Notify(1) update the notification so that the user can see the change.

Full code for the Main Module below:
B4X:
Sub Process_Globals
   Dim HttpReq As HttpRequest
   Dim hc As HttpClient
   Dim tmrIP As Timer
   Dim IP As String
   Dim OldIP As String
   Dim ConIP As String
   Dim local As Boolean : local = True
   Dim res As String
   Dim Packet As UDPPacket
   Dim data() As Byte
   Dim str As String
End Sub

Sub Globals
   Dim btnChange As Button
   Dim txtIP As EditText
End Sub 

Sub Activity_Create(FirstTime As Boolean)
   Activity.LoadLayout("main")
   tmrIP.Initialize("tmrIP", 6000)
   tmrIP.Enabled = True
   If FirstTime Then
      hc.Initialize("http")
      ConIP = "10.54.12.248"
      StartService(getnotif)
      If local = False Then
         HttpReq.InitializeGet("http://automation.whatismyip.com/n09230945.asp")
         hc.Execute(HttpReq, 1)
      Else
         IP = "10.54.12.201"
         str = "IP:" & IP
          data = str.GetBytes("UTF8")
         Packet.Initialize(data,   ConIP, 4444)
          getnotif.Socket1.Send(Packet)
      End If
   End If
End Sub

Sub Activity_Resume

End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub

Sub btnChange_Click
   ConIP = txtIP.Text
End Sub

Sub tmrIP_Tick
   If local = False Then 
      HttpReq.InitializeGet("http://automation.whatismyip.com/n09230945.asp")
      hc.Execute(HttpReq, 1)
   Else 
      IP = "10.54.12.201"
      str = "IP:" & IP
       data = str.GetBytes("UTF8")
      Packet.Initialize(data,   ConIP, 4444)
       getnotif.Socket1.Send(Packet)
   End If
End Sub

Sub http_responsesuccess(Response As HttpResponse, TaskId As Int)
   res = Response.GetString("UTF8")
   IP = res
   If IP <> OldIP Then
      OldIP = IP
      str = "IP:" & IP
       data = str.GetBytes("UTF8")
       Packet.Initialize(data,   ConIP, 4444)
       getnotif.Socket1.Send(Packet)
   End If
End Sub

Full code for the getnotif service module below:
B4X:
Sub Process_Globals
   'These global variables will be declared once when the application starts.
   'These variables can be accessed from all modules.
   Dim n As Notification
   Dim Socket1 As UDPSocket
   Dim FirstTime As Boolean : FirstTime = True
End Sub
Sub Service_Create
   n.Initialize
    n.Icon = "icon"
   n.Vibrate = False
End Sub

Sub Service_Start (StartingIntent As Intent)
   Dim Packet As UDPPacket
   Dim data() As Byte
   Dim str As String
   If FirstTime = True Then
      Socket1.Initialize("Socket1", 4444, 8000)
      n.SetInfo("Network Test", "Waiting for server...", Main)
      n.Sound = False
   End If
   Service.StartForeground(1, n)
   FirstTime = False
End Sub

Sub Service_Destroy

End Sub

Sub Socket1_PacketArrived (Packet As UDPPacket)
   Log("received packet")
    Dim msg As String
    msg = BytesToString(Packet.Data, Packet.Offset, Packet.Length, "UTF8")
    n.SetInfo("Network Test", msg, Main)
   n.Notify(1)
End Sub
 
Last edited:

MiniDemonic

Member
Licensed User
Longtime User
Yes, it's more like a poll server, that's why i put quote marks around push.

Unfortunately I do not know of any hosts that support Java.
 

MiniDemonic

Member
Licensed User
Longtime User
It is possible to just ping the server every 10 minutes or so just to keep connection up.
And then on the server you make it push out notifications whenever you want.

That's basically how real push notifications works, and I'm not sure if it is possible with the network library but it should be.
 

MiniDemonic

Member
Licensed User
Longtime User
Updated the tutorial, it should be better now and also includes a working server.

Edit:
In this reworked tutorial the application will not poll the server for a new notification, instead it updates the IP Address it currently has and sends that to the server so that the server knows where to send the push notifications. In the tutorial the update timer is set to 6 seconds, but I would recommend setting it to 10minutes if you decide to use this method.

Sure, by setting it to 10 minutes you might miss one push notification but you could always change the code to include an ID number aswell, and then code a server that uses that to send out specific notifications to specific devices. I might consider updating this someday to include that.

Oh, if anyone is interested I could write a tutorial for making an UDP Chat client that you can use to chat with another device.
 
Last edited:

Rusty

Well-Known Member
Licensed User
Longtime User
Nice tutorial, thanks.
In your tutorial you mentioned: "there is a way to get this IP automatically but my device does not like that way of doing it so I will not include that in this tutorial."
Could you advise me on how this might be done?
I'm trying to use a "datagram" to have my android units identify themselves (their IP address) to a PC server.
The Android devices don't know the IP address of the server. I'm trying to avoid having users edit an IP address.
Thanks in advance,
Rusty
 
Top