Does Broadcastreceiver.Onreceive Always Run in the UI Thread

Does BroadcastReceiver.onReceive always run in the UI thread?

Does BroadcastReceiver.onReceive always run in the UI thread?

Yes.

Running broadcast receiver on a separate thread

I would suggest you should use HandlerThread instead of subclassing a Thread

for example

HandlerThread handlerThread = new HandlerThread("DifferentThread" , android.os.Process.THREAD_PRIORITY_BACKGROUND);
handlerThread.start();
Looper looper = handlerThread.getLooper();
private Handler handler = new Handler(looper, this);
// Register the broadcast receiver to run on the separate Thread
registerReceiver (myReceiver, intentFilter, broadcastPermission, handler);

Hope this will help in your Experiment ;)

Njoy!

Are Android's BroadcastReceivers started in a new thread?

The onReceive() method is always called on the main thread (which is also referred to as "UI thread"), unless you requested it to be scheduled on a different thread using the registerReceiver() variant:

Context.registerReceiver(BroadcastReceiver receiver,
IntentFilter filter,
String broadcastPermission,
Handler scheduler)

sendBroadcast thru UI or non-UI thread?

You can read in documentation for sendBroadcast:

This call is asynchronous; it returns immediately, and you will continue executing while the receivers are run.

so it is perfectly safe to call it on UI thread

On which thread does onReceive() of a BroacastReceiver registered with LocalBroadcastManager run?

sendBroadcastSync() is indeed run on the thread it is called from (except if there is a race going on). Its implementation should be:

public void sendBroadcastSync(Intent intent) { // directly calls executePendingBroadcasts
if (sendBroadcast(intent)) {
executePendingBroadcasts();
}
}

The race part I am not sure about enters via the sendBroadcast() call which returns true if it found any matching receiver (registered with LBM for this intent), after sending a message to a private handler associated with the main loop - abbreviated:

@Override
public boolean sendBroadcast(Intent intent) {
synchronized (mReceivers) {
final String action = intent.getAction();
final ArrayList<ReceiverRecord> entries = mActions.get(action);
if (entries == null) return false; // no receivers for that action
ArrayList<ReceiverRecord> receivers = new ArrayList<ReceiverRecord>();
for (ReceiverRecord receiver : entries) {
if (receiver.broadcasting) continue;
// match the intent
int match = receiver.filter.match(action,
intent.resolveTypeIfNeeded(mAppContext.getContentResolver()),
intent.getScheme(), intent.getData(),
intent.getCategories(), "LocalBroadcastManager");
if (match >= 0) {
receivers.add(receiver);
receiver.broadcasting = true;
}
}
final int size = receivers.size();
if (size == 0) return false; // no receivers for this intent
for (int i = 0; i < size; i++) {
receivers.get(i).broadcasting = false;
}
mPendingBroadcasts.add(new BroadcastRecord(intent, receivers));
if (!mHandler.hasMessages(MSG_EXEC_PENDING_BROADCASTS)) {
mHandler.sendEmptyMessage(MSG_EXEC_PENDING_BROADCASTS);
}
return true;
}
}

where:

    mHandler = new Handler(context.getMainLooper()) {

@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_EXEC_PENDING_BROADCASTS:
executePendingBroadcasts();
break;
default:
super.handleMessage(msg);
}
}

I am not sure if there can be a race between the main thread and the thread sendBroadcastSync() is executing - so the executePendingBroadcasts() will run on the main thread. If not then executePendingBroadcasts() runs on the thread sendBroadcastSync is run and directly calls the onReceive of the receivers

One of these days I should look into why (in executePendingBroadcasts) synchronized(mReceivers) and not synchronized(mPendingBroadcasts).

Are broadcasts queued or dropped in broadcast receivers (android)?

whether or not broadcasts are processed sequentially, in parallel or dropped

Broadcasts are based on publish-subscribe design pattern.

The onReceive method runs in the main thread, so it runs sequentially.
Android system will enqueue all the broadcasts until they're delivered to your receiver, so that none of them gets dropped.

Additionally, there is a timeout of 10 seconds for the onReceive method after which android considers the receiver to be blocked. So, if your onReceive method takes too long for a single broadcast, android will block/kill it and the subsequent broadcast messages will be missed/dropped.

How to wait for onReceive to finish while in same thread?

You seem to be over-complicating things. It's hard to know what you're really after based on the example code, but the code that comes after registerReceiver() should just do whatever else it needs to do and then return, without waiting for or hoping for the Broadcast to have been received. onReceive() should include whatever code you want to have executed at that point (which may well just be a method call, e.g. updateA("bye").

How to update UI in a BroadcastReceiver

I suggest you use a Handler.

  1. Initialize a Handler in the Activity, example: handler = new Handler()
  2. Provide the handler to the BroadcastReceiver in the constructor, in the same way as I did for NissanTabBroadcast above
  3. Use post() method of your Handler instance in the onReceive() 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();
}
});
}
}
}

How does a Broadcastreceiver work?

Specifically, does each broadcastreceiver run in a separate thread ?

No. onReceive() is always called on the process' main application thread.

Then, does the receiver have some sort of queue to manage incoming requests when the intensive task gets over ?

Your "computationally intensive task" should not be running on the main application thread and therefore should not interfere with the timely receipt of broadcasts.



Related Topics



Leave a reply



Submit