Domanda

ho bisogno di controllare se il mio ricevitore registrato è ancora registrato se non Come faccio a verificare che tutti i metodi?

È stato utile?

Soluzione

Non sono sicuro l'API fornisce direttamente un'API, se si considera questa discussione :

  

Mi chiedevo la stessa cosa.
  Nel mio caso ho un implementazione BroadcastReceiver che le chiamate   Context#unregisterReceiver(BroadcastReceiver) sé passando come argomento dopo aver toccato l'intento che riceve.
  C'è una piccola possibilità che il metodo onReceive(Context, Intent) del ricevitore si chiama   più di una volta, dal momento che è registrato con IntentFilters multipla, creando il potenziale per una IllegalArgumentException essere stato gettato da Context#unregisterReceiver(BroadcastReceiver).

     

Nel mio caso, posso memorizzare un membro privato sincronizzato a controllo prima di chiamare Context#unregisterReceiver(BroadcastReceiver), ma sarebbe   molto più pulito se l'API fornito un metodo di controllo.

Altri suggerimenti

Non v'è alcuna funzione API per verificare se un ricevitore è registrato. La soluzione è quello di mettere il codice in un try catch block as done below.

try {

 //Register or UnRegister your broadcast receiver here

} catch(IllegalArgumentException e) {

    e.printStackTrace();
}

soluzione più semplice

ricevitore:

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

nel codice:

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

ad 1

- in risposta a:

  

questo non è davvero che elegante perché si deve ricordarsi di impostare la   isRegistered bandiera dopo la registrazione. - Stealth Rabbi

- "modo più ellegant", ha aggiunto il metodo ricevitore per registrare e set bandiera

  

questo non funzionerà se si riavvia il dispositivo o se la vostra applicazione è stato ucciso da   OS. - Amin 6 ore fa

@amin - vedi vita di nel codice (non sistema registrato da ingresso manifesto) Ricevitore registrati:)

io sto usando questa soluzione

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

Sono disponibili diverse opzioni

  1. Si può mettere una bandiera nella tua classe o attività. Mettere una variabile booleana nella tua classe e dare un'occhiata a questo flag per sapere se avete il ricevitore registrata.

  2. Creare una classe che estende il ricevitore e non è possibile utilizzare:

    1. Singleton modello per avere una sola istanza di questa classe nel progetto.

    2. implementare i metodi per sapere se il ricevitore è il registro.

Devi usare try / catch:

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

Si può fare facile ....

1) creare una variabile booleana ...

private boolean bolBroacastRegistred;

2) Quando si registra il ricevitore broadcast, impostarlo su TRUE

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

3) Nella onPause () lo fanno ...

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

Basta, e ora, non riceveranno più il messaggio di errore di eccezione sul onPause ().

Tip1: Usare sempre l'unregisterReceiver () in onPause () non in OnDestroy () Tip2: Non dimenticate di impostare la variabile bolBroadcastRegistred a FALSE quando eseguire l'unregisterReceive ()

Successo!

Se si mette questo su OnDestroy o il metodo onStop. Penso che quando l'attività si è creato di nuovo il MessageReciver non è stato in fase di creazione.

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

}

ho usato l'intenzione di lasciare Broadcast Receiver sapere su istanza Handler di filo attività principale e messaggio utilizzato per passare un messaggio all'attività principale

Ho usato tale meccanismo per controllare se Broadcast Receiver è già registrato o meno. A volte è necessaria quando si registra il ricevitore broadcast in modo dinamico e non voglio farlo due volte o si presenta all'utente se Broadcast Receiver è in esecuzione.

Principale attività:

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

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

Broadcast Receiver:

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

}

}

Personalmente io uso il metodo di chiamare unregisterReceiver e la deglutizione l'eccezione se è gettato. Sono d'accordo questo è brutto, ma il metodo migliore attualmente previsto.

Ho sollevato una richiesta di funzionalità per ottenere un metodo booleano per controllare se un ricevitore è registrato aggiunto alla API di Android. Si prega di sostenere qui se volete vedere ha aggiunto: https://code.google.com/p/android/issues/detail ? id = 73.718

ho il tuo problema, ho affrontato lo stesso problema nella mia applicazione. Ho chiamato registerReceiver () ora multipla all'interno dell'applicazione.

Una semplice soluzione a questo problema è quello di chiamare il registerReceiver () nella classe di applicazioni personalizzate. Questo farà sì che il ricevitore broadcast sarà chiamato solo uno in tutto il ciclo di vita dell'applicazione.

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

    }
}

Ecco come ho fatto, si tratta di una versione modificata della risposta data dal ceph3us e curato da slinden77 (tra le altre cose ho valori restituiti rimossi di metodi che non ho avuto bisogno):

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

Poi su una classe di attività:

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

ho messo questo codice nella mia attività principale

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

Ecco quello che ho fatto per verificare se l'emittente è già registrato, anche se si chiude l'applicazione (finitura ())

Firstime eseguire l'applicazione, inviare una trasmissione prima tornerà vero / falso dipende se la vostra emittente in ancora in esecuzione o meno.

Il mio Broadcaster

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

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

È possibile utilizzare Dagger per creare un punto di riferimento di quella ricevente.

Per prima fornirli:

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

Poi iniettarlo in cui è necessario (utilizzando constructor o campo injection)

e semplicemente passarlo al registerReceiver.

Anche lo mise in blocco try/catch troppo.

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

Basta controllare NullPointerException. Se il ricevitore non esiste, allora ...

try{
    Intent i = new Intent();
    i.setAction("ir.sss.smsREC");
    context.sendBroadcast(i);
    Log.i("...","broadcast sent");
}
catch (NullPointerException e)
{
    e.getMessage();
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top