使用registerReceiver动态注册C2DM接收器

5
我可以在Android应用中使用manifest中的``成功地注册C2DM。但是,如果我从manifest中删除``并使用上下文的`registerReceiver`方法注册接收器,我收到`SERVICE_NOT_AVAILABLE`错误响应。我已在模拟器和真实设备中重现了此行为。
动态地注册C2DM接收器是否可行?
这是我删除的manifest片段:
<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>

这是代码:

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");
        }   
    }
}
3个回答

3
您可以在清单文件中注册接收器C2DMReceiver,并将意图分派给真正的BroadcastReceiver来处理它。

谢谢。这就是我所做的,但我接受了其他答案,因为我更多地是在寻求解释而不是解决方法。 - hectorct
@hectorct 我有一个非常相似的问题。如果我动态注册BroadcastReceiver,我的应用程序将不再发送消息。当我切换回清单模式时,它可以正常工作。也许你已经在这方面有所发现了。 - Edmond Tamas

2
当系统发送广播时,如果应用在清单文件中声明了匹配的意图过滤器,它将启动应用程序来处理此意图。由于C2DM的特性,动态安装Broadcast Receiver并不实用,因为当接收到C2DM消息时,您的应用程序可能没有运行。如果应用程序没有运行,则不会为动态安装的接收器启动它。

0
可能会有意义将c2dm/gcm REGISTERED的意图接收到在活动中动态注册的广播接收器中,但是就像原作者一样,我发现这种方法不起作用(除了在JB上的GCM)。有什么原因吗?我在文档中找不到这个限制。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接