4

By default, an application which in stopped state (not yet run even once) could not receive broadcasts. There is a way to receive it if we add the flag FLAG_INCLUDE_STOPPED_PACKAGES to the broadcast intent.

My problem is that I need to receive system intent android.intent.action.MEDIA_MOUNTED (and I don't want to add that flag to it).

How can I receive it even in stopped application?

It seems to me that for sure it's possible because for example com.android.shell application is able to receive such intents even if it's force stopped. How it does it?


EDIT:

Just to clarify, because it appeared that this is not obvious:

Everything here is from the point of view of Android Open Source Project developer. I'm modifying the operating system source code and the application which I want to receive the broadcast could be preinstalled, signed with platform certificate, it can use hidden API, etc. Everything is permitted, even modifications of the system.

Druska
  • 4,752
  • 2
  • 30
  • 34
damgad
  • 1,446
  • 9
  • 24
  • 2
    "My problem is that i need to receive system intent android.intent.action.MEDIA_MOUNTED (and I don't want to add that flag to it)" -- you cannot add the flag to it, even if you wanted to, as you are not the one broadcasting the `Intent`. "How can I receive it even in stopped application?" -- an ordinary SDK app cannot do this. It is conceivable that system apps can do this, at least pre-installed ones. And, of course, a custom ROM with a modified version of Android could offer this. – CommonsWare Jul 20 '16 at 20:47
  • @CommonsWare: Please see the edited question. My app is not an ordinary SDK app, and I'm able to modify the system. The question is how to do it in convenient way. – damgad Jul 20 '16 at 21:35
  • Ah, yes, that significantly changes the situation. I can't help you with that, and on the whole Stack Overflow tends to have more resources for supporting ordinary SDK apps. A possible solution would be to disable force-stop for your app. A bunch of system apps do that, and I presume that there's a recipe for configuring some other system app that way. Then, the user should have no way of moving your app into the stopped state in the first place. – CommonsWare Jul 20 '16 at 21:38
  • What version do you work on, is add priority to the broadcast is relevant option? – Nir Duan Jul 25 '16 at 12:53

3 Answers3

4

Declaring your application as a system app should allow you to receive regular broadcasts even if your app is in "stopped state".

Add the following to your manifest and make sure your application is signed by the platform key:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
...
...
android:sharedUserId="android.uid.system">
David Lev
  • 813
  • 5
  • 12
  • What happens if I don't have android:sharedUserId="android.uid.system"? – JohnyTex Aug 12 '16 at 10:02
  • Does my app have to be signed with platform signature, or is it enough to put it in /system/priv-app ? – JohnyTex Aug 12 '16 at 10:07
  • 1
    As of Android 4.4, /system/priv-app APKs will get the system permissions even if they are not signed with the platform key. For more information: http://stackoverflow.com/a/20104400/6587754 – David Lev Aug 12 '16 at 17:47
  • That works perfectly. I would also add that the application really needs to be in /system/priv-app. Signing with platform certificate is not sufficient. – damgad Jan 12 '17 at 13:03
0

If you are not referring to Force Stopped applications, but rather to closed applications that are in the stopped state, then look at these two links to find out how to implement a BroadcastReceiver that can be activated after the app is closed. Otherwise a custom ROM and or sys app is the way to go probably.

BroadcastReceiver 1

BroadcastReceiver 2

MedievalCoder
  • 627
  • 7
  • 10
-1

If you are on a rooted device you can use Xposed to modify android.content.Intent#isExcludingStopped, as such:

public class DontExcludeStoppedPackagesFromIntents implements IXposedHookLoadPackage {
    @Override
    public void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) throws Throwable {
        if (lpparam.packageName.equals("android")) {
            XposedBridge.log("In package: " + lpparam.packageName);

            findAndHookMethod("android.content.Intent", lpparam.classLoader, "isExcludingStopped", new XC_MethodReplacement() {
                @Override
                protected Object replaceHookedMethod(MethodHookParam param) throws Throwable {
                    return false;
                }
            });
        }
    }
}

Don't forget to put the class name in xposed_init. Of course this has some security implications, effectively taking you back to Android 3.0-, though this shouldn't be much of an issue because noone expects to exploit a vulnerability that is not present on nearly all existing Android devices that do no have this patch applied.

I tried the above and it works!

JohnyTex
  • 3,323
  • 5
  • 29
  • 52