APP和Service怎么判断是处于前台还是后台

转载:https://blog.csdn.net/rusbme/article/details/52241941

一. APP

1. RunningTask

原理: 
当一个 App 处于前台的时候,会处于 RunningTask 的这个栈的栈顶,所以我们可以取出 RunningTask 的栈顶的任务进程,看他与我们的想要判断的 App 的包名是否相同,来达到效果

缺点: 
getRunningTask 方法在 Android5.0 以上已经被废弃,只会返回自己和系统的一些不敏感的 task,不再返回其他应用的 task,用此方法来判断自身 App 是否处于后台,仍然是有效的,但是无法判断其他应用是否位于前台,因为不再能获取信息

<uses-permission android:name="android.permission.GET_TASKS" />  
    public static boolean isApplicationBroughtToBackground(final Context context) {
        ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
        List<ActivityManager.RunningTaskInfo> tasks = am.getRunningTasks(1);
        if (!tasks.isEmpty()) {
            ComponentName topActivity = tasks.get(0).topActivity;
            if (!topActivity.getPackageName().equals(context.getPackageName())) {
                return true;
            }
        }
        return false;
    }

2. RunningProcess

原理 
通过 runningProcess 获取到一个当前正在运行的进程的 List,我们找到与想要判断app包名一样的进程并判断这个进程的 importance 属性是否是前台进程,如果是那这个 App 就处于前台 
缺点: 
在聊天类型的 App 中,常常需要常驻后台来不间断的获取服务器的消息,这就需要我们把 Service 设置成 START_STICKY,kill 后会被重启(等待 5 秒左右)来保证 Service 常驻后台。如果 Service 设置了这个属性,这个 App 的进程就会被判断是前台,代码上的表现就是 appProcess.importance 的值永远是 ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND,这样就永远无法判断出到底哪个是前台了。

  public static boolean isBackground(Context context) {
        ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
        List<ActivityManager.RunningAppProcessInfo> appProcesses = activityManager.getRunningAppProcesses();
        for (ActivityManager.RunningAppProcessInfo appProcess : appProcesses) {
            if (appProcess.processName.equals(context.getPackageName())) {
                if (appProcess.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND) {
                    Log.i("后台", appProcess.processName);
                    return true;
                }else{
                    Log.i("前台", appProcess.processName);
                    return false;
                }
            }
        }
        return false;
    }

3. ActivityLifecycleCallbacks

public class Application extends ContextWrapper implements ComponentCallbacks2 {
    。。。
    public interface ActivityLifecycleCallbacks {
        void onActivityCreated(Activity activity, Bundle savedInstanceState);
        void onActivityStarted(Activity activity);
        void onActivityResumed(Activity activity);
        void onActivityPaused(Activity activity);
        void onActivityStopped(Activity activity);
        void onActivitySaveInstanceState(Activity activity, Bundle outState);
        void onActivityDestroyed(Activity activity);
    }
    。。。
}

Application类里有ActivityLifecycleCallbacks回调接口,我们在Application的onCreate()注册该接口。

一个app内从ActivityA跳转到ActivityB的回调方法如下: 
A.onPause() -> B.onStart() -> B.onResume() -> A.onStop()

通过这些回调我们可以在onStart()和onStop()中进行计数,如果start就+1,onstop就-1,这样可以根据计数是否为0来判断是否是前台了。

4. /proc目录下的process进程信息

原理: 
Linux系统内核会把process进程信息保存在/proc目录下,Shell命令去获取的他,再根据进程的属性判断是否为前台。 
优点: 
不需要任何权限 
可以判断任意一个应用是否在前台,而不局限在自身应用 
缺点: 

当/proc下文件夹过多时,此方法是耗时操作


二.Service

String serviceName = NotificationService.class.getName()

public static boolean isServiceRunning(Context context, String serviceName ) {  
        if (("").equals(serviceName) || serviceName == null)  
            return false;  
        ActivityManager myManager = (ActivityManager) context  
                .getSystemService(Context.ACTIVITY_SERVICE);  
        ArrayList<RunningServiceInfo> runningService = (ArrayList<RunningServiceInfo>) myManager
                .getRunningServices(1);  
        for (int i = 0; i < runningService.size(); i++) {  
            if (runningService.get(i).service.getClassName().toString()  
                    .equals(serviceName)) {  
                return true;  
            }  
        }  
        return false;  
    }  
}

猜你喜欢

转载自blog.csdn.net/luhuiwan1314/article/details/80691150