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

Arn*_* C. 68 android intentfilter broadcastreceiver android-intent

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

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

<?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>
Run Code Online (Sandbox Code Playgroud)

但是如果我更换android.media.AUDIO_BECOMING_NOISYandroid.intent.action.HEADSET_PLUG接收器没有被触发(Android文档)

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

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

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

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

Nik*_*kov 91

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

至于HEADSET_PLUG广播,似乎这个想法是你已经运行的应用程序可以让这个特定于应用程序的UI,音量等调整.如果你的应用程序没有运行,你不应该真的关心耳机被拔掉.

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

  • 对于第一段......休息:) (2认同)

小智 20

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

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

<receiver
   android:name=".ConnectivityChangeReceiver">
   <intent-filter>
      <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
   </intent-filter>
</receiver>
Run Code Online (Sandbox Code Playgroud)

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

Dyanmic Broadcast Recievers

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

registerReceiver()方法有两个参数:

registerReceiver()方法的参数

  • receiver: 要注册的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();
}
Run Code Online (Sandbox Code Playgroud)

何时使用哪种方法进行注册

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

  • 您的应用程序围绕这些活动提供某种服务
  • 您的应用程序希望对状态更改做出慷慨的反应

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

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

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