Chat App for Android using a XMPP Server and Google Cloud Messaging (or the newer Firebase Cloud Messaging) for Push Notifications
Asked Answered
F

5

23

I'm developing a Chat App for Android. I have been reading for weeks about XMPP and Google Cloud Messaging (and Firebase Cloud Messaging) and I am still very confused.

Currently, I already setup an XMPP server locally (Ejabberd) and successfully connected my Android App to it using the Smack library.

To my understanding, I need to use GCM or the newer FCM for Push Notifications, so I already created a project in Google Cloud Platform. My Android App can connect to it using the Smack library too (instead of connecting to my XMPP server directly). In my server I have an small Java app that connects to GCM using the Smack library too.

Everything is fine until here. My big confusion is: How can I use my XMPP server with GCM for Push Notifications? Every documentation, examples, guides, tutorials I found for server-side implementations just tell me how to connect to GCM but none tell me how to use my XMPP server in conjunction with GCM. What I'm missing? My Java app just connects to GCM, receive and send messages from and to GCM, but my XMPP server is just sitting there doing nothing. Actually my Android App and server Java App use GCM exclusively, not my XMPP server.

I hope someone can help me to understand this as a whole, I am obviously missing some key elements to achieve this implementation.

Fernery answered 3/7, 2016 at 7:18 Comment(4)
Hey SF, can you help me out with the connecting XMPP server to android ?Paralytic
can you get your answer?Unshapen
can you please help me i'm facing same problem here #41631478Unshapen
#41734543Unshapen
P
19

You need to mix both Ejabberd and FCM together, that's how all the big chat apps do it out there. For the very basics, there are 3 components: App Server connected via XMPP to FCM, Ejabberd and your client app.

  1. When the app is in the foreground, you use Smack library to connect directly to your Ejabberd server, send messages, change user's presence, etc. The connection to your Ejabberd is kept during that time. You don't send upstream messages during this time!
  2. Once the user navigates away from your app, you close the connection. The user is now considered "Away" or "Offline".
  3. From this point and on, your App Server communicates with FCM to send downstream messages to the device using Smack library as well.
  4. On the client device: You handle the incoming message and show a notification. With Android N, users can reply directly from the notification. I assume that in this case, you would use FCM to send an upstream message to your app server since during that time, there's no active connection to your Ejabberd server.
  5. Once the user taps on the notification, the app comes back to foreground and you re-connect to Ejabberd and back to step 1.

This is the very basic description of the architecture you should have to achieve what you want.

Penalty answered 4/8, 2016 at 20:10 Comment(4)
In step 1 when you say that "You don't send upstream messages during this time", do you mean upstream messages to FCM right? In other words, the client device always send messages directly to Ejabberd when in foreground. The client device receive message from FCM and Ejabberd or just from FCM?Ratline
Yes, I referred to FCM. The client device receives messages from Ejabberd. While the app is in background, you use FCM to notify the device of new messages. Even though you can send the up to 4KB payload with FCM, I suggest that you only send a so call "push-to-sync" message using FCM and get the actual messages from Ejabberd. So Ejabberd is the main data store for all messages and your App Server with FCM downstream messages is dedicated to one thing only - making the client sync with Ejabberd. This also means that Ejabberd and your App Server need to communicate of course.Penalty
Now I need to know how to connect Ejabberd and the App Server. By the way, I already have the Client App up and running using only FCM for downstream and upstream with no problems, I need to use Ejabberd too for scalability matters right? What are the limits of a FCM-only approach?Ratline
Check out this post #16190112 for forwarding Ejabberd offline messages to your app server. It's not only for scalability, but the fact that Ejabberd is designed to be a chat server so no need to re-invent the wheel :) I'm unsure of other limitations of FCM aside the 4KB per message. Please accept this answer if it helped you, thanks! :)Penalty
D
7

This is a sample java project to showcase the Firebase Cloud Messaging (FCM) XMPP Connection Server. This project is a very simple standalone server that I developed as a base of a larger project. It is an application server that we must implement in our environment. This server sends data to a client app via the FCM CCS Server using the XMPP protocol.

https://github.com/carlosCharz/fcmxmppserver

And also I've created a video in youtube where I explain what it does.

