Android應用鎖之獲取棧頂Activity
1、在早期的安卓版本當中,我們可以使用ActivityManager. getRunningTasks 方法來獲取當前執行棧頂程式。
ActivityManager安卓官方API文件實現的核心程式碼如下:
List<PackageInfo> packages = getPackageManager(). getInstalledPackages(0); ActivityManager mActivityManager; mActivityManager = (ActivityManager) this.getSystemService( Context.ACTIVITY_SERVICE); ComponentName topActivity = mActivityManager. getRunningTasks(1).get(0).topActivity; String packageName = topActivity.getPackageName();
需要開啟這個許可權:需要注意的是:在官方文件裡面明確說明,該方法在sdk 21之後就被棄用了。This method was deprecated in API level 21.所以下面要介紹API 21之後的實現方式。
2、 Android 5.0下如何獲取棧頂Activity需要使用的是getRunningAppProcesses方法來實現。完整實現的程式碼如下:
String packname = ""; /* Android5.0之後獲取程式鎖的方式是不一樣的*/ if (Build.VERSION.SDK_INT > 20) { // 5.0及其以後的版本 List<RunningAppProcessInfo> tasks = am.getRunningAppProcesses(); if (null != tasks && tasks.size() > 0) { packname = tasks.get(0).processName; } } else{ // 5.0之前 // 獲取正在執行的任務棧(一個應用程式佔用一個任務棧) 最近使用的任務棧會在最前面 // 1表示給集合設定的最大容量 List<RunningTaskInfo> infos = am.getRunningTasks(1); // 獲取最近執行的任務棧中的棧頂Activity(即使用者當前操作的activity)的包名 packname = infos.get(0).topActivity.getPackageName(); }
需要說明的是,還有人提到了另外一種實現的方式,和這個略微不同,據說都能在Android 5.0 當中實現。具體的方式如下:
if (Build.VERSION.SDK_INT > 21) { // 5.0及其以後的版本 List<ActivityManager.AppTask> tasks = mActivityManager.getAppTasks(); if (null != tasks && tasks.size() > 0) { for (ActivityManager.AppTask task:tasks){ packageName = task.getTaskInfo().baseIntent.getComponent().getPackageName(); lable = getPackageManager().getApplicationLabel(getPackageManager().getApplicationInfo(packageName, PackageManager.GET_META_DATA)).toString(); //Log.i(TAG,packageName + lable); } } } else{ // 5.0之前 // 獲取正在執行的任務棧(一個應用程式佔用一個任務棧) 最近使用的任務棧會在最前面 // 1表示給集合設定的最大容量 List<RunningTaskInfo> infos = am.getRunningTasks(1); // 獲取最近執行的任務棧中的棧頂Activity(即使用者當前操作的activity)的包名 packageName = mActivityManager.getRunningTasks(1).get(0).topActivity.getPackageName(); //Log.i(TAG,packageName); }
另外還有一種方式,大家可以看一看,不過整個第二種都用的不多,所以大家也沒必要深究。
public void updateServiceNotification(String message) { if (!PreferenceUtils.getPrefBoolean(this, PreferenceConstants.FOREGROUND, true)) return; String title = PreferenceUtils.getPrefString(this, PreferenceConstants.ACCOUNT, ""); Notification n = new Notification(R.drawable.login_default_avatar, title, System.currentTimeMillis()); n.flags = Notification.FLAG_ONGOING_EVENT | Notification.FLAG_NO_CLEAR; Intent notificationIntent = new Intent(this, MainActivity.class); notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); n.contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT); n.setLatestEventInfo(this, title, message, n.contentIntent); startForeground(SERVICE_NOTIFICATION, n); } Runnable monitorStatus = new Runnable() { public void run() { try { L.i("monitorStatus is running... " + mPackageName); mMainHandler.removeCallbacks(monitorStatus); // 如果在後臺執行並且連線上了 if (!isAppOnForeground()) { L.i("app run in background..."); // if (isAuthenticated())//不判斷是否連線上了。 updateServiceNotification(getString(R.string.run_bg_ticker)); return;// 服務已在前臺執行,可以停止重複執行此任務 } else { stopForeground(true); } mMainHandler.postDelayed(monitorStatus, 1000L); } catch (Exception e) { e.printStackTrace(); L.i("monitorStatus:"+e.getMessage()); } } }
在後來的Android 5.1當中上述方法貌似都不能實現了,這是谷歌出於對使用者隱私的保護而採取的措施。
3、Android 5.1及以上的實現方式使用的方法是:usageStatsManager.queryUsageStats
要使用這個方法,需要在手機設定中開啟該應用的這個許可權。首先需要在manifest.xml當中加入下面的許可權:同時在手機當中也需要使用者手動開啟該許可權的開關。否則將不能獲取當前執行的應用。實現的核心程式碼如下:
private String getRunningApp() {
long ts = System.currentTimeMillis();
List<UsageStats> queryUsageStats = usageStatsManager.queryUsageStats(
UsageStatsManager.INTERVAL_BEST,ts-2000, ts);
if (queryUsageStats == null || queryUsageStats.isEmpty()) {
return null;
}
UsageStats recentStats = null;
for (UsageStats usageStats : queryUsageStats) {
if (recentStats == null ||
recentStats.getLastTimeUsed() < usageStats.getLastTimeUsed()) {
recentStats = usageStats;
}
}
return recentStats.getPackageName();
}
使用這個方法還有兩點需要加以注意:
1、首先要判斷應用是否已經獲取到UsageState的許可權,如果已經獲取,不用做別的操作。
2、應用沒獲取許可權,應當給出一個跳轉的方式,直接跳到該設定的頁面。針對這兩個問題,下面將給出是否有許可權和頁面跳轉的程式碼:
//判斷呼叫該裝置中“有權檢視使用許可權的應用”這個選項的APP有沒有開啟 private boolean isNoSwitch() { long ts = System.currentTimeMillis(); UsageStatsManager usageStatsManager = (UsageStatsManager) getApplicationContext() .getSystemService("usagestats"); List queryUsageStats = usageStatsManager.queryUsageStats( UsageStatsManager.INTERVAL_BEST, 0, ts); if (queryUsageStats == null || queryUsageStats.isEmpty()) { return false; } return true; } //然後就是跳轉的程式碼了: if (isNoOption()) { buttonGuide.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent( Settings.ACTION_USAGE_ACCESS_SETTINGS); startActivity(intent); } });
目前幾乎所有的應用鎖都採用的第3和第1的方式來實現,需要加一個判斷當前版本號的語句。在5.1之後我還沒有找到別的實現方式,如果大家有什麼更好的實現方式,歡迎留言討論。一個簡單的應用鎖實現,能夠在安卓5.1之後的系統完美執行。
https://github.com/liaoxd/asLockApp
原文連結:http://www.jianshu.com/p/eb531b2d1d8e
相關文章
- Android判斷當前棧頂Activity的包名Android
- Android獲取應用基本資訊Android
- android利用adb命令,獲取當前介面(當前Task的棧頂).Android
- Linux應用程式獲取執行緒棧的資訊Linux執行緒
- Android基礎之Activity 執行模式與回退棧Android模式
- 自制懸浮框,愉快地檢視棧頂 Activity
- Android獲取當前Activity的螢幕截圖Android
- Android開發16——獲取網路資源之基礎應用Android
- Android之ActivityAndroid
- Android探索之旅 | 用ADB獲取應用APK名AndroidAPK
- 解開Android應用程式元件Activity的"singleTask"之謎(3)Android元件
- Android Activity Deeplink啟動來源獲取原始碼分析Android原始碼
- android應用Dialog跳轉到ActivityAndroid
- Flutter獲取IOS bundle id和Android應用包名FlutteriOSAndroid
- android 5.0以上獲取前臺應用的包名Android
- Android逆向之旅---Android中如何獲取在非Root裝置中獲取應用隱私資料Android
- 完全理解android Activity啟動模式LauchMode (深入Activity與任務棧)Android模式
- android之使用signapk打包成系統應用,獲取系統許可權AndroidAPK
- Activity 知識梳理(2) Activity 棧
- flutter 獲取應用快取以及清除快取Flutter快取
- Android技術棧(一)從Activity遷移到FragmentAndroidFragment
- Android解析ActivityManagerService(二)ActivityTask和Activity棧管理Android
- Android之Activity全面解析Android
- Android Apt之Activity RouteAndroidAPT
- Android之獲取手機UDIDAndroid
- Android基本控制元件和Activity的基本應用Android控制元件
- android應用開發—獲取當前執行的services列表Android
- Android中獲取應用程式(包)的資訊-----PackageManager的使用(一)AndroidPackage
- Android中獲取應用程式(包)的大小-----PackageManager的使用(二)AndroidPackage
- 應用程式和Activity
- 棧(2)--棧的應用
- Android進階;Activity的棧與跳轉(筆記)Android筆記
- Android應用開發之(利用好圖片快取)Android快取
- 獲取棧中任意位置的元素
- Android 之 遠端圖片獲取和本地快取Android快取
- Linux應用程式設計:用一種討巧方式,來獲取執行緒棧的使用資訊Linux程式設計執行緒
- Web應用怎樣獲取Access Token?Web
- iOS 應用下載連結獲取iOS