How to update UI in a BroadcastReceiver
How to re-use BroadcastReceiver in any Activity?
Consider situations where,
- You want to use the same
BroadcastReceiver
in different activities - You have written
BroadcastReceiver
in a separate file and want to accessActivity
methods, UI elements, etc.
In these cases using an interface is a great idea. I will explain the advantage and a use case in more detail. But first, let's see how it's done.
1) Create an interface
public interface MyBroadcastListener{
public void doSomething(String value);
}
2) Initialize the Listener in your BroadcastReceiver
public class MyReceiver extends BroadcastReceiver {
private MyBroadcastListener listener;
public MyReceiver(MyBroadcastListener listener){
this.listener = listener;
}
@Override
public void onReceive(Context context, Intent intent) {
listener.doSomething("Some Result");
}
}
3) Implement the interface in your Activity and override the method
public MainActivity extends AppCompatActivity implements MyBroadcastListener{
private BroadcastReceiver receiver;
@Override
public void onCreate(Bundle sis){
// Related code
receiver = new MyReceiver(this); // This is how you initialise receiver
// Register receiver etc
}
public void updateUI(String msg) {
TextView textView = (TextView) findViewById(R.id.textView);
textView .setText(msg);
}
@Override
public void doSomething(String result){
updateUI(result); // Calling method from Interface
}
}
Advantage and Use case?
Using an interface approach makes BroadcastReceiver independent of any Activity. Let's say in future you want to use this BroadCastReceiver with another activity which takes the result from BroadcastReceiver and start a DetailActivity.
Notice that this is a completely different task but you can use same BroadcastReceiver without even any code change inside the BroadcastReceiver.
How to do that?
Simple! Implement the interface in the Activity
and Override the method. That's it!
public ListActivity extends AppCompatActivity implements MyBroadcastListener{
// Your Activity code goes here
public void startDetailActivity(String title) {
Intent i = new Intent(ListActivity,this, DetailActivity.class);
i.putExtra("Title", title);
startActivity(i);
}
@Override
public void doSomething(String result){
startDetailActivity(String title); // Calling method from Interface
}
}
I suggest you use a Handler.
- Initialize a Handler in the Activity, example:
handler = new Handler()
- Provide the handler to the BroadcastReceiver in the constructor, in the same way as I did for NissanTabBroadcast above
- Use
post()
method of your Handler instance in theonReceive()
method to submit the Runnable that updates the UI
This is the cleanest solution I can imagine.
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();
}
});
}
}
}