如何检查Receiver是否在Android中注册?

时间:2010-04-21 10:25:33

标签: android api broadcastreceiver android-broadcast android-broadcastreceiver

我需要检查我的注册接收者是否仍然注册,如果不是我如何检查任何方法?

18 个答案:

答案 0 :(得分:285)

没有API函数来检查接收器是否已注册。解决方法是将您的代码放在try catch block as done below.

try {

 //Register or UnRegister your broadcast receiver here

} catch(IllegalArgumentException e) {

    e.printStackTrace();
}

答案 1 :(得分:63)

如果您考虑this thread

,我不确定API会直接提供API
  

我想知道同样的事情   在我的情况下,我有一个BroadcastReceiver实现调用   Context#unregisterReceiver(BroadcastReceiver)在处理收到的Intent后将自身作为参数传递   调用接收者的onReceive(Context, Intent)方法的可能性很小   不止一次,因为它已在多个IntentFilters注册,因此IllegalArgumentException可能会导致Context#unregisterReceiver(BroadcastReceiver)被抛出。

     

在我的情况下,我可以在调用Context#unregisterReceiver(BroadcastReceiver)之前存储一个私有同步成员进行检查,但确实如此   如果API提供了检查方法,那就更清洁了。

答案 2 :(得分:30)

最简单的解决方案

接收方

public class MyReceiver extends BroadcastReceiver {   
    public boolean isRegistered;

    /**
    * register receiver
    * @param context - Context
    * @param filter - Intent Filter
    * @return see Context.registerReceiver(BroadcastReceiver,IntentFilter)
    */
    public Intent register(Context context, IntentFilter filter) {
        try {
              // ceph3us note:
              // here I propose to create 
              // a isRegistered(Contex) method 
              // as you can register receiver on different context  
              // so you need to match against the same one :) 
              // example  by storing a list of weak references  
              // see LoadedApk.class - receiver dispatcher 
              // its and ArrayMap there for example 
              return !isRegistered 
                     ? context.registerReceiver(this, filter) 
                     : null;
            } finally {
               isRegistered = true;
            }
    }

    /**
     * unregister received
     * @param context - context
     * @return true if was registered else false
     */
     public boolean unregister(Context context) {
         // additional work match on context before unregister
         // eg store weak ref in register then compare in unregister 
         // if match same instance
         return isRegistered 
                    && unregisterInternal(context);
     }

     private boolean unregisterInternal(Context context) {
         context.unregisterReceiver(this); 
         isRegistered = false;
         return true;
     }

    // rest implementation  here 
    // or make this an abstract class as template :)
    ...
}
代码中的

MyReceiver myReceiver = new MyReceiver();
myReceiver.registerReceiver(Conext, IntentFilter); // register 
myReceiver.unregister(Context); // unregister 

ad 1

- 回复:

  

这真的不那么优雅,因为你必须记住设置   注册后的isRegistered标志。 - Stealth Rabbi

- “更优雅的方式”在接收器中添加了注册和设置标志的方法

  

这将无效如果您重新启动设备或您的应用程序被杀死   OS。 - amin 6小时前

@amin - 查看代码的生命周期(不是由manifest条目注册的系统)注册的接收者:)

答案 3 :(得分:27)

我正在使用此解决方案

public class ReceiverManager {

    private static List<BroadcastReceiver> receivers = new ArrayList<BroadcastReceiver>();  
    private static ReceiverManager ref;
    private Context context;

    private ReceiverManager(Context context){
        this.context = context;
    }

    public static synchronized ReceiverManager init(Context context) {      
        if (ref == null) ref = new ReceiverManager(context);
        return ref;
    }

    public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter intentFilter){
        receivers.add(receiver);
        Intent intent = context.registerReceiver(receiver, intentFilter);
        Log.i(getClass().getSimpleName(), "registered receiver: "+receiver+"  with filter: "+intentFilter);
        Log.i(getClass().getSimpleName(), "receiver Intent: "+intent);
        return intent;
    }

    public boolean isReceiverRegistered(BroadcastReceiver receiver){
        boolean registered = receivers.contains(receiver);
        Log.i(getClass().getSimpleName(), "is receiver "+receiver+" registered? "+registered);
        return registered;
    }

    public void unregisterReceiver(BroadcastReceiver receiver){
        if (isReceiverRegistered(receiver)){
            receivers.remove(receiver);
            context.unregisterReceiver(receiver);
            Log.i(getClass().getSimpleName(), "unregistered receiver: "+receiver);
        }
    }
}

答案 4 :(得分:22)

你有几个选择

  1. 您可以在您的课程或活动中添加标记。将一个布尔变量放入您的类并查看此标志以了解您是否已注册Receiver。

  2. 创建一个扩展Receiver的类,您可以使用:

    1. 单例模式只在项目中有一个此类的实例。

    2. 实施知道接收者是否注册的方法。

答案 5 :(得分:10)

你必须使用try / catch:

try {
    if (receiver!=null) {
        Activity.this.unregisterReceiver(receiver);
    }
} catch (IllegalArgumentException e) {
    e.printStackTrace();
}

答案 6 :(得分:7)

你可以轻松搞定......

1)创建一个布尔变量...

private boolean bolBroacastRegistred;

2)注册广播接收器时,将其设置为TRUE

...
bolBroacastRegistred = true;
this.registerReceiver(mReceiver, new IntentFilter(BluetoothDevice.ACTION_FOUND));
....

3)在onPause()中执行...

if (bolBroacastRegistred) {
    this.unregisterReceiver(mReceiver);
    bolBroacastRegistred = false
}

就是这样,现在,你不会在onPause()上收到更多异常错误消息。

提示1:始终使用onPause()中的unregisterReceiver()而不是onDestroy() 提示2:运行unregisterReceive()时,别忘了将bolBroadcastRegistred变量设置为FALSE

成功!

答案 7 :(得分:5)

如果你把它放在onDestroy或onStop方法上。我认为,当再次创建活动时,没有创建MessageReciver。

@Override 
public void onDestroy (){
    super.onDestroy();
LocalBroadcastManager.getInstance(context).unregisterReceiver(mMessageReceiver);

}

答案 8 :(得分:3)

我使用Intent让Broadcast Receiver了解主Activity线程的Handler实例,并使用Message将消息传递给Main activity

我已经使用这种机制来检查广播接收器是否已经注册。有时,当您动态注册广播接收器并且不想两次播放时,或者如果广播接收器正在运行,则需要向用户显示。

主要活动:

public class Example extends Activity {

private BroadCastReceiver_example br_exemple;

final Messenger mMessenger = new Messenger(new IncomingHandler());

private boolean running = false;

static class IncomingHandler extends Handler {
    @Override
    public void handleMessage(Message msg) {
        running = false;    
        switch (msg.what) {
        case BroadCastReceiver_example.ALIVE:
    running = true;
            ....
            break;
        default:

            super.handleMessage(msg);
        }

    }
    }

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

    IntentFilter filter = new IntentFilter();
        filter.addAction("pl.example.CHECK_RECEIVER");

        br_exemple = new BroadCastReceiver_example();
        getApplicationContext().registerReceiver(br_exemple , filter); //register the Receiver
    }

// call it whenever you want to check if Broadcast Receiver is running.

private void check_broadcastRunning() {    
        /**
        * checkBroadcastHandler - the handler will start runnable which will check if Broadcast Receiver is running
        */
        Handler checkBroadcastHandler = null;

        /**
        * checkBroadcastRunnable - the runnable which will check if Broadcast Receiver is running
        */
        Runnable checkBroadcastRunnable = null;

        Intent checkBroadCastState = new Intent();
        checkBroadCastState .setAction("pl.example.CHECK_RECEIVER");
        checkBroadCastState .putExtra("mainView", mMessenger);
        this.sendBroadcast(checkBroadCastState );
        Log.d(TAG,"check if broadcast is running");

        checkBroadcastHandler = new Handler();
        checkBroadcastRunnable = new Runnable(){    

            public void run(){
                if (running == true) {
                    Log.d(TAG,"broadcast is running");
                }
                else {
                    Log.d(TAG,"broadcast is not running");
                }
            }
        };
        checkBroadcastHandler.postDelayed(checkBroadcastRunnable,100);
        return;
    }

.............
}

广播接收器:

public class BroadCastReceiver_example extends BroadcastReceiver {


public static final int ALIVE = 1;
@Override
public void onReceive(Context context, Intent intent) {
    // TODO Auto-generated method stub
    Bundle extras = intent.getExtras();
    String action = intent.getAction();
    if (action.equals("pl.example.CHECK_RECEIVER")) {
        Log.d(TAG, "Received broadcast live checker");
        Messenger mainAppMessanger = (Messenger) extras.get("mainView");
        try {
            mainAppMessanger.send(Message.obtain(null, ALIVE));
        } catch (RemoteException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    .........

}

}

答案 9 :(得分:3)

我个人使用调用unregisterReceiver的方法,并在抛出异常时吞下它。我同意这是丑陋的,但目前提供的最佳方法。

我已经提出了一个功能请求来获取一个布尔方法来检查接收器是否已注册添加到Android API。如果你想看到它添加,请在这里支持: https://code.google.com/p/android/issues/detail?id=73718

答案 10 :(得分:2)

我遇到了你的问题,我在我的应用程序中遇到了同样的问题。我在应用程序中多次调用registerReceiver()。

解决此问题的一个简单方法是在自定义应用程序类中调用registerReceiver()。这将确保您的广播接收器在整个应用程序生命周期中仅被调用一个。

public class YourApplication extends Application
{
    @Override
    public void onCreate()
    {
        super.onCreate();

        //register your Broadcast receiver here
        IntentFilter intentFilter = new IntentFilter("MANUAL_BROADCAST_RECIEVER");
        registerReceiver(new BroadcastReciever(), intentFilter);

    }
}

答案 11 :(得分:2)

对我来说,以下工作有效:

if (receiver.isOrderedBroadcast()) {
   requireContext().unregisterReceiver(receiver);
}

答案 12 :(得分:1)

我就是这样做的,它是由ceph3us给出并由slinden77编辑的答案的修改版本(除其他外我删除了我不需要的方法的返回值):

public class MyBroadcastReceiver extends BroadcastReceiver{
    private boolean isRegistered; 

    public void register(final Context context) {
        if (!isRegistered){
            Log.d(this.toString(), " going to register this broadcast receiver");
            context.registerReceiver(this, new IntentFilter("MY_ACTION"));
            isRegistered = true;
        }
    }
    public void unregister(final Context context) {
        if (isRegistered) {            
            Log.d(this.toString(), " going to unregister this broadcast receiver");
            context.unregisterReceiver(this);
            isRegistered = false;
        }
    }
    @Override
    public void onReceive(final Context context, final Intent intent) {        
        switch (getResultCode()){
        //DO STUFF
        }        
    }        
}

然后在Activity类上:

public class MyFragmentActivity extends SingleFragmentActivity{
    MyBroadcastReceiver myBroadcastReceiver;

    @Override
    protected void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);
        registerBroacastReceiver();       
    }

    @Override
    protected Fragment createFragment(){
        return new MyFragment();
    }

    //This method is called by the fragment which is started by this activity, 
    //when the Fragment is done, we also register the receiver here (if required)
    @Override
    public void receiveDataFromFragment(MyData data) {
        registerBroacastReceiver();
        //Do some stuff                
    }

    @Override
    protected void onStop(){        
        unregisterBroacastReceiver();
        super.onStop();
    }

    void registerBroacastReceiver(){
        if (myBroadcastReceiver == null)
            myBroadcastReceiver = new MyBroadcastReceiver();
        myBroadcastReceiver.register(this.getApplicationContext());
    }

    void unregisterReceiver(){
        if (MyBroadcastReceiver != null)
            myBroadcastReceiver.unregister(this.getApplicationContext());
    }
}

答案 13 :(得分:1)

我把这段代码放在我的父活动

列出registeredReceivers = new ArrayList&lt;&gt;();

@Override
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
    registeredReceivers.add(System.identityHashCode(receiver));
    return super.registerReceiver(receiver, filter);
}

@Override
public void unregisterReceiver(BroadcastReceiver receiver) {
    if(registeredReceivers.contains(System.identityHashCode(receiver)))
    super.unregisterReceiver(receiver);
}

答案 14 :(得分:0)

这就是我做了什么来检查Broadcaster是否已经注册,即使你关闭了你的应用程序(finish())

第一次运行您的应用程序,首先发送广播它将返回true / false取决于您的广播公司是否仍在运行。

我的广播员

public class NotificationReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        if(intent.getExtras() != null && intent.getStringExtra("test") != null){
            Log.d("onReceive","test");
            return;
        }
    }
}

我的主要活动

// init Broadcaster
private NotificationReceiver nr = new NotificationReceiver();


Intent msgrcv = new Intent("Msg");
msgrcv.putExtra("test", "testing");
boolean isRegistered = LocalBroadcastManager.getInstance(this).sendBroadcast(msgrcv);

if(!isRegistered){
    Toast.makeText(this,"Starting Notification Receiver...",Toast.LENGTH_LONG).show();
    LocalBroadcastManager.getInstance(this).registerReceiver(nr,new IntentFilter("Msg"));
}

答案 15 :(得分:0)

您可以使用Dagger创建该接收者的参考。

首先提供它:

@Provides
@YourScope
fun providesReceiver(): NotificationReceiver{
    return NotificationReceiver()
}

然后将其注入到您需要的位置(使用constructor或字段injection

,然后将其传递给registerReceiver

也将其放在try/catch块中。

答案 16 :(得分:-3)

if( receiver.isOrderedBroadcast() ){
     // receiver object is registered
}
else{
     // receiver object is not registered
}

答案 17 :(得分:-7)

只需检查NullPointerException。如果接收器不存在,那么......

try{
    Intent i = new Intent();
    i.setAction("ir.sss.smsREC");
    context.sendBroadcast(i);
    Log.i("...","broadcast sent");
}
catch (NullPointerException e)
{
    e.getMessage();
}