Android獲取棧頂的應用包名

有時候我們需要判斷棧頂的應用是否是我們的應用,於是獲取棧頂的應用包名的需求就出現了

在android5.0之前,系統有提供API藉口用於獲取TopActivity包名:

ActivityManager manager = (ActivityManager) getApplicationContext().getSystemService(ACTIVITY_SERVICE);
String currentClassName = manager.getRunningTasks(1).get(0).topActivity.getPackageName();

但在5.0之後,Google做了限制,getRunningTasks() 接口加了 @Deprecated 註解,被棄用了

但天無絕人之路,這邊有兩個方式可以獲取TopActivity的包名:

第一種:使用UsageStatsManager(適用於三方應用或者系統應用)

UsageStatManager是一個使用情況統計管理者,通過它可以獲取應用的使用情況,通過List集合來記錄APP的使用情況,通過UsageStats對象可以獲取包名,最後的在前臺的時間,在前臺的次數等等

需要權限:

<uses-permission android:name="android.permission.PACKAGE_USAGE_STATS"
         tools:ignore="ProtectedPermissions"/>

下面是獲取的方法:
ForegroundAppUtils:將獲取前臺包名等方法封裝成一個工具類

public class ForegroundAppUtil { 
	private static final long END_TIME = System.currentTimeMillis(); 
	private static final long TIME_INTERVAL = 7 * 24 * 60 * 60 * 1000L; 
	private static final long START_TIME = END_TIME - TIME_INTERVAL;

    // 獲取棧頂Activity包名
	public static String getForegroundActivityName(Context context) {
		String currentClassName = null; 
		if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { // 5.0之前,用getRunningTasks()接口
			ActivityManager manager = (ActivityManager)context.getApplicationContext()
			        .getSystemService(Context.ACTIVITY_SERVICE); 
			currentClassName = manager.getRunningTasks(1).get(0).topActivity.getPackageName(); 
		} else { // 5.0之後,用UsageStatManager
			UsageStats initStat = getForegroundUsageStats(context, START_TIME, END_TIME); 
			if (initStat != null) { 
				currentClassName = initStat.getPackageName(); 
			}
		} 
		return currentClassName; 
	}

    // 獲取記錄前臺應用的UsageStats對象
    private static UsageStats getForegroundUsageStats(Context context, long startTime, long endTime) {
    	UsageStats usageStatsResult = null; 
    	if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 
    		List<UsageStats> usageStatses = getUsageStatsList(context, startTime, endTime); 
    		if (usageStatses == null || usageStatses.isEmpty()) return null; 
    			for (UsageStats usageStats : usageStatses) { 
    				if (usageStatsResult == null || usageStatsResult.getLastTimeUsed()
    						< usageStats.getLastTimeUsed()) { 
    					usageStatsResult = usageStats; 
    				} 
    			} 
    		} 
    		return usageStatsResult; 
    }

    // 獲取記錄當前應用的UsageStats對象
    public static UsageStats getCurrentUsageStats(Context context, long startTime, long endTime) { 
    	if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 
    		List<UsageStats> usageStatses = getUsageStatsList(context, startTime, endTime); 
    		if (usageStatses == null || usageStatses.isEmpty()) return null; 
    		for (UsageStats usageStats : usageStatses) { 
    			if (TextUtils.equals(usageStats.getPackageName(), context.getPackageName())) { 
    				return usageStats; 
    			} 
    		} 
    	} 
    	return null; 
    }

    // 通過UsageStatsManager獲取List<UsageStats>集合
	public static List<UsageStats> getUsageStatsList(Context context, long startTime, long endTime) { 
		if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 
			UsageStatsManager manager = (UsageStatsManager) context.getApplicationContext()
                    .getSystemService(Context.USAGE_STATS_SERVICE);
            //UsageStatsManager.INTERVAL_WEEKLY,UsageStatsManager的參數定義了5個,具體查閱源碼 
			List<UsageStats> usageStatses = 
					manager.queryUsageStats(UsageStatsManager.INTERVAL_BEST, startTime, endTime); 
			if (usageStatses == null || usageStatses.size() == 0) { // 沒有權限,獲取不到數據 
				Intent intent = new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS);
				intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
				context.getApplicationContext().startActivity(intent); 
				return null;
			} 
			return usageStatses; 
		} 
		return null; 
	}

    // 判斷當前應用是否在前臺
    public static boolean isForegroundApp(Context context) { 
    	return TextUtils.equals(getForegroundActivityName(context), context.getPackageName()); 
    }

    // 獲取時間段內
    public static long getTotleForegroundTime(Context context) { 
    	UsageStats usageStats = getCurrentUsageStats(context, START_TIME, END_TIME);
    	if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 
    		return usageStats != null ? usageStats.getTotalTimeInForeground() : 0; 
    	} 
    	return 0; 
    }
}
第二種:在framework添加相關接口實現(適用於系統應用)
  • 在IActivityManager.aidl添加接口:
String getTopActPkg();
  • 在ActivityManager.java裏面添加實現:
 /**
 * @hide
 */
 public String getTopActPkg() {
     try {
         return getService().getTopActPkg();
     } catch (RemoteException e) {
         throw e.rethrowFromSystemServer();
     }
  }
  • 在ActivityManagerService.java添加具體實現:
@Override
public String getTopActPkg() throws RemoteException {
    return mTopActPackage;
}

其中mTopActPackage是一個私有全局變量,在private final ActivityRecord resumedAppLocked()方法return之前把該方法的局部變量pkg賦值給mTopActPackage進行初始化

  • 調用該接口獲取TopActivity的包名
public static String getForegroundActivityName(Context context) {
	ActivityManager activityManager =
	        (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
	String topPackage = activityManager.getTopActPkg();
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章