广播接收器在清单与活动中注册

时间:2012-06-04 03:28:16

标签: android android-intent broadcastreceiver intentfilter

我需要一些帮助来了解何时我可以预期我的广播接收器只能在清单中注册而不必从正在运行的活动或服务进行注册。

因此,例如,如果我使用以下意图过滤器注册一个独立的接收器,它可以在没有服务/活动引用的情况下工作:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.blk_burn.standalonereceiver"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk android:minSdkVersion="10" />
    <uses-permission android:name="android.permission.WAKE_LOCK"/>

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >

        <receiver android:name="TestReceiver">
            <intent-filter>
                <action android:name="android.media.AUDIO_BECOMING_NOISY"/>
            </intent-filter>
        </receiver>

    </application>

</manifest>

但是,如果我将android.media.AUDIO_BECOMING_NOISY替换为android.intent.action.HEADSET_PLUG,则不会触发接收方(Android Documentation

根据我在本网站上发现的内容,您必须从已经运行的活动或服务中注册此接收器(Post)。

  • 任何人都可以告诉我为什么只在清单中调整您的意图过滤器以及为什么需要在后台运行引用/注册接收器的服务时这不起作用?

  • 是否有解决办法,以便我可以使用android.intent.action.HEADSET_PLUG的意图过滤器在我的应用清单中注册我的接收器?

  • 如何确定android documentation需要有服务或活动的哪些广播操作注册它们而不是在清单中使用正确的过滤器?

2 个答案:

答案 0 :(得分:89)

如果您的接收器已在清单中注册,并且您的应用未运行,则将创建一个新进程来处理广播。如果您在代码中注册它,它与您注册它的活动/服务的生命周期有关。对于某些广播,如果它不存在,或者有一些新的应用程序进程,那么创建一个新的应用程序进程并没有多大意义。安全性,性能等含义,因此您只能在代码中注册接收器。

对于HEADSET_PLUG广播,似乎您的已经运行的应用可以让它对UI,音量等进行特定于应用的调整。如果您的应用未运行,则不应该真的关心耳机被拔掉了。

AFAIK,没有一个地方可以为所有广播汇总此信息,但是每个Intent应该在JavaDoc中有关于如何注册和使用它的注释,但显然它缺少地方。如果您为Intent.FLAG_RECEIVER_REGISTERED_ONLY Android源代码树grep,那么您应该能够编译一个列表。

答案 1 :(得分:16)

像往常一样,广播接收器可以在manifest fileAndroidManifest.xml中配置。以这种方式配置的BroadcastReceiver称为静态注册。

您可以使用以下元素在清单文件中注册接收器:

<receiver
   android:name=".ConnectivityChangeReceiver">
   <intent-filter>
      <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
   </intent-filter>
</receiver>

嵌套元素用于指定接收者应该响应的事件。

Dyanmic Broadcast Recievers

作为替代方案,您可以在代码中动态注册BroadcastReceiver实现。您只需要在Context对象上调用registerReceiver()方法。

registerReceiver()方法有两个参数:

registerReceiver()方法的参数

  • 接收方:您要注册的BroadcastReceiver
  • filter: IntentFilter对象,用于指定接收方应侦听的事件。

当您以这种方式注册接收器时,只要组件存在,它就会存在,并且Android会向此接收器发送事件,直到创建组件本身被破坏为止。

正确处理生命周期是你的任务。因此,当您动态添加接收器时,请注意在Activity的onPause()方法中取消注册相同的接收器!

我建议在Activity的onResume()方法中注册接收器,并在onPause()方法中取消注册:

@Override
protected void onPause() {
   unregisterReceiver(mReceiver);
   super.onPause();
}

@Override
protected void onResume() {
   this.mReceiver = new ConnectivityChangeReceiver();
   registerReceiver(
         this.mReceiver, 
         new IntentFilter(
               ConnectivityManager.CONNECTIVITY_ACTION));
   super.onResume();
}

何时使用哪种方法注册

用于注册BroadcastReceiver的方法取决于您的应用对系统事件的处理方式。我认为您的应用程序想要了解系统范围的事件基本上有两个原因:

  • 您的应用提供围绕这些活动的某种服务
  • 您的应用想要慷慨地对状态变化作出反应

第一类 的示例是需要在设备启动后立即工作的应用,或者在安装应用时必须开始某种工作的应用。 Battery Widget Pro或App2SD就是这类应用的好例子。对于此类型,您必须在Manifest文件中注册BroadcastReceiver。

第二类 的示例是指示您的应用可能依赖的环境发生变化的事件。假设您的应用取决于已建立的蓝牙连接。您必须对状态更改做出反应 - 但仅限于您的应用处于活动状态时。在这种情况下,不需要静态注册的广播接收器。动态注册的会更合理。

还有一些事件甚至不允许您静态注册。一个例子是每分钟广播的Intent.ACTION_TIME_TICK事件。这是一个明智的决定,因为静态接收器会不必要地耗尽电池。