简体   繁体   English

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

[英]Programmatically register a broadcast receiver

I'd like to know what is the best practice/way of programmatically register a broadcast receiver. 我想知道以编程方式注册广播接收器的最佳实践/方法是什么。 I want to register specific receivers according to user choice. 我想根据用户的选择注册特定的接收器。

As the registration is done through the manifest file, I'm wondering if there's a proper way to achieve this in code. 由于注册是通过清单文件完成的,我想知道是否有一种正确的方法可以在代码中实现这一点。

In your onCreate method you can register a receiver like this: 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);
}

Remember to run this in the onDestroy method: 记得在onDestroy方法中运行它:

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

One important point that people forget to mention is the life time of the Broadcast Receiver . 人们忘记提到的一个重点是Broadcast Receiver的使用寿命。 The difference of programmatically registering it from registering in AndroidManifest.xml is that. 以编程方式将其注册到AndroidManifest.xml中注册的区别在于。 In the manifest file, it doesn't depend on application life time. 在清单文件中,它不依赖于应用程序的生命周期。 While when programmatically registering it it does depend on the application life time. 在以编程方式注册时,它确实取决于应用程序的生命周期。 This means that if you register in AndroidManifest.xml , you can catch the broadcasted intents even when your application is not running. 这意味着如果您在AndroidManifest.xml中注册,即使应用程序未运行,您也可以捕获广播的意图。

Edit: The mentioned note is no longer true as of Android 3.1, the Android system excludes all receiver from receiving intents by default if the corresponding application has never been started by the user or if the user explicitly stopped the application via the Android menu (in Manage → Application). 编辑:提到的注释不再适用于Android 3.1,如果相应的应用程序从未被用户启动或者用户通过Android菜单明确停止了应用程序,则Android系统会默认情况下将所有接收者排除在接收意图之外(在管理→申请)。 https://developer.android.com/about/versions/android-3.1.html https://developer.android.com/about/versions/android-3.1.html

This is an additional security feature as the user can be sure that only the applications he started will receive broadcast intents. 这是一个额外的安全功能,因为用户可以确保只有他启动的应用程序才会收到广播意图。

So it can be understood as receivers programmatically registered in Application's onCreate() would have same effect with ones declared in AndroidManifest.xml from Android 3.1 above. 因此可以理解,在应用程序的onCreate()以编程方式注册的接收器与上述Android 3.1的AndroidManifest.xml中声明的接收器具有相同的效果。

It sounds like you want to control whether components published in your manifest are active, not dynamically register a receiver (via Context.registerReceiver()) while running. 听起来您想要控制清单中发布的组件是否处于活动状态,而不是在运行时动态注册接收器(通过Context.registerReceiver())。

If so, you can use PackageManager.setComponentEnabledSetting() to control whether these components are active: 如果是这样,您可以使用PackageManager.setComponentEnabledSetting()来控制这些组件是否处于活动状态:

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

Note if you are only interested in receiving a broadcast while you are running, it is better to use registerReceiver(). 请注意,如果您只对在运行时接收广播感兴趣,最好使用registerReceiver()。 A receiver component is primarily useful for when you need to make sure your app is launched every time the broadcast is sent. 接收器组件主要用于在每次发送广播时确保启动应用程序的情况。

Define a broadcast receiver anywhere in Activity/Fragment like this: 在Activity / Fragment中的任意位置定义广播接收器,如下所示:

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

Define IntentFilter in onCreate() onCreate()定义IntentFilter

mIntentFilter=new IntentFilter("action_name");

Now register the BroadcastReciever in onResume() and Unregister it in onPause() [because there is no use of broadcast if the activity is paused]. 现在在onResume()注册BroadcastReciever并在onPause()取消注册[因为如果活动暂停,则不使用广播]。

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

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

For detail tutorial, have a look at broadcast receiver-two ways to implement . 有关详细教程,请查看广播接收器 - 两种实现方式

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();
   }
}

It is best practice to always supply the permission when registering the receiver, otherwise you will receive for any application that sends a matching intent. 最佳做法是在注册接收器时始终提供权限,否则您将收到任何发送匹配意图的应用程序。 This can allow malicious apps to broadcast to your receiver. 这可以允许恶意应用程序广播到您的接收器。

According to Listening For and Broadcasting Global Messages, and Setting Alarms in Common Tasks and How to Do Them in Android : 根据倾听和广播全球消息,以及设置常见任务中的警报以及如何在Android中执行这些操作

If the receiving class is not registered using in its manifest, you can dynamically instantiate and register a receiver by calling Context.registerReceiver() . 如果未在其清单中使用接收类进行注册,则可以通过调用Context.registerReceiver()来动态实例化和注册接收方。

Take a look at registerReceiver (BroadcastReceiver receiver, IntentFilter filter) for more info. 查看registerReceiver(BroadcastReceiver接收器,IntentFilter过滤器)以获取更多信息。

for LocalBroadcastManager 对于LocalBroadcastManager

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

and register in onResume 并注册onResume

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

and Unregister it onStop 并在onStop取消注册

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

and recieve it .. 并收到它..

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

where IntentFilter is IntentFilter在哪里

 new IntentFilter("any.action.string")

Two choices 两个选择

1) If you want to read Broadcast only when the Activity is visible then, 1)如果您只想在活动可见时阅读广播,那么,

registerReceiver(... ) in onStart() and unregisterReceiver(...) in onStop() registerReceiver(... )的onStart()unregisterReceiver(...)onStop()

2) If you want to read Broadcast even if Activity is in Background then, 2)如果你想阅读广播,即使活动在后台,那么,

registerReceiver(...) in onCreate(...) and unregisterReceiver(...) in onDestroy() registerReceiver(...)onCreate(...)unregisterReceiver(...)onDestroy()

Bonus: 奖金:

If you are lazy 如果你很懒

If you don't want to write boilerplate code for registering and unregistering a BroadcastReceiver again and again in each Activity then, 如果你不想编写样板代码来在每个Activity中反复注册和取消注册BroadcastReceiver,那么,

  1. Create an abstract Activity 创建一个抽象活动
  2. Write boilerplate code in Activity 在Activity中编写样板代码
  3. Leave the implementation as abstract methods 将实现保留为抽象方法

Here is the code snippet: 这是代码片段:

Abstract Activity 抽象活动

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();

}

Using this approach you can write more boilerplate code such as writing common animations, binding to a service, etc. 使用这种方法,您可以编写更多样板代码,例如编写常用动画,绑定到服务等。

See full code: 查看完整代码:

HERE 这里

Create a broadcast receiver 创建广播接收器

[BroadcastReceiver(Enabled = true, Exported = false)] [BroadcastReceiver(Enabled = true,Exported = false)]

public class BCReceiver : BroadcastReceiver
{

    BCReceiver receiver;

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

From your activity add this code: 从您的活动中添加以下代码:

LocalBroadcastManager.getInstance(ApplicationContext)
    .registerReceiver(receiver, filter);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM