Pregunta

Tengo que comprobar si mi receptor registrado aún está registrado, si no ¿cómo puedo comprobar que los métodos?

¿Fue útil?

Solución

No estoy seguro de la API proporciona una API directamente, si se tiene en cuenta este hilo :

  

Me preguntaba lo mismo.
  En mi caso, tengo una aplicación BroadcastReceiver que las llamadas   Context#unregisterReceiver(BroadcastReceiver) haciéndose pasar como argumento después de manipular la intención de que recibe.
  Hay una pequeña posibilidad de que el método onReceive(Context, Intent) del receptor se llama   más de una vez, ya que se ha registrado en IntentFilters múltiple, creando el potencial para un IllegalArgumentException ser arrojado desde Context#unregisterReceiver(BroadcastReceiver).

     

En mi caso, se puede almacenar un miembro privado sincronizado con cheque antes de llamar Context#unregisterReceiver(BroadcastReceiver), pero sería   mucho más limpio si la API proporciona un método de verificación.

Otros consejos

No hay función de la API para comprobar si se ha registrado un receptor. La solución consiste en poner el código en un try catch block as done below.

try {

 //Register or UnRegister your broadcast receiver here

} catch(IllegalArgumentException e) {

    e.printStackTrace();
}

solución más simple

en el receptor:

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

en el código:

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

ad 1

- en respuesta a:

  

Esto realmente no es tan elegante porque hay que recordar para establecer el   isRegistered bandera después de registrarse. - sigilo rabino

- método "de manera más ellegant" añadido en el receptor para registrar y conjunto del indicador

  

esto no funcionará Si reinicia el dispositivo o si su aplicación se mató por   OS. - Amin hace 6 horas

@amin - ver tiempo de vida de en el código (no sistema registrado por la entrada manifiesto) receptor registrado:)

Estoy utilizando esta solución

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

Existen varias opciones

  1. Se puede poner una bandera en su clase o actividad. Ponga una variable booleana en su clase y vistazo a este indicador para saber si tiene el receptor registrado.

  2. Cree una clase que extiende el receptor y no se puede utilizar:

    1. Singleton patrón por sólo tener una instancia de esta clase en su proyecto.

    2. Implementar los métodos para saber si el receptor es el registro.

Usted tiene que usar try / catch:

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

Se puede hacer que sea fácil ....

1) crear una variable booleana ...

private boolean bolBroacastRegistred;

2) Al registrar el receptor de difusión, ponemos a true

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

3) En el onPause () lo hace ...

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

Así que, y ahora, usted no recibirá más mensajes de error de excepción en onPause ().

Tip1: utilice siempre el unregisterReceiver () en onPause () no en OnDestroy () Tip2: No se olvide de establecer la variable bolBroadcastRegistred en FALSO cuando se ejecuta el unregisterReceive ()

Éxito!

Si pones esto en OnDestroy o método onStop. Creo que cuando la actividad se ha creado de nuevo el MessageReciver no estaba siendo creado.

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

}

utiliza intención de dejar Receptor Broadcast conocimientos acerca ejemplo Manipulador de hilo Actividad principal y mensaje utilizado para transmitir un mensaje a la actividad principal

He utilizado como mecanismo para comprobar si el receptor de difusión ya está registrado o no. A veces se necesita cuando se registra el receptor de difusión de forma dinámica y no quieren que sea el doble o se presentan al usuario si el receptor de difusión se está ejecutando.

Actividad principal:

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

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

Receptor Broadcast:

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

}

}

En lo personal yo uso el método de llamar unregisterReceiver y tragar la excepción si se ha tirado. Estoy de acuerdo en que esto es feo, pero el mejor método proporciona actualmente.

He criado a una solicitud de función para obtener un método booleano para comprobar si un receptor se ha registrado añadido a la API de Android. Por favor apoye aquí si quieres verlo añadido: https://code.google.com/p/android/issues/detail ? id = 73718

consigo su problema, que se enfrentó al mismo problema en mi aplicación. Estaba llamando registerReceiver () múltiples veces dentro de la aplicación.

Una solución simple a este problema es llamar a la registerReceiver () en su clase de aplicaciones personalizadas. Esto asegurará que su receptor de difusión será único en todo el ciclo de vida de aplicaciones llama.

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

    }
}

Esta es la forma en que lo he hecho, es una versión modificada de la respuesta dada por ceph3us y editado por slinden77 (entre otras cosas tengo valores de retorno retirados de métodos que no era necesario):

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

A continuación, en una tipo de actividad:

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

i poner este código en mi actividad principal

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

Esto es lo que hice para comprobar si la emisora ??ya está registrado, incluso si se cierra la aplicación (acabado ())

Firstime ejecución de la aplicación, enviar una difusión primera devolverá verdadero / falso depende de si su emisora ??en aún en marcha o no.

Mi Transmisor

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

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

Se puede usar Daga para crear una referencia de ese receptor.

En primer lugar se proporcionan:

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

A continuación inyectarlo donde se necesita (usando constructor o campo injection)

y simplemente pasarlo a registerReceiver.

También puso en el bloque try/catch también.

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

Sólo echa un NullPointerException. Si no existe el receptor, entonces ...

try{
    Intent i = new Intent();
    i.setAction("ir.sss.smsREC");
    context.sendBroadcast(i);
    Log.i("...","broadcast sent");
}
catch (NullPointerException e)
{
    e.getMessage();
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top