अगर एंड्रॉइड में रिसीवर पंजीकृत है तो कैसे जांचें?


254

मुझे यह जाँचने की आवश्यकता है कि क्या मेरा पंजीकृत रिसीवर अभी भी पंजीकृत है यदि नहीं तो मैं इसे किसी भी तरीके की जाँच कैसे करूँ?


जवाबों:


68

मुझे यकीन नहीं है कि यदि आप इस धागे पर विचार करते हैं तो एपीआई सीधे एपीआई प्रदान करता है :

मैं उसी चीज़ पर हैरान हो रहा था।
मेरे मामले में मेरे पास एक BroadcastReceiverकार्यान्वयन है Context#unregisterReceiver(BroadcastReceiver)जो इसे प्राप्त करने वाले इरादे को संभालने के बाद तर्क के रूप में स्वयं को पारित करता है।
एक छोटा सा मौका है कि रिसीवर की onReceive(Context, Intent)विधि को एक से अधिक बार कहा जाता है, क्योंकि यह कई के साथ पंजीकृत है IntentFilters, जिससे IllegalArgumentExceptionफेंके जाने की संभावना पैदा होती है Context#unregisterReceiver(BroadcastReceiver)

मेरे मामले में, मैं कॉल करने से पहले जांच करने के लिए एक निजी सिंक्रनाइज़ सदस्य को स्टोर कर सकता हूं Context#unregisterReceiver(BroadcastReceiver), लेकिन अगर एपीआई एक चेक विधि प्रदान करता है तो यह बहुत साफ होगा।


313

यदि कोई रिसीवर पंजीकृत है, तो यह जांचने के लिए कोई एपीआई फ़ंक्शन नहीं है। वर्कअराउंड में अपना कोड डालना हैtry catch block as done below.

try {

 //Register or UnRegister your broadcast receiver here

} catch(IllegalArgumentException e) {

    e.printStackTrace();
}

83
यह एक
दमदार है

4
मजेदार बात यह है कि इस कॉल के लिए ErrorReceiver को रजिस्टरराइवर (MReceiver, filter1) के लिए त्रुटि न पकड़ें;
जेपीएम

1
@JPM हाँ यह है। मैं अपने रिसीवर के एक उदाहरण को संग्रहीत करने जा रहा था और इसे अनरजिस्टर्ड करने के लिए जांच करता हूं यदि यह नहीं है null। लेकिन जैसा कि आपने बताया, मैं जा रहा हूं try catch। हास्यास्पद।

9
उस के लिए एक एपीआई नहीं बनाने के लिए Android के लिए डाउनवोट। +1 आपको एक कार्यशील समाधान प्रदान करने के लिए :)
Denys Vitali

1
बेहतर क्या है? एक ध्वज के रूप में इसका उपयोग करना या बूलियन चर का उपयोग करना?
DAVIDBALAS1

34

सबसे सरल उपाय

रिसीवर में:

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 

विज्ञापन १

-- प्रतिउत्तर में:

यह वास्तव में इतना सुरुचिपूर्ण नहीं है क्योंकि आपको पंजीकरण के बाद isRegistered ध्वज सेट करना याद रखना होगा। - चुपके रब्बी

- झंडे को पंजीकृत करने और सेट करने के लिए रिसीवर में एक और तरीका "जोड़ा गया तरीका"

यह काम नहीं करेगा यदि आप डिवाइस को पुनरारंभ करते हैं या यदि आपका ऐप ओएस द्वारा मारा गया है। - 6 घंटे पहले

@amin - कोड में जीवनकाल देखें (न कि सिस्टम, जो कि उपस्थिति प्रविष्टि द्वारा पंजीकृत है) पंजीकृत रिसीवर :)


2
यह वास्तव में एक सुरुचिपूर्ण समाधान है। एफडब्ल्यूआईडब्ल्यू, एंड्रॉइड स्टूडियो में, जब मैं ब्रॉडकास्टसीवर को विस्तारित करने की कोशिश करता हूं, तो यह शिकायत करता है और ऑनरसेक्टिव का ओवरराइड चाहता है। सौभाग्य से, मेरे मामले में, मुझे ScreenReceiver का विस्तार करने की आवश्यकता थी, जो कि यहाँ ceph3us का वर्णन करता है।
मार्कजेल 60

यह वास्तव में इतना सुरुचिपूर्ण नहीं है क्योंकि आपको पंजीकरण के बाद isRegistered ध्वज को सेट करना याद रखना होगा।
चुपके रब्बी

हां, हालाँकि आप इस लाइन को अपने "कोड इन" सेक्शन से हटा सकते हैं। myReceiver.isRegistered = true;
चुपके रब्बी

क्या यह अमूर्त वर्ग नहीं होना चाहिए? ब्रॉडकास्टिंग ब्रॉडसीवर को आपको ऑनरेक्टिव विधि को लागू करने की आवश्यकता है।
यॉर्क यांग

@YorkYang ने कक्षा में जानकारी को नीचे जोड़ा
ceph3us

27

मैं इस समाधान का उपयोग कर रहा हूं

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
हाहा, मैं उन्हें सुविधाजनक लगता हूं :) प्रारूप पर त्वरित अवलोकन और जहां सामान शुरू होता है और समाप्त होता है :) प्रत्येक अपने स्वयं के अनुमान पर
slinden77

1
mmm, आपकी टिप्पणी के अनुसार, अच्छी लग रही है! बेशक यह मेरे ग्रहण कार्यक्षेत्र को खराब कर देता है, लेकिन इसके लिए बहुत ज्यादा जरूरत नहीं है :)
slinden77

2
ओह, IntelliJ पर स्विच करें, एक बार जब आपको इसकी आदत हो जाती है, तो ग्रहण वास्तव में पुराना लगता है;) दूसरी तरफ, नया एंड्रॉइड स्टूडियो सिर्फ कुछ ऐड-ऑन के साथ एक इंटेलीज है, इसलिए यदि आप इंटेलीज, एंड्रॉइड स्टूडियो का उपयोग करेंगे। आप घर पर सही महसूस करते हैं।
मार्टिन मार्कोसिनी

2
@ MartínMarconcini अंत में मुझे IntelliJ पर स्विच करने के लिए मजबूर किया गया। मुझे यह बहुत पसंद है, लेकिन मैं इस तथ्य को तुच्छ समझता हूं कि 2 परियोजनाओं में एक साथ काम करना असंभव है।
slinden77

1
अंधेरे पक्ष में आपका स्वागत है;) मेरे पास अभी तीन अलग-अलग परियोजनाओं के साथ तीन एंड्रॉइड स्टूडियो खुले हैं ... निश्चित नहीं कि आपकी कई-परियोजना समस्या क्या है, लेकिन मैं आपको आश्वस्त कर सकता हूं कि यह कई परियोजनाओं के साथ काम करता है। :)
मार्टिन मार्कोसिनी

22

आपके पास कई विकल्प हैं

  1. आप अपनी कक्षा या गतिविधि में एक झंडा लगा सकते हैं। अपनी कक्षा में एक बूलियन चर डालें और इस झंडे को देखें ताकि यह पता चल सके कि आपके पास प्राप्तकर्ता पंजीकृत है या नहीं।

  2. एक वर्ग बनाएं जो रिसीवर को बढ़ाता है और वहां आप उपयोग कर सकते हैं:

    1. आपकी परियोजना में इस वर्ग का केवल एक उदाहरण के लिए सिंगलटन पैटर्न है।

    2. यदि प्राप्तकर्ता पंजीकृत है, तो यह जानने के लिए तरीकों को लागू करें।


1
मैंने भी ऐसा ही किया है, लेकिन मेरा रिसीवर AppWidgetProvider है और मैं SCREEN_ON_OFF संदेश प्राप्त करना चाहता हूं - लेकिन जब मैं अपंजीकृत (यह) करता हूं, तो ऑनडिसिबल (); - यह अपवाद फेंकता है।
hB0

