Here is my scenario,
Suppose I have package name of some application, and presently I’m finding whether the application is running by passing the "packagename" to following method
boolean isNamedProcessRunning(String packageName){
if (packageName == null)
return false;
ActivityManager manager =
(ActivityManager) context.getSystemService(ACTIVITY_SERVICE);
List<RunningAppProcessInfo> processes = manager.getRunningAppProcesses();
for (RunningAppProcessInfo process : processes)
{
Log.e("", "----> processname "+process.processName);
if (packageName.equals(process.processName))
{
return true;
}
}
return false;
}
I know, by default android takes the package name as the process name. But if process property in application tag is defined in manifest file android:process="com.example.newprocessname" then the application will run with this name "com.example.newprocessname".
How to handle this scenario?
Try this
boolean isNamedProcessRunning(String packageName){
if (packageName == null)
return false;
ActivityManager manager =
(ActivityManager) this.getSystemService(ACTIVITY_SERVICE);
List<RunningAppProcessInfo> processes = manager.getRunningAppProcesses();
for (RunningAppProcessInfo process : processes)
{
for(int i = 0;i < process.pkgList.length; i++){
Log.e("", "----> pkg name "+ i + process.pkgList[i]);
if(process.pkgList[i].equals(packageName))
return true;
}
}
return false;
}
Use :
String arr[] = process.pkgList;
then compare the package name with arr items. It will give all packages that have been loaded into the process(As per doc).
Is it possible on Android to detect if another app is running? I need to trigger some action in my app when a Map application (like Waze or Google Maps) is running.
You can use ActivityManager class:
final ActivityManager activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
final List<RunningTaskInfo> recentTasks = activityManager.getRunningTasks(Integer.MAX_VALUE);
for (int i = 0; i < recentTasks.size(); i++)
{
Log.d("Executed app", "Application executed : " +recentTasks.get(i).baseActivity.toShortString()+ "\t\t ID: "+recentTasks.get(i).id+"");
}
Please be aware that this capability was deprecated in API level-21.
An alternative could be getRunningAppProcesses() method of ActivityManager.
I need create a function but I don't know how to get the PID of the app.
// here return -1 but I need PID to kill process
Integer PID1= android.os.Process.getUidForName("com.android.email");
android.os.Process.killProcess(PID1);
try
restartPackage code
ActivityManager aM = (ActivityManager);
getApplicationContext().getSystemService(getApplicationContext().ACTIVITY_SERVICE);
aM.restartPackage("com.android.email");
Kill BackGround Process Code
ActivityManager aM = (ActivityManager)
getApplicationContext().getSystemService(Catalogue.content_holder.getApplicationContext().ACTIVITY_SERVICE);
aM.killBackgroundProcesses("com.android.email");
Here is code which fetches all running Application and check wether email app is already running or not , if it is running then kill that process
ActivityManager manager = (ActivityManager) getApplicationContext.getSystemService(getApplicationContext.ACTIVITY_SERVICE);
List<RunningAppProcessInfo> activityes = ((ActivityManager)manager).getRunningAppProcesses();
for (int iCnt = 0; iCnt < activityes.size(); iCnt++){
System.out.println("APP: "+iCnt +" "+ activityes.get(iCnt).processName);
if (activityes.get(iCnt).processName.contains("com.android.email")){
android.os.Process.sendSignal(activityes.get(iCnt).pid, android.os.Process.SIGNAL_KILL);
android.os.Process.killProcess(activityes.get(i).pid);
//manager.killBackgroundProcesses("com.android.email");
//manager.restartPackage("com.android.email");
System.out.println("Inside if");
}
}
I need to create an app that is able to check when other apps are opened or closed ("on resume" or "on pause") on the device. I need to check the time of use of each app.
Can I do it without root access in the device?
try this code
ActivityManager activityManager = (ActivityManager) this.getSystemService( ACTIVITY_SERVICE );
List<RunningAppProcessInfo> procInfos = actvityManager.getRunningAppProcesses();
for(int i = 0; i < procInfos.size(); i++){
if(procInfos.get(i).processName.equals("com.android.browser")) {
Toast.makeText(getApplicationContext(), "Browser is running", Toast.LENGTH_LONG).show();
}
}
find the package name using download package name viewer
https://play.google.com/store/apps/details?id=com.gijoon.pkgnameviewer&hl=en
I wish to have one application that runs in the background, which knows when any of the built-in applications (messaging, contacts, etc) is running.
So my questions are:
How I should run my application in the background.
How my background application can know what the application currently running in the foreground is.
Responses from folks with experience would be greatly appreciated.
With regards to "2. How my background application can know what the application currently running in the foreground is."
Do NOT use the getRunningAppProcesses() method as this returns all sorts of system rubbish from my experience and you'll get multiple results which have RunningAppProcessInfo.IMPORTANCE_FOREGROUND. Use getRunningTasks() instead
This is the code I use in my service to identify the current foreground application, its really easy:
ActivityManager am = (ActivityManager) AppService.this.getSystemService(ACTIVITY_SERVICE);
// The first in the list of RunningTasks is always the foreground task.
RunningTaskInfo foregroundTaskInfo = am.getRunningTasks(1).get(0);
Thats it, then you can easily access details of the foreground app/activity:
String foregroundTaskPackageName = foregroundTaskInfo .topActivity.getPackageName();
PackageManager pm = AppService.this.getPackageManager();
PackageInfo foregroundAppPackageInfo = pm.getPackageInfo(foregroundTaskPackageName, 0);
String foregroundTaskAppName = foregroundAppPackageInfo.applicationInfo.loadLabel(pm).toString();
This requires an additional permission in activity menifest and works perfectly.
<uses-permission android:name="android.permission.GET_TASKS" />
Try the following code:
ActivityManager activityManager = (ActivityManager) newContext.getSystemService( Context.ACTIVITY_SERVICE );
List<RunningAppProcessInfo> appProcesses = activityManager.getRunningAppProcesses();
for(RunningAppProcessInfo appProcess : appProcesses){
if(appProcess.importance == RunningAppProcessInfo.IMPORTANCE_FOREGROUND){
Log.i("Foreground App", appProcess.processName);
}
}
Process name is the package name of the app running in foreground. Compare it to the package name of your application. If it is the same then your application is running on foreground.
I hope this answers your question.
i had to figure out the right solution the hard way. the below code is part of cyanogenmod7 (the tablet tweaks) and is tested on android 2.3.3 / gingerbread.
methods:
getForegroundApp - returns the foreground application.
getActivityForApp - returns the activity of the found app.
isStillActive - determines if a earlier found app is still the active app.
isRunningService - a helper function for getForegroundApp
this hopefully answers this issue in all extend (:
private RunningAppProcessInfo getForegroundApp() {
RunningAppProcessInfo result=null, info=null;
if(mActivityManager==null)
mActivityManager = (ActivityManager)mContext.getSystemService(Context.ACTIVITY_SERVICE);
List <RunningAppProcessInfo> l = mActivityManager.getRunningAppProcesses();
Iterator <RunningAppProcessInfo> i = l.iterator();
while(i.hasNext()){
info = i.next();
if(info.importance == RunningAppProcessInfo.IMPORTANCE_FOREGROUND
&& !isRunningService(info.processName)){
result=info;
break;
}
}
return result;
}
private ComponentName getActivityForApp(RunningAppProcessInfo target){
ComponentName result=null;
ActivityManager.RunningTaskInfo info;
if(target==null)
return null;
if(mActivityManager==null)
mActivityManager = (ActivityManager)mContext.getSystemService(Context.ACTIVITY_SERVICE);
List <ActivityManager.RunningTaskInfo> l = mActivityManager.getRunningTasks(9999);
Iterator <ActivityManager.RunningTaskInfo> i = l.iterator();
while(i.hasNext()){
info=i.next();
if(info.baseActivity.getPackageName().equals(target.processName)){
result=info.topActivity;
break;
}
}
return result;
}
private boolean isStillActive(RunningAppProcessInfo process, ComponentName activity)
{
// activity can be null in cases, where one app starts another. for example, astro
// starting rock player when a move file was clicked. we dont have an activity then,
// but the package exits as soon as back is hit. so we can ignore the activity
// in this case
if(process==null)
return false;
RunningAppProcessInfo currentFg=getForegroundApp();
ComponentName currentActivity=getActivityForApp(currentFg);
if(currentFg!=null && currentFg.processName.equals(process.processName) &&
(activity==null || currentActivity.compareTo(activity)==0))
return true;
Slog.i(TAG, "isStillActive returns false - CallerProcess: " + process.processName + " CurrentProcess: "
+ (currentFg==null ? "null" : currentFg.processName) + " CallerActivity:" + (activity==null ? "null" : activity.toString())
+ " CurrentActivity: " + (currentActivity==null ? "null" : currentActivity.toString()));
return false;
}
private boolean isRunningService(String processname){
if(processname==null || processname.isEmpty())
return false;
RunningServiceInfo service;
if(mActivityManager==null)
mActivityManager = (ActivityManager)mContext.getSystemService(Context.ACTIVITY_SERVICE);
List <RunningServiceInfo> l = mActivityManager.getRunningServices(9999);
Iterator <RunningServiceInfo> i = l.iterator();
while(i.hasNext()){
service = i.next();
if(service.process.equals(processname))
return true;
}
return false;
}
From lollipop onwards this got changed. Please find below code, before that user has to go Settings -> Security -> (Scroll down to last) Apps with usage access -> Give the permissions to our app
private void printForegroundTask() {
String currentApp = "NULL";
if(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
UsageStatsManager usm = (UsageStatsManager) this.getSystemService(Context.USAGE_STATS_SERVICE);
long time = System.currentTimeMillis();
List<UsageStats> appList = usm.queryUsageStats(UsageStatsManager.INTERVAL_DAILY, time - 1000*1000, time);
if (appList != null && appList.size() > 0) {
SortedMap<Long, UsageStats> mySortedMap = new TreeMap<Long, UsageStats>();
for (UsageStats usageStats : appList) {
mySortedMap.put(usageStats.getLastTimeUsed(), usageStats);
}
if (mySortedMap != null && !mySortedMap.isEmpty()) {
currentApp = mySortedMap.get(mySortedMap.lastKey()).getPackageName();
}
}
} else {
ActivityManager am = (ActivityManager)this.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningAppProcessInfo> tasks = am.getRunningAppProcesses();
currentApp = tasks.get(0).processName;
}
Log.e(TAG, "Current App in foreground is: " + currentApp);
}
In order to determine the foreground application, you can use for detecting the foreground app, you can use https://github.com/ricvalerio/foregroundappchecker. It uses different methods depending on the android version of the device.
As for the service, the repo also provides the code you need for it. Essentially, let android studio create the service for you, and then onCreate add the snippet that uses the appChecker. You will need to request permission however.
For cases when we need to check from our own service/background-thread whether our app is in foreground or not. This is how I implemented it, and it works fine for me:
public class TestApplication extends Application implements Application.ActivityLifecycleCallbacks {
public static WeakReference<Activity> foregroundActivityRef = null;
#Override
public void onActivityStarted(Activity activity) {
foregroundActivityRef = new WeakReference<>(activity);
}
#Override
public void onActivityStopped(Activity activity) {
if (foregroundActivityRef != null && foregroundActivityRef.get() == activity) {
foregroundActivityRef = null;
}
}
// IMPLEMENT OTHER CALLBACK METHODS
}
Now to check from other classes, whether app is in foreground or not, simply call:
if(TestApplication.foregroundActivityRef!=null){
// APP IS IN FOREGROUND!
// We can also get the activity that is currently visible!
}
Update (as pointed out by SHS):
Do not forget to register for the callbacks in your Application class's onCreate method.
#Override
public void onCreate() {
...
registerActivityLifecycleCallbacks(this);
}
Taking into account that getRunningTasks() is deprecated and getRunningAppProcesses() is not reliable, I came to decision to combine 2 approaches mentioned in StackOverflow:
private boolean isAppInForeground(Context context)
{
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP)
{
ActivityManager am = (ActivityManager) context.getSystemService(ACTIVITY_SERVICE);
ActivityManager.RunningTaskInfo foregroundTaskInfo = am.getRunningTasks(1).get(0);
String foregroundTaskPackageName = foregroundTaskInfo.topActivity.getPackageName();
return foregroundTaskPackageName.toLowerCase().equals(context.getPackageName().toLowerCase());
}
else
{
ActivityManager.RunningAppProcessInfo appProcessInfo = new ActivityManager.RunningAppProcessInfo();
ActivityManager.getMyMemoryState(appProcessInfo);
if (appProcessInfo.importance == IMPORTANCE_FOREGROUND || appProcessInfo.importance == IMPORTANCE_VISIBLE)
{
return true;
}
KeyguardManager km = (KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE);
// App is foreground, but screen is locked, so show notification
return km.inKeyguardRestrictedInputMode();
}
}
The ActivityManager class is the appropriate tool to see which processes are running.
To run in the background, you typically want to use a Service.
This worked for me. But it gives only the main menu name. That is if user has opened Settings --> Bluetooth --> Device Name screen, RunningAppProcessInfo calls it as just Settings. Not able to drill down furthur
ActivityManager activityManager = (ActivityManager) context.getSystemService( Context.ACTIVITY_SERVICE );
PackageManager pm = context.getPackageManager();
List<RunningAppProcessInfo> appProcesses = activityManager.getRunningAppProcesses();
for(RunningAppProcessInfo appProcess : appProcesses) {
if(appProcess.importance == RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
CharSequence c = pm.getApplicationLabel(pm.getApplicationInfo(appProcess.processName, PackageManager.GET_META_DATA));
Log.i("Foreground App", "package: " + appProcess.processName + " App: " + c.toString());
}
}
An easy solution is to use LiveData.
Create a singleton LiveData variable. (probably in a plain Kotlin file).
val foregroundHelper = MutableLiveData<Unit>()
Observe From Activity or Fragment:
foregroundHelper.observe(this, Observer {}) // for Activity
foregroundHelper.observe(viewLifecycleOwner, Observer {}) // for Fragments
Now from Your Background Service, Broadcast Receiver, etc:
val appIsVisibleToTheUser = foregroundHelper.hasActiveObservers()
// Now your logic goes.
if (!appIsVisibleToUser) {
// App is in background
// So In my case:
// I'm showing Notification to the user for the error happened in Background Service.
}
Thanks.
Do something like this:
int showLimit = 20;
/* Get all Tasks available (with limit set). */
ActivityManager mgr = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningTaskInfo> allTasks = mgr.getRunningTasks(showLimit);
/* Loop through all tasks returned. */
for (ActivityManager.RunningTaskInfo aTask : allTasks)
{
Log.i("MyApp", "Task: " + aTask.baseActivity.getClassName());
if (aTask.baseActivity.getClassName().equals("com.android.email.activity.MessageList"))
running=true;
}
In lollipop and up:
Add to mainfest:
<uses-permission android:name="android.permission.GET_TASKS" />
And do something like this:
if( mTaskId < 0 )
{
List<AppTask> tasks = mActivityManager.getAppTasks();
if( tasks.size() > 0 )
mTaskId = tasks.get( 0 ).getTaskInfo().id;
}
This is how I am checking if my app is in foreground. Note I am using AsyncTask as suggested by official Android documentation.`
`
private class CheckIfForeground extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... voids) {
ActivityManager activityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningAppProcessInfo> appProcesses = activityManager.getRunningAppProcesses();
for (ActivityManager.RunningAppProcessInfo appProcess : appProcesses) {
if (appProcess.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
Log.i("Foreground App", appProcess.processName);
if (mContext.getPackageName().equalsIgnoreCase(appProcess.processName)) {
Log.i(Constants.TAG, "foreground true:" + appProcess.processName);
foreground = true;
// close_app();
}
}
}
Log.d(Constants.TAG, "foreground value:" + foreground);
if (foreground) {
foreground = false;
close_app();
Log.i(Constants.TAG, "Close App and start Activity:");
} else {
//if not foreground
close_app();
foreground = false;
Log.i(Constants.TAG, "Close App");
}
return null;
}
}
and execute AsyncTask like this.
new CheckIfForeground().execute();
I combined two solutions in one method and it works for me for API 24 and for API 21. Others I didn't test.
The code in Kotlin:
private fun isAppInForeground(context: Context): Boolean {
val appProcessInfo = ActivityManager.RunningAppProcessInfo()
ActivityManager.getMyMemoryState(appProcessInfo)
if (appProcessInfo.importance == IMPORTANCE_FOREGROUND ||
appProcessInfo.importance == IMPORTANCE_VISIBLE) {
return true
} else if (appProcessInfo.importance == IMPORTANCE_TOP_SLEEPING ||
appProcessInfo.importance == IMPORTANCE_BACKGROUND) {
return false
}
val am = context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
val foregroundTaskInfo = am.getRunningTasks(1)[0]
val foregroundTaskPackageName = foregroundTaskInfo.topActivity.packageName
return foregroundTaskPackageName.toLowerCase() == context.packageName.toLowerCase()
}
and in Manifest
<!-- Check whether app in background or foreground -->
<uses-permission android:name="android.permission.GET_TASKS" />