it-swarm.com.de

Wie überprüfe ich, ob Receiver in Android registriert ist?

Ich muss prüfen, ob mein registrierter Empfänger noch registriert ist.

222
Mikey

Ich bin nicht sicher, ob die API direkt eine API bietet, wenn Sie diesen Thread betrachten:

Ich wunderte mich dasselbe.
In meinem Fall habe ich eine BroadcastReceiver-Implementierung, die .__ aufruft. Context#unregisterReceiver(BroadcastReceiver) übergibt sich selbst als Argument, nachdem er die empfangene Absicht behandelt hat.
Es besteht eine geringe Chance, dass die onReceive(Context, Intent)-Methode des Empfängers .__ heißt. mehr als einmal, da es mit mehreren IntentFilters registriert ist, wodurch das Potenzial besteht, dass eine IllegalArgumentException von Context#unregisterReceiver(BroadcastReceiver) geworfen wird.

In meinem Fall kann ich ein privates synchronisiertes Mitglied speichern, um es vor dem Aufruf von Context#unregisterReceiver(BroadcastReceiver) zu überprüfen, aber es wäre viel sauberer, wenn die API eine Prüfmethode bereitstellt. 

62
VonC

Es gibt keine API-Funktion, um zu überprüfen, ob ein Empfänger registriert ist. Die Problemumgehung besteht darin, Ihren Code in einen try catch block as done below. einzugeben.

try {

 //Register or UnRegister your broadcast receiver here

} catch(IllegalArgumentException e) {

    e.printStackTrace();
}
280
Daniel Velkov

einfachste Lösung

im Empfänger:

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 :)
    ...
}

in Code:

MyReceiver myReceiver = new MyReceiver();
myReceiver.registerReceiver(Conext, IntentFilter); // register 
myReceiver.unregister(Context); // unregister 

editiere ich

-- als Antwort auf 

Das ist wirklich nicht so elegant, weil Sie daran denken müssen, das .__ einzustellen. isRegistered-Flag nach der Registrierung. - Stealth Rabbi

- "elleganter Weg" hinzugefügt Methode im Empfänger zum Registrieren und Setzen der Flagge 

29
ceph3us

Ich verwende diese Lösung

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

Sie haben mehrere Möglichkeiten

  1. Sie können eine Markierung in Ihre Klasse oder Aktivität setzen. Fügen Sie eine boolesche Variable in Ihre Klasse ein und prüfen Sie, ob Sie den Empfänger registriert haben.

  2. Erstellen Sie eine Klasse, die den Empfänger erweitert. Dort können Sie Folgendes verwenden:

    1. Singleton-Muster für nur eine Instanz dieser Klasse in Ihrem Projekt.

    2. Implementieren Sie die Methoden, um zu wissen, ob der Empfänger registriert ist.

22
chemalarrea

Sie müssen try/catch verwenden:

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

Sie können es einfach machen ....

1) Eine boolesche Variable erstellen ...

private boolean bolBroacastRegistred;

2) Wenn Sie Ihren Broadcast-Receiver registrieren, setzen Sie ihn auf TRUE

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

3) In der onPause () mach es ...

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

Es ist nur so, und jetzt werden Sie keine weitere Ausnahmefehlermeldung bei onPause () erhalten.

Tipp1: Verwenden Sie unregisterReceiver () immer in onPause () und nicht in onDestroy () Tipp2: Vergessen Sie nicht, die Variable bolBroadcastRegistred auf FALSE zu setzen, wenn Sie unregisterReceive () ausführen.

Erfolg!

7
Biruel Rick

Wenn Sie dies auf die Methode onDestroy oder onStop setzen. Ich denke, wenn der Vorgang erneut erstellt wurde, wurde der MessageReciver nicht erstellt.

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

}
5
eloirobe

Ich habe Intent verwendet, um Broadcast Receiver über die Handler-Instanz des Hauptaktivitätsthreads zu informieren, und Message, um eine Nachricht an die Hauptaktivität zu übergeben

Ich habe einen solchen Mechanismus verwendet, um zu überprüfen, ob der Broadcast Receiver bereits registriert ist oder nicht. Dies ist manchmal erforderlich, wenn Sie Ihren Broadcast Receiver dynamisch registrieren und ihn nicht zweimal machen möchten oder wenn Sie dem Benutzer mitteilen, ob Broadcast Receiver ausgeführt wird.

Hauptaktivität:

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

.............
}

Rundfunkempfänger:

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
jarek

Ich habe Ihr Problem, ich hatte das gleiche Problem in meiner Bewerbung. Ich habe registerReceiver () mehrfach in der Anwendung aufgerufen. 

Eine einfache Lösung für dieses Problem ist das Aufrufen von registerReceiver () in Ihrer benutzerdefinierten Anwendungsklasse. Dadurch wird sichergestellt, dass Ihr Broadcast-Empfänger in Ihrem gesamten Anwendungslebenszyklus nur einen einzigen Anruf erhält.

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

    }
}
2
Sameer Ranjan

Ich persönlich benutze die Methode, um unregisterReceiver aufzurufen und die Ausnahme zu schlucken, wenn sie ausgelöst wird. Ich stimme zu, dass dies hässlich ist, aber die derzeit beste Methode.

Ich habe eine Funktionsanforderung ausgelöst, um eine boolesche Methode zu erhalten, um zu überprüfen, ob ein Empfänger registriert ist, der zur Android-API hinzugefügt wurde. Bitte unterstützen Sie es hier, wenn Sie möchten, dass es hinzugefügt wird: https://code.google.com/p/Android/issues/detail?id=73718

2
ojf

ich habe diesen Code in meine übergeordnete Aktivität aufgenommen

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

Sie können Dagger verwenden, um eine Referenz dieses Empfängers zu erstellen.

Zuerst geben Sie es an:

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

Dann injizieren Sie es an der gewünschten Stelle (mit constructor oder Feld injection)

und übergeben Sie es einfach an registerReceiver.

Legen Sie es auch in try/catch block.

0
Mahdi-Malv

So habe ich es gemacht, es ist eine modifizierte Version der Antwort, die von ceph3us gegeben und von slinden77 bearbeitet wurde (unter anderem habe ich Rückgabewerte von Methoden entfernt, die ich nicht brauchte):

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

Dann zu einer Aktivitätsklasse:

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
Víctor Gil

So habe ich überprüft, ob der Broadcaster bereits registriert ist, auch wenn Sie Ihre Anwendung schließen (finish ())

Wenn Sie Ihre Anwendung zum ersten Mal ausführen, senden Sie zuerst eine Rundsendung. Sie gibt true/false zurück, je nachdem, ob Ihr Sender noch läuft.

Mein Sender

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

Meine Hauptaktivität

// 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
user6558470