Как проверить, зарегистрирован ли Receiver в Android?

193

Мне нужно проверить, зарегистрирован ли зарегистрированный ресивер, если нет, как проверить его какие-либо методы?

Теги:
broadcastreceiver
android-broadcastreceiver
android-broadcast

15 ответов

50
Лучший ответ

Я не уверен, что API напрямую предоставляет API, если вы считаете этот поток:

Мне было интересно то же самое.
В моем случае у меня есть реализация BroadcastReceiver, которая вызывает Context#unregisterReceiver(BroadcastReceiver) передается как arg после обработки намерения, которое оно получает.
Существует небольшая вероятность того, что метод получателя onReceive(Context, Intent)несколько раз, так как он зарегистрирован с несколькими IntentFilters, создавая потенциал для IllegalArgumentException, который вызывается из Context#unregisterReceiver(BroadcastReceiver).

В моем случае я могу сохранить приватный синхронизированный элемент для проверки перед вызовом Context#unregisterReceiver(BroadcastReceiver), но это будет гораздо чище, если API предоставил метод проверки.

238

Нет функции API, чтобы проверить, зарегистрирован ли приемник. Обходной путь состоит в том, чтобы поместить ваш код в блок try {...} catch(IllegalArgumentException e) {...}.

  • 73
    это облом ... :(
  • 3
    Забавно, что не ловит ошибку для этого вызова BroadcastReceiver для registerReceiver (mReceiver, filter1);
Показать ещё 7 комментариев
24

Я использую это решение

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);
        }
    }
}
  • 2
    ха-ха, я нахожу их удобными :) Более быстрый обзор формата и того, где все начинается и заканчивается :) Я думаю, что каждый свой.
  • 1
    Я думаю, что я привык к IntelliJ;)
Показать ещё 7 комментариев
22

У вас есть несколько вариантов

  • Вы можете поместить флаг в свой класс или активность. Поместите логическую переменную в ваш класс и посмотрите на этот флаг, чтобы узнать, зарегистрирован ли ваш ресивер.

  • Создайте класс, который расширяет приемник и там вы можете использовать:

    • Шаблон Singleton имеет только один экземпляр этого класса в вашем проекте.

    • Внедрить методы, чтобы знать, зарегистрирован ли приемник.

  • 1
    Я сделал то же самое, но мой получатель - AppWidgetProvider, и я хочу получать сообщения SCREEN_ON_OFF - но onDisabled (), когда я отменяю регистрацию Receiver (this); - это исключение.
  • 0
    объединенный первый и второй вариант, флаг в классе приемника, работает отлично
Показать ещё 1 комментарий
18

простейшее решение

в приемнике:

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 

изменить I

- в ответ на

Это действительно не так элегантно, потому что вы должны помнить, что isRegistered flag после регистрации. - Стелс Рабби

- "более ellegant way" добавил метод в приемнике для регистрации и установки флага

  • 2
    Это действительно элегантное решение. FWIW, в Android Studio, когда я пытаюсь расширить BroadcastReceiver, он жалуется и хочет переопределить onReceive. К счастью, в моем случае мне понадобилось расширить ScreenReceiver, который работает именно так, как описано здесь ceph3us.
  • 0
    Это действительно не так уж и элегантно, потому что вы должны помнить, чтобы установить флаг isRegistered после регистрации.
Показать ещё 3 комментария
5

Если вы положите это на метод onDestroy или onStop. Я думаю, что когда действие было создано снова, MessageReciver не создавался.

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

}
4

Вам нужно использовать try/catch:

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

Вы можете сделать это легко....

1) создать логическую переменную...

private boolean bolBroacastRegistred;

2) Когда вы регистрируете свой широковещательный приемник, установите для него значение ИСТИНА

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

3) В onPause() сделайте это...

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

Только это, и теперь вы не получите больше сообщений об ошибке исключения на onPause().

Tip1: Всегда используйте unregisterReceiver() в onPause() не в onDestroy() Tip2: Не забудьте установить переменную bolBroadcastRegistred в FALSE при запуске unregisterReceive()

Успех!

3

Я использовал Intent, чтобы позволить Broadcast Receiver узнать о экземпляре Handler основного потока Activity и использовать 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();
        }
    }
    .........

}

}
1

Лично я использую метод вызова unregisterReceiver и проглатывает исключение, если оно было выбрано. Я согласен, что это уродливый, но лучший способ, который в настоящее время предоставляется.

Я поднял запрос функции, чтобы получить логический метод, чтобы проверить, добавлен ли ресивер в API Android. Пожалуйста, поддержите его здесь, если хотите добавить его: https://code.google.com/p/android/issues/detail?id=73718

0

Я помещаю этот код в свою родительскую активность

Список зарегистрированныхReceivers = новый 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);
}
0
if( receiver.isOrderedBroadcast() ){
     // receiver object is registered
}
else{
     // receiver object is not registered
}
  • 1
    Заказанная трансляция это совсем другое дело, посмотрите на эту ссылку
0

Вот как я это сделал, это модифицированная версия ответа, данного 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());
    }
}
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;
        }
    }
}

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

Просто проверьте исключение NullPointerException. Если приемник не существует, то...

try{
    Intent i = new Intent();
    i.setAction("ir.sss.smsREC");
    context.sendBroadcast(i);
    Log.i("...","broadcast sent");
}
catch (NullPointerException e)
{
    e.getMessage();
}
  • 1
    Как / где это бросает NPE?
  • 0
    На самом деле он не выдает никаких ошибок, когда это не удается. К сожалению.
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню