在一些場景下我們需要知道應用是否在前台顯示,當不在前台顯示的時候,一些后台進程可以暫時停止,比如一些查詢任務、不必要的線程、不需要的渲染等,以減少對設備資源的占用。判斷應用是否在前台通常可以使用一下方式:
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(); } }