Dynamic register of C2DM receiver using registerReceiver

android, android-c2dm, broadcastreceiver

Solution

When a broadcast is sent by the system it will start applications to handle the intent if they have a matching intent filter declared in the manifest. Due to the nature of C2DM it is not useful to have a Broadcast Receiver installed dynamically because your application might not be running when a C2DM message is received. If its not running it won't be started for a dynamically installed receiver.

Problem

I can register my android app with C2DM successfully using a `<receiver>` in my manifest. However, if I delete the `<receiver>` from the manifest and register my receiver using the method registerReceiver of the context, I receive a `SERVICE_NOT_AVAILABLE` error response. I have reproduced this behaviour in the emulator and in a real device. Is dynamically registering a C2DM receiver possible? This is the fragment of the manifest I deleted: ``` <receiver android:name=".service.C2DM.C2DMReceiver" android:permission="com.google.android.c2dm.permission.SEND"> <intent-filter> <action android:name="com.google.android.c2dm.intent.RECEIVE" /> <category android:name="mytestapp" /> </intent-filter> <intent-filter> <action android:name="com.google.android.c2dm.intent.REGISTRATION" /> <category android:name="mytestapp" /> </intent-filter> </receiver> ``` And here is the code: ``` public class C2DMReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { String registration = intent.getStringExtra("registration_id"); if (intent.getStringExtra("error") != null) { //TODO: Registration failed, should try again later. Log.e("MyTestAppC2DM", "C2DM Error = " + intent.getStringExtra("error")); } else if (intent.getStringExtra("unregistered") != null) { Log.d("MyTestAppC2DM", "C2DM Unregistered"); } else if (registration != null) { Log.d("MyTestAppC2DM","C2DM registration_id = " + registration); } else { Log.w("MyTestAppC2DM", "C2DM No registration_id"); } } public static void register(Context context){ /* BEGIN OF DYNAMIC REGISTER */ C2DMReceiver c2dmReceiver = new C2DMReceiver(); IntentFilter receiveIntentFilter = new IntentFilter(); receiveIntentFilter.addAction("com.google.android.c2dm.intent.RECEIVE"); receiveIntentFilter.addCategory("mytestapp"); context.registerReceiver(c2dmReceiver, receiveIntentFilter, "com.google.android.c2dm.permission.SEND", null); IntentFilter registrationIntentFilter = new IntentFilter(); registrationIntentFilter.addAction("com.google.android.c2dm.intent.REGISTRATION"); registrationIntentFilter.addCategory("mytestapp"); context.registerReceiver(c2dmReceiver, registrationIntentFilter, "com.google.android.c2dm.permission.SEND", null); /*END OF DYNAMIC REGISTER*/ Intent registrationIntent = new Intent("com.google.android.c2dm.intent.REGISTER"); registrationIntent.putExtra("app", PendingIntent.getBroadcast(context, 0, new Intent(), 0)); registrationIntent.putExtra("sender", "mysender@gmail.com"); ComponentName service = context.startService(registrationIntent); if(service!=null){ Log.d("MyTestAppC2DM","C2DM Registration sent"); }else{ Log.d("MyTestAppC2DM","C2DM Service not found"); } } } ```

Original source