277

我需要检查我的注册接收器是否仍然注册,如果没有我如何检查它的任何方法?

4

17 回答 17

338

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

try {

 //Register or UnRegister your broadcast receiver here

} catch(IllegalArgumentException e) {

    e.printStackTrace();
}
于 2010-08-25T18:05:46.243 回答
74

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

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

在我的例子中,我可以在调用之前存储一个私有同步成员来检查Context#unregisterReceiver(BroadcastReceiver),但如果 API 提供一个检查方法会更干净。

于 2010-04-21T10:50:59.427 回答
35

最简单的解决方案

在接收器中:

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.register(Context, IntentFilter); // register 
myReceiver.unregister(Context); // unregister 

广告 1

——回复:

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

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

如果您重新启动设备或您的应用程序被操作系统杀死,这将不起作用。– 阿明 6 小时前

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

于 2015-04-24T00:21:19.650 回答
30

我正在使用这个解决方案

public class ReceiverManager {
    private WeakReference<Context> cReference;
    private static List<BroadcastReceiver> receivers = new ArrayList<BroadcastReceiver>();
    private static ReceiverManager ref;

    private ReceiverManager(Context context) {
        cReference = new WeakReference<>(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 = cReference.get().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);
            cReference.get().unregisterReceiver(receiver);
            Log.i(getClass().getSimpleName(), "unregistered receiver: " + receiver);
        }
    }
}

于 2013-04-13T07:59:45.817 回答
22

你有几个选择

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

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

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

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

于 2012-02-14T15:20:03.623 回答
12

你必须使用 try/catch:

try {
    if (receiver!=null) {
        Activity.this.unregisterReceiver(receiver);
    }
} catch (IllegalArgumentException e) {
    e.printStackTrace();
}
于 2017-03-15T23:03:56.240 回答
9

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

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

成功!

于 2014-11-16T13:56:58.297 回答
6

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

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

}
于 2013-06-06T18:28:58.220 回答
3

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

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

于 2014-07-17T13:35:41.683 回答
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();
        }
    }
    .........

}

}
于 2013-10-13T18:49:35.730 回答
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);

    }
}
于 2018-03-21T05:00:23.657 回答
1

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

列出已注册的接收者 = 新的 ArrayList<>();

@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);
}
于 2017-08-31T00:54:07.567 回答
1

对我来说,以下工作:

if (receiver.isOrderedBroadcast()) {
   requireContext().unregisterReceiver(receiver);
}
于 2020-02-07T08:44:56.127 回答
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());
    }
}
于 2016-12-18T13:49:12.713 回答
0

这是我检查广播公司是否已经注册的方法,即使你关闭了你的应用程序(finish())

首次运行您的应用程序时,首先发送一个广播,它将返回真/假,这取决于您的广播器是否仍在运行。

我的主播

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"));
}
于 2016-07-07T00:24:31.053 回答
-3
if( receiver.isOrderedBroadcast() ){
     // receiver object is registered
}
else{
     // receiver object is not registered
}
于 2017-06-01T07:52:06.207 回答
-9

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

try{
    Intent i = new Intent();
    i.setAction("ir.sss.smsREC");
    context.sendBroadcast(i);
    Log.i("...","broadcast sent");
}
catch (NullPointerException e)
{
    e.getMessage();
}
于 2014-06-25T07:38:39.723 回答