سؤال

أحتاج إلى التحقق مما إذا كان جهاز الاستقبال المسجل لا يزال مسجلًا إن لم يكن كيف يمكنني التحقق من أي طرق؟

هل كانت مفيدة؟

المحلول

لست متأكدًا من أن واجهة برمجة التطبيقات توفر واجهة برمجة تطبيقات مباشرة ، إذا كنت تفكر هذا الموضوع:

كنت أتساءل نفس الشيء.
في حالتي لدي BroadcastReceiver التنفيذ الذي يدعو Context#unregisterReceiver(BroadcastReceiver) تمرير نفسها كحجة بعد التعامل مع النية التي يتلقاها.
هناك فرصة صغيرة أن يكون المتلقي onReceive(Context, Intent) تسمى الطريقة أكثر من مرة ، لأنها مسجلة بالعديد IntentFilters, ، خلق احتمال IllegalArgumentException يتم إلقاؤها من Context#unregisterReceiver(BroadcastReceiver).

في حالتي ، يمكنني تخزين عضو خاص متزامن للتحقق منه قبل الاتصال Context#unregisterReceiver(BroadcastReceiver), ، ولكن سيكون أكثر نظافة إذا وفرت واجهة برمجة التطبيقات طريقة فحص.

نصائح أخرى

لا توجد وظيفة API للتحقق مما إذا كان جهاز الاستقبال مسجلاً. الحل البديل هو وضع الكود الخاص بك في try catch block as done below.

try {

 //Register or UnRegister your broadcast receiver here

} catch(IllegalArgumentException e) {

    e.printStackTrace();
}

أبسط حل

في المتلقي:

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

-- ردا على:

هذا ليس بالأنيق حقًا لأنك يجب أن تتذكر أن تقوم بتعيين العلم المتساوي بعد التسجيل. - حاخام خلسة

- أضافت طريقة "More Ellegant Way" في جهاز الاستقبال للتسجيل وتعيين العلم

لن يعمل هذا إذا قمت بإعادة تشغيل الجهاز أو إذا تم قتل تطبيقك بواسطة نظام التشغيل. - أمين منذ 6 ساعات

amin - راجع عمر في الكود (وليس النظام المسجل عن طريق إدخال البيان) جهاز الاستقبال المسجل :)

أنا أستخدم هذا الحل

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

لديك العديد من الخيارات

  1. يمكنك وضع العلم في الفصل أو نشاطك. ضع متغيرًا منطقيًا في فصلك وانظر إلى هذه العلامة لمعرفة ما إذا كان لديك جهاز الاستقبال مسجل.

  2. قم بإنشاء فصل يمتد جهاز الاستقبال ويمكنك استخدامه:

    1. نمط Singleton للحصول على مثيل واحد فقط من هذه الفئة في مشروعك.

    2. تنفيذ طرق معرفة ما إذا كان المتلقي هو التسجيل.

عليك استخدام Try/Catch:

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

يمكنك أن تفعل ذلك بسهولة ....

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 على خطأ عند تشغيل unregisterReceive ()

النجاح!

إذا وضعت هذا على طريقة OnDestroy أو Onstop. أعتقد أنه عندما يتم إنشاء النشاط مرة أخرى ، لم يتم إنشاء Messagereciver.

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

}

لقد استخدمت نية لإعلام جهاز استقبال البث حول مثيل معالج مؤشر ترابط النشاط الرئيسي واستخدمته لتمرير رسالة إلى النشاط الرئيسي

لقد استخدمت هذه الآلية للتحقق مما إذا كان جهاز استقبال البث مسجلاً بالفعل أم لا. في بعض الأحيان تكون هناك حاجة عند تسجيل مستقبل البث بشكل ديناميكي ولا ترغب في جعله مرتين أو يمكنك تقديمه للمستخدم إذا كان جهاز استقبال البث قيد التشغيل.

النشاط الرئيسي:

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 وابتلاع الاستثناء إذا تم إلقاؤه. أوافق على أن هذا قبيح ولكن أفضل طريقة مقدمة حاليًا.

لقد قمت برفع طلب ميزة للحصول على طريقة منطقية للتحقق مما إذا كان جهاز الاستقبال قد تم إضافته إلى Android API. يرجى دعمه هنا إذا كنت تريد رؤيته إضافة:https://code.google.com/p/android/issues/detail؟id=73718

أحصل على مشكلتك ، واجهت نفس المشكلة في طلبي. كنت أتصل بـ 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);

    }
}

هذه هي الطريقة التي قمت بها ، إنها نسخة معدلة من الإجابة التي قدمها 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());
    }
}

لقد وضعت هذا الرمز في نشاط الأم

قائمة 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 ())

Firstime تشغيل طلبك ، أرسل بثًا أولاً ، سيعود 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;
        }
    }
}

بلدي الرئيسي

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

يمكنك استخدام خنجر لإنشاء مرجع لهذا المتلقي.

أولا توفيره:

@Provides
@YourScope
fun providesReceiver(): NotificationReceiver{
    return NotificationReceiver()
}

ثم حقنه حيث تحتاج (باستخدام constructor أو الحقل injection)

وببساطة تمريرها إلى registerReceiver.

أيضا وضعه في try/catch كتلة أيضا.

if( receiver.isOrderedBroadcast() ){
     // receiver object is registered
}
else{
     // receiver object is not registered
}

فقط تحقق من nullpointerxception. إذا لم يكن جهاز الاستقبال موجودًا ، فعندئذ ...

try{
    Intent i = new Intent();
    i.setAction("ir.sss.smsREC");
    context.sendBroadcast(i);
    Log.i("...","broadcast sent");
}
catch (NullPointerException e)
{
    e.getMessage();
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top