Sending Messages via a Data Plan

With most service providers now offering “unlimited talk and text” it seems like a simple choice to use the native texting application on your smart phone to stay in touch with all your friends, family, and those bots the internet sold your information too. However, the Android Market seems to have a large area dedicated to applications that send messages through your limited data plan.

While the motivation to have such apps comes from a few places, it is much more interesting to analyze how these messages are sent as opposed to why.

Sending messages over Internet or data connections is not as straight forward as sending a message through your cellular service provider. The three most popular apps: Whatsapp, Kik!, and Telegram each implement their own method of connecting users. Understanding how these networks are created is beneficial for recognizing how data is moved to and from your device. After a basic understanding has been achieved, it becomes possible for a developer to implement a private web server to accomplish the same goals.

 

Whatsapp

Whatsapp uses a custom XMPP server built on Erlang to handle the messaging backend (Quora.com). They call theirs funXMPP. XMPP passes XML based code to and from the Whatsapp server. When a user logs on, or opens up the application, the server passes any messages to the phone. Whatsapp forces users to register their phone number and to create a username. This is used for the authentification of connecting to the server. Since Whatsapp is designed to be a replacement of SMS messaging, it does not store the messages after they have been sent to the receiving phone.

 

Telegram

Directly from Telegram’s website, “Unlike WhatsApp, Telegram is cloud-based and heavily encrypted”. When two devices begin a chat, Telegram creates a space for them on their cloud server. All messages, pictures, and data are stored on that server. A mobile device simply connects to the server and copies out new information. This allows for mobility. A user can access a conversation from any device at any time. However, it requires the user to trust the encryption of the Telegram server. Like Whatsapp, Telegram uses a variation on XMPP (source).

 

XMPP

Since both of these applications use XMPP, it is beneficial to set up a few components of the chat in order to understand how information is passed. XMPP comes in many flavors and there are lots of libraries available as open source. Google has it’s own version called GCM that can easily be configured for Android devices. Google Cloud Messaging (GCM) uses asynchronous tasks and allows for bidirectional communication via cloud messaging.

This is more similar to Telegram than Whatsapp. Telegram is open platform and the api is readily accessible. The api provides detailed tutorials on creating applications for Telegram. They can be referenced for further information.

The first step to setting up a chat is to register the android device with the cloud manager.

    public String registerGCM() {
		gcm = GoogleCloudMessaging.getInstance(this);
		regId = getRegistrationId(context);

		if (TextUtils.isEmpty(regId)) {
			registerInBackground();
			Log.d("RegisterActivity",
			    "registerGCM - successfully registered with GCM server - regId: " + regId);
		} else {
			Toast.makeText(getApplicationContext(),
					"RegId already available. RegId: " + regId,
					Toast.LENGTH_LONG).show();
		}
		return regId;
    }

 

Once a connection has been established and validated such that both the cloud and the device are aware of each other, the device can then interact through the cloud to the XMPP server. From there a chat can be created.

To do this, a Notification service needs to be created and a broadcast receiver must be set up.

public class GCMNotificationIntentService extends IntentService {

	public static final int NOTIFICATION_ID = 1;
	private NotificationManager mNotificationManager;
	NotificationCompat.Builder builder;

	public GCMNotificationIntentService() {
		super("GcmIntentService");
	}

	public static final String TAG = "GCMNotificationIntentService";

	@Override
	protected void onHandleIntent(Intent intent) {
		Bundle extras = intent.getExtras();
		GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(this);

		String messageType = gcm.getMessageType(intent);

		if (!extras.isEmpty()) {
			if (GoogleCloudMessaging.MESSAGE_TYPE_SEND_ERROR
					.equals(messageType)) {
				sendNotification("Send error: " + extras.toString());
			} else if (GoogleCloudMessaging.MESSAGE_TYPE_DELETED
					.equals(messageType)) {
				sendNotification("Deleted messages on server: "
						+ extras.toString());
			} else if (GoogleCloudMessaging.MESSAGE_TYPE_MESSAGE
					.equals(messageType)) {

				sendNotification("SERVER_MESSAGE: " + extras.get("SERVER_MESSAGE"));
				Log.i(TAG, "SERVER_MESSAGE: " + extras.toString());
				
			}
		}
		GcmBroadcastReceiver.completeWakefulIntent(intent);
	}

	private void sendNotification(String msg) {
		Log.d(TAG, "Preparing to send notification...: " + msg);
		mNotificationManager = (NotificationManager) this
				.getSystemService(Context.NOTIFICATION_SERVICE);

		PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
				new Intent(this, RegisterActivity.class), 0);

		NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(
				this).setSmallIcon(R.drawable.gcm_cloud)
				.setContentTitle("GCM XMPP Message")
				.setStyle(new NotificationCompat.BigTextStyle().bigText(msg))
				.setContentText(msg);

		mBuilder.setContentIntent(contentIntent);
		mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build());
		Log.d(TAG, "Notification sent successfully.");

 

This Notification class sends notifications to and from the XMPP server. This is done with the help of a broadcast receiver.

public class GcmBroadcastReceiver extends WakefulBroadcastReceiver {

	@Override
	public void onReceive(Context context, Intent intent) {
		ComponentName comp = new ComponentName(context.getPackageName(),
				GCMNotificationIntentService.class.getName());
		startWakefulService(context, (intent.setComponent(comp)));
		setResultCode(Activity.RESULT_OK);
	}
}

Conclusion

For the purpose of sending and receiving messages speed, reliability and security are the main drives behind each of these applications.Statistics both scientific and user responses indicate that Whatsapp is the worse of the two. The methods used to implement highlight the difficulties of doing all three of these things. However, each application provides more of a testament of how quickly technology and has evolved since the creation of these applications. Telegram, as a much newer application has a much cleaner, user friendly service that allows for further development.

 

Further Reference on Google Cloud Messaging at javapapers.