android 判断应用是否在前台显示
在一些场景下我们需要知道应用是否在前台显示,当不在前台显示的时候,一些后台进程可以暂时停止,比如一些查询任务、不必要的线程、不需要的渲染等,以减少对设备资源的占用。判断应用是否在前台通常可以使用一下方式:
ActivityManager am = (ActivityManager) getSystemService(ACTIVITY_SERVICE); List<RunningTaskInfo> runnings = am.getRunningTasks(Integer.MAX_VALUE); for(RunningTaskInfo info : runnings){ if(info.topActivity.equals(activityName)){ Log.i("my","前台显示"); } }
因为系统api的变迁,也可以使用下面的方式:
ActivityManager am = (ActivityManager) getSystemService(ACTIVITY_SERVICE); List<RunningAppProcessInfo> runnings = am.getRunningAppProcesses(); for(RunningAppProcessInfo running : runnings){ if(running.processName.equals(getPackageName())){ if(running.importance == RunningAppProcessInfo.IMPORTANCE_FOREGROUND || running.importance == RunningAppProcessInfo.IMPORTANCE_VISIBLE){ //前台显示... }else{ //后台显示... } break; } }
这里后者判断加上了可见。比如,当用户点击了home键,这时候方法1和方法2都可以判断出来处于后台显示,然后再点击应用 再快速的打开其他的应用,这时候我们的应用就被其他应用盖在上面了,而方法1和方法2判断的结果都是在前台显示,这种情况下,就无法做出正确的判断,
通过研究和测试,发现使用下面的方式可以正确判断出来,方法如下:
public boolean isAppOnForeground(Context context) { ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); boolean isOnForground = false; List<ActivityManager.RunningAppProcessInfo> runnings = am.getRunningAppProcesses(); for (ActivityManager.RunningAppProcessInfo running : runnings) { if (running.processName.equals(getPackageName())) { if (running.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND || running.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE) { //前台显示... Log.e("my", "前台显示"); isOnForground = true; } else { //后台显示... Log.e("my", "后台显示"); isOnForground = false; } break; } } String currentPackageName = ""; if (am.getRunningTasks(1).size() > 0) { ComponentName cn = am.getRunningTasks(1).get(0).topActivity; currentPackageName = cn.getPackageName(); } // Log.e("my", "isAppOnForeground :" + currentPackageName + " getPackageName:" + getPackageName()); // return !TextUtils.isEmpty(currentPackageName) && currentPackageName.equals(getPackageName()); return isOnForground; }
下面的部分代码虽然没用到,但是不可省略,删去则不能正确判断。产生这个问题的原因,可能是因为线程管理进入list中时,必须需要同步安全的操作,找到对应的源代码如下:
public int addAppTask(@NonNull Activity activity, @NonNull Intent intent, @Nullable TaskDescription description, @NonNull Bitmap thumbnail) { Point size; synchronized (this) { ensureAppTaskThumbnailSizeLocked(); size = mAppTaskThumbnailSize; } final int tw = thumbnail.getWidth(); final int th = thumbnail.getHeight(); if (tw != size.x || th != size.y) { Bitmap bm = Bitmap.createBitmap(size.x, size.y, thumbnail.getConfig()); // Use ScaleType.CENTER_CROP, except we leave the top edge at the top. float scale; float dx = 0, dy = 0; if (tw * size.x > size.y * th) { scale = (float) size.x / (float) th; dx = (size.y - tw * scale) * 0.5f; } else { scale = (float) size.y / (float) tw; dy = (size.x - th * scale) * 0.5f; } Matrix matrix = new Matrix(); matrix.setScale(scale, scale); matrix.postTranslate((int) (dx + 0.5f), 0); Canvas canvas = new Canvas(bm); canvas.drawBitmap(thumbnail, matrix, null); canvas.setBitmap(null); thumbnail = bm; } if (description == null) { description = new TaskDescription(); } try { return ActivityManagerNative.getDefault().addAppTask(activity.getActivityToken(), intent, description, thumbnail); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } }