4

Let's say the user open "Settings" application, is there a way to "intercept" this intent, from my app's service, in order to detect that "Settings" app is going to be openned?

For instance, in SOTI MobiControl app you can manage (from a web dashboard) the permissions of the user with the app installed (and enrolled to your server). If you don't allow one user to open Settings app, when he tries to open it, a toast appears saying "Unauthorized". How do they that?

Héctor
  • 24,444
  • 35
  • 132
  • 243
  • 1
    @pskink I wonder how [AppLock](https://play.google.com/store/apps/details?id=com.domobile.applock&hl=en) works? – Emil Oct 07 '15 at 08:33
  • 1
    i mean there is no `SDK` support for this kind of notifications – pskink Oct 07 '15 at 08:42
  • 2
    There is no way to intercept intents. As far as app locker is concerned they scan device for every second or 5 to check if locked application i opened or not by scanning list of running application and if found they push their activity upon it. If they close their applocker screen they also kill the process of opened activity by their package name. – Abhinav Singh Maurya Oct 07 '15 at 08:47
  • 1
    as @AbhinavSinghMaurya said [this](http://stackoverflow.com/a/8516789/1529129) is how app lockers work. – Rahul Tiwari Oct 21 '15 at 10:37

3 Answers3

4

Doing so is against Google Play Developer Program Policy, as it states in its System Interference section:

  • An app downloaded from Google Play (or its components or derivative elements) must not make changes to the user’s device outside of the app without the user’s knowledge and consent.

  • This includes behavior such as replacing or reordering the default presentation of apps, widgets, or the settings on the device. If an app makes such changes with the user’s knowledge and consent, it must be clear to the user which app has made the change and the user must be able to reverse the change easily, or by uninstalling the app altogether.

  • Apps and their ads must not modify or add browser settings or bookmarks, add homescreen shortcuts, or icons on the user’s device as a service to third parties or for advertising purposes.

  • Apps and their ads must not display advertisements through system
    level notifications on the user’s device, unless the notifications
    derive from an integral feature provided by the installed app (e.g., an airline app that notifies users of special deals, or a game that
    notifies users of in-game promotions).

  • Apps must not encourage, incentivize, or mislead users into removing or disabling third-party apps except as part of a security service
    provided by the app.

https://play.google.com/intl/ALL_us/about/developer-content-policy.html

Kistamushken
  • 221
  • 3
  • 11
  • Interesting, thanks. But technically it is possible. I would like to know how catch this kind of events. Many apps like AppLock or SOTI MobiControl do it. – Héctor Oct 07 '15 at 08:46
  • 3
    My personal guess, is that the Apps you've named, are basically launchers for Android. Which means they wrap functionality of your system. Think about an App with a button "Settings" inside it, when user clicks it, your App checks if the user has the right access. Basically, these kind of Apps don't intercept anything outside of them, they just filter interaction inside them, imo. – Kistamushken Oct 07 '15 at 09:04
  • They are definitely not launcher apps. They are able to kick in whenever the settings are opened, no matter what launched them. Honestly I don't see how an app like that would violate the policies you list above? It's all happening with the user's consent. – Emanuel Moecklin Oct 23 '15 at 12:53
2

Is there a way to "intercept" this intent, from my app's service, in order to detect that "Settings" app is going to be opened?

As other mentioned before it's not possible to intercept a launch intent.

For instance, in SOTI MobiControl app you can manage (from a web dashboard) the permissions of the user with the app installed (and enrolled to your server). If you don't allow one user to open Settings app, when he tries to open it, a toast appears saying "Unauthorized". How do they that?

It's however possible to determine if an app is opened and "intercept" that call. By intercept I mean draw over the starting app's screen and present a login screen or a not authorized screen.

I haven't worked out a full sample that would work an any Android version but from my research with AppLocks, I'd say it works more or less like this:

On pre-Lollipop Android you'd use this to retrieve the running processes:

    ActivityManager manager = (ActivityManager)getSystemService(ACTIVITY_SERVICE);
    for (ActivityManager.RunningAppProcessInfo info : manager.getRunningAppProcesses()) {
        Log.e("TAG", "Running process: " + info.processName);
        if ("com.mycompany.mycoolapp".equals(info.processName)) {
           // do stuff...
        }
    }

requires:

<uses-permission android:name="android.permission.GET_TASKS"/>

or alternatively:

    for (ActivityManager.RunningTaskInfo recentTaskInfo : manager.getRunningTasks(100)) {
        Log.e("TAG", "Recent tasks: " + recentTaskInfo.baseActivity.getPackageName());
    }

On Lollipop and higher you'd use UsageStats to determine if an app is running:

    UsageStatsManager usageStatsManager = (UsageStatsManager)getSystemService(USAGE_STATS_SERVICE);
    Calendar cal = Calendar.getInstance();
    cal.add(Calendar.YEAR, -1);
    long start = cal.getTimeInMillis();
    long end = System.currentTimeMillis();
    List<UsageStats> queryUsageStats = usageStatsManager.queryUsageStats(UsageStatsManager.INTERVAL_DAILY, start, end);
    for (UsageStats stats : queryUsageStats) {
        Log.e("TAG", "Usage stats for: " + stats.getPackageName());
    }

requires:

<uses-permission android:name="android.permission.PACKAGE_USAGE_STATS"/>

I would probably run both using the AlarmManager to perform that recurring task.

I'm fairly certain these are the two ways to get the list of running apps. If the permission for usage stats is denied to AppLock it's not working any more an Android 6.0 devices. On pre-M devices it however still works which is an indicator that the app has an alternative way to get the list of running apps (the first option described above).

Once it's determined an app has been started (it's running and hasn't been running the last time we checked), we can "take over" the screen. And that's how I'd do it: http://www.piwai.info/chatheads-basics/

Of course that's just the basic idea and I'm sure there are a couple of pitfalls when implementing a reliable solution but this should give you something to start with.

Emanuel Moecklin
  • 28,488
  • 11
  • 69
  • 85
  • Thanks. Very interesting. And what about hide application icons from menu in order to restrict the access? How is it possible? – Héctor Oct 26 '15 at 06:59
  • That would be possible only if the default launcher is replaced by a custom launcher. I haven't used SOTI myself but from the description that doesn't seem to be what they are doing. A lot of what's described on their website on the other hand can be done by acting as a a device administrator: http://developer.android.com/guide/topics/admin/device-admin.html – Emanuel Moecklin Oct 27 '15 at 01:58
  • Thank you very much. This link has been very useful. – Héctor Oct 27 '15 at 07:03
0

Let's say the user open "Settings" application, is there a way to "intercept" this intent, from my app's service, in order to detect that "Settings" app is going to be openned?

No, unless you are the one that is calling startActivity() to launch the application in the first place.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491