1. 程式人生 > >判斷指定App是否位於前臺的方法

判斷指定App是否位於前臺的方法

原文地址:http://p.codekk.com/detail/Android/wenmingvs/AndroidProcess

提供6種方法來判斷App處於前臺還是後臺,並且封裝成工具類供大家使用

最後一種方法堪稱android黑科技(非原創),既可以突破Android5.0以上的許可權封鎖,獲取任意前臺App的包名,又不需要許可權,歡迎大家star我的新專案

2016.2.11更新------感謝@EffectiveMatrix大神帶來的新的判斷前後臺的方法

六種判斷方法展示

enter image description here

用法

傳入Context引數與想要判斷是否位於前臺的App的包名,會返回ture或者false表示App是否位於前臺


//六種方法任選其一

//使用方法一
Boolean isForeground = BackgroundUtil.getRunningTask(context, packageName);
//使用方法二
Boolean isForeground = BackgroundUtil.getRunningAppProcesses(context, packageName);
//使用方法三
Boolean isForeground = BackgroundUtil.getApplicationValue(context);
//使用方法四
Boolean isForeground = BackgroundUtil.queryUsageStats(context, packageName);
//使用方法五
Boolean isForeground = BackgroundUtil.getFromAccessibilityService(context, packageName);
//使用方法六
Boolean isForeground = BackgroundUtil.getLinuxCoreInfo(context, packageName);

六種方法的區別

方法 判斷原理 需要許可權 可以判斷其他應用位於前臺 特點
方法一 RunningTask Android4.0系列可以,5.0以上機器不行 5.0此方法被廢棄
方法二 RunningProcess 當App存在後臺常駐的Service時失效
方法三 ActivityLifecycleCallbacks 簡單有效,程式碼最少
方法四 UsageStatsManager 需要使用者手動授權
方法五 通過Android無障礙功能實現 需要使用者手動授權
方法六 讀取/proc目錄下的資訊 當proc目錄下資料夾過多時,過多的IO操作會引起耗時

方法一:通過RunningTask

enter image description here

原理
當一個App處於前臺的時候,會處於RunningTask的這個棧的棧頂,所以我們可以取出RunningTask的棧頂的任務程序,看他與我們的想要判斷的App的包名是否相同,來達到效果

缺點
getRunningTask方法在Android5.0以上已經被廢棄,只會返回自己和系統的一些不敏感的task,不再返回其他應用的task,用此方法來判斷自身App是否處於後臺,仍然是有效的,但是無法判斷其他應用是否位於前臺,因為不再能獲取資訊

方法二:通過RunningProcess

enter image description here

原理
通過runningProcess獲取到一個當前正在執行的程序的List,我們遍歷這個List中的每一個程序,判斷這個程序的一個importance 屬性是否是前臺程序,並且包名是否與我們判斷的APP的包名一樣,如果這兩個條件都符合,那麼這個App就處於前臺

缺點
在聊天型別的App中,常常需要常駐後臺來不間斷的獲取伺服器的訊息,這就需要我們把Service設定成START_STICKY,kill 後會被重啟(等待5秒左右)來保證Service常駐後臺。如果Service設定了這個屬性,這個App的程序就會被判斷是前臺,程式碼上的表現就是appProcess.importance的值永遠是 ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND,這樣就永遠無法判斷出到底哪個是前臺了。

方法三:通過ActivityLifecycleCallbacks

enter image description here

原理
AndroidSDK14在Application類裡增加了ActivityLifecycleCallbacks,我們可以通過這個Callback拿到App所有Activity的生命週期回撥。

 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);
    }

知道這些資訊,我們就可以用更官方的辦法來解決問題,當然還是利用方案二里的Activity生命週期的特性,我們只需要在Application的onCreate()裡去註冊上述介面,然後由Activity回調回來執行狀態即可。

可能還有人在糾結,我用back鍵切到後臺和用Home鍵切到後臺,一樣嗎?以上方法適用嗎?在Android應用開發中一般認為back鍵是可以捕獲的,而Home鍵是不能捕獲的(除非修改framework),但是上述方法從Activity生命週期著手解決問題,雖然這兩種方式的Activity生命週期並不相同,但是二者都會執行onStop();所以並不關心到底是觸發了哪個鍵切入後臺的。另外,Application是否被銷燬,都不會影響判斷的正確性

方法四:通過使用UsageStatsManager獲取

enter image description here

原理
通過使用UsageStatsManager獲取,此方法是Android5.0之後提供的新API,可以獲取一個時間段內的應用統計資訊,但是必須滿足一下要求

