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


73

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

因此,例如,如果我使用以下意图过滤器注册独立接收器,则该接收器可以在不具有服务/活动引用的情况下运行:

<?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_NOISYandroid.intent.action.HEADSET_PLUG接收器没有被触发(Android文档

根据我在该站点上发现的信息,您必须从已经运行的一项活动或服务中注册该接收器,以使其正常工作(发布)。

  • 谁能告诉我为什么仅在清单中调整意图过滤器时为什么此方法不起作用,以及为什么需要在后台运行一个引用/注册接收器的服务?

  • 有没有变通的方法,这样我就可以使用intent过滤器在我的应用清单中注册接收者了android.intent.action.HEADSET_PLUG

  • 我该如何确定android文档中的哪些Broadcast操作需要服务或活动进行注册,而不是在清单中添加正确的过滤器?

Answers:


100

如果您的接收者已在清单中注册,而您的应用未运行,则将创建一个新的过程来处理广播。如果您在代码中进行注册,则它与您在其中注册的活动/服务的寿命有关。对于某些广播,如果不存在则创建一个新的应用程序流程实际上是没有意义的,或者安全性,性能等方面的影响,因此您只能在代码中注册接收者。

至于HEADSET_PLUG广播,似乎是您已经在运行的应用程序可以使它针对UI,音量等进行应用程序特定的调整。如果您的应用程序未运行,则您不必担心拔掉耳机。

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


1
intent.Flag ..并在源代码中找到它是有意义的。谢谢
Arnab C. 2012年

2
对于第一段。..休息:)
拉胡尔·拉斯托吉

1
您是否有任何官方文件来支持您的声明(如果清单中注册了收件人,并且您的应用未运行,则会创建一个新的流程来处理广播。)?
Behzad Bahmanyar's

@BehzadBahmanyar下面的链接是我能找到的最接近的东西。 developer.android.com/reference/android/content/…
AnV

@BehzadBahmanyar也请参阅此问题中的CommonsWare评论:stackoverflow.com/a/3652085/2818583
AnV

27

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

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

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

嵌套元素用于指定接收方应做出的反应。

动态广播接收器

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

registerReceiver()方法采用两个参数:

registerReceiver()方法的参数

  • 接收者: 您要注册的BroadcastReceiver
  • 过滤器: 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是此类应用程序的很好示例。对于这种类型,您必须在清单文件中注册BroadcastReceiver。

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

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


说得很好,兄弟。
杰伊·蒙加拉

很好的解释。
Abhishek kumar
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.