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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10876015/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 05:19:03  来源:igfitidea点击:

Broadcast Receiver Register in Manifest vs. Activity

androidandroid-intentbroadcastreceiverintentfilter

提问by Arnab C.

I need some help to understand when I can expect my broadcast receiver will work when just registered in the manifest versus having to be registered from a running activity or service.

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

So for example if I register a stand alone receiver with the following intent filter it works without having a service/activity reference to it:

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

<?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>

However if I replace android.media.AUDIO_BECOMING_NOISYwith android.intent.action.HEADSET_PLUGthe receiver is not triggered (Android Documentation)

但是,如果我android.media.AUDIO_BECOMING_NOISYandroid.intent.action.HEADSET_PLUG接收器替换不会触发(Android 文档

From what I found on this site you have to register this receiver from an activity or service that is already running for it to work (Post).

根据我在此站点上的发现,您必须从已运行的活动或服务中注册此接收器才能使其工作(Post)。

  • Can anyone tell me why this does not work when just adjusting your intent filter in the manifest and why you need to have a service running in the background that references/registers the receiver?

  • Is there a work around so that I can just register my receiver in my app's manifest using an intent filter with android.intent.action.HEADSET_PLUG?

  • How can do I identify which Broadcast actions from the android documentationneed to have a service or activity register them versus just having the right filter in the manifest?

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

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

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

回答by Nikolay Elenkov

If your receiver is registered in the manifest, and your app is not running, a new process will be created to handle the broadcast. If you register it in code, it's tied to the life of the activity/service you registered it in. For some broadcasts, it doesn't really make sense to create a new app process if it doesn't exist, or there are some security, performance, etc. implications, and thus you can only register the receiver in code.

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

As for the HEADSET_PLUGbroadcast, it seems the idea is that your already running app can get this to do app-specific adjustments to UI, volume, etc. If your app is not running, you shouldn't really care about the headphones being unplugged.

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

AFAIK, there is no single place this info is summarized for all broadcasts, but each Intent should have a comment in the JavaDoc about how to register and use it, but apparently it's lacking in places. You should be able to compile a list if you grep the Android source tree for Intent.FLAG_RECEIVER_REGISTERED_ONLY.

AFAIK,没有一个地方为所有广播总结了这个信息,但是每个 Intent 都应该在 JavaDoc 中有一个关于如何注册和使用它的评论,但显然它缺乏地方。如果您为Intent.FLAG_RECEIVER_REGISTERED_ONLY 搜索Android 源代码树,您应该能够编译一个列表。

回答by Haythem BEN AICHA

As usual broadcast receivers can be configured in the manifest fileAndroidManifest.xml. A BroadcastReceiver that is configured in this way is called statically registered.

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

You can register your receiver in the manifest file by using the element:

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

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

The nested element is used to specify the event the receiver should react to.

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

Dyanmic Broadcast Recievers

动态广播接收器

As an alternative you can register your BroadcastReceiver implementation dynamically in your code. You just need to call the registerReceiver() method on your Context object.

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

The registerReceiver() method takes two parameters:

registerReceiver() 方法有两个参数:

The arguments of the registerReceiver() method

registerReceiver() 方法的参数

  • receiver :The BroadcastReceiver you want to register
  • filter :The IntentFilter object that specifies which event your receiver should listen to.
  • 接收器:您要注册的广播接收器
  • filter :IntentFilter 对象,指定您的接收器应侦听哪个事件。

When you register your receiver in this way, it lives for as long as the component livesand Android sends events to this receiver until the creating component itself gets destroyed.

当你以这种方式注册你的接收器时,它会一直存在,只要组件存在并且 Android 向这个接收器发送事件,直到创建的组件本身被销毁。

It's your task to handle the lifecycle correctly. Thus when you add a receiver dynamically, take care to unregister the same receiver in the onPause() method of your Activity!

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

I suggest to register the receiver in the onResume() method of your Activity and to unregister it in your onPause() method:

我建议在您的 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();
}

When to use which method to register

何时使用哪种方法注册

Which method to use for registering your BroadcastReceiver depends on what your app does with the system event. I think there are basically two reasons why your app wants to know about system-wide events:

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

  • Your app offers some kind of service around these events
  • Your app wants to react graciously to state changes
  • 您的应用程序围绕这些事件提供某种服务
  • 你的应用想要对状态变化做出优雅的反应

Examples for the first categoryare apps that need to work as soon as the device is booted or that must start some kind of work whenever an app is installed. Battery Widget Pro or App2SD are good examples for these kinds of apps. For this type you must register the BroadcastReceiver in the Manifest file.

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

Examples for the second categoryare events that signal a change to circumstances your app might rely on. Say your app depends on an established Bluetooth connection. You have to react to a state change – but only when your app is active. In this case there is no need for a statically registered broadcast receiver. A dynamically registered one would be more reasonable.

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

There are also a few events that you are not even allowed to statically register for. An example for this is the Intent.ACTION_TIME_TICK event which is broadcast every minute. Which is a wise decision because a static receiver would unnecessarily drain the battery.

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