1

With the two type of broadcast implicit and explicit broadcast in Android - for the implicit we would declare the broadcast in AndroidManifest.xml and when some app sends a broadcast with the action the all the apps which declares the broadcast in their manifest with that action would get invoked and do the job.

With the background execution limits imposed by Android from O, I'm not allowed to send a broadcast only with the intent containing action. I must specify explicitly the package name and the receiving class name.

Now by doing something like this, I'm able to overcome the implicit broadcast limitation

String action = "com.android.intent.CUSTOM";
Intent intent = new Intent();
intent.setAction(intent);

//Though this is a deprecated method
List<ResolveInfo> resolvedBroadcasts = List<ResolveInfo> queryBroadcastReceivers(intent, 0, current_user_id);

for (ResolveInfo info : resolvedBroadcasts) {
   ServiceInfo serviceInfo = info.serviceInfo;

   //Note: Now this is becoming explicit broadcast
   intent.setAction(serviceInfo.packageName, serviceInfo.name);
   context.sendBroadcast(intent);
}

Am I missing something here? Got confused at this point like if I'm able to do this way then why Android imposed me this background execution limits?

gooogle
  • 375
  • 4
  • 16

1 Answers1

3

Am I missing something here?

Google engineers have indicated that if too many apps do this, this approach will be banned, somehow.

FWIW, I blogged about this approach two years ago.

if I'm able to do this way then why Android imposed me this background execution limits?

Google is hoping that few developers will employ this workaround and instead will use some other IPC mechanism.

The issue is process churn. Suppose that your implicit broadcast matches 25 apps' manifests. When your code executes, Android needs to pass your Intent to 25 receivers. However, only a couple of those will be in memory — many of the apps will not have running processes. So, Android now needs to fork a whole bunch of processes to deliver your Intent. That in turn is likely to force other processes to be terminated, to free up system RAM. The net result is poor performance on low-end devices.