संयुक्त प्रथम और द्वितीय विकल्प, रिसीवर वर्ग में एक ध्वज, बहुत काम करता है
गेबुरिडर

क्या आप मुझे एक कोड उदाहरण दे सकते हैं जैसे कि वास्तव में उर क्या नहीं कर रहा है ... क्या इससे बड़ी मदद मिलेगी @ chemalarrea
तपनह


7

आप इसे आसान कर सकते हैं ...।

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
}

बस यह, और अब, आपको ऑनपॉज़ () पर अधिक अपवाद त्रुटि संदेश नहीं मिलेगा।

टिप 1: हमेशा ऑनग्रेज़र () ऑनपॉज़ में उपयोग न करें

सफलता!


6

यदि आप इसे onDestroy या onStop विधि पर रखते हैं। मुझे लगता है कि जब गतिविधि फिर से बनाई गई है MessageReciver नहीं बनाया जा रहा था।

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

}

3

मैंने प्रसारण प्राप्तकर्ता को मुख्य गतिविधि थ्रेड के हैंडलर उदाहरण के बारे में बताने के लिए आशय का उपयोग किया और संदेश का उपयोग मुख्य गतिविधि को संदेश देने के लिए किया

मैंने इस तरह के तंत्र का उपयोग यह जांचने के लिए किया है कि ब्रॉडकास्ट रिसीवर पहले से पंजीकृत है या नहीं। कभी-कभी इसकी आवश्यकता तब होती है जब आप अपने प्रसारण रिसीवर को गतिशील रूप से पंजीकृत करते हैं और दो बार या आप उपयोगकर्ता को प्रस्तुत करना नहीं चाहते हैं यदि प्रसारण रिसीवर चल रहा है।

मुख्य गतिविधि:

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

}

}

3

व्यक्तिगत रूप से मैं unregisterReceiver को कॉल करने और अपवाद को निगलने की विधि का उपयोग करता हूं यदि इसे फेंक दिया जाता है। मैं मानता हूं कि यह बदसूरत है लेकिन वर्तमान में प्रदान की गई सबसे अच्छी विधि है।

मैंने यह देखने के लिए बूलियन पद्धति प्राप्त करने के लिए एक सुविधा अनुरोध उठाया है कि क्या कोई रिसीवर एंड्रॉइड एपीआई में जोड़ा गया है। अगर आप इसे जोड़ना चाहते हैं तो कृपया इसे यहाँ सपोर्ट करें: https://code.google.com/p/android/issues/detail?id=71818


2

मुझे आपकी समस्या है, मैंने अपने आवेदन में उसी समस्या का सामना किया। मैं आवेदन के भीतर कई बार 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);

    }
}

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

फिर एक गतिविधि वर्ग पर:

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

1

मैंने इस कोड को अपनी मूल गतिविधि में डाल दिया है

सूचीबध्द सूची = नया एरियर सूची <> ();

@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

यहां मैंने यह जांचने के लिए किया था कि क्या ब्रॉडकास्टर पहले से पंजीकृत है, भले ही आप आवेदन बंद कर दें (खत्म करें)

फ़र्स्टटाइम आपके एप्लिकेशन को चलाने वाला, पहले प्रसारण भेजें, यह सही / गलत होगा, यह इस बात पर निर्भर करता है कि आपका ब्रॉडकास्टर अभी भी चल रहा है या नहीं।

माय ब्रॉडकास्टर

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

0

आप उस रिसीवर का संदर्भ बनाने के लिए डैगर का उपयोग कर सकते हैं ।

पहले इसे प्रदान करें:

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

फिर उसे इंजेक्ट करें जहाँ आपको ज़रूरत हो (उपयोग constructorया फ़ील्ड injection)

और बस इसे पास करें registerReceiver

इसे try/catchब्लॉक में भी रखें।



-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
कैसे / जहां यह एक एनपीई फेंक देता है?
डस्टबिन

यह वास्तव में असफल होने पर कोई त्रुटि नहीं करता है। अफसोस की बात है।
१४:१४ बजे domenukk

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.