android-push

Hello everyone. In this post I will try to provide you with a quick example on how to implement push notifications for your Android app using MQTT protocol. I will NOT discuss here why an application might need push notifications or the advantages of Push over Pull. I assume that you know exactly what I mean by push notifications are and why you might need them. However, before jumping in straight to the good stuff, let’s go over how it all started.

Introduction

It’s been around 4 months now since I’ve started developing apps on the Android platform. It began with me scoring a free Nexus One phone at one of the Android Developer Labs.  Obviously, I couldn’t resist trying to hack around with some code, so I downloaded the SDK and dove in. I guess in some sense, that’s exactly what Google was hoping for when they starting giving out free phones. While it might sound like I got lucky, in the end Google is the one who won.

Anyway, developing for the Android platform turned out to the a pleasure. The SDK was easy to setup, easy to use and and easy to understand. Putting together your first app was a breeze. I was very impressed.

Unfortunately, I soon realized that Android is not perfect. One of the things that really disappointed me was the lack of a native method for performing push notifications. Over the past year push notifications became almost a standard in the mobile space thanks to Apple. Even though BlackBerry utlilized Push since god knows when, it was Apple that really brought Push mainstream. Obviously, lack of native Push on Android seems like a huge drawback. Naturally, I started looking around for a solution. After Googling through dozens and dozens of blogs and message boards, I’ve realized that there are 3 generally accepted ways to implement push notifications for your Android app. All of which are non-trivial, hacky and have their own disadvantages. Let’s go over the list:

  • Poll? The name obviously tells you that it’s really not even push. The idea here is to periodically poll the server for new messages from a background local or remote service. The more often you poll the closer you get to the real-time push.
Advantages: easy to implement. no cost solution
Disadvantages: Obviously, you will never be actually real-time. If you polling interval is 30 min, you can get a message that is 29 minutes and 59 seconds late. Moreover, polling more often than every 15-30 min will kill your battery pretty quickly: https://labs.ericsson.com/apis/mobile-java-push/blog/save-device-battery-mobile-java-push
  • SMS Android allows you to intercept SMS messages. Your server sends a specially encoded SMS to your phone, whenever there is something new. Your app intercepts all messages, looks for the ones from the server, then pops up a notification.
Advantages: easy to implement. Fully real-time updates. Known drop-in solutions exist such as one provided by Ericsson  Labs: https://labs.ericsson.com/apis/mobile-java-push/
Disadvantages: Can be costly to you and the user. There are only a few services that allow you send around free SMS and even those are often limited to North America. If you want to have a reliable SMS-based service that is available worldwide, you will likely need to pay. Similar goes for the users. Not everyone has an SMS plan and you don’t want your users getting charged by 3rd party for using your app.
  • Persistent TCP/IP The phone initiates a long-lived mostly idle TCP/IP connection with the server and maintains it by occasionally sending keepalive messages. Whenever there is something new on the server, it sends a messages to the phone over the TCP connection.
Advantages: Fully real-time updates.
Disadvantages: Hard to implement a reliable service on both the phone and the server side. The Android OS is known to be able to kill services when it’s running low on memory, so your notifications service can easily disappear. What happens when your phone goes to sleep? Some people complain about battery life issues related to maintaining an active connection.

The first two methods have significant disadvantages that we cannot do anything about. However, the third method’s drawbacks are not as severe. It seems like with enough work and a good design, the persistent TCP/IP method can work. After all, that’s how GMail, GTalk and Google Voice implement their real-time updates. In fact, many developers out there agree that it is probably the best way to go until Google actually takes the matter in their own hands.

Persistent TCP/IP

After more Googling around I was able to come across three reasonable efforts to implement push notifications using a persistent TCP/IP connection:

While all of the work done by these guys is incredible, none of their results are quite ready for drop-in use by other developers. In my effort to implement push notifications, I decided to put the pieces of the puzzle together and combine their results to produce a relatively stable way of implementing push. The example that I provide you with further, is a combination of Josh Guilfoyle’s TestKeepAlive project and Dale Lane’s MQTT work. I borrow quite a bit of code from those guys, so they should get most of the credit.  Anyways, enough for the introduction, let’s get to the good stuff.

My Idea

The problem with the TestKeepAlive project is that it creates a raw TCP connection, which means that you need write your own server to take care of push on the other side. While it’s, without a question, doable, it is exactly why TestKeepAlive is far from a working solution. On the other hand, the MQTT example shown by Dale Lane uses the IBM’s MQTT broker to handle the server work. To backup a little, MQTT stands for MQ Telemetry Transport, which is a protocol developed by IBM. Let’s take a quick look at the man page:

mqtt is a publish/subscribe messaging protocol intended that is designed to be lightweight. It is useful for use with low power sensors, but is applicable to many scenarios.

Did you see the part about ‘low power’? So did I. Basically, the reason why one might consider using MQTT is that it was designed to be very lightweight, so that it doesn’t consume much power. This is ideal for a mobile push solution as it addresses many battery life related concerns about persistent TCP/IP connections. Obviously, MQTT also has some disadvantages such as privacy, but we can talk about that later.

So, my idea consists of taking a KeepAliveService and replacing the raw TCP/IP connection with an MQTT connection. In this case, each device can simply subscribe to a unique topic which is based on its device ID. Now, assuming that your server knows the device ID, it can push data to the device over MQTT by publishing to that unique topic.

Architecture

