Persisting BroadcastReceiver reference - android

What I want to achieve is to give user a button saying 'Start broadcast receiving' and another one saying 'Stop broadcast receiving'.
I'm registering BroadcastReceiver for "android.provider.Telephony.SMS_RECEIVED" intent ('Start broadcast receiving' functionality):
incomingSmsReceiver = new IncomingSmsReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction("android.provider.Telephony.SMS_RECEIVED");
getApplicationContext().registerReceiver(incomingSmsReceiver, filter);
Then I'm using unregisterReceiver() for 'Stop broadcast receiving':
getApplicationContext().unregisterReceiver(incomingSmsReceiver);
As you can see it's using the same reference (private static BroadcastReceiver incomingSmsReceiver;).
The problem is:
This works fine as long as my app's process is not terminated. When user click 'Start receiving broadcast' and after that my app is been killed by Android I'm loosing incomingSmsReceiver reference (when I run my app next time it's set to null by default). There's no way for user to stop receiving broadcast as the reference is lost.
How to persist this reference? And how to make it possible to call getApplicationContext().unregisterReceiver(incomingSmsReceiver); after recreating app's process by Android?

I've found better solution for such problem: Enable and disable a Broadcast Receiver (CommonsWare's answer).
The solution is to register BroadcastReceiver in AndroidManifest file. Then to use PackageManager.setComponentEnabledSetting(...) to enable / disable this component.

AFAIK, you don't need to hold on to the exact same BroadcastReciever reference. Create a new reference in the exact same way in which you would create one normally and pass it to unregisterService.

Related

boot_completed action to register programmatically and not in manifest

I was trying to register a receiver programmatically for actionandroid.intent.action.BOOT_COMPLETED ,
i.e
Lets take i have reciever class named BootReceiver which extends BroadCastReceiver class.
So in one of my activity class i have written this code,
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("android.intent.action.BOOT_COMPLETED");
intentFilter.addAction("android.intent.action.PACKAGE_REPLACED");
BootReceiver receiver = new BootReceiver();
getApplicationContext().registerReceiver(receiver, intentFilter);
I was trying to do both update of app as well boot_completed action to same broadcast receiver.
So what i tried is,
I ran the activity with registering of above code and then restarted the device. I was not getting any callback to BootReceiver onReceive() method.
Is it possible to programmatically declare receiver for the boot_completed action or is it necessary to declare receiver in manifest file.
Actually my requirement is to programmatically declare it.
Thanks in advance.
I was trying to register a receiver programmatically for actionandroid.intent.action.BOOT_COMPLETED
By the time registerReceiver() is called, the boot will have long since happened. The only place to register for android.intent.action.BOOT_COMPLETED is in the manifest, as that is able to register interest in broadcasts even when you do not have a process running.
Is it possible to programmatically declare receiver for the boot_completed action
No. You can request it, but it will never work.
is it necessary to declare receiver in manifest file
If you want one to work, yes.

Android SDK : Broadcastreceiver Intentservice and configuration changes

I am using a broadcastreceiver to listen for an intentservice which is set off via an onclick method. This is all fine but if the screen is rotated, I have had to put an unregister in the onPause (I have also tried this in onDestory) method and then in the onResume I re-register the broadcastreceiver.
My problem is, during the time of the broadcastreceiver being unregistered/registered the intentservice can send its broadcast back to say its done and then this means that the broadcastreceiver is still sitting there waiting for something that has already happened.
I have tried to use a sleep in the intentservice before the broadcast but this is by no means full proof as if the device is rotated again there is a timing issue.
I start and register the intent service and broadcastreceiver from the onClick as follows :
Intent intentMyIntentService = new Intent(myclass.this,myservice.class);
startService(intentMyIntentService);
mybroadcastreciver = new br();
IntentFilter intentFilter = new IntentFilter(myservice.ACTION_ServiceE);
intentFilter.addCategory(Intent.CATEGORY_DEFAULT);
registerReceiver(mybroadcastreciver, intentFilter);
I the br method is the broadcastreceiver which as its onReceive method and I handle the configuration change with the onSaveInstanceState method and then check in the onCreate to see if the Bundle != null to then retrieve the Boolean which are set depending whether the intentservice is complete using the broadcast that it sends to the receiver.
This does all work if the screen is not rotated. However I know there are other ways to handle screen rotation but I am writing an app to work from API 8 to 17 .
Thanks
Tim
One way is to maintain the same BroadcastReceiver object across screen orientation change:
1) Return the BroadcastReceiver object in Activity.onRetainNonConfigurationInstance().
2) Fetch it in Activity.onCreate() using (BroadCastReceiver) getLastNonConfigurationInstance(). It returns null if not saved.
3) In onClick(), only create the BroadcastReceiver object if it's not obtained in Activity.onCreate().

Get BroadcastRecevier Object from ResloveInfo

I am stuck up just now; issue is my one of activity has register one private broadcastReceiver and I need to unregister it and as usual I cannot change that file.
My approach is get all broadcast receiver information () for that intent by Package Manager.queryBraodcastReceiver method.
Now I want to get broadcast receiver object from it.
Is there any other approach to work out this problem?
Is there any other approach to work out this problem?
Fix the activity to unregister its receiver. You cannot do this from anywhere else in your app.

Using a broadcast intent/broadcast receiver to send messages from a service to an activity

