最近接到一个新的需求,需要得到运行在前台应用的上一个应用的包名,比如我现在正在使用音乐播放器,这时候由于某种原因开启了另外一个应用,我需要在新开启的应用中拿到音乐播放器的包名。
实现这个需求尝试过几个方法,具体实现情况如下:
1、getRunningTasks() :获取当前打开的所有应用程序,但是这个方法只能拿到最顶层的也就是显示在前台的应用包名,无法满足需求,且在Android5.0后该方法已经失效。
ActivityManager manager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningTaskInfo> localList = manager.getRunningTasks(Integer.MAX_VALUE);
if (localList != null && localList.size() > 0) {
for (ActivityManager.RunningTaskInfo info : localList) {
Log.d("TAG", "ID : " + info.id + " " + info.topActivity.getPackageName() + " " + info.baseActivity.getPackageName());
/*if (containsTaskID(info.id)) {
return info.topActivity;
}*/
}
}
2、getRunningAppProcesses() :获取正在运行的所有应用程序的进程,在Android6.0后该方法失效,使用该方法只能获取到顶层应用信息,如果要获取列表需要系统签名或者修改Framework代码,后来我用Android4.4.2的模拟器试了一下,确实获取到了正在运行的应用列表,但是顺序是打乱的,无法确定哪个是上一个位于前台的应用。
ActivityManager mActivityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
// 通过调用ActivityManager的getRunningAppProcesses()方法获得系统里所有正在运行的进程
List<ActivityManager.RunningAppProcessInfo> appProcessList = mActivityManager.getRunningAppProcesses();
for (ActivityManager.RunningAppProcessInfo appProcess : appProcessList) {
int pid = appProcess.pid; // pid
String processName = appProcess.processName; // 进程名
String[] pkgNameList = appProcess.pkgList; // 获得运行在该进程里的所有应用程序包
}
3、UsageStatsManger类:Android5.0后新加类,用来获取应用的使用统计信息,调用他的queryUsageStats方法来获得应用的启动历史记录,通过启动时间来判断应用启动的先后顺序,下面来分析一下使用方法:
(1)添加权限
<uses-permission android:name="android.permission.PACKAGE_USAGE_STATS"
tools:ignore="ProtectedPermissions" />
(2)在代码中动态设定权限,并获取指定时间范围内的应用列表的统计信息列表
第一步添加的权限,是允许查看应用的使用情况的权限,由于Android5.0以下是没有该权限设置页面的,所以要判断一下安卓版本。
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
//得到UsageStatsManager对象
UsageStatsManager manager = (UsageStatsManager) context.getApplicationContext().getSystemService(Context.USAGE_STATS_SERVICE);
//获取指定时间范围内的应用统计信息列表
/**
* queryUsageStats : 获取应用统计信息
* 参数一:intervalType:时间间隔类型,有五种
* INTERVAL_DAILY: 日长短级别数据,最长7天内的数据;
* INTERVAL_WEEKLY: 星期长短级别数据,最长4个星期内的数据;
* INTERVAL_MONTHLY: 月长短级别数据,最长6个月内的数据;
* INTERVAL_YEARLY: 年长短级别数据,最长2年内的数据,也就是说,数据最长保存2年;
* INTERVAL_BEST: 根据提供的时间间隔(根据与第二个参数和第三个参数获取),自动搭配最好的级别
* 参数二:beginTime:开始统计的时间
* 参数三: endTime:结束的时间
*/
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;
}
(3)拿到应用列表后,获取前台应用的记录信息,得到上一个在前台的应用
UsageStats usageStatsResult = null;
List<UsageStats> livingUsageStates = new ArrayList<>();
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 (usageStats.getLastTimeUsed() > 0) {
Log.d("TAG", " " + usageStats.getLastTimeUsed() + " " + usageStats.getPackageName());
livingUsageStates.add(usageStats);
}
}
// 按照使用时间对应用进行排序
Collections.sort(livingUsageStates, new Comparator<UsageStats>() {
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@Override
public int compare(UsageStats o1, UsageStats o2) {
if (o1.getLastTimeUsed() > o2.getLastTimeUsed()) {
return -1;
} else {
return 1;
}
}
});
for (int i = 0; i < livingUsageStates.size(); i++) {
//打印应用的最后使用时间以及应用包名
Log.d("TAG", " " + livingUsageStates.get(i).getLastTimeUsed() + " " + livingUsageStates.get(i).getPackageName());
}
usageStatsResult = livingUsageStates.get(1);
}
(4)得到上一个在前台得应用包名
UsageStats initStat = getForegroundUsageStats(context, START_TIME, END_TIME);
if (initStat != null) {
currentClassName = initStat.getPackageName();
}
总结:大体逻辑基本这样,可能细节之处还有不足需要调整,希望能给有该需求的开发人员一个参考。