In my example, I utilize a PHP script as a server. This uses the Simple Asynchronous Messaging  library (see project SAM http://project-sam.awardspace.com/) to publish MQTT messages to the broker on which I host on my server. Let’s have a look at the overall system diagram:

system_diagram

wmqtt.jar is a simple drop-in implementation of MQTT protocol provided by IBM. It can be downloaded from http://www-01.ibm.com/support/docview.wss?rs=171&uid=swg24006006. The file that you download has a bunch of different stuff. Just look for the right jar file. You can include this jar as a part of your Android app.

Really Small Message Broker (RSMB) is a simple MQTT broker also provided by IBM http://www.alphaworks.ibm.com/tech/rsmb. It runs on port 1883 by default. In our architecture it accepts messages from the server and passes them on to the right devices. RSMB can also be replaced by the Mosquitto server http://mosquitto.atchoo.org/.

SAM is a drop-in PHP library for MQTT and other stuff. You can either get it as PECL extension or download the source online http://pecl.php.net/package/sam/download/0.2.0.

send_mqtt.php is a simple PHP script that accepts messages over POST and uses SAM to pass-on messages to the broker.

Sample Code and Demo

push-app

The goal of my work on push notifications was to develop a working demo, which is what all other examples out there lack. I’m happy to say that I accomplished my objective. You can download the sample android app on GitHub.

This app (shown on the left) has a TextView and two buttons. The TextView contains your device ID and the buttons are used to start and stop the push notifications service. Once you have the app on your phone, start the service. Then go to http://tokudu.com/demo/android-push/ and enter the device ID in the first text box and enter the message text in the textarea below. Press “Send Push Message” and you should get a notification on your phone. It’s as easy as that.

You can see the source code for andoid-push in this GitHub project. It contains the aforementioned send_mqtt.php script.

If you didn’t get a notification, make sure you have network connectivity. It can also be that the broker is down on my server (see server status on the page). If that’s the case, please post a comment and I will look into it bringing the broker back up.

Final Thoughts and Comments

MQTT is definitely not the best way to implement push for Android, but it does work. One of the main drawbacks of MQTT is that anyone who knows the IP and the PORT at which the broker is running can connect and intercept your Push messages. So it’s probably a good idea to encrypt them. Alternatively, you could write your own broker and introduce some sort of authentication to MQTT.

The code I provide here for the push service still needs more testing. Reliability is definitely the main question. I think the code can definitely be improved to better handle connectivity loss and other erroneous situations. You are welcome to post your comments here regarding how it can be improved.

Also let me know if you find any bad bugs. Good luck testing!

Anton Lopyrev

Follow me on twitter @tokudu

40 Responses to “How to Implement Push Notifications for Android”

  1. Posted by MQTT Push on Android | Mosquitto

    [...] MQTT for push in Android apps, you’ll probably want to head over to Anton L’s blog post How to Implement Push Notifications for Android. He has a sample Android app that uses the IBM Java library to implement push notifications using [...]

  2. Posted by josh

    Anton -
    Great post. Push Notifications will be a growing part of the application eco-system. Particulalry on Android where messaging can be incredibly rich (including intents).
    At Xtify we have seen real adoption of our SDK by developers eager to take advantage of the Android OS.
    Our service provides for FREE push notificationa to Android devices. Any developer can download our SDK, compile into their application and immediately have a full push platform available.
    Our service is free because we expect that over time the analytical and geo tools we are building will be more valuable.
    You can have a go at it here: developer.xtify.com

  3. Posted by klaus

    Thanks Anton! Your post took me a big step forward. I used mosquitto as message broker. Got my proof of concept working without problems based on your article.

    Regards
    Klaus

    P.S.: I found the smiley at the bottom of this page. ;-)

  4. Posted by Mirko

    Good job. Many thanks.

    P.S. server is down.

  5. Posted by thk

    Thank you, it should be back up now

  6. Posted by jschram

    Nice work, however you were right Google did take matters into their own hands and the Android Cloud to Device Messaging Framework is poised to be the defacto standard for push messages.

    http://code.google.com/android/c2dm/

  7. Posted by thk

    I’m very excited of try it out. However, if you wish your app to support devices 1.5 + you might still consider using mqtt.

  8. Posted by glouz

    very interesting post, i’m actually looking at those different solutions. yours seems very good, but did you try xmmp solution with the asmack library?
    Android Cloud to Device Messaging Framework works from android 2.2 and i am targeting sdk from 1.5.
    Furthermore, is mqtt implementation a good solution if i want differents devices to communicate to share data or multimedia sessions, i think that xmmp with jingle could maybe do the trick. I’m still investigating so do you have any idea of a simple way to do this?

  9. Posted by thk

    XMPP could be a viable solution, after all, that’s what Google Talk is based on. I think it uses libjingle. I haven’t played around with it myself, but I have seen it on blogs online. Take a look at this for instance:
    http://credentiality2.blogspot.com/2010/03/xmpp-asmack-android-google-talk.html.

    Let me know if you get it to work nicely.

  10. Posted by glouz

    actually, it works pretty well. i do use google app engine for the native xmmp client service allowing 1 milion plus notifications. xmpp smack client on the devices and an xmpp serveur. only thing is i got some annoying timely disconnections but i’m working on it actually.
    I’m about to try mqtt to see which one is easier to deploy and maintain. I’ll let you know.
    Other thing interesting with xmpp is the implementation of multimedia session between users, but not yet on the mobile devices library i guess.

  11. Posted by Vijay C

    Thanks Anton.
    You got me working and gave a direction….. :)

  12. Posted by babach

    Thanks! Tokudu!!! I got many helps.!!
    but, I have a problem.
    This demo app was running very well one week ago, but now is not running.
    In other words, When I enter site ” http://tokudu.com/demo/android-push/
    and click “send push message”, my android phone doesn’t react.
    Have to I re-install demo app??? or server port number change???
    I don’t know what problem is. I need your help~

  13. Posted by thk

    Hi there,
    Try re-downloading the source code from GitHub. I changed somethings, so that’s why it’s probably not working. I just tested it myself, it’s working fine for me.

    Good luck.

  14. Posted by bostjan

    Hey,

    I was just wondering if mqtt (mosquitto for instance) allows multiple subscriptions from the same IP, but to different topics? I seem to get disconnects when I try to connect though to a different topic.

  15. Posted by thk

    Yes it does. However, you need to make sure you have a different client name.

  16. Posted by Geoff

    Fantastic post, thanks thk! Just wanted to mention that for some reason on my Nexus One, the “connectivity changed” event fires as soon as the service starts and makes the client think that the network connection has been lost. I had to comment out the “registerReceiver” and “unregisterReceiver” lines to get it to work. It works great now though (until I lose network connectivity, I suppose). :)

  17. Posted by Joene

    Hi,

    I succesfully made an apk of the sourcecode and i can start the application on my HTC desire. However when i fill in the device id and message on your website, the notification will not be displayed.

    Do you know why this happens?

  18. Posted by alan

    I have copied your code over to a scripting service that is “hosting” my page. I changed only the IP address to be the one where my page is hosted (I think). The problem is when I try to use it, the page comes up but it says that it is offline. I turned debug on and it says: Server status: –>SAMConnection_MQTT()
    <–SAMConnection_MQTT(). What should I look at or what could be my problem?

    Thanks for the wonderful tutorial by the way.

  19. Posted by Joene

    [22:42:20] Opened log.
    [22:42:20] Service started with intent=Intent { act=tokudu.START cmp=com.tokudu.demo/.PushService }
    [22:42:20] Starting service…
    [22:42:20] Connecting…
    [22:42:21] Connection established to 209.124.50.185 on topic tokudu/200145745b9784f9
    [22:42:21] Connectivity changed: connected=false

  20. Posted by thk

    @ alan: what version of PHP are you running? Try to turn on your warnings and see what’s being output.

    @Joene from the log file it looks like it connects successfully, but then the network connectivity is lost. Have a look at Geoff’s comment above, he might have had a similar problem. Seems like the connection monitor is experiencing some issues. You can try to rework some code near “BroadcastReceiver mConnectivityChanged” and see when it starts working for you.

  21. Posted by alan

    PHP API 20041225
    PHP Extension 20060613
    If this isn’t what you want go to the following webpage where there is a lot of information:
    http://alanma.scripts.mit.edu/QotD/
    also: what address should I use for
    fsockopen(ip_address, 1883);
    I think my problem is occuring because that returns false

  22. Posted by alan

    found this also: PHP Version 5.2.13

  23. Posted by alan

    Notice: (alanma) Use of undefined constant SAM_HOST - assumed ‘SAM_HOST’ in index.php
    Notice: (alanma) Use of undefined constant SAM_PORT - assumed ‘SAM_PORT’ in index.php
    Warning: (alanma) fsockopen() [function.fsockopen]: unable to connect to 18.98.4.32:1883 (Connection timed out)
    I’m guessing I have the IP wrong… How can I find out what address to put there?

  24. Posted by veejayc

    Hi Anton,

    I am having following problem when i deployed the php script..

    Server status:
    Warning: fsockopen() [function.fsockopen]: unable to connect to 127.0.0.1:1883 (A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond. ) in C:\wamp\www\tokudu\SAM\MQTT\sam_mqtt.php on line 640

    Fatal error: Maximum execution time of 60 seconds exceeded in C:\wamp\www\tokudu\SAM\MQTT\sam_mqtt.php on line 640

    Am i missing something here…
    I am using wamp server which has php 5.3.0

  25. Posted by Roger

    There’s a bug in the SAM MQTT code - they assume that the network data reads are always of the correct length. This can sometimes cause problems with mosquitto for some reason, which might be the reason for the disconnections. This is discussed briefly (including a fix) at http://chemicaloliver.net/programming/mqtt-mosquitto-and-php/

  26. Posted by Varun

    Sir,
    The blog entry was extremely helpful to get started with Push notifications.
    I spent some time looking into the basic function calls to push messages via the IBM really small broker.
    I have a query.How did you make the ‘push messaging’ localized to a specific device id?..The publish function for the client has only four parameters namely
    Topic,payload,qos and the retained flag i.e.:
    “publish(java.lang.String thisTopic, byte[] thisMessage, int thisQoS, boolean retained)”
    Since the source of the IBM broker is not available , how is the default broadcasting of the broker stopped and ability to push messages to a particular device with a specific device id can be implemented?

  27. Posted by thk

    @veejayc You need to change the IP address to the IP address of the server, where you have the MQTT broker running.

    @Roger Thanks for that link. I was wondering why the mosquitto server was not working for me.

    @Varun, I embed the device ID as part of the topic. Have a look at the source code

  28. Posted by babach

    Thanks for your helps!
    and I have a question.
    Instead of using PHP and PHP library, is it possible to implement server layer using java and java library or api?
    if possible, do you know solution?

    thanks.

  29. Posted by thk

    Yeah for sure! You can simply use the same wmqtt.jar file that you include as a part of your android app and use the same function calls.

  30. Posted by Enoch

    Just wonder do you need to have the app running to receive the push?
    Thanks

  31. Posted by Jason Kim

    thk thanks for your extreamly helpful blog!
    I’ve testing the push notification on my HTC Desire and it worked just fine two month ago but now I don’t receive the notification. Is there any problem on the server? or is it just me?

  32. Posted by Paul DeFoe

    Thank-you for the extremely informative post Anton. At the end of your article you say that MQTT is not the best way to implement push for Android, is there a better solution?

    Paul

  33. Posted by notox

    Thanks a lot for helping the community !!
    So i started to make some work based on yours, to be able to make broadcast and terminal to terminal communication, but i’m worried about something.

    Is there any limitation (other than with my own server) in the “(SAM+MQTT) solution” on the number of clients that can be registered at the same time ?

    PS And about other limitations, if it can help some people, i saw the MQTT client ID cannot be more that 6 characters (the target part before the slash).

    Thanks, and congrats again for the work !

  34. Posted by thk

    MQTT does have a limitation on the number of clients, but it’s due to the number of sockets that the Linux kernel supports. By default it’s around 1032, but it can be changed in the kernel to a really large number when needed.

    The MQTT client ID limit is I believe 8 characters, or smth like that.

  35. Posted by josh

    For those of you that prefer a simple implementation and/or are not interested in maintaining your own servers, give Xtify a try.

    Xtify is an out-of-the-box push notification service - download and include the Xtify SDK with your application. Then you can use our web console to configure message campaigns or call our webservice for system / device generated messages.

    You can even create geo-triggered push notification campaigns by adding some locations and rules.

    Xtify is also compatible with iPhone and Blackberry so you have one place to push across your entire user base.

  36. Posted by links for 2010-08-02 « Bloggitation

    [...] How to Implement Push Notifications for Android (tags: mobile android rtw) [...]

  37. Posted by Roger

    A clarification: according to the MQTT spec, the length of the client id should be between 1 and 23 characters. Mosquitto doesn’t enforce the upper limit though.

    I can also comment on the limitations on the number of clients that can be connected to a broker. I believe (although I may be wrong) that RSMB is limited to approximately 1024 clients connected at once. Mosquitto on the other hand is capable of having greater than 1024 clients connected, although this needs a small amount of configuring on the server to increase the limits imposed by the OS.

  38. Posted by Park Jeongil

    How to Implement Push Notifications for Android

  39. Posted by Alex

    Tokudu Android Push Demo:

    PHP Version 5.2.10
    Apache 2.0 Handler

    Server status:
    Warning: fsockopen() [function.fsockopen]: unable to connect to 127.0.0.1:1883 (ѕопытка установить соединение была безуспешной, т.к. от другого компьютера за требуемое врем€ не получен нужный отклик, или было разорвано уже установленное соединение из-за неверного отклика уже подключенного компьютера. ) in C:\SERVER\www\lesson\android\PhpMQTTClient\SAM\MQTT\sam_mqtt.php on line 640

  40. Posted by Confluence: dotPW Mobile

    Handling Notifications…

    What support do platforms provide?……

Leave a Reply