smack message sent status - android

I am using smack and openfire for create chat app in android .
for message status I have no problem with delivered and displayed message in other
client (double check).
I will send a simple json message like bellow to sender:
{"delivery":timestapmp}
and parse it and double check messages with lower than timestamp that sent before.
the problem is about sent status (one check).
When i send message the server no response anything that message has sent .
is it possible in smack to send message with callback from server.
if possible and is it possible to send time server in callback response .
thanks .

private void acknowledgementFromServer(final Message message) throws StreamManagementException.StreamManagementNotEnabledException {
if (connection != null && connection.isSmEnabled()) {
connection.addStanzaIdAcknowledgedListener(message.getStanzaId(), new StanzaListener() {
#Override
public void processStanza(Stanza packet) throws SmackException.NotConnectedException, InterruptedException {
MessageAsyncTask task = new MessageAsyncTask(packet.getStanzaId(), MSG_STATUS_SENT);
task.execute();
}
});
}
Hey you can do it like this.. call method every time you send message by passing that message as a parameter in above method
Note: Stream Management should be enabled for this to work, can be done like below:
DeliveryReceiptManager.setDefaultAutoReceiptMode(DeliveryReceiptManager.AutoReceiptMode.always);
ProviderManager.addExtensionProvider(DeliveryReceipt.ELEMENT, DeliveryReceipt.NAMESPACE, new DeliveryReceipt.Provider());
ProviderManager.addExtensionProvider(DeliveryReceiptRequest.ELEMENT, DeliveryReceipt.NAMESPACE, new DeliveryReceiptRequest.Provider());

According to my knowledge I have got up to this Inteface : ReceiptReceivedListener which is in smack 4.2
below is how I have implemented this :
private ReceiptReceivedListener receiptReceivedListener;
/**
* get DeliveryReceiptManager
*
* #return
*/
private DeliveryReceiptManager getDeliveryReceiptManager() {
if (deliveryReceiptManager == null && getConnection() != null) {
deliveryReceiptManager = DeliveryReceiptManager.getInstanceFor(getConnection());
}
return deliveryReceiptManager;
}
add Listener
getDeliveryReceiptManager().addReceiptReceivedListener(receiptReceivedListener);
Received the call back
receiptReceivedListener = new ReceiptReceivedListener() {
#Override
public void onReceiptReceived(Jid fromJid, Jid toJid, String receiptId, Stanza receipt) {
//TODO : on recieved status of message delivery
}
};
This will help you for sure
Below is the Interface for Smack 4.2 with full details :
/**
* Callback invoked when a new receipt got received.
* <p>
* {#code receiptId} correspondents to the message ID, which can be obtained with
* {#link org.jivesoftware.smack.packet.Stanza#getStanzaId()}.
* </p>
*
* #param fromJid the jid that send this receipt
* #param toJid the jid which received this receipt
* #param receiptId the message ID of the stanza(/packet) which has been received and this receipt is for
* #param receipt the receipt
*/
void onReceiptReceived(Jid fromJid, Jid toJid, String receiptId, Stanza receipt);

Related

Implement receiver status(read or typing) in messaging app using smack - Android

I am creating an instant messaging app in android using smack library and openfire as a server but i cannot implement the feature of the person with whom the current user is talking to. i.e. like when user read the message or when he starts typing.
Is there any way of achieving this using smack or other ?
For knowing which user is current you must implement your own in your logic. You must use Roster (contact list in xmpp servers) to get contacts of current user and save them in database or somewhere. Then create an activity to show contacts in a list. Each contact has a unique jid that can be distinguished from others with it. So with click on each contact, send it's object(include jid) to chat-activity. In chat-activity you must get previous messages from database or MAM(archived messages in server) and you can send a message to current contact(set contact jid as To).
To achieving delivery of message you must use this link. you can set request of it with this code:
Message message = … //make your stanza
DeliveryReceiptRequest.addTo(message); //add delivery request to message
connection.sendStanza(message); //send message
then you can be notified of delivery with this code:
private void setDelRecListener() {
DeliveryReceiptManager d = DeliveryReceiptManager.getInstanceFor(connection);
d.addReceiptReceivedListener(new ReceiptReceivedListener() {
#Override
public void onReceiptReceived(Jid fromJid, Jid toJid, String receiptId, Stanza receipt) {
Msg msg = F.getMsgBySid(receiptId);
if (msg == null)
return;
Boolean isUpdated = F.setMsgDelivered(msg);
Log.i("m/serv/UpdateDelivery", "for: " + receiptId + (isUpdated ? " Founded&Updated" : " NotFounded"));
if (isUpdated) {
BCTool.notifyPMDelivered(msg.id, msg.conv.frnd.getBareJid());
}
}
});
}
Keep in mind that every stanza has a sid(stanza id) and you must save each corresponding sid to message model in database when send is successful. This way you can detect which message delivery you got.
- For sending chat states like composing you can use this method:
public void sendChatState(String _jid, ChatState chatState) {
try {
Message msg = new Message();
msg.addExtension(new ChatStateExtension(chatState));
msg.setTo(JidCreate.bareFrom(_jid));
msg.setType(Message.Type.chat);
connection.sendStanza(msg);
Log.e("m/service", "ChatStateSent");
} catch (SmackException.NotConnectedException | InterruptedException | XmppStringprepException e) {
Log.e("m/service", "ChatState Not Sent: " + e.getMessage());
e.printStackTrace();
}
}
You must set a timer to prevent send composing in next 5Sec and reset timer when a character typed.
Consider reading this: ChatStateNotifications

Moto G5 Plus can't connect via Socket to a local server

I have an application where the smartphone must connect via SSLSocket to a local server. I tested my app on 5 different smartphones: Moto G2 (6.0), Redmi 3S (6.0.1), LG K5 (6.0), Moto G5 Plus (7.1.1) and OnePlus 5 (8.0). The Moto G5 Plus was the only one to show this problem.
This is the line that causes the problematic behaviour. All tests where done on the same network.
socket = (SSLSocket) sslContext.getSocketFactory().createSocket(serverAddress, serverPort);
Is there any known problem with Moto G5 Plus or with Android 7+ around this behaviour?
EDIT: Some more tests are leading to an idea of Android system trying to force the Socket to connect through mobile network when identifying that WiFi interface is connected, but with no internet. Is there any way to enforce the Socket to use WiFi instead of mobile network?
Disclaimer: I didn't test this so I'm really not sure if it works.
The Network class has a bind(Socket) method, maybe you could find the wifi network and then bind it to your socket. From the doc it seems that this is what you need, it says:
/**
* Binds the specified {#link Socket} to this {#code Network}. All data traffic on the socket
* will be sent on this {#code Network}, irrespective of any process-wide network binding set by
* {#link ConnectivityManager#bindProcessToNetwork}. The socket must not be connected.
*/
The Socket shouldn't be connected before binding to the network, so I think you should create it with socketFactory.createSocket() and connect it only after the binding.
So, you should first find your Network (Kotlin):
val connectivityManager = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
val wifiNetwork = connectivityManager.allNetworks.firstOrNull {
val info = connectivityManager.getNetworkInfo(it)
info.type == ConnectivityManager.TYPE_WIFI
}
or (Java)
ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE);
Network wifiNetwork = null;
for(Network network : connectivityManager.getAllNetworks()){
NetworkInfo networkInfo = connectivityManager.getNetworkInfo(network);
if(networkInfo.getType() == ConnectivityManager.TYPE_WIFI){
wifiNetwork = network;
break;
}
}
Then bind it to the Socket and finally connect (Kotlin):
wifiNetwork?.bindSocket(socket)
val socketAddress = InetSocketAddress(hostname, port)
socket.connect(socketAddress)
or (Java)
if(wifiNetwork != null){
wifiNetwork.bindSocket(socket);
}
InetSocketAddress socketAddress = InetSocketAddress(hostName, port);
socket.connect(socketAddress);
Note, it needs ACCESS_NETWORK_STATE permission
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
i hope it helps you,i just found your solution on github.
for further details and for official link,please check this out, i think this can be helpful to you.
if it is not the answer,please ignore this answer.
We are using AsyncTask to avoid StrictMode fatal error for network access ( Look in references ). The StrictMode policy is simply forbidding us to affect on UI Thread.
/* AsyncTask class which manages connection with server app and is sending shutdown command.
*/
public class ShutdownAsyncTask extends AsyncTask<String, String, TCPClient> {
private static final String COMMAND = "shutdown -s" ;
private TCPClient tcpClient ;
private Handler mHandler ;
private static final String TAG = "ShutdownAsyncTask";
/**
* ShutdownAsyncTask constructor with handler passed as argument. The UI is updated via handler.
* In doInBackground(...) method, the handler is passed to TCPClient object.
* #param mHandler Handler object that is retrieved from MainActivity class and passed to TCPClient
* class for sending messages and updating UI.
*/
public ShutdownAsyncTask(Handler mHandler){
this.mHandler = mHandler;
}
/**
* Overriden method from AsyncTask class. There the TCPClient object is created.
* #param params From MainActivity class empty string is passed.
* #return TCPClient object for closing it in onPostExecute method.
*/
#Override
protected TCPClient doInBackground(String... params) {
Log.d(TAG, "In do in background");
try{
tcpClient = new TCPClient(mHandler,
COMMAND,
"192.168.1.1",
new TCPClient.MessageCallback() {
#Override
public void callbackMessageReceiver(String message) {
publishProgress(message);
}
});
}catch (NullPointerException e){
Log.d(TAG, "Caught null pointer exception");
e.printStackTrace();
}
tcpClient.run();
return null;
}
In this AsyncTask we are creating TCPClient object ( explained below ). In the TCPClient constructor we are passing Handler object for changing the UI, COMMAND - the String with the "shutdown -s" command for shutting down the computer, IP number - the servers ip number; Callback object - when we are getting servers response, the callback method 'messageCallbackReceiver' is starting 'publishProgress' method, which is publishing progress to 'onProgressUpdate' AsyncTask's method.
/**
* Overriden method from AsyncTask class. Here we're checking if server answered properly.
* #param values If "restart" message came, the client is stopped and computer should be restarted.
* Otherwise "wrong" message is sent and 'Error' message is shown in UI.
*/
#Override
protected void onProgressUpdate(String... values) {
super.onProgressUpdate(values);
Log.d(TAG, "In progress update, values: " + values.toString());
if(values[0].equals("shutdown")){
tcpClient.sendMessage(COMMAND);
tcpClient.stopClient();
mHandler.sendEmptyMessageDelayed(MainActivity.SHUTDOWN, 2000);
}else{
tcpClient.sendMessage("wrong");
mHandler.sendEmptyMessageDelayed(MainActivity.ERROR, 2000);
tcpClient.stopClient();
}
}
After receiving proper message, we are sending command, or if we received wrong message, we are sending message "wrong" and stopping client. After this we are being transferred to the 'onPostExecute' method:
#Override
protected void onPostExecute(TCPClient result){
super.onPostExecute(result);
Log.d(TAG, "In on post execute");
if(result != null && result.isRunning()){
result.stopClient();
}
mHandler.sendEmptyMessageDelayed(MainActivity.SENT, 4000);
}
}
So step by step:
->AsyncTask is creating TCPClient object.
->In TCPClient constructor we are passing Handler, Command, IP Number and Callback object.
->When TCPClient begins connection, it sends message "shutdown" to the server.
->When we are receiving message from server, the callback is passing it to 'onProgressUpdate'.
->If the received message ( response from server ) is equal to "shutdown", we are sending COMMAND to server.
->After sending it we are stopping client, which is transferring us to 'onPostExecute' method.
->Meanwhile, the handler is receiving empty messages with 'msg.what' integers defined in MainActivity, which are responsible for updating the GUI.
Example of how the widget UI is updated:
mHandler = new Handler(){
public void handleMessage(Message msg) {
switch(msg.what){
case SHUTDOWN:
Log.d(mTag, "In Handler's shutdown");
views = new RemoteViews(context.getPackageName(), R.layout.activity_main);
widget = new ComponentName(context, MainActivity.class);
awManager = AppWidgetManager.getInstance(context);
views.setTextViewText(R.id.state, "Shutting PC...");
awManager.updateAppWidget(widget,views);
break;
TCPClient
This class is responsible for maintaining the connection. I will explain it step by step:
In the first step we can see the objects passed from ShutdownAsyncTask and others. Additionally we can see the sendMessage and stopClient methods.
public class TCPClient {
private static final String TAG = "TCPClient" ;
private final Handler mHandler ;
private String ipNumber, incomingMessage, command;
BufferedReader in ;
PrintWriter out ;
private MessageCallback listener = null ;
private boolean mRun = false ;
/**
* TCPClient class constructor, which is created in AsyncTasks after the button click.
* #param mHandler Handler passed as an argument for updating the UI with sent messages
* #param command Command passed as an argument, e.g. "shutdown -r" for restarting computer
* #param ipNumber String retrieved from IpGetter class that is looking for ip number.
* #param listener Callback interface object
*/
public TCPClient(Handler mHandler, String command, String ipNumber, MessageCallback listener) {
this.listener = listener;
this.ipNumber = ipNumber;
this.command = command ;
this.mHandler = mHandler;
}
/**
* Public method for sending the message via OutputStream object.
* #param message Message passed as an argument and sent via OutputStream object.
*/
public void sendMessage(String message){
if (out != null && !out.checkError()) {
out.println(message);
out.flush();
mHandler.sendEmptyMessageDelayed(MainActivity.SENDING, 1000);
Log.d(TAG, "Sent Message: " + message);
}
}
/**
* Public method for stopping the TCPClient object ( and finalizing it after that ) from AsyncTask
*/
public void stopClient(){
Log.d(TAG, "Client stopped!");
mRun = false;
}
The magic happens here - in 'run()' method. Here we are using 'try-catch' tools for handling exceptions ( server not enabled, ip not proper etc. ). As you can see below, we have infinite while() loop for listening to the incoming messages. We can simply stop it and finalize with 'stopClient()' method ( used in ShutdownAsyncTask's 'onProgressUpdate' method)
public void run() {
mRun = true;
try {
// Creating InetAddress object from ipNumber passed via constructor from IpGetter class.
InetAddress serverAddress = InetAddress.getByName(ipNumber);
Log.d(TAG, "Connecting...");
/**
* Sending empty message with static int value from MainActivity
* to update UI ( 'Connecting...' ).
*
* #see com.example.turnmeoff.MainActivity.CONNECTING
*/
mHandler.sendEmptyMessageDelayed(MainActivity.CONNECTING,1000);
/**
* Here the socket is created with hardcoded port.
* Also the port is given in IpGetter class.
*
* #see com.example.turnmeoff.IpGetter
*/
Socket socket = new Socket(serverAddress, 4444);
try {
// Create PrintWriter object for sending messages to server.
out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);
//Create BufferedReader object for receiving messages from server.
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
Log.d(TAG, "In/Out created");
//Sending message with command specified by AsyncTask
this.sendMessage(command);
//
mHandler.sendEmptyMessageDelayed(MainActivity.SENDING,2000);
//Listen for the incoming messages while mRun = true
while (mRun) {
incomingMessage = in.readLine();
if (incomingMessage != null && listener != null) {
/**
* Incoming message is passed to MessageCallback object.
* Next it is retrieved by AsyncTask and passed to onPublishProgress method.
*
*/
listener.callbackMessageReceiver(incomingMessage);
}
incomingMessage = null;
}
Log.d(TAG, "Received Message: " +incomingMessage);
} catch (Exception e) {
Log.d(TAG, "Error", e);
mHandler.sendEmptyMessageDelayed(MainActivity.ERROR, 2000);
} finally {
out.flush();
out.close();
in.close();
socket.close();
mHandler.sendEmptyMessageDelayed(MainActivity.SENT, 3000);
Log.d(TAG, "Socket Closed");
}
} catch (Exception e) {
Log.d(TAG, "Error", e);
mHandler.sendEmptyMessageDelayed(MainActivity.ERROR, 2000);
}
}
The last thing in the client is the Callback interface. We have it in the TCPClient class in the end:
/**
* Callback Interface for sending received messages to 'onPublishProgress' method in AsyncTask.
*
*/
public interface MessageCallback {
/**
* Method overriden in AsyncTask 'doInBackground' method while creating the TCPClient object.
* #param message Received message from server app.
*/
public void callbackMessageReceiver(String message);
}

LoganSquare and Salut libraries - Android Wifip2p

I try to using salut librari (wifip2p library) for Android.
All work fine, discover devices, connect host, connect clients...
But when I need send a message, I have a problem.
I follow Salut tutorial: Salut
I send a message, and in console say me tha tthe message is received.
09-13 13:21:58.633 21798-21906/app.ingenia.marse.ingeniamarse D/Salut: Listening for service data...
09-13 13:21:58.643 21798-21986/app.ingenia.marse.ingeniamarse V/Salut: A device is sending data...
09-13 13:21:58.675 21798-21986/app.ingenia.marse.ingeniamarse D/Salut: Successfully received data.
But I can't read the received message.
The sender function:
public void sendData(){
Message myMessage = new Message();
myMessage.description = "See you on the other side!";
network.sendToAllDevices(myMessage, new SalutCallback() {
#Override
public void call() {
Log.e(TAG, "Oh no! The data failed to send.");
}
});
}
Where I received data:
#Override
public void onDataReceived(Object data) {
Log.d(TAG, "Received network data.");
try
{
Message newMessage = LoganSquare.parse((Message)data, Message.class);
Log.d(TAG, newMessage.description); //See you on the other side!
//Do other stuff with data.
}
catch (IOException ex)
{
Log.e(TAG, "Failed to parse network data.");
}
}
The code don't excecute the log received network data. And I need to change one line:
Message newMessage = LoganSquare.parse((Message)data, Message.class);
//to
Message newMessage = LoganSquare.parse(String.valueOf((Message)data), Message.class);
And the Message.class:
#JsonObject
public class Message{
/*
* Annotate a field that you want sent with the #JsonField marker.
*/
#JsonField
public String description;
/*
* Note that since this field isn't annotated as a
* #JsonField, LoganSquare will ignore it when parsing
* and serializing this class.
*/
public int nonJsonField;
#OnJsonParseComplete
void onParseComplete() {
Log.d("PARSED", "onParseComplete: PARSED!!");
}
/*
* Optional callback method to do something before your
* object serializes.
*/
#OnPreJsonSerialize
void onPreSerialize() {
Log.d("SERIALIZED", "onParseComplete: SERIALIZED!!");
}
}
The two logs in message.class nor they have executed
It is because according to documentation, onDataRecieve() is not executed as data.isEmpty() returns true. Check what i mean from here.

Android GCM: sendRegistrationIdToBackend syntax error on token void

I'm following the android GCM tutorial provided by google, and I get the following errors:
on the line:
private void sendRegistrationIdToBackend() {
// Your implementation here.
}
Syntax error on Token "Void", # expected.
Syntax error insert "enum Identifier" to complete EnumHeader.
Using, compiler 1.6
Thank you so much.
The entire function:
private void registerInBackground() {
new AsyncTask() {
#Override
protected String doInBackground(Void... params) {
String msg = "";
try {
if (gcm == null) {
gcm = GoogleCloudMessaging.getInstance(context);
}
regid = gcm.register(SENDER_ID);
msg = "Device registered, registration ID=" + regid;
// You should send the registration ID to your server over HTTP,
// so it can use GCM/HTTP or CCS to send messages to your app.
// The request to your server should be authenticated if your app
// is using accounts.
sendRegistrationIdToBackend();
// For this demo: we don't need to send it because the device
// will send upstream messages to a server that echo back the
// message using the 'from' address in the message.
// Persist the regID - no need to register again.
storeRegistrationId(context, regid);
} catch (IOException ex) {
msg = "Error :" + ex.getMessage();
// If there is an error, don't just keep trying to register.
// Require the user to click a button again, or perform
// exponential back-off.
}
return msg;
}
#Override
protected void onPostExecute(String msg) {
mDisplay.append(msg + "\n");
}
}.execute(null, null, null);
/**
* Sends the registration ID to your server over HTTP, so it can use GCM/HTTP
* or CCS to send messages to your app. Not needed for this demo since the
* device sends upstream messages to a server that echoes back the message
* using the 'from' address in the message.
*/
private void sendRegistrationIdToBackend() {
// Your implementation here.
}
}
It seems you forgot to close the registerInBackground() method.
Add } after }.execute(null, null, null);
Another way to look at it is that you put private void sendRegistrationIdToBackend() {} inside the registerInBackground() method, which is wrong.

GCM Service for android shows java.net.UnknownHostException: android.googleapis.com

Code for the GCMService:
package com.avilyne.gcm;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.google.android.gcm.server.Message;
import com.google.android.gcm.server.MulticastResult;
import com.google.android.gcm.server.Sender;
/**
* Servlet implementation class GCMBroadcast
*/
#WebServlet("/GCMBroadcast")
public class GCMBroadcast extends HttpServlet {
private static final long serialVersionUID = 1L;
// The SENDER_ID here is the "Browser Key" that was generated when I
// created the API keys for my Google APIs project.
private static final String SENDER_ID = "AIzaSyCOLAYwS2P3ELqnTiPs3VPHGquQy1UoEIQ";
// This is a *cheat* It is a hard-coded registration ID from an Android device
// that registered itself with GCM using the same project id shown above.
private static final String ANDROID_DEVICE = "APA91bEF-_Y7t3Vc59OGuK9gnBWDegE4g2KyVgNeVIZbjGWe-4b9FMHrL82oOEYRPVz7_GaCOHbq3PatsuU_pk8jhvGng3Xp-CAv48iPqamer8Y2aajyTvUho9hsy39uNudA8XI4ML09eUsPNH87zcuGc_v2uJj65g";
// This array will hold all the registration ids used to broadcast a message.
// for this demo, it will only have the ANDROID_DEVICE id that was captured
// when we ran the Android client app through Eclipse.
private List<String> androidTargets = new ArrayList<String>();
/**
* #see HttpServlet#HttpServlet()
*/
public GCMBroadcast() {
super();
// we'll only add the hard-coded *cheat* target device registration id
// for this demo.
androidTargets.add(ANDROID_DEVICE);
}
// This doPost() method is called from the form in our index.jsp file.
// It will broadcast the passed "Message" value.
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// We'll collect the "CollapseKey" and "Message" values from our JSP page
String collapseKey = "";
String userMessage = "";
try {
userMessage = request.getParameter("Message");
collapseKey = request.getParameter("CollapseKey");
} catch (Exception e) {
e.printStackTrace();
return;
}
// Instance of com.android.gcm.server.Sender, that does the
// transmission of a Message to the Google Cloud Messaging service.
Sender sender = new Sender(SENDER_ID);
// This Message object will hold the data that is being transmitted
// to the Android client devices. For this demo, it is a simple text
// string, but could certainly be a JSON object.
Message message = new Message.Builder()
// If multiple messages are sent using the same .collapseKey()
// the android target device, if it was offline during earlier message
// transmissions, will only receive the latest message for that key when
// it goes back on-line.
.collapseKey(collapseKey)
.timeToLive(30)
.delayWhileIdle(true)
.addData("message", userMessage)
.build();
try {
// use this for multicast messages. The second parameter
// of sender.send() will need to be an array of register ids.
MulticastResult result = sender.send(message, androidTargets, 1);
if (result.getResults() != null) {
int canonicalRegId = result.getCanonicalIds();
if (canonicalRegId != 0) {
}
} else {
int error = result.getFailure();
System.out.println("Broadcast failure: " + error);
}
} catch (Exception e) {
e.printStackTrace();
}
// We'll pass the CollapseKey and Message values back to index.jsp, only so
// we can display it in our form again.
request.setAttribute("CollapseKey", collapseKey);
request.setAttribute("Message", userMessage);
request.getRequestDispatcher("index.jsp").forward(request, response);
}
}
Since it is a web service, it does not have android_manifest.xml. So permission for internet cannot be added.
If I want to change the host(android.googleapis.com), then how should I do it. (it seems broken).
Have you tried to turn off your firewall? You have to enable gcm ports.
If your organization has a firewall that restricts the traffic to or
from the Internet, you need to configure it to allow connectivity with
GCM. The ports to open are: 5228, 5229, and 5230. GCM typically only
uses 5228, but it sometimes uses 5229 and 5230. GCM doesn't provide
specific IPs, so you should allow your server to accept incoming
connections from all IP addresses contained in the IP blocks listed in
Google's ASN of 15169.
BTW GCM message request is a simple http post, without Message Builder you have to post a message in json format.
Android developer site
More information about message fields

Categories

Resources