Are static Broadcast Receivers inefficient? - android

Unlike dynamically registered Broadcast Receivers, the ones registered in the manifest are able to respond to events even after the activity or even the app that created it has been closed.
So, my questions are:
Every time there is an event, is an instance of every broadcast receiver registered for that event created? (even if the app is not running anymore)
In that case, isnĀ“t it a performance issue? Potentially every time there is an event the system might have to recreate a bunch of old broadcast receivers just to handle that event.
I know the developer should be responsible, but since potentially this is possible to do, why does the system allow this outside the lifecycle of an app?

As of Android 8 implicit broadcasts no longer work except for those ones.
So unless the package is explicitly set on the intent to have your package, your package will not receive the broadcast. The link above explains in more details.

Related

How to make android start my application automatically when battery is fully charged?

My question is similar to this one:
battery receiver fully charged doesnt work
. That question has no answers.
Here are the approaches I have thought of so far:
Approach 1: Register a BroadcastReceiver in the AndroidManifest.xml for ACTION_BATTERY_CHANGED.
This won't work because of the following reason:
I cannot register a BroadcastReceiver in the AndroidManifest.xml to listen for ACTION_BATTERY_CHANGED because it is a Sticky Intent as stated here: https://developer.android.com/reference/android/content/Intent.html#ACTION_BATTERY_CHANGED.
Approach 2: Register a BroadcastReceiver programatically in the MainActivity.java's onCreate() method.
Issue with this approach is : Avoid registering duplicate broadcast receivers in Android
In addition to the above issue, I do not understand the scope of broadcast receivers properly. To be more precise, I don't understand what happens to the broadcast receivers that an app has registered when the app is:
1) Destroyed by the Android system by calling it's onDestroy() method
2) When the app is force stopped by the user via the Application Manager setting.
Could someone please explain it please?
Approach 3: Use a work around that uses SharedPreferences and a BroadcastReceiver for listening to device reboot.
Have a shared preference that let's me know if I have previously registered a broadcast receiver for ACTION_BATTERY_CHANGED. If yes, don't create a new one, else, create a new broadcast receiver for ACTION_BATTERY_CHANGED. As pointed out in the link in Approach 2, the value in the SharedPreference becomes invalid upon device reboot, so have a separate broadcast receiver to create the receiver again on reboot and update the shared preferences to reflect the same.
Although, approach 3 may work, I feel it is a cumbersome way. Is there a simpler approach?
Additionally, my application will be inefficient since it is going to run for every change in battery state. Is there a way to make it run, only when the battery is full, which is my main purpose?

Why some broadcast receiver can only be registered through either Code or AndroidManifest

Some broadcast receivers only work if they are registered via code rather than defined in AndroidManifest.
For example:
SCREEN_ON, SCREEN_OFF
These actions will only work with receivers registered in code. No errors happen if they are registered in the manifest, but they never get called either.
What are the reasons for this undocumented behavior? Security?
I don't think there is a security issue around this.
Manifest defined broadcast receivers are registered and can receive intents even if the application is not in memory. The opposite doesn't occur.
It could be a performance issue because registering a receiver for this type of events, may drain the user battery.
Main difference between Manifest and Programmatic registering of BroadcastReceiver
I think this is a design decision. We can register our broadcast receivers statically or dynamically. Both receiver types treated slightly different by Android system.
Mainly;
Dynamic broadcast receiver live with application. We can use it multiple times. Most important thing about it, it runs on UI thread.
Statical broadcast receiver live with OS. Package manager handles its life cycle. The transient nature of a statically registered BroadcastReceiver means that its onReceive() method cannot use any functionality which is asynchronous, for example, binding to a Service.
And some broadcast like SCREEN_ON, SCREEN_OFF... can be called continuously. If we can register this kind of broadcast. A lot of number app want to use it. And every time we open device screen, all of this app will be triggered by OS. This is not a good behavior for any kind of OS.
On the other hand, there are some broadcast that is meaningless when we use in code. Such as "BOOT_COMPLETED". It should be registered system-wide, not in UI thread.
I think this kind of decisions depends on security, performance and use case scenario.
P.S.: Long time ago, I had searched but didn't find any documentation for exact reason about it.
It seems this answer is good for me but still this is not telling the reason why some can only be registered in AndroidManifest and some only through code
The primary use of manifest-registered receivers is for broadcasts that may go on while your code is not in memory (e.g., BOOT_COMPLETED, your scheduled alarms via AlarmManager).
This behaviour does not have any relation to security as Diogo Bento mentioned it.
If there is a resource that is precious and prermission is needed before using it, then you have to ask for that permissions, no matter weather you declare your Broadcast Receiver in the manifest or register it in the code. Without the required permissions, both will fail.
I think the reason of the code only actions is that, Googe does not want to let your app being started by that action. SCREEN_ON and SCREEN_OFF is a good example. It would be easy to make an annoying application that would do something as the screen turns on. With this restriction its much harder. If you really need your application to be started as the screen turns on, then you have to do more work to accomplish the same effect. For example you have to maintain a Service that listens for those events.
In addition, most applications care about those screen events only if they are in the foreground, so there is no need to wake up every applications, which not even running. Lets say that you have 10 apps that in a way interested in the SCREEN_ON action. As you turn your screen on, 10 process would have to be started by Android just to ignore those events, because none of them running. And process is one of the most expensive resource from the perspective of an OS...

