Determining the current foreground application from a background task or service

后端 未结 13 1429
我寻月下人不归
我寻月下人不归 2020-11-22 02:29

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

相关标签:
13条回答
  • 2020-11-22 02:45

    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.

    0 讨论(0)
  • 2020-11-22 02:47

    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());
                        }               
                    }
    
    0 讨论(0)
  • 2020-11-22 02:48

    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" />
    
    0 讨论(0)
  • 2020-11-22 02:49

    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;
    }
    
    0 讨论(0)
  • 2020-11-22 02:51

    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();
            }
        }
    
    0 讨论(0)
  • 2020-11-22 02:52

    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);
    }
    
    0 讨论(0)
提交回复
热议问题