Reputation:
I am using Google Cloud Messaging API to send push notifications to Android devices. I have implemented the IntentService
and corresponding logic to handle notifications from the GCM server. The problem is that GCM sometimes takes up to fifteen minutes to dispatch messages, and it has made debugging a huge pain.
I have searched for how to mock GCM, but did not find any solutions that apply to my situation. I already have the third-party client server implemented; the problem is waiting for GCM to actually dispatch the messages to the Android device.
The entry point on the Android device is the IntentService
that has a hook method handleIntent(Intent)
. It seems like one possibility would be to write another program that sends a "spoofed" intent to the system, such that the system loads my IntentService
with an intent that acts, looks and feels like an authentic GCM intent. That way, my apps could receive messages instantaneously.
Has anybody encountered this issue, or have any tips on how to solve it?
Upvotes: 4
Views: 2896
Reputation: 1536
I use Postman to fake the notification.
You'll need headers:
// Please note that the authorization header's KEY is actually "key=<your GCM API key>"
Authorization: key=<your GCM API key>
Content-Type: application/json
Then POST to https://android.googleapis.com/gcm/send (this is for Android, I'm assuming that somewhere out there there is also an iOS one now that Google is supporting iOS devices as well).
Your body must look like this:
{
"registration_ids":["<Your device registration token from GCM>"],
"data": {
"message" : "your message here"
}
}
I'm assuming (but I have not confirmed):
You can put other fields inside that "data" json; any that might be passable via a Bundle. This is based on the fact that this code works:
public class PushNotificationListenerService extends GcmListenerService {
private static final String TAG = "NotificationListener";
/**
* Called when message is received.
*
* @param from SenderID of the sender.
* @param data Data bundle containing message data as key/value pairs.
* For Set of keys use data.keySet().
*/
// [START receive_message]
@Override
public void onMessageReceived(String from, Bundle data) {
// Pay attention to this line of code; this indicates
// that you could have ANY key-value pair passed in
// as long as it's capable of being serialized into a Bundle object
String message = data.getString("message");
Log.d(TAG, "From: " + from);
Log.d(TAG, "Message: " + message);
/**
* In some cases it may be useful to show a notification
* indicating to the user that a message was received.
*/
sendNotification(message);
//TODO any of your own logic to handle the notification
}
// [END receive_message]
/**
* Create and show a simple notification containing the received GCM
* message.
*
* @param message GCM message received.
*/
private void sendNotification(String message) {
Intent intent = new Intent(this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0
/* Request code */, intent,
PendingIntent.FLAG_ONE_SHOT);
Uri defaultSoundUri =
RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder = new
NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_favorite_white_shadow_36dp)
.setContentTitle("GCM Message")
.setContentText(message)
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setContentIntent(pendingIntent);
NotificationManager notificationManager =
(NotificationManager)
getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0 /* ID of notification */, notificationBuilder.build());
}
}
Upvotes: 1
Reputation: 2898
If you want to mock something and you do not know how to do this, use the following approach.
Classes can now talk to the intentservice with the adapater or to a Mock instead. A solution can be to make your own class that talks to the dependancy you need to mock.
Mocking can be hard. A Mock needs to implement the same interface as the normal class. However, if this class has a huge interface or no interface at all than it can be a problem (these are just examples). Writing your own class that calls the class you need to mock can be a solution
Upvotes: 3