Why the receiver defined in manifest is not receiving broadcasts when used with LocalBroadcastManager?

Few days ago I read that there is a better mechanism for sending broadcasts within single application - the LocalBroadcastManager.
It works well (just like standard broadcasts..). However, yesterday I've found out that it cannot send broadcasts to receivers, which are defined in the manifest (when I temporarily switched it to use the standard Activity's sendBroadcast method, it worked).
The reason why I want this (and correct me if there is a more preferred way to do it) is:
Lets's say I want to download a file. I will use a service, because that's how Android wants us to do. OK, now I want to display (and periodically update) its progress in my activity. So service will be sending broadcasts to my activity and the activity has to register to receive them. The preferred way to handle broadcasts is to register in onResume() and unregister in onPause(). Now let's imagine that the user is bored with the slowly moving progressbar, so he presses Home and goes to do something else. Later he comes back and wants to see the current status of the download, but how can I tell him, when I unregistered from broadcasts that second he left my application?
That's why I use a receiver defined in the manifest, to be always ready to receive the broadcast and store it permanently (shared preferences, database...), so the activity can reconstruct the latest broadcast when it becomes visible.
However now I'm not sure, whether this routine is not recommended, or why the LocalBroadcastManager is not allowing me to do it.
If you are using SharedPreferences a workaround would be to make your activity implement OnSharedPreferenceChangeListener. So the service writes the pref and the activity listens for the change and updates progress bar. onResume() you also check the preference and update the UI accordingly.
The nice thing with this is you don't really have a leak if you fail to unregister them - see
Android : Where should a OnSharedPreferenceChangeListener be defined/registered - I prefer to unregister to onDestroy() as I want to have my activity updated even if not in the foreground - and the listener will go away even if onDestroy is not called.
As for why it does not work with manifest registered receivers - could you post some code ? Do you actually register the receivers with LBM ?

How to determine if Android's BOOT_COMPLETED has occurred (not receiving it)

I am not trying to create a BOOT_COMPLETED receiver (and doing so would not solve my problem).
Is there a way to determine if BOOT_COMPLETED has occurred? I have a library which is being called before (as well as after) Android has finished booting, and I do not want my library to complete its request if the system has not finished booting. Setting up a BOOT_COMPLETED receiver in every application that may use this library is not a reasonable approach for several reasons.
Are there any Android calls I can make to determine if the device's boot has completed? It appears that there is a property, dev.bootcomplete, which I may have to use if no better method exists.
I'm afraid the only official way of achieving this is to create RECEIVE_BOOT_COMPLETED receiver.
I would advise you not to rely on properties, since they often are OEM specific. Otherwise you may end up with your application working on one Android model, but not another.
Setting up a BOOT_COMPLETED receiver in every application
I guess you mean to say you dont want BOOT_COMPLETED receiver in each activity .
Its very much possible.
You can register BOOT_COMPLETED receiver for Activity A.and once Activity A a gets broadcast it can notify other activities using sendBroadcast (custom broadcast).
To see how to use custom broadcast look here

Android - Going from Binders to Broadcasts

I started with a standard local android service, and used Binders with Listeners to communicate. Then: I began noticing some serious issues with handling orientation changes, so I decided to skip the whole binder thing, and just go with broadcasting intents (and using startService exclusively) that contain all the data/commands that need to be passed.
My question is: what are some of the pitfalls I have to look out for when using this approach?
Are there any disadvantages?
If you are supporting API Level 4 and above, use setPackage() to make your "broadcast" be a "narrowcast" -- keeping the broadcast within your app. By default, the broadcast is truly broadcast, to all apps, which may or may not be a good thing for your data.
Don't forget to unregister your BroadcastReceiver (i.e., don't register it and forget it). At the same time, you will need to consider what to do if the service wraps up and the activity is long gone (e.g., BACK button). One approach is to use an ordered broadcast with a low-priority manifest-registered receiver that will raise a Notification if no activity handles the broadcast -- this sample app demonstrates what I mean.
You might consider a Messenger instead of the broadcast approach, as it is intrinsically a "narrowcast", probably is a smidge less overhead, and can't be leaked. I am still working through the mechanics of using this with configuration changes, though.

Categories

Resources