I argued that, rather than ban implicit broadcasts, Android should implement a store-and-forward mechanism, slowly delivering the broadcast at a pace that will limit the process churn. My suggestion was rejected.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • +1 for `store-and-forward` approach. Though not related to this topic, have someone faced the issue like the broadcast is timed-out before getting delivered ? I'm facing this may be I thought that the broadcast queue is filled and it's taking time to deliver the message before it's configured timeout. – gooogle Jul 13 '19 at 16:34
  • I need one suggestion please. When my I'm doing some operation I need to notify other apps that the action has happened - in this case which is the faster approach to communicate the event to other process? To be more clear the other apps in my case could be 3 or 4. But I would not know all those I would not be aware at compile time. So, seeking for some dynamic way for achieving the same. – gooogle Jul 13 '19 at 16:36
  • I'm still not able to believe that you think through this 2 years ago. :o Great ! – gooogle Jul 13 '19 at 16:45
  • @gooogle: "have someone faced the issue like the broadcast is timed-out before getting delivered ?" -- I am not certain what you mean by this, sorry. "I need to notify other apps that the action has happened" -- do those apps need to know, even if their process is not running? Can they simply find out when they run the next time for other reasons? – CommonsWare Jul 13 '19 at 16:56
  • When I run my code on low end devices (with poor ram and cpu) I'm sometimes observing that my broadcast is being missed (not delivered) - So how do I say that I'm not receiving the broadcast? I've a log print at the beginning of `onReceive` method (also before `sendBroadcast`) which I'm not seeing. One reason I could think why this broadcast is not delivered is, the broadcast queue might have filled up, so it might have taken time (~15secs) so when it tries to deliver it could have been timedout. – gooogle Jul 13 '19 at 17:50
  • do those apps need to know, even if their process is not running? - Not really :) If my running apps are able to know the event I'm more than happy. And as you said, the dead app when they come alive they can find out the event state and they can proceed. – gooogle Jul 13 '19 at 17:51
  • @gooogle: In that case, have your running apps register a receiver for your action dynamically, via `registerReceiver()`, and do a simple `sendBroadcast()`. Implicit intents work for dynamically registered receivers, just not for those registered in the manifest. This will get your broadcast to the running apps; the other apps can find out about the state by some other means when they run again. – CommonsWare Jul 13 '19 at 18:22
  • Yes I agree with you. But I'm facing the problem like the broadcast is not being received few times.. So, seeking for some reliable way to achieve the same. So, when I went for alternative like binding to the service within the other apps, android kicks me out saying I'm not allowed to bind to a service on an app (which is in background) and will be allowed to execute only 5 seconds within which I should start the service as foreground with some ui element like notification. Also, I find the approach which I tried looks like overkill to me :( – gooogle Jul 13 '19 at 18:26
  • @gooogle: If your broadcast is not being received by running processes... I don't know what would cause that, and I don't know if other IPC options will suffer similar problems. You could have the other apps bind to a service in the action app and register event callbacks. Or, you could have the action app export a `ContentProvider` and update a `Uri` on the events and having the other apps register a `ContentObserver`. – CommonsWare Jul 13 '19 at 18:29
  • You could have the other apps bind to a service in the action app and register event callbacks. -> This is an interesting solution. But what happens when my action app killed and recreated? And one more hurdle which I find here is that though my action app is used or not it's always considered to be used and other apps would bind to the service within it.. – gooogle Jul 13 '19 at 18:34
  • Or, you could have the action app export a ContentProvider and update a Uri on the events and having the other apps register a ContentObserver. - This approach looks great. But when the other apps are registered to the content provider (which would be within my action app) it would get recreated even when it's not alive. Is there any way to prevent this? – gooogle Jul 13 '19 at 18:35
  • But from the other answer here (https://stackoverflow.com/a/19249652/6680585) it looks like the content observer within the app which is not currently running will not be notified. But I've seen it getting notified even when it's not alive. Trying to reconfirm this behaviour now. – gooogle Jul 13 '19 at 18:43
  • @gooogle: "But what happens when my action app killed and recreated?" -- that is less likely with bound clients, but it could happen. In that case, you have problems. "Is there any way to prevent this?" -- I don't know what the behavior is if you register a `ContentObserver` for a provider from an app that is not currently running. To be honest, I assumed that the action app was dominated by a foreground service or something and would be running most of the time. – CommonsWare Jul 13 '19 at 18:46
  • @gooogle: "But from the other answer here" -- that is referring to the observer side of the connection. You cannot have a `ContentObserver` without a running process, by definition, as a `ContentObserver` is just a Java object and vanishes when the process is terminated. – CommonsWare Jul 13 '19 at 18:47
  • It makes more sense that the `ContentObserver` vanishes after the process getting cleared. I overlooked it. – gooogle Jul 13 '19 at 18:50
  • I assumed that the action app was dominated by a foreground service or something and would be running most of the time. - Even I'm not very sure on how the user would use my app :) - so i'm considering the possibility for my app being in foreground to be 50-50%. – gooogle Jul 13 '19 at 18:53
  • But one problem I could think of being the other apps registering to with a content observer is that my action app needs to be alive always (but that would not be the case). If I allow other apps to register to my content provider - it's more likely that i would not be allowed to kill.. – gooogle Jul 13 '19 at 18:56
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/196425/discussion-between-gooogle-and-commonsware). – gooogle Jul 13 '19 at 18:57
  • One more suggestion please, is it possible to secure setting change with the help of content observer? – gooogle Jul 16 '19 at 14:59
  • @gooogle: Sorry, but I do not know what "secure setting change" means. If you mean monitor changes in `Settings.Secure`, I have not tried that. – CommonsWare Jul 16 '19 at 15:08
  • I created a test app to confirm this. The content observer works well with content provider as well as secure setting. But I'm now skeptical on when should I use which one. – gooogle Jul 16 '19 at 18:44