我要當學霸這款App有個學習監督的功能,當你啟動它的時候,你將無法使用其他App,以此達到幫助人提高自覺性,起到監督學習的效果。最近和同學做了個小App,正好有這個功能,所以就來說說它是怎么實現的。
PS:本篇描述的是我們做這個小App過程中的一些嘗試。
效果
首先還是先來看下效果是怎么樣的:
實現思路
先說下我們這個小App的功能:學習監督的功能(即禁掉其他App的使用) + 桌面小寵物(用來給用戶提示的)。
從上圖也可以看出,當啟動我們這個小App時,開啟監督功能后,再點擊其他App(如QQ)的時候,桌面小寵物是會給出一些溫馨提示的,然后再把剛才你打開的App關閉掉。
那么它是怎么實現呢?首先我們肯定需要監測到用戶打開了什么App,那這點怎么實現呢?
1. getRunningTasks()
最開始想到的是能否用Activity堆棧,也就是ActivityManager里的一個getRunningTasks()方法,調用這個方法也就可以獲取當前正在運行中的任務棧,而處於棧頂的也就是我們在這個時刻打開的App。我們只要不斷地讀取這個任務棧,也就能達到了監測用戶打開App的功能了,完美解決。
但很遺憾,使用的時候才發現這個方法已經被拋棄了。我們看下源代碼里怎么說的:
也就是說在安卓5.0以上的機器,這個方法已經不再為第三方應用使用的了。所以只能另想辦法了。
2. getRunningAppProcesses()
接下去沒思路了,就到網上隨便搜一些關鍵詞,出來了很多博客,有說用getRunningAppProcesses(),先看下這個方法的介紹:
返回正在運行中的應用進程集合,然后再通過進程找到對應的包名就可以了。可是返回的集合序列並沒有什么特定的排序方式,也就是隨機的,那么我們該怎么判斷哪個進程才是剛打開的App創建的呢?
要么可以先指定一些應用程序,只要判斷返回的集合里有我們指定的應用程序,那么就可以判斷是打開了那個應用。
要么可以比較上一時刻返回的集合和這一時刻返回的集合,對比看多了哪些進程,少了哪些進程也就可以判斷出打開或關閉了某個應用。
好,實現的思路大概有了,接下去可以敲代碼了。當敲完在真機上測試時,發現不管怎么樣返回的都只有該應用的信息。
網上搜了下,發現這個方法權限又被官方弱化了:
我測試用的真機是5.0.+的安卓系統,網上也有解釋說有的手機廠家在5.0版本上就已經弱化了getRunningAppProcesses的權限,難怪只會返回應用本身的信息。可這樣一來就又跟第一個思路一樣了,這個方法也不能采用了。
3. Linux系統內核會把process進程信息保存在/proc目錄下
上面兩種思路都不行,只能再找思路了,后來在stackoverflow中,無意間搜到了國外一牛人的解決方法,他是利用Linux系統的漏洞,Linux系統內核會把process進程信息保存在/proc目錄下,只要讀取到進程信息,就可以根據進程的屬性來判斷是否是前台進程了。這個牛人還把它封裝成了個開源項目,附上Github地址:https://github.com/jaredrummler/AndroidProcesses。
這樣一來就可以獲取到所有的進程信息,但就算拿到所有進程信息又要怎么通過進程判斷出用戶打開了哪個App呢?
進程有個屬性可以用來區分它是前台進程還是后台進程,關於這兩者的區別我不是很理解,但我猜想,是否可以將前台進程類比成正在運行中的進程?如果可以這樣,那么再利用第2個思路中提到的方案,就可以實現監測用戶打開App的功能了。
於是,我便去嘗試一下。后來真機測試時,發現當打開大多數應用時都可以達到預期的效果。但是有個別應用無論用戶打開與否,總能被檢測到是處於前台進程中,后來在網上發現有人這么解釋:
在聊天類型的App中,常常需要常駐后台來不間斷的獲取服務器的消息,這就需要我們把Service設置成START_STICKY,kill 后會被重啟(等待5秒左右)來保證Service常駐后台。如果Service設置了這個屬性,這個App的進程就會被判斷是前台,代碼上的表現就是appProcess.importance的值永遠是 ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND,這樣就永遠無法判斷出到底哪個是前台了。
於是,這個思路也只能放一邊了。
4. 某大神總結
嘗試了各種方法,始終達不到想要的效果。一次偶然情況下,在Github搜到了完美的解決方案,先附上Github地址:https://github.com/wenmingvs/AndroidProcess。
你可以看到這個大神,對監測運行中的進程進行了非常詳細的講解,而且列舉了目前能實現的各種方法,也分別介紹了各自的優缺點。
得益於這個大神的分享,我把它的項目clone下來學習,最后選擇了方法五:通過Android無障礙功能實現。
至此,監測用戶打開App的功能終於可以實現,有點不足的是每次使用需要用戶自己授權,可能會引起用戶反感,但想想也是,這種涉及安全性問題的,如果不通過用戶自行授權,就好像有點惡意軟件的嫌疑了,hhh。
(小小吐槽:早知道有這么個大神給出了這么詳細的介紹,我就不用自己花那么多時間去各種嘗試了。哭喪臉)
好了,監測用戶打開App的功能解決了,那么剩下的就是實現桌面寵物了。這個挺簡單的,也就是懸浮窗,只是在布局文件里換成動圖而已,而要實現動圖,這里是使用的也是一個開源項目:android-gif-drawable。
之后只需要當監測到用戶打開App時,發送廣播通知我們的App,做出一些相應的動作,比如桌面寵物給出溫馨提示、關閉用戶打開的App等等。
最近剛開通了公眾號,想激勵自己堅持寫作下去,初期主要分享原創的Android或Android-Tv方面的小知識,感興趣的可以點一波關注,謝謝支持~~