以编程方式注册广播接收器


149

我想知道以编程方式注册广播接收器的最佳实践/方式是什么。我想根据用户选择注册特定的接收器。

由于注册是通过清单文件完成的,因此我想知道是否存在通过代码实现此目标的正确方法。



Answers:


64

听起来您想控制清单中发布的组件是否处于活动状态,而不是在运行时动态地注册接收器(通过Context.registerReceiver())。

如果是这样,则可以使用PackageManager.setComponentEnabledSetting()来控制这些组件是否处于活动状态:

http://developer.android.com/reference/android/content/pm/PackageManager.html#setComponentEnabledSetting(android.content.ComponentName、int、int)

请注意,如果仅在运行时对接收广播感兴趣,最好使用registerReceiver()。接收器组件主要用于需要确保每次发送广播时都启动应用程序的情况。


1
聪明!你让我直率。非常感谢你
CoolStraw

好人-不知道您可以这样做:)
克里斯·诺尔德斯


1
@hackbod如何在自定义接收器中添加元数据标签?你有什么想法!我需要添加我们在androidmanifest.xml中使用的元数据标签。
Zala Janaksinh'5

1
迄今为止最好的教程coderzpassion.com/implement-broadcastreceiver-android并且使用简单语言
Jagjit Singh

269

在您的onCreate方法中,您可以像这样注册接收者:

private BroadcastReceiver receiver;

@Override
public void onCreate(Bundle savedInstanceState){

  // your oncreate code should be

  IntentFilter filter = new IntentFilter();
  filter.addAction("SOME_ACTION");
  filter.addAction("SOME_OTHER_ACTION");

  receiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
      //do something based on the intent's action
    }
  };
     registerReceiver(receiver, filter);
}

请记住在onDestroy方法中运行此命令:

 @Override
 protected void onDestroy() {
  if (receiver != null) {
   unregisterReceiver(receiver);
   receiver = null;
  }
  super.onDestroy();
 }

19
谢谢,这很好。为了发送广播,我使用了代码Intent i = new Intent(“ SOME_ACTION”); sendBroadcast(i);
Ben Clayton

7
为什么不参加简历和起步呢?
Syed Raza Mehdi 2015年

如果我不注销广播接收器会怎样?即使重新启动后,它也会使广播接收器保持注册状态吗?
Jaydev '16

5
无法保证onDestroy()会被调用,从而导致潜在的内存泄漏。最好在onStart()/中进行注册/注销onStop()
Neria Nachum

这是否意味着我不必创建广播接收器类?我可以将所有onReceive()代码放在这里,这样行得通吗?
塔斯林·奥塞尼

70

人们忘记提及的重要一点是生命的时间Broadcast Receiver。以编程方式注册它与在AndroidManifest.xml中注册的区别在于。在清单文件中,它不依赖于应用程序生存时间。以编程方式注册时,它的确取决于应用程序的寿命。这意味着,如果您在AndroidManifest.xml中注册,即使您的应用程序未运行,您也可以捕获广播的意图。

编辑:从Android 3.1开始,上述注释不再适用,如果用户从未启动过相应的应用程序,或者用户通过Android菜单明确停止了该应用程序,则Android系统默认将所有接收者排除在接收意图之外管理→应用程序)。https://developer.android.com/about/versions/android-3.1.html

这是一项附加的安全功能,因为用户可以确保只有他启动的应用程序才能收到广播意图。

因此,可以理解为,以编程方式在Application的应用程序中注册的接收者onCreate()将与上述Android 3.1 中的AndroidManifest.xml中声明的接收者具有相同的效果。


1
这是一个很好的笔记。我实际上正在看一本我正在阅读的有关android的书,想知道为什么两种实现广播的方法都完成了。在我看来,这确实是为了向后兼容。但是我不确定。
霓虹灯Warge

好吧,您真的认为修改是正确的吗?我的意思是最后一句话。Android可能会随时终止您的应用程序,这将导致您以编程方式注册的接收器不再起作用,但已注册的清单仍将起作用。
JacksOnF1re

40

在“活动/片段”中的任何地方定义广播接收器,如下所示:

mReceiver = new BroadcastReceiver() {
 @Override
 public void onReceive(Context context, Intent intent) {
     Log.d(TAG," onRecieve"); //do something with intent
   }
 };

在中定义IntentFilter onCreate()

mIntentFilter=new IntentFilter("action_name");

现在在中注册BroadcastReciever onResume()并在中注销onPause()(因为如果活动暂停,则不会使用广播)。

@Override
protected void onResume() {
     super.onResume();
     registerReceiver(mReceiver, mIntentFilter);
}

@Override
protected void onPause() {
    if(mReceiver != null) {
            unregisterReceiver(mReceiver);
            mReceiver = null;
    }
    super.onPause();
}

有关详细教程,请看广播接收器-两种实现方法


到目前为止,我发现了最好的例子!谢谢!
Ayush Goyal

1
@SohailAziz链接提供了一个很好的答案。您能否将链接的上下文放在答案中,以便如果链接断开,您的答案仍然有意义?
iRuth 2015年

