Android Tutorial Google Push Notification for dummies (GCM)

It took me some time to check how GCM works. See Erels example: https://www.b4x.com/android/forum/t...ion-gcm-framework-and-tutorial.19226/#content

A lot of excellent stuff but sometimes too much for a quick try. So here I would like to do a summary with more explanations and how it works.

Let's take a look at WhatsApp. If you get a message you get notified about it. The developers of the app could check the server's databases every second if there's a new message for you. This would cause about 1 billion apps to make db requests every second which will cause very big troubles. The servers would be killed due to traffic.

Checking all users if a new message has arrived makes no sence, too because - let's say in a minute - only "50.000" users send messages. So it would be better to notify just those 50K.

As the creator of WhatsApp you then have to think about how to reach a user (app) when a message has arrives for him/her. That's the moment when Google does the trick. They offer a api to send some sort of a ping to the device (phone/tablet, etc.) to say "hey, there is a message".

As there are several apps on your device which need to receive "notifications" (e.g. WhatsApp, Facebook, GMail, etc.) each app has to register itsself to the Google api for a sender.

So what is a "sender" and how is it named?

Get to https://console.cloud.google.com and login with your developer account. Here you can create a new project (see Erel's example above how to do that). When the project is created, you get a project number. And this is the sender-id (12 digits like 123456789012)

Register the app

See Erel's example code (device). Open it in B4a. In "Main/Process_Globals" you find:

B4X:
b Process_Globals
    Public DeviceBoardPassword, BoardUrl, SenderId, DeviceName As String
    DeviceBoardPassword = "********" 
    BoardUrl = "http://b4aserver******************.php"
    'Set this field to match the project ID in Google Console.
    SenderId = "123456789012"
End Sub

Change "123456789012" to the one you get from Google (project-number/id).

Start it. In "RegisterDevice" the device will be registered to the project number (Google services are called). In "HandleRegistrationResult" Google get's back and answeres with a registration id. This long string is the unique key for the device registered to the sender. 10 devices will have 10 different id's

B4X:
...
Else If Intent.HasExtra("registration_id") Then
        Dim rid As String
        rid = Intent.GetExtra("registration_id")

In debug just copy the content of "rid" to the clipboard. It looks like:

B4X:
APA91bHX8sFyx413fEDhL8e696zWeJWivpYB-isYmrJDiU4oBG042-E-SMLwatbc4l*********************************************************************

How do we send a notification/message to the device?

This is a server thing as this is not about sending messages like a WhatsApp massage. It's a server message from the sender to the device (ID) that there IS something to do. Of course (like WhatsAPP) we can send some additional data, too (e.g. to show the first line of the real message for a notification).

Erel uses a php-script to do that (this of course a similar one)

B4X:
<?php
// API access key from Google API's Console
define( 'API_ACCESS_KEY', 'AI*********************' );
$registrationIds = array( $_GET['id'] );
// prep the bundle
$msg = array
(
    'message'     => 'here is a message. message',
    'title'        => 'This is a title. title',
    'subtitle'    => 'This is a subtitle. subtitle',
    'tickerText'    => 'Ticker text here...Ticker text here...Ticker text here',
    'vibrate'    => 1,
    'sound'        => 1,
    'largeIcon'    => 'large_icon',
    'smallIcon'    => 'small_icon'
);
$fields = array
(
    'registration_ids'     => $registrationIds,
    'data'            => $msg
);
$headers = array
(
    'Authorization: key=' . API_ACCESS_KEY,
    'Content-Type: application/json'
);
$ch = curl_init();
curl_setopt( $ch,CURLOPT_URL, 'https://android.googleapis.com/gcm/send' );
curl_setopt( $ch,CURLOPT_POST, true );
curl_setopt( $ch,CURLOPT_HTTPHEADER, $headers );
curl_setopt( $ch,CURLOPT_RETURNTRANSFER, true );
curl_setopt( $ch,CURLOPT_SSL_VERIFYPEER, false );
curl_setopt( $ch,CURLOPT_POSTFIELDS, json_encode( $fields ) );
$result = curl_exec($ch );
curl_close( $ch );
echo $result;

Replace "'AI*********************'" with your own key of the project. That's it!

To send a message from a browser just call it (I've put it in a folder called "GCM"):

B4X:
http://yourdomain.com/GCM/gcm.php?id=APA91bHX8sFyx413fEDhL8e696zWe

APA91bHX8sFyx413fEDhL8e696zWe -> this is the key from above which you copied into the clipboard.

That's all you have to do..

Google returns:

B4X:
{"multicast_id":8199xxxxxxxxxxx,"success":1,"failure":0,"canonical_ids":0,"results":[{"message_id":"0:146238xxxxxxxxxxxxxxxxxx"}]}


In Erel's app "MessageArrived" will called immediately like magic (take care you didn't stop the debugger). Here you can get the data from the php (e.g. "'message' => 'here is a message. message'"). Inside the code you get it with:

B4X:
If Intent.HasExtra("message") Then Data = Intent.GetExtra("message")

In the php you just can expand the array with other key/value pairs like you want. Very easy.

Summary:

1. Create an new Messaging project
2. Get the project name (12 digits) - sometimes called project id
3. Get the "browser key" (=api access key)


Workflow:

Project name -> put it inside the app as "SenderID"
Access Key -> put it in the php
Run the app -> get the rid (registration id)
Call the php with the rid via HttpUtils or via Browser to send a message


Errors:

- rid correct?
- others: Use Google :)


As always:

- protect the php and the access key
- use the php code inside your database php's as a function
- store the registration id's in a table with user credentials (phone number?)
- use pw's, etc.
 

inakigarm

Well-Known Member
Licensed User
Longtime User
B4x push server is simple to setup up and easy to modify (ex: have a messages DB from you could get statistics/queries, etc..)
 

Chicao99

Member
Licensed User
Longtime User
Hello, I am getting :

Unauthorized
Error 401

Do you know what should I do? I have already created a new project, changed device, created new key on Google, but nothing works, any idea?
Thanks.
 

Chicao99

Member
Licensed User
Longtime User
Using the desktop solution suggested by Erel (on prompt), I got the same error, with these words:

Server returned Http response code: 401 for URL: https://android.googleapis.com/gcm/send
at anywheresoftware.b4a.c2dm.C2DM.sendMessageTo(C2DM.java:57)
at anywheresoftware.b4a.c2dm.C2DM.main(C2DM.java:218)

Any idea?
 

mrjaw

Active Member
Licensed User
Longtime User
One question:
Using B4X Server Push , I dont need to use Google and all API google to send notifications to Android and IOs?
This server can run into a VPS running Linux, not GUI ?

Thks
 
Top