Why receiver receive broadcast every time the onResume() method activated? - android

In my onresume() of activity, I have this
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
registerReceiver(mReceiver, intentFilter);
Every time the onResume() activate, mReceiver always received a broadcast have the action of ConnectivityManager.CONNECTIVITY_ACTION
That's strange, because my networkstate is in a stable wifi and does not changed at all.

every time onresume is activited , registerReceiver is called one more each time.
registerReceiver sends bck sticky broadcasts. Sticky broadcasts are sent to receiver as soon as registerBroadcast is called.
you can use unregisterReceiver or check you will have to check whether you have already registered and skip , if yes..

As per documentation for registerReceiver (BroadcastReceiver receiver, IntentFilter filter):
The system may broadcast Intents that are "sticky" -- these stay around after the broadcast as finished, to be sent to any later registrations. If your IntentFilter matches one of these sticky Intents, that Intent will be returned by this function and sent to your receiver as if it had just been broadcast.
Though you are just registering your receiver right now but it's up to the system when to broadcast that Intent and since that intent is a sticky one so it gets broadcasted as soon as you register.
Check out this ConnectivityManager.CONNECTIVITY_ACTION, always broadcast when registering a receiver?

Seems sticky broadcasts is a common problem for action ConnectivityManager.CONNECTIVITY_ACTION,
Follow the instruction I tried to describe the receiver in XML but it seems NOT OK with that
AT last,I used a flexible method to resolve this:Since everytime in Onresume will send that broadcast,I set a boolean value to be 'false',when the onresume called the receiver for the first time,the program will do nothing but just set this boolean value to 'true'.
Then when CONNECTIVITY changed,it will go normal process.
This seems not an elegant method ,but it worked in my app.

A solution is to use isInitialStickyBroadcast in the onReceive callback of your BroadcastReceiver to know if you are actually proceeding a sticky broadcast and act accordingly (BroadcastReceiver : isInitialStickyBroadcast)

Related

How to avoid broadcast from being wasted when receiver is registered inside activity?

I have a service which will broadcast a message to broadcast receiver which is registered in some activity. The activity might be running or not. If it's open then broadcast will be received. But if not, the broadcast will be wasted. Is there a way to avoid this broadcast from being wasted without adding the broadcast inside manifest?
Consider to start/stop that service based on Activity's lifecycle, when Activity is created (onCreate()) start that service. When Activity is destroyed (onDestroy()) stop the service so you avoid "waste" those messages and even have a service running.
1- Create an inner class in your activity that extends BroadcastReceiver.
2- Create an object of your receiver and an intent filter.
3- Override onResume and registerReceiver(receiver, intentFilter);
4- Override onPause and unregisterReceiver(receiver);
Take a look at this answer. you dont have to add it in the manifest.
answer here

Always check for screen on/off

To implement a simple sleep detection app I need to handle ACTION_SCREEN_OFF and ACTION_SCREEN_ON broadcasts in order to get the timing related to user's sleep (based on device inactivity). However, these broadcasts cannot be put in the manifest; the receiver has to be un-/registered in some app component.
How can I implement that? It seems to me that registering the receiver in, say,
a Service won't do much since after the service is done it should call for unregister. Unless I have a long, persistent service which is not doing anything.
You can create a STIKY service that is registering to a broadcast receiver.
In your broadcast check for on/off state in onReceive method:
if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
// screen off
} else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
// screen on
}
And register like this in your service:
YourBroadcastReceived receiver = new YourBroadcastReceiver();
IntentFilter screenStateFilter = new IntentFilter();
screenStateFilter.addAction(Intent.ACTION_SCREEN_ON);
screenStateFilter.addAction(Intent.ACTION_SCREEN_OFF);
registerReceiver(receiver, screenStateFilter);
Don't forget to unregister after service is killed and always register just one time when service is created.

When will dynamically registered BroadcastReceiver start being considered by system?

My question is about: "when will my postbox be noticed by the postman", not "when will I be able to read any letters"?
I have an Activity which allows the user to edit a list. As soon as the user commits the edit, an IntentService is started which in turn calls a database helper to change the database entries as required.
As soon as the database is updated successfully (nothing crashed until then), the database helper writes "ok" to SharedPreferences and returns to the IntentService. The IntentService sends a message to a BroadcastReceiver which now causes the list to be reloaded from db with the current data.
The BroadcastReceiver is an inner class of the Activity and it is registered dynamically in onCreate():
mReceiver = new MyMessageReceiver();
IntentFilter iFilter = new IntentFilter();
iFilter.addAction("com.example.mycoolapp.LOCALINTENT");
LocalBroadcastManager.getInstance(this).registerReceiver(mReceiver, iFilter);
If the user stayed in my Activity until the list could be reloaded, there would be no problem at all. But imagine the user moving around and somehow causing an orientation change... that's why I have the "ok" in SharedPeferences:
In onCreate(), after registering the receiver, I check whether there is an action pending:
If the database was updated successfully, I can load the data and just set a flag for my receiver to ignore the next message. Which will come, as the IntentService was configured with setIntentRedelivery(true).
If I find that the database is not yet updated, I decide to wait for the broadcast from the IntentService.
The one thing I'm extremely uncertain of is the following:
From which moment on will the system consider my receiver to be "up and running"? I know that onReceive() can only be called after onCreate() is finished.
Is it possible that while onCreate() is being executed, the IntentService fires the local Broadcast ("too soon") and my receiver will never get it?
Then that list would never be refreshed until the user left the Activity (which is quite likely) and returned once more (then not so likely).
The Broadcast Receiver is not registered in the Activity but in the main application thread. The registerReceiver method is defined in the Context class.
That means that your Broadcast receiver will remain registered until you un-register it or your application is destroyed (ie. not having the receiver in a Service)
Check the documentation
From which moment on will the system consider my receiver to be "up
and running"? I know that onReceive() can only be called after
onCreate() is finished.
From the moment registerReceiver() returns
Is it possible that while onCreate() is being executed, the
IntentService fires the local Broadcast ("too soon") and my receiver
will never get it?
You can avoid this by registering the receiver in the onCreate method of a class that extendsApplication. That's how you can make sure that the broadcast receiver is the first thing done.

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.

Broadcast receiver registered from code

I register receiver from the onCreate from my activity like this
IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_SCREEN_OFF);
BroadcastReceiver mReceiver = new ScreenOnOffReceiver();
registerReceiver(mReceiver, filter);
And everything works good and the receiver get the intents, and everything is working good until, i close the activity. When I close the activity the method doesn't receive intents any more...
Does someone one know how can I register for receiver . . .
Note : I do not unregistered the receiver , but it happens somehow magically it just stop working properly . . .
The idea of registering a broadcast receiver in an activity is to get notified of some event while the activity is on (register the receiver in onResume, unregister it in onPause).
If you need a broadcast receiver to handle the event while the activity isn't showing, then register your broadcast receiver in your manifest.
If you need to handle both cases in a different way, then use a ordered broadcast.
If you want to receive messages all the time than you will need to create your own service and do your intent filter in onStartCommand method and unregister in onDestroy.
More details here http://developer.android.com/reference/android/app/Service.html

Categories

Resources