在進行程序鎖開發的時候,我們會發現程序鎖實現的核心難點是如何監視應用程序的啟動,於是我們主要着手實現如何對應用程序的啟動進行監測,這個功能的實現經歷了三種方案的嘗試,也符合我們實際開發中的思路,具體的實現過程如下:
- 嘗試方案一
設想每個應用在啟動的時候會發送一個廣播,那么我們就能通過廣播接收者來訂閱這個廣播從而達到監視應用程序啟動的目的,於是我們在廣播接收者的動作名稱中去尋找這樣的廣播動作,但是很可惜系統並沒有為我們提供這樣一種廣播。
- 嘗試方案二
設想系統自身是否有一個服務對應用程序的啟動做監視,如果這個服務里面的一個方法能夠得到前台應用任務棧最頂端的 Activity,那么我們也能夠達到監視應用程序啟動的目的;一般情況下,系統的服務都是以 aidl 的形式出現的,這是因為系統底層的服務都封裝在 Application Framework 層,而開發者的調用是在 Applications 層,這種調用屬跨進程的調用,所以 Applications 層和 Application Framework 層的交互需要通過 aidl 來實現,於是我們就可以在系統源碼中查找與之相關的 aidl 文件,但是同樣系統也沒有提供這樣的一種服務。
- 嘗試方案三
設想應用程序在啟動過程中 LogCat 是否會對 Activity 的啟動進行記錄,於是我們嘗試啟動安卓手機上的系統應用計算器來觀察 LogCat 的日志,通過對日志的觀察我們發現 ActivityManager 可以檢測到應用的 Activity 的啟動,如下圖:
有了上面的信息,我們就可以從 ActivityManager 入手來實現監視應用程序的啟動,經過嘗試 ActivityManager 的 API 可以通過如下代碼來實現對應用程序啟動的監視了。
package cn.sunzn.activitymonitor; import java.util.List; import android.app.Activity; import android.app.ActivityManager; import android.app.ActivityManager.RunningTaskInfo; import android.content.ComponentName; import android.os.Bundle; import android.os.SystemClock; import android.util.Log; import android.view.Menu; /** * 程序運行需要在清單文件中添加 <uses-permission android:name="android.permission.GET_TASKS"/> */ public class MainActivity extends Activity { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); /** 獲取系統服務 ActivityManager */ ActivityManager manager = (ActivityManager) getSystemService(ACTIVITY_SERVICE); while (true) { /** 獲取當前正在運行的任務棧列表, 越是靠近當前運行的任務棧會被排在第一位,之后的以此類推 */ List<RunningTaskInfo> runningTasks = manager.getRunningTasks(1); /** 獲得當前最頂端的任務棧,即前台任務棧 */ RunningTaskInfo runningTaskInfo = runningTasks.get(0); /** 獲取前台任務棧的最頂端 Activity */ ComponentName topActivity = runningTaskInfo.topActivity; /** 獲取應用的包名 */ String packageName = topActivity.getPackageName(); /** 輸出檢測到的啟動應用信息 */ Log.i("sunzn", packageName); /** 為了便於觀察信息的輸出,程序休眠2秒 */ SystemClock.sleep(2000); } } public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.activity_main, menu); return true; } }
實現以上的代碼后,我們將該程序部署到模擬器進行測試,通過測試我們會發現被啟動的應用程序的包名都會被輸出到 LogCat 界面,這也就證明程序成功的檢測到了應用程序的啟動,所以程序鎖的實現即可以此為基礎將得到的包名與加鎖應用數據庫中的數據進行比對來實現應用程序啟動時 是否進行密碼驗證的功能。最后的測試圖如下,在下面的測試結果中我們可以發現程序成功的檢測到了瀏覽器和計算器的啟動。