在我个人看来,广播应该按照您的建议在onResume和onPause中进行注册,但有些人说广播必须在onCreate和onDestroy上,您能否解释两者的利弊?
Syed Raza Mehdi 2015年

2
@SyedRazaMehdi,如果使用广播来更新UI(在大多数情况下),则应在onResume中注册它,并在onPause中注销,因为否则广播将无用。
SohailAziz 2015年

谢谢。这是最好的答案。
赛义德Z

4
package com.example.broadcastreceiver;


import android.app.Activity;
import android.content.IntentFilter;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;
import android.widget.Toast;

public class MainActivity extends Activity {

   UserDefinedBroadcastReceiver broadCastReceiver = new UserDefinedBroadcastReceiver();

   @Override
   public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);
   }

   @Override
   public boolean onCreateOptionsMenu(Menu menu) {
      getMenuInflater().inflate(R.menu.main, menu);
      return true;
   }

   /**
    * This method enables the Broadcast receiver for
    * "android.intent.action.TIME_TICK" intent. This intent get
    * broadcasted every minute.
    *
    * @param view
    */
   public void registerBroadcastReceiver(View view) {

      this.registerReceiver(broadCastReceiver, new IntentFilter(
            "android.intent.action.TIME_TICK"));
      Toast.makeText(this, "Registered broadcast receiver", Toast.LENGTH_SHORT)
            .show();
   }

   /**
    * This method disables the Broadcast receiver
    *
    * @param view
    */
   public void unregisterBroadcastReceiver(View view) {

      this.unregisterReceiver(broadCastReceiver);

      Toast.makeText(this, "unregistered broadcst receiver", Toast.LENGTH_SHORT)
            .show();
   }
}

1
您能否向OP解释为什么这是最佳做法?
Martin Prikryl 2013年

1
他们不解释,“他们”总是发布代码,因为您知道它要好得多。
霓虹灯Warge

2

根据在Android中侦听和广播全局消息以及在常见任务中设置警报以及如何执行以下操作

如果未在清单中使用接收类注册接收类,则可以通过调用Context.registerReceiver()动态实例化并注册接收器。

看一看registerReceiver(BroadcastReceiver接收器,IntentFilter过滤器)以获取更多信息。


1
我尝试致电context.registerReceiver但未致电,请您看一下这个问题stackoverflow.com/questions/13238600/…– 2012
狩猎

2

最佳实践是在注册接收者时始终提供许可,否则,对于发送匹配意图的任何应用程序,您都会收到该许可。这可以允许恶意应用广播到您的接收器。


1

对于LocalBroadcastManager

   Intent intent = new Intent("any.action.string");
   LocalBroadcastManager.getInstance(context).
                                sendBroadcast(intent);

并注册 onResume

LocalBroadcastManager.getInstance(
                    ActivityName.this).registerReceiver(chatCountBroadcastReceiver, filter);

并取消注册 onStop

LocalBroadcastManager.getInstance(
                ActivityName.this).unregisterReceiver(chatCountBroadcastReceiver);

并收到它..

mBroadcastReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            Log.e("mBroadcastReceiver", "onReceive");
        }
    };

IntentFilter在哪里

 new IntentFilter("any.action.string")

1

两种选择

1)如果您只想在活动可见时阅读广播,

registerReceiver(...)in onStart()unregisterReceiver(...)inonStop()

2)如果即使活动处于后台,您仍要阅读广播,

registerReceiver(...)onCreate(...)unregisterReceiver(...)onDestroy()

奖金:

如果你很懒

如果您不想编写用于在每个Activity中一次又一次地注册和注销BroadcastReceiver的样板代码,

  1. 创建一个抽象活动
  2. 在活动中编写样板代码
  3. 将实现保留为抽象方法

这是代码片段:

抽象活动

public abstract class BasicActivity extends AppCompatActivity {

    private BroadcastReceiver broadcastReceiver;
    private IntentFilter filter;
    private static final String TAG = "BasicActivity";

    /**********************************************************************
    *                   Boilerplate code
    **********************************************************************/

    @Override
    public void onCreate(Bundle sis){
        super.onCreate(sis);
        broadcastReceiver = getBroadcastReceiver();
        filter = getFilter();
    }

    @Override
    public void onStart(){
        super.onStart();
        register();
    }

    @Override
    public void onStop(){
        super.onStop();
        unregister();
    }

    private void register(){
        registerReceiver(broadcastReceiver,filter);
    }

    private void unregister(){
        unregisterReceiver(broadcastReceiver);
    }

    /**********************************************************************
    *                   Abstract methods
    **********************************************************************/

    public abstract BroadcastReceiver getBroadcastReceiver();

    public abstract IntentFilter getFilter();

}

使用这种方法,您可以编写更多样板代码,例如编写常见动画,绑定到服务等。

查看完整代码:

这里


0

创建广播接收器

[BroadcastReceiver(Enabled = true,导出= false)]

public class BCReceiver : BroadcastReceiver
{

    BCReceiver receiver;

    public override void OnReceive(Context context, Intent intent)
    {
        //Do something here
    }
}

在您的活动中添加以下代码:

LocalBroadcastManager.getInstance(ApplicationContext)
    .registerReceiver(receiver, filter);
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.