使用前提

  1. 此方法只在android5.0以上有效
  2. AndroidManifest中加入此許可權
    <uses-permission xmlns:tools="http://schemas.android.com/tools" android:name="android.permission.PACKAGE_USAGE_STATS" tools:ignore="ProtectedPermissions" />
    
  3. 開啟手機設定,點選安全-高階,在有權檢視使用情況的應用中,為這個App打上勾

enter image description here

方法五:通過Android自帶的無障礙功能

此方法無法直觀的通過下拉通知檢視來進行前後臺的觀察,請到LogCat中進行觀察即可,以下是LogCat中列印的資訊

enter image description here

原理
Android 輔助功能(AccessibilityService) 為我們提供了一系列的事件回撥,幫助我們指示一些使用者介面的狀態變化。 我們可以派生輔助功能類,進而對不同的 AccessibilityEvent 進行處理。 同樣的,這個服務就可以用來判斷當前的前臺應用

優勢

  1. AccessibilityService 有非常廣泛的 ROM 覆蓋,特別是非國產手機,從 Android API Level 8(Android 2.2) 到 Android Api Level 23(Android 6.0)
  2. AccessibilityService 不再需要輪詢的判斷當前的應用是不是在前臺,系統會在視窗狀態發生變化的時候主動回撥,耗時和資源消耗都極小
  3. 不需要許可權請求
  4. 它是一個穩定的方法,與 “方法6”讀取 /proc 目錄不同,它並非利用 Android 一些設計上的漏洞,可以長期使用的可能很大
  5. 可以用來判斷任意應用甚至 Activity, PopupWindow, Dialog 物件是否處於前臺

劣勢

  1. 需要要使用者開啟輔助功能
  2. 輔助功能會伴隨應用被“強行停止”而剝奪

方法六:讀取Linux系統核心儲存在/proc目錄下的process程序資訊

enter image description here

原理
無意中看到烏雲上有人提的一個漏洞,Linux系統核心會把process程序資訊儲存在/proc目錄下,Shell命令去獲取的他,再根據程序的屬性判斷是否為前臺

優點

  1. 不需要任何許可權
  2. 可以判斷任意一個應用是否在前臺,而不侷限在自身應用

缺點

  1. 當/proc下資料夾過多時,此方法是耗時操作

用法
獲取一系列正在執行的App的程序

List<AndroidAppProcess> processes = ProcessManager.getRunningAppProcesses();

獲取任一正在執行的App程序的詳細資訊

AndroidAppProcess process = processes.get(location);
String processName = process.name;

Stat stat = process.stat();
int pid = stat.getPid();
int parentProcessId = stat.ppid();
long startTime = stat.stime();
int policy = stat.policy();
char state = stat.state();

Statm statm = process.statm();
long totalSizeOfProcess = statm.getSize();
long residentSetSize = statm.getResidentSetSize();

PackageInfo packageInfo = process.getPackageInfo(context, 0);
String appName = packageInfo.applicationInfo.loadLabel(pm).toString();

判斷是否在前臺

if (ProcessManager.isMyProcessInTheForeground()) {
  // do stuff
}

獲取一系列正在執行的App程序的詳細資訊

List<ActivityManager.RunningAppProcessInfo> processes = ProcessManager.getRunningAppProcessInfo(ctx);

相關推薦

判斷指定App是否位於前臺方法

原文地址:http://p.codekk.com/detail/Android/wenmingvs/AndroidProcess 提供6種方法來判斷App處於前臺還是後臺,並且封裝成工具類供大家使用 最後一種方法堪稱android黑科技(非原創),既可以突破Andro

PHP判斷指定時間段的2個方法

