Cómo actualizar la interfaz de usuario en un BroadcastReceiver

Creé una aplicación en la que registré un receptor de difusión dentro de mi clase principal ( Main Activity ) y cada vez que recibo algo en mi BroadcastReceiver deseo actualizar la interfaz de usuario, por ejemplo, quiero mostrar un cuadro de alerta o establecer una vista de texto de mi MainActivity . Recibo todos los valores en mi receptor pero no puedo configurarlos, ¿alguien puede ayudarme para poder actualizar mi UI en el BroadcastReceiver ?

Mi clase BroadcastReceiver es clase interna de MainActivity como esta: –

 public class MainActivity extends Activity { .......... public static class NissanTabBroadcast extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { SharedPreferences shrd = context.getSharedPreferences("NissanGallery", context.MODE_WORLD_READABLE); type = shrd.getString("type", "null"); badges = shrd.getString("badge_count", "null"); //badge_tips_text.setText(badges); /*Editor edit = shrd.edit(); edit.remove("type");*/ Toast.makeText(context, "" + type + "\n" + badge_tips_text.getText().toString(), Toast.LENGTH_LONG).show(); } } } 

Cualquier ayuda será apreciable

Gracias

Te sugiero que uses un controlador.

  1. Inicialice un handler = new Handler() en la actividad, por ejemplo: handler = new Handler()
  2. Proporcione el controlador al BroadcastReceiver en el constructor, de la misma manera que lo hice para NissanTabBroadcast anterior
  3. Use el método post() de su instancia de Handler en el método onReceive() para enviar Runnable que actualice la interfaz de usuario

Esta es la solución más limpia que puedo imaginar.

 public class MainActivity extends Activity { private MyReceiver receiver; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); receiver = new MyReceiver(new Handler()); // Create the receiver registerReceiver(receiver, new IntentFilter("some.action")); // Register receiver sendBroadcast(new Intent("some.action")); // Send an example Intent } public static class MyReceiver extends BroadcastReceiver { private final Handler handler; // Handler used to execute code on the UI thread public MyReceiver(Handler handler) { this.handler = handler; } @Override public void onReceive(final Context context, Intent intent) { // Post the UI updating code to our Handler handler.post(new Runnable() { @Override public void run() { Toast.makeText(context, "Toast from broadcast receiver", Toast.LENGTH_SHORT).show(); } }); } } } 

Mi caso fue actualizar el campo de texto en uno de los fragmentos alojados por MainActivity. La solución más simple que encontré fue la siguiente:

En mi clase MainActivity recuperé la instancia en ejecución de MainActivtiy. Esta es mi MAinActivity

 private static MainActivity mainActivityRunningInstance; public static MainActivity getInstace(){ return mainActivityRunningInstance; } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mainActivityRunningInstance =this; ---------- } 

Ahora, en el método onRecieve del receptor de difusión, obtenga esa instancia y llame al método de actualización

  @Override public void onReceive(Context context, Intent intent) { if (intent.getAction().matches(Intents.PROVIDER_CHANGED_ACTION)) { String textValue="the text field value"; // the null check is for, if the activity is not running or in paused state, in my case the update was required onlyif the main activity is active or paused if(MainActivity.getInstace()!=null) MainActivity.getInstace().updateUI(textValue); } 

Ahora, para la parte donde necesitamos ejecutar la actualización en UIThread, el método updateUI de MainActivity llamará al método de actualización de fragmentos.

  public void updateUI(final String str) { MainActivity.this.runOnUiThread(new Runnable() { public void run() { //use findFragmentById for fragments defined in XML ((SimpleFragment)getSupportFragmentManager().findFragmentByTag(fragmentTag)).updateUI(str); } }); } 

y el último paso es actualizar el campo de texto del fragmento

 public void updateUI(String str){ tv_content.setText(str); } 

y Bingo, está hecho. Remití este enlace para resolver mi problema. Espero que ayude a otros.

Use runOnUiThread :

  MainActivity.this.runOnUiThread(new Runnable() { @Override public void run() { // show alert } }); 

Utilicé Intent para que Broadcast Receiver sepa sobre la instancia de Handler del hilo de actividad principal y el mensaje utilizado para pasar un mensaje a la actividad principal.

He usado ese mecanismo para verificar si Broadcast Receiver ya está registrado o no. Algunas veces es necesario cuando registra su Receptor de radiodifusión de manera dinámica y no desea hacerlo dos veces o presenta al usuario si Broadcast Receiver 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 de radiodifusión:

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

Estoy usando un enfoque completamente diferente para eso. Paso la instancia de controlador para transmitir el receptor poniéndolo en el bash. En el receptor de difusión usé ese controlador para enviarle un mensaje a su clase de actividad que actualiza la UI en su método onHandleMessage de su controlador personalizado. clase.

 create handler class like public class MyHandler extends Handler{ onHandlerMessage(Message msg){//do whatever you want here after broadcast get fired} } 

ahora use el Myhandler handler=new MyHandler(); crear este objeto controlador en el ámbito de nivel global en la actividad.

Ahora ponga este controlador en su intención mediante putExtra y luego envíe este bash a través de sendBraodcast(intent) .

en la clase de receptor de difusión obtén este objeto de controlador por getExtras y úsalo como se onReceive() continuación en el método onReceive()

  handler.sendEmptyMessage(); 

En mi caso, quiero actualizar mi vista de texto en mi actividad con los sms entrantes, lo que hice fue agregar la información requerida usando putextra y luego comencé la actividad desde el receptor de difusión:

 Intent bashne = new Intent(context.getApplicationContext(), enroll.class); bashne.putExtra("pinbody",message); bashne.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK); context.startActivity(bashne); 

Y luego en el extremo receptor, es decir, en la actividad de inscripción, extraje esa información usando la siguiente y actualicé mi vista de texto:

 Bundle extras = getIntent().getExtras(); String message = extras.getString("pinbody"); 

No estoy seguro de si ayuda, pero definitivamente lo guiará a lo que quiere.

¡Salud!

El uso de getters y setters puede resolver fácilmente este problema.

solo declara una clase de la siguiente manera.

 public class DetailsGetters { private View view; public View getview() { return view; } public void setview(View view) { this.view = view; } } 

En su actividad principal o actividad de fragmento, cree una instancia de la clase DetailsGetters.

 DetailsGetters newdetailsinstance=new DetailsGetters(); 

Antes de la vista de replanteo, llame a newdetailsinstance.setview(view);

En el receptor de difusión, obtenga la vista como newdetailsinstance.getview(view);

El follwing se puede usar para obtener vista desde el fragmento y actualizar Ui usando setText, etc.

Para actualizar la interfaz de usuario en la actividad principal, pase la vista de texto y cambie la clase DeailsGetters y cree getters y setters para Textview. Espero que esto ayude a alguien.

Usé Handler y su método post (). En lugar de runOnUiThread (). No es necesario convertir el Contexto en Actividad. Es una alternativa para runOnUiThread ()

 Handler handler = new Handler(); Runnable runnable = new Runnable() { private long startTime = System.currentTimeMillis(); public void run() { while (gameState == GameState.Playing) { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } handler.post(new Runnable(){ public void run() { tvTime.setText("" + ((System.currentTimeMillis() - this.startTime) / 1000)); } }); } } }; new Thread(runnable).start(); 

Debes hacer que el receptor de Broadcast sea de clase interna, de esta forma tendrá acceso a todos los campos para actualizar la UI.

Mira esta aplicación de cuadros por nick carnicero Plaid- Nick Butcher (Github)