5

I've developed an application that receives a Broadcast and then launches an Activity, where that Activity queries a ContentProvider which pulls information out of the DNS in real-time.

I'd like to be able to shuffle this so that instead of going:

BroadcastReceiver.onReceive() {
  Intent intent = new Intent(...);
  intent.setData(...); // set a single String data
  context.startActivity(intent);
}

Activity.onCreate() {
  String value = intent.getData();  // get the String data
  Cursor = ContentProvider.query(search);
  ...
  setContentView(...);
}

it goes:

BroadcastReceiver.onReceive() {
  Cursor = ContentProvider.query(...);
  if (cursor != null) {
     Intent intent = new Intent(...);
     // how do I pass the cursor?
     getContext().startActivity(intent);
  }
}

Activity.onCreate() {
  // how do I retrieve the cursor?
  setContentView(...);
}

i.e. if the query() returns no data I want to miss out launching the Activity, and allow the Broadcast message to fall through as normal.

If the query() does return data, I want that Cursor to be supplied to the Activity, so that I don't have to go and query for the data again.

In turn, the Activity has its own UI which the user needs to respond to.

Is this possible?

Alnitak
  • 334,560
  • 70
  • 407
  • 495

2 Answers2

6

What you want is somewhat difficult and to me, rather inefficient. I would propose that you use the first alternative, but when you load the Cursor in the activity, check if there is no data, and then exit the activity.

BroadcastReceiver.onReceive() {
  Intent intent = new Intent(...);
  intent.setData(...); // set a single String data
  context.startActivity(intent);
}

Activity.onCreate() {
  String value = intent.getData();  // get the String data
  Cursor = ContentProvider.query(search);

  if(cursor.isEmpty() ...){
    finish();
    return;
  }
  ...
  setContentView(...);
}

This will have the exact same effect, the cursor will only be loaded once, and the activity will only be displayed if something exists in the cursor. The only extra overhead is that the intent is fired no matter what, but that's not exactly taxing :)

Note that there won't be any flicker or anything either, Android handles the case of calling finish in onCreate() (I believe onStart and onResume as well) so that the user never knows it happened.

sooniln
  • 14,607
  • 4
  • 29
  • 35
  • ok, sounds good - but - when does the call to context.startActivity() return? – Alnitak Mar 19 '09 at 18:19
  • and how do I let the BroadcastReceiver know whether the Activity did anything useful? AFAIK I can't use startActivityForResult() in a BroadcastReceiver. – Alnitak Mar 19 '09 at 18:26
  • The call to context.startActivity returns immediately, essentially, all it does is schedule the activity to be started at a later time as soon as the main event thread is free. – sooniln Mar 19 '09 at 22:03
  • Well, it depends on what you want the broadcast receiver to do. Without knowing, I would recommend doing whatever you were planning to have the broadcast reciever do with inside the Activity instead. – sooniln Mar 19 '09 at 22:03
  • I'm catching the NEW_OUTGOING_CALL action, but if I launch the Activity I have to set the BroadcastReceiver's returnData to null otherwise the call progresses as normal. If I ultimately place the outbound call in the Activity then it makes it impossible for the user to chain BroadcastRecevers. – Alnitak Mar 21 '09 at 09:44
  • I don't think you are going to be able to chain BroadcastReceivers. Broadcast receivers are designed to be a short running as possible, and they definitely are not meant to be interactive. They are one way communication (X is happening), not two way (X is happening, give me your thoughts on X). – sooniln Mar 21 '09 at 19:34
  • I doubt you'll be able to do a real-time blocker with broadcasts. What I would suggest is a white/black list based blocker so when the call goes through, the receiver just checks through your black/white list (which the user has set up earlier) and doesn't try to launch an Activity. – sooniln Mar 21 '09 at 19:40
  • From the docs: "asynchronous operation is not available, because you will need to return from the function to handle the asynchronous operation, but at that point the BroadcastReceiver is no longer active". – sooniln Mar 21 '09 at 19:48
  • it's not a call blocker - it's a call re-router. It looks like I'll have to do as you suggest at comment #4 and have my Activity generate the new call. re: #6 - NEW_OUTGOING_CALL _does_ allow the receiver to change the dialed number with setResultData(). – Alnitak Mar 23 '09 at 11:19
  • Ah, ok! Well in any case you'll have to arrange for any user input to happen previous to the broadcast receiver. Hope that helps! – sooniln Mar 24 '09 at 21:15
0

You'll need to find or make a Cursor that's Serializable or Parcelable (and then use intent.setExtra()). Or maybe it's possible to instead read all the data in as a parcel and pass that on to the Activity?

pjz
  • 41,842
  • 6
  • 48
  • 60
  • that's sort of my thinking too - probably Parcelable, as the Activity is actually a ListActivity so I need to pass the data through a ListAdapter. – Alnitak Mar 19 '09 at 15:36