有時我們需要在一天中的某個時間段進行某項任務,或者在一天中的不同小時裡進行不同的任務,使用PHP如何實現呢,下面的兩個例子都可以解決這個問題 一、包含小時和分鐘的判斷date_default_timezone_set("Asia/Shanghai"); $time = intval (date(

只要兩行程式碼,就能判斷一個App是否在前臺執行

公司最近做專案有這樣的一個需求:當App在前臺執行的時候,不接受推送通知;當App在後臺執行的時候,接受推送通知。很顯然,這是一個非常常見的功能,我們在微信或者QQ就能體驗到這樣的功能。 首先分析一下,假如我們需要完成這樣的一個功能,谷歌官方有沒有給我們提供現成的介面供我

安卓判斷APP是在前臺還是在後臺

安卓中判斷APP是否在前臺: 方法一:CCApplication 中判斷 private boolean mIsInForeground = false; public boolean isInForeground() { return mIsInForeground; }

U3D獲取IOS裝置所在時區、是否安裝指定APP判斷真機還是模擬器

  unity是無法直接獲取ios裝置資訊的,但是unity可以與IOS程式碼進行互動,這就可以完成你想要實現的功能了。   直接上程式碼: CheckCountry.h檔案: #import <Foundation/Foundation.h> @interface CheckCountry

【C#】判斷字串中是否包含指定字串,contains與indexof方法效率問題

1 class Program 2 { 3 private const int N = 10000000; 4 private static Stopwatch watch = new Stopwatch(); 5 static v

判斷指定的程序或程式是否存在方法小結(vc等)

一、判斷指定程式名的程序是否存在     BOOL EnumWindows( WNDENUMPROC lpEnumFunc, // pointer to callback function LPARAM lParam //   application-defined val

判斷當前 App 是否被切換到後臺的方法

有兩種方法: 1. 需要許可權  <uses-permission android:name="android.permission.GET_TASKS"/>, 普通App也可獲取,不需要確認,Android 5.1 之後已經廢棄,但是 compileSdkVe

判斷App整體處於前臺還是後臺

轉載請註明轉自:[noyet12的部落格](http://blog.csdn.net/u012975705) 部落格原址:http://blog.csdn.net/u012975705/article

mongodb 判斷座標是否在指定多邊形區域內的方法

MongoDB是一個基於分散式檔案儲存的資料庫,並提供建立基於地理空間的索引的能力,本文將使用MongoDB 基於地理空間索引進行座標所在區域的判斷及使用。 1.使用百度拾取座標工具,在地圖上定義多邊形的座標點,並把每個點的座標儲存。 多邊形的座標點如下

判斷app是否在前臺執行

     public static boolean isAppRunningForeground(String pkgname, Context context) {        boolean isAppRunning = false;        ActivityManager am = (Acti

怎麽判斷一個APP是原生APP、混合APP還是WEB APP ?

大眾點評 支付寶 開發者 文章 螞蟻 1、看斷網情況 通過斷開網絡,刷新頁面,觀察內容緩存情況來有個大致的判斷,可以正常顯示的就是原生寫的,顯示404或者錯誤頁面的就是html頁面。2、看布局編輯3、看復制文章的提示,需要通過對比才能得出結果。 比如文章資訊頁面可以長按頁面試試,如

在JSP使用EL中判斷指定元素是否存在於指定集合中

element span cti ems 頁面 指定元素 jsp 指定 col 在JSP使用EL中判斷指定元素是否存在於指定集合中 1、問題描述   在JSP頁面中使用EL表達式判斷一個指定元素是否存在於指定集合中? 2、問題解決   eg:指定集合:collection:

js實現獲取兩個日期之間篩選出指定周日制的方法

js var start = "2017-5-25"; var end = "2017-6-5"; var startTime = new Date(start); var endTime = new Date(end) var timeArr = []; var weekDay = ["1","2

判斷你的應用在前臺還是在後臺

keyword 優化 rdm span sap ber callback handle tex 我的嘗試 /** * 判斷應用是否是在後臺 */ public static boolean isBackground(Context conte

第一篇、Android Supersu 權限管理定制,隱藏過濾權限,指定APP最高權限

權限 一律 例如 mod 系統 權限管理 過濾 tracking 屏蔽 近期有個需求,在預裝ROM的時候,須要權限,可是又不同意全部的應用都有權限,僅僅同意自己的應用有最高的權限(當然沒有系統簽名情況下)。 所以。編譯了CM 提取了supersu進行了二次定制,讓他進行

Java指定保留小數位數的方法

小數位數 mode down ceil package style spa 直接 obj package com.qiyuan.util; import java.math.BigDecimal; import java.math.RoundingMode; impor

ios-APP後臺切前臺token處理

obj erro highlight str post res json cat true /* APP從後臺轉前臺調用的方法 */ - (void)applicationDidBecomeActive:(UIApplication *)application {

判斷圖連通的三種方法——dfs,bfs,並查集

題目 pan closed 節點 out esp cli div find Description 如果無向圖G每對頂點v和w都有從v到w的路徑,那麽稱無向圖G是連通的。現在給定一張無向圖,判斷它是否是連通的。 Input 第一行有2個整數n和m(0 <

Set集合判斷對象重復的方法

set集合 rgs pwd 依次 code style nbsp string類 println Set<User> userSet = new HashSet<>(); User user1= new User("aa","11"