Как проверить, если приемник зарегистрирован в Android?
Мне нужно проверить, зарегистрирован ли мой зарегистрированный приемник, если нет, как я могу проверить его любыми методами?
16 ответов:
Я не уверен, что API предоставляет непосредственно API, если вы считаете этой теме:
мне было интересно то же самое.
В моем случае у меня естьBroadcastReceiver
реализации, что вызываетContext#unregisterReceiver(BroadcastReceiver)
передача себя в качестве arg после обработки намерения, которое он получает.
Существует небольшой шанс, что приемникonReceive(Context, Intent)
метод называется более одного раза, так как он зарегистрирован с несколькимиIntentFilters
, создавая потенциал дляIllegalArgumentException
быть выброшенным изContext#unregisterReceiver(BroadcastReceiver)
.в моем случае я могу хранить частный синхронизированный член для проверки перед вызовом
Context#unregisterReceiver(BroadcastReceiver)
, но это будет гораздо чище, если API предоставил метод проверки.
нет функции API, чтобы проверить, зарегистрирован ли приемник. Обходной путь заключается в том, чтобы поместить ваш код в
try {...} catch(IllegalArgumentException e) {...}
заблокировать.
простое решение
в приемник:
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
edit I
-- в ответ
это действительно не так элегантно, потому что вы должны помнить, чтобы установить флаг зарегистрирован после регистрации. - Стелс Рабби
-- "более элегантный способ" добавлен метод в приемник, чтобы зарегистрировать и установить флаг
Я использую это решение
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); } } }
У вас есть несколько вариантов
вы можете поместить флаг в свой класс или деятельность. Поместите логическую переменную в свой класс и посмотрите на этот флаг, чтобы узнать, зарегистрирован ли получатель.
создать класс, который расширяет приемник и там вы можете использовать:
одноэлементный шаблон только для одного экземпляра этого класса в вашем проекте.
реализовать методы для знать, если приемник-регистр.
вы должны использовать try / catch:
try { if (receiver!=null) { Activity.this.unregisterReceiver(receiver); } } catch (IllegalArgumentException e) { e.printStackTrace(); }
Если вы ставите это на onDestroy или onStop метод. Я думаю, что когда активность была создана снова MessageReciver не был создан.
@Override public void onDestroy (){ super.onDestroy(); LocalBroadcastManager.getInstance(context).unregisterReceiver(mMessageReceiver); }
вы можете сделать это легко....
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().
Tip1: всегда используйте unregisterReceiver() в onPause () не в onDestroy() Tip2: не забудьте установить переменную bolBroadcastRegistred в FALSE при запуске unregisterReceive ()
успехов!
я использовал намерение, чтобы широковещательный приемник знал об экземпляре обработчика основного потока активности и использовал сообщение для передачи сообщения в основную активность
я использовал такой механизм, чтобы проверить, если широковещательный приемник уже зарегистрирован или нет. Иногда это необходимо, когда вы регистрируете свой широковещательный приемник динамически и не хотите делать это дважды или вы представляете Пользователю, если широковещательный приемник работает.
основная деятельность:
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(); } } ......... } }
лично я использую метод вызова unregisterReceiver и проглатывания исключения, если оно брошено. Я согласен, что это некрасиво, но лучший метод в настоящее время предоставляется.
Я поднял запрос функции, чтобы получить логический метод, чтобы проверить, зарегистрирован ли приемник, добавленный в API Android. Пожалуйста, поддержите его здесь, Если вы хотите, чтобы он был добавлен: https://code.google.com/p/android/issues/detail?id=73718
Я положил этот код в моей родительской деятельности
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); }
вот что я сделал, чтобы проверить, если вещатель уже зарегистрирован, даже если вы закрываете приложение (finish ())
Firsttime запуск приложения, отправить трансляцию сначала он будет возвращать 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; } } }
Мой Класс 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")); }
вот как я это сделал, это модифицированная версия ответа, данного 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 } } }
затем в классе активности:
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()); } }
Я понимаю вашу проблему, я столкнулся с той же проблемой в моем приложении. Я вызывал 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); } }