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

Mik*_*key 236 api android broadcastreceiver android-broadcast android-broadcastreceiver

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

Dan*_*kov 296

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

try {

 //Register or UnRegister your broadcast receiver here

} catch(IllegalArgumentException e) {

    e.printStackTrace();
}
Run Code Online (Sandbox Code Playgroud)

  • 这是一个无赖...... :( (77认同)
  • 向下注意Android,因为没有为此创建API.+1为您提供工作解决方案:) (8认同)
  • 有趣的是,对于registerReceiver(mReceiver,filter1)的BroadcastReceiver调用没有捕获错误; (4认同)

Von*_*onC 63

如果你考虑这个线程,我不确定API直接提供API :

我想知道同样的事情.
在我的例子中,我有一个BroadcastReceiver实现,Context#unregisterReceiver(BroadcastReceiver)它在处理它收到的Intent之后调用 自己作为参数.
接收方的onReceive(Context, Intent)方法被调用的可能性很小,因为它注册了多个IntentFilters,从而产生了IllegalArgumentException被抛出的可能性Context#unregisterReceiver(BroadcastReceiver).

在我的情况下,我可以在调用之前存储一个私有的同步成员进行检查Context#unregisterReceiver(BroadcastReceiver),但如果API提供了一个检查方法,它会更加清晰.


cep*_*3us 32

最简单的解决方案

在接收器中:

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 :)
    ...
}
Run Code Online (Sandbox Code Playgroud)

在代码中:

MyReceiver myReceiver = new MyReceiver();
myReceiver.register(Context, IntentFilter); // register 
myReceiver.unregister(Context); // unregister 
Run Code Online (Sandbox Code Playgroud)

编辑我

- 回复

这真的不那么优雅,因为你必须记住在注册后设置isRegistered标志. - 隐形拉比

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

  • 这确实是一个优雅的解决方案.FWIW,在Android Studio中,当我尝试扩展BroadcastReceiver时,它抱怨并想要覆盖onReceive.幸运的是,在我的情况下,我需要扩展ScreenReceiver,它完全按照ceph3us描述的方式运行. (2认同)

sli*_*n77 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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 哈哈,我发现它们很方便:)更快的格式概述和东西开始和结束的地方:)我想他自己 (2认同)
  • 哦,切换到IntelliJ,一旦你习惯了它,Eclipse感觉真的很旧;)从好的方面来说,新的Android Studio只是一个带有一些附加组件的IntelliJ,所以如果你习惯了Intellij,Android Studio会让你感到宾至如归. (2认同)
  • @MartínMarconcini最后我被迫切换到IntelliJ.我非常喜欢它,但我鄙视这样一个事实:不可能同时在2个项目中工作. (2认同)

小智 22

你有几个选择

  1. 你可以在你的班级或活动中加上一面旗帜.将一个布尔变量放入您的类并查看此标志以了解您是否已注册Receiver.

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

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

    2. 实现知道接收器是否注册的方法.


Moh*_*ari 11

你必须使用try/catch:

try {
    if (receiver!=null) {
        Activity.this.unregisterReceiver(receiver);
    }
} catch (IllegalArgumentException e) {
    e.printStackTrace();
}
Run Code Online (Sandbox Code Playgroud)


Bir*_*ick 7

你可以轻松做到....

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

private boolean bolBroacastRegistred;
Run Code Online (Sandbox Code Playgroud)

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

...
bolBroacastRegistred = true;
this.registerReceiver(mReceiver, new IntentFilter(BluetoothDevice.ACTION_FOUND));
....
Run Code Online (Sandbox Code Playgroud)

3)在onPause()中做...

if (bolBroacastRegistred) {
    this.unregisterReceiver(mReceiver);
    bolBroacastRegistred = false
}
Run Code Online (Sandbox Code Playgroud)

只是它,现在,你不会在onPause()上收到更多异常错误消息.

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

成功!


elo*_*obe 5

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

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

}
Run Code Online (Sandbox Code Playgroud)