如何检查接收者是否在Android中注册?

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

155237 次浏览

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

我也在想同样的事情 在我的例子中,我有一个BroadcastReceiver实现调用 Context#unregisterReceiver(BroadcastReceiver)在处理接收到的Intent后将自身作为参数传递 有很小的机会调用接收器的onReceive(Context, Intent)方法 由于它被多个IntentFilters注册,因此有可能从Context#unregisterReceiver(BroadcastReceiver)抛出IllegalArgumentException 在我的例子中,我可以在调用Context#unregisterReceiver(BroadcastReceiver)之前存储一个私有同步成员来检查,但它将是 如果API提供了一个检查方法,就会干净得多。< / p >

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

try {


//Register or UnRegister your broadcast receiver here


} catch(IllegalArgumentException e) {


e.printStackTrace();
}

你有几个选择

  1. 你可以在你的班级或活动中放置一个标志。在类中放入一个布尔变量,并查看这个标志,以了解是否注册了Receiver。

  2. 创建一个扩展Receiver的类,在那里你可以使用:

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

    2. 实现了解Receiver是否为寄存器的方法。

    3. 李< / ol > < / >

我用的是这个解

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

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

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


}

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

我已经使用这样的机制来检查广播接收器是否已经注册。有时需要动态注册Broadcast Receiver,并且不想让它重复,或者如果Broadcast Receiver正在运行,则需要向用户显示。

主要活动:

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


}


}

检查NullPointerException。如果接收者不存在,那么…

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

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

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

你可以做得很容易....

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:总是使用unregisterReceiver()在onPause()不是在onDestroy() 提示2:不要忘记在运行unregisterReceive()

时设置bolbroadcastregistered变量为FALSE

成功!

简单的解决方案

接收方:

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标志后,您注册。-隐身拉比

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

如果你重新启动设备或如果你的应用程序被杀死,这将不起作用 操作系统。- amin 6 hours ago

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

下面是我检查广播器是否已经注册,即使您关闭应用程序(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;
}
}
}

我MainActivity

// 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"));
}

这是我怎么做的,这是cep3us给出的答案的修改版本,并由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());
}
}

你必须使用try/catch:

try {
if (receiver!=null) {
Activity.this.unregisterReceiver(receiver);
}
} catch (IllegalArgumentException e) {
e.printStackTrace();
}
if( receiver.isOrderedBroadcast() ){
// receiver object is registered
}
else{
// receiver object is not registered
}

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

List registeredReceivers = new 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);
}

我明白你的问题,我在我的申请中也遇到过同样的问题。我在应用程序中多次调用registerReceiver()。

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

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


}
}

对我来说,以下方法是有效的:

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