I am writing an Andoid app so that when battery life gets below a certain level, a dialog with options of how to save the battery appears. One of those options is to close all background apps/services (processes) using ActivityManager.killBackgroundProcesses(). The code is shown here:
public void TaskKiller( View view){
List<ApplicationInfo> packages;
PackageManager pm;
pm = getPackageManager();
packages = pm.getInstalledApplications(0);
ActivityManager mActivityManager = (ActivityManager)this.getSystemService(Context.ACTIVITY_SERVICE);
for (ApplicationInfo packageInfo : packages) {
mActivityManager.killBackgroundProcesses(packageInfo.packageName);
}
}
However, when I click the button that calls TaskKiller() and closes the background processes, some of the apps (Email, Google Maps) instantly begin he process of restarting. How can I alter my code so these apps stay closed until they are reopened? Also, is this approach sensible in regard to saving power or am I attacking this the wrong way?
I don't think that's the right way of handeling the problem.
These apps have broadcast receivers, which mean they'll restart the service whenever something happens (i.e. AC plugged in/WiFi turned on), and I don't think there's a way to stop that without root, and actually disabling the broadcast receiver.
You could make something that kills it every 5 minutes, but that wouldn't be very battery-friendly.
I don't think it's a good idea to force close the Maps app everytime, it's a bug in Android i think..
One of the answers is as following:
"
Actually, Maps always runs when you have "Backround Data" checkmarked in your General Sync Settings under Account Settings in your phone's Gmail app. Syncing backround data is necessary, unfortunately, in order for your phone service provider to provide calling and texting (although internet access will still work without this item checkmarked). Unchecking this box will remove Maps from Running applications (& any other app that needs it), improving battery time and speeding up your phone. But, if you want to make calls, text or use apps that require Backround sync, you have to have this ckeckmarked. If all you want to do is browse the net...uncheckmark it. There are currently no other legitimate solutions to the issue. Hope this is helpful...
"
See this issue (https://code.google.com/p/android/issues/detail?id=10251)
Related
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?
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
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.
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.
I want to implement an app which can detect what app launched, to do something with that!
for example I have a list of installed applications in my app and mark one favorite app. and when I start that marked app from default launcher or anyway, I could detect it and do something with that by a background service or broadcast receiver(For example launch a toast message).
How can I do this?
this isnt possible.. to be able to monitor all intents would make android extremely insecure
http://groups.google.com/group/andro...ddc9d36a24d77b
but there are ways to know when an application is launched. you just have to be creative.
this will give you a list of all the applications running.
Code:
ActivityManager am = (ActivityManager)getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningAppProcessInfo> runningAppProcessInfo = am.getRunningAppProcesses();
however to know when an app is launched you would need a timed loop and then check between versions of the List to see if there is a new app. this would suck the juice and be inneficient
AppProtector seem to access the eventlog. maybe you could have a ContentObserver attached to the event log
http://developer.android.com/referen.../EventLog.html
http://developer.android.com/referen...tObserver.html
EDIT
Interesting.
I also found this which solve your problem.
When you open any app from launcher below code will return the info of opened app so now you need to compare a package name with your favourite app package name which you already stored in your app database.
Code:
String str = ((ActivityManager.RunningTaskInfo)this.am.getRunningTasks(1).get(0)).topActivity.getPackageName();
I wish to know is it possible to write an android app that when it runs at the background, it can track user activities?(Such as what other app did the user used, what phone number did user dial, the GPS location for user, etc) Cause I am not sure can a single android app react to other application, does anyone know the answer? Thanks
In the general case, no, you can't. And users would probably prefer it so.
Once this has been said, there are certain partial solutions. Sometimes the system is so helpful that it will publish Intents reflecting user actions: for example when the user uninstalls an app -- with the caveat that you don't get that intent on the app itself being uninstalled.
It used to be the case that before Jelly Bean (4.1) apps could read the log that other applications publish and try to extract info from there, but it was a cumbersome, error prone, ungrateful task. For example, the browser shows nothing when it navigates to a certain page. You may read the logs for a while with adb logcat to get a feeling of what was possible and what isn't. This action requires the relevant permission, which cannot be held by regular apps now.
Thanks to #WebnetMobile for the heads up about logs and to #CommonsWare for the link, see the comments below.
Yes you can.
You can look here for instance about phone info:
Track a phone call duration
or
http://www.anddev.org/video-tut_-_querying_and_displaying_the_calllog-t169.html
There is a way to let Android and users know you are using and accessing their data for them to determine if they will allow it.
I am unsure you can simply access any app, but in theory if you know how to read the saved files that might be possible.
For instance Runtime.getRuntime().exec("ls -l /proc"); will get you the "proc" root folder with lots of data you might need there. This might have been changed, I am not sure, and I also don't know what you need.
Perhaps to get running process try:
public static boolean getApplications(final Context context) {
ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
List<RunningTaskInfo> tasks = am.getRunningTasks(1);
}
For this to work you should include this in your AndroidManifest.xml
<uses-permission android:name="android.permission.GET_TASKS" />
See more about it: http://developer.android.com/reference/android/app/ActivityManager.html#getRunningAppProcesses%28%29
You certainly could but I think reporting that data back to you, unbeknownst to the user, via the internet, would be considered spyware and almost certainly illegal in most jurisdictions.
Fortunately spying users at that level should not be possible. Certain features can be achieved with abusing bugs in android which sooner than later will be fixed. I see absolutely no reason for you to know what number I am calling and where I've been lately. It's basically none of your business.
This question already has answers here:
Is it possible to detect Android app uninstall?
(8 answers)
Perform a task on uninstall in android [duplicate]
(4 answers)
Closed 7 years ago.
I though it was not possible but I noticed that NQ Mobile Security is able to show a message after I click on Uninstall and before the PackageUninstaller is called.
I would like to replicate this behavior in my App.
I tried with an Activity listening to "android.intent.action.DELETE" Intent, as suggested here:
How to know my app is uninstalled from the device...?
But as I'm about to uninstall my app, the chooser pops up asking to pick my application or the package uninstaller. How can I avoid this?
Is there a different way to intercept your application UNINSTALL event? (before answering that it is not possible, please try to uninstall NQ Mobile Security and see what happens. On my Android 2.3.4 it shows a nice screen saying that is not safe to go without a security app).
I noticed that NQ Mobile Security is able to show a message after I click on Uninstall and before the PackageUninstaller is called
They must be exploiting some security flaw in Android. I will research it and see if I can get it fixed. Apps are not supposed to get control at uninstall time.
Thanks for pointing this out!
Is there a different way to intercept your application UNINSTALL event?
I sure hope not.
Opera Max is an app that does something similar - after being uninstalled opens a webpage.
How do they do this?
By using libevent, from native code, they watch /data/data/com.opera.max directory to be removed and then post good old action.VIEW broadcast when it happens.
Install their app, run it, and on rooted device from adb shell remove /data/data/com.opera.max directory
UPDATE: I created a sample app that shows how it works. BTW it doesn't work with recent (KitKat+ I think) Android versions: https://github.com/pelotasplus/ActionAfterUninstall
I'm pretty sure that they are monitoring the LogCat to intercept when the Activity Manager calls the PackageUninstaller. I think they kill the task and start their own Activity.
It's pretty clever but it's definitely exploiting a security hole in Android.
They are likely asking for a very critical permission that the user is granting them unknowingly. Look at the "Permissions" tab for this app (as of 6/15/2012): https://play.google.com/store/apps/details?id=com.nqmobile.antivirus20&hl=en.
The list of permissions this app gets is downright chilling. Among other things:
SYSTEM TOOLS RETRIEVE RUNNING APPS Allows the app to retrieve
information about currently and recently running tasks. Malicious apps
may discover private information about other apps.
CHANGE/INTERCEPT NETWORK SETTINGS AND TRAFFIC Allows the app to change network settings
and to intercept and inspect all network traffic, for example to
change the proxy and port of any APN. Malicious apps may monitor,
redirect, or modify network packets without your knowledge.
PREVENT TABLET FROM SLEEPING PREVENT PHONE FROM SLEEPING Allows the app to
prevent the tablet from going to sleep. Allows the app to prevent the
phone from going to sleep.
CHANGE YOUR UI SETTINGS Allows the app to
change the current configuration, such as the locale or overall font
size.
MODIFY GLOBAL SYSTEM SETTINGS Allows the app to modify the
system's settings data. Malicious apps may corrupt your system's
configuration.
DISPLAY SYSTEM-LEVEL ALERTS Allows the app to show
system alert windows. Malicious apps may take over the entire screen.
MOUNT AND UNMOUNT FILESYSTEMS Allows the app to mount and unmount
filesystems for removable storage.
CHANGE NETWORK CONNECTIVITY Allows
the app to change the state of network connectivity.
CHANGE WI-FI STATE Allows the app to connect to and disconnect from Wi-Fi access
points, and to make changes to configured Wi-Fi networks.
-- Update --
I also found that the Android Package Manager pretty much just deletes a package if it is asked to do so. The only check it performs prior to doing so is whether the package being deleted is currently registered as having an active device admin:
try {
if (dpm != null && dpm.packageHasActiveAdmins(packageName)) {
Slog.w(TAG, "Not removing package " + packageName + ": has active device admin");
return PackageManager.DELETE_FAILED_DEVICE_POLICY_MANAGER;
}
} catch (RemoteException e) {
}
See line 6900 in PackageManagerService in the AOSP source here.
For this, the application must be explicitly registered as a device admin by the user. See notes on device administration here: http://developer.android.com/training/enterprise/device-management-policy.html.
As per https://stackoverflow.com/a/26829978/1317564, here is some example code that does it: https://github.com/zzljob/android-uninstall-feedback/blob/master/library/jni/feedback-uninstall.c. This won't actually stop the uninstall from taking place, but does provide a way to catch it and take some action. I'm honestly surprised that this works in Android and the team may have plugged the gap in recent releases.
is it possible somehow to listen to the events of the ActivityManager, e.g. when activities are started? Does the ActivityManager send broadcasts? I havn't found anything indicating that it does.
What I basically need to do: I want my app to launch one of my activities whenever a certain (thirdparty) app is launched/takes focus. Problem is this needs to happen before the thirdparty app is actually displayed.
What I have tried so far as workarounds:
Logcat output: I query logcat every 0.8s (filtered to show ActivityManager events only) but this eats up to many ressources
getRunningTasks: Slows down the phone a lot too and is not very safe, as an activity might be running but not currently in focus
Any ideas?
I suppose there is no actually other legacy way to handle glabal system state, only
(ActivityManager)getSystemService(Context.ACTIVITY_SERVICE);
ActivityManager.getRecentTasks() - Return a list of the tasks that are currently running, with the most recent being first and older ones after in order.
For details check docs
Perhaps though Android is a Linux you can run system tools like
Runtime.getRuntime().exec("ps -aux | grep smth")
But I think it would be hard to detect particular java application.
I think you can use the launch mode to determine which activity to launch to top level. Please check the question: Android singleTask or singleInstance launch mode?. Maybe it will help you.
I had a look in the android source, but there doesn't seem to be any events broadcasted.
https://android.googlesource.com/platform/packages/providers/ApplicationsProvider