So I understand (I think) about broadcast intents and receiving messages to them.
So now, my problem/what I can't work out is how to send a message from the onReceive method of a receiver to an activity. Lets say I have a receiver as such:
public class ReceiveMessages extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
String action = intent.getAction();
if(action.equalsIgnoreCase(TheService.DOWNLOADED)){
// send message to activity
}
}
}
How would I send a message to an activity?
Would I have to instantiate the receiver in the activity I want to send messages to and monitor it somehow? Or what? I understand the concept, but not really the application.
Any help would be absolutely amazing, thank you.
Tom
EDITED Corrected code examples for registering/unregistering the BroadcastReceiver and also removed manifest declaration.
Define ReceiveMessages as an inner class within the Activity which needs to listen for messages from the Service.
Then, declare class variables such as...
ReceiveMessages myReceiver = null;
Boolean myReceiverIsRegistered = false;
In onCreate() use myReceiver = new ReceiveMessages();
Then in onResume()...
if (!myReceiverIsRegistered) {
registerReceiver(myReceiver, new IntentFilter("com.mycompany.myapp.SOME_MESSAGE"));
myReceiverIsRegistered = true;
}
...and in onPause()...
if (myReceiverIsRegistered) {
unregisterReceiver(myReceiver);
myReceiverIsRegistered = false;
}
In the Service create and broadcast the Intent...
Intent i = new Intent("com.mycompany.myapp.SOME_MESSAGE");
sendBroadcast(i);
And that's about it. Make the 'action' unique to your package / app, i.e., com.mycompany... as in my example. This helps avoiding a situation where other apps or system components might attempt to process it.
No offense, but your question is still damn vague. So, I'm going to outline a whole mess of scenarios and hope that one of them actually hits whatever problem you think you have.
Scenario A: Only The Activity
If you only need to receive the broadcast when you have an activity in the foreground, have the activity register the BroadcastReceiver using registerReceiver(). As #MisterSquonk indicated, you would register the receiver in onResume() and unregister it in onPause().
Scenario B: Activity If In Foreground, Else Other; Ordered Broadcast
If you want the foreground activity to handle the broadcast, but you want something else to happen if that activity is not in the foreground (e.g., raise a Notification), and the broadcast is an ordered broadcast (e.g., incoming SMS), then you would still use the Scenario A solution, but with a higher-priority IntentFilter (see setPriority()). In addition, you would register a BroadcastReceiver via a <receiver> element in the manifest, with a lower-priority <intent-filter> for the same broadcast. In the activity's BroadcastReceiver, call abortBroadcast() to consume the event and prevent it from reaching your manifest-registered BroadcastReceiver.
Scenario C: Activity If In Foreground, Else Other; Regular Broadcast
If Scenario B almost fits, but the broadcast you are listening for is not an ordered broadcast, you will need to start with Scenario B. However, have the broadcast that both receivers have in their respective filters be one of your own, using a private action string as #MisterSquonk suggested. In addition, have another BroadcastReceiver registered in the manifest, whose <intent-filter> is for the real broadcast you're listening for. That receiver would simply call sendOrderedBroadcast() to send out the ordered broadcast that the other receivers are listening on.
Scenario D: Activity Regardless of Foreground
If some activity of yours needs to know about the broadcast, and it does not matter whether or not it is in the foreground, you need to rethink what you mean by that. Usually, this really means that the broadcast affects your data model in some way, in which case your concern should not be to let the activities know, but rather to update your data model, and use your already-existing "let the activities know about the data model change" logic handle the rest.
If, however, you are convinced that this is not part of your data model, you can implement Scenario B or Scenario C, plus stick some information in a static data member. Your activities can examine that static data member in onResume() to pick up the information about the broadcast when they return to the foreground.
If you're thinking "but, what if my process is terminated between the broadcast and the other activity coming to the foreground?", then your broadcast really is updating your data model, per the opening paragraph of this scenario.
If you're thinking "but, I want to update an activity that is doing work in the background", then the activity in question is broken. Activities should never be doing work in the background. That work should be delegated to some form of service, and there's a whole related set of scenarios for getting a broadcast to the service.
To broadcast an intent:
Intent intent = new Intent("com.yourcompany.testIntent");
intent.putExtra("value","test");
sendBroadcast(intent);
To receive the same intent use:
IntentFilter filter = new IntentFilter("com.yourcompany.testIntent");
BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String value = intent.getExtras().getString("value");
}
};
registerReceiver(receiver, filter);
Possibly not relevant at the time of the question being asked but there is now the LocalBroadcastManager in the Android Support Package.
Works pretty much the same way as normal broadcasts but all "chatter" is local to the app it is running in.
Advantages:
You know that the data you are broadcasting won't leave your app, so don't need to worry about leaking private data.
It is not possible for other applications to send these broadcasts to your app, so you don't need to worry about having security holes they can exploit.
It is more efficient than sending a global broadcast through the system.
Example:
Intent i = new Intent("my.local.intent");
LocalBroadcastManager.getInstance(context).sendBroadcast(i);
and to receive
receiver = new MyBroadcastReceiverToHandleLocalBroadcast();
IntentFilter i = new IntentFilter();
i.addAction("my.local.intent");
LocalBroadcastManager.getInstance(context).registerReceiver(receiver, i);

How BroadcastReceiver is different from Intent

Hello I see contradicting definitions. Android experts, can you explain this to me please?
1) If BroadCastReceiver is a component in android that responds to intents, then I can as well register an filter for activity in androidManifest xml file and have it do my job based on intent like battery low, no network, orientation change etc. these are intents I might be interested to react in my code.
2) Why register whole another filter for BroadcastReceiver in androoidManifest.xml and perform action at onReceive() inside the BCRCVR class?
3.Can we really perform intent driven operations in an activity? yes right?
I guess the title should be "How BroadcastReceiver is different from Activity".
In my opinion, Broadcast receiver is independent unit, because sometimes you don't want the system to create a new Activity object just to handle arrived intent. Moreover, you don't your activity to be shown. Broadcast receivers are independent and can be used outside any Activity. Activity is more about user interface and broadcast is about handling events.

Categories

Resources