https://www.youtube.com/watch?v=PA91bVq5sHw

Hope you find it useful.

Demello answered 22/9, 2016 at 22:39 Comment(3)
@CarlosBecerraRodríguez i have tried to implement your server at google cloud module(endpoints) but i get an error and downstream messages are not sent.Hatcher
@CarlosBecerraRodríguez error is The following addresses failed: 'fcm-xmpp.googleapis.com:5236' failed because java.net.SocketException: Permission denied: connection to (10, [2607:f8b0:4001:c06::bc]:5236,6) denied due to policy i have even opened an issue @ GithubHatcher
@JiTHiN sorry to answer too late. I have not received notifications from stackoverflow. I indeed receive notifications from the GitHub project. Did you put your error there?Demello
S
5

You should set up a Java server which connects to FCM (formerly GCM). Then you can from your device send an upstream message to FCM who then sends that upstream message to your java server and then within that Java server you can handle that upstream message to send a downstream message to the targeted device(s). Then on the device side you can handle those downstream messages being received to give a push notification.

A few useful links:

How to send an upstream message:
https://firebase.google.com/docs/cloud-messaging/upstream#sample-send

How to receive and handle downstream messages:
https://firebase.google.com/docs/cloud-messaging/downstream#sample-receive

How I set up an example Java server:
https://mcmap.net/q/585664/-building-authenticating-and-parsing-with-the-smack-library

Somnambulate answered 3/7, 2016 at 13:32 Comment(6)
Really thanks for your answer but I'm still confused. I already have a Java server which connects to FCM (very similar to the code of that link), but it works without my XMPP server, it just use FCM for everything. What I am missing?Ratline
FCM has two supported protocols HTTP and XMPP. HTTP is used to ONLY send messages from your server, through FCM, to your device. XMPP allows both server to device and device to server messages, both through FCM.Bekki
@ArthurThompson Right, so... How can I use my XMPP server with FCM for Push Notifications?, Every implementation, example, guide I found (including the one in the link of this answer) just use and explain the FCM part, what about XMPP? That Java server works without my XMPP server running at all.Ratline
@Santiago Fermin You would make an XMPP connection between your app server and FCM (CCS to be exact), you can make that connection using something like the Smack Java XMPP Library: igniterealtime.org/projects/smack. Your app server will be the XMPP server.Bekki
@ArthurThompson And what is the role of my XMPP server (Ejabberd)? That is my confusion, with FCM, Ejabberd does nothing, anything connects to it.Ratline
You don't need an XMPP server, CCS (part of FCM) is the XMPP server. Your app server would be an XMPP client to CCS and communicate with it.Bekki
D
1

I am also building chat application in Android using Smack v.4.1.8 which latest version of Smack, and our server is using ejabberd. I am not use any third party like GCM or Firebase to push downstream message from user to user message. If i am not wrong you going to use GCM or Firebase to push user to user message, if yes just dont do that.

Why? TCP protocol is keep listening a invoke listener which you registered in App when the connecting establish and still connected. Smack has a listener which called "addAsyncStanzaListener()"

addAsyncStanzaListener is used to listen a receive packet in App. They have

 public void processPacket(Stanza packet) 

You can invoke that, and you will listen the packet over the time.

I do a research about keeping stable connection of Smack. Most of Android Smartphone have each configuration, and restriction. We cannot test all of devices. Here my tips to keep connection stable:

  1. Use ForegroundService instead BackgroundService, i propose this approach because most of Android Device have restriction to an app which run in background. They will kill app when the app swipe from task manager. (e.g Asus zenphone have power management)
  2. ForegroundService will prevent app from being idle.
  3. Register ReconnectingManager
  4. Register Pingfailed
  5. Register ServerPingWithAlarmManager

And that's it. Any enquiries, just comment below :)

Best Regard R Aditya Gumay

Disfrock answered 13/10, 2016 at 15:25 Comment(0)
U
0

Your suggestion is valid for a connection with tcp/ip never drop. which is not the case in Mobile 3G/4G network. So in real 3G/4G network, the mobile client/APP might be in zombie state(disconnected). That is why you need Firebase/FCM to come to play.

Ungrudging answered 8/7, 2018 at 22:11 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.