应用安全总是一个绕不过的话题,识别哪些应用拉起了我们,可以为我们做很多事情哦。这里对如何识别拉起我们应用的来源方案预研做个记录。
介绍下:UsageStatsManager,
这个系统服务主要有以下功能:提供对设备使用历史记录和统计信息的访问。使用数据汇总为时间间隔:天、周、月和年。 当请求特定时间以来的使用情况数据时,请求可能如下所示: 过去的请求_时间今天将来。 使用这个需要 android.permission.PACKAGE_USAGE_STATS 权限,需要设备的用户仍通过“设置”应用程序授予权限 代码如下
首先检查这个权限,没有的话需要到设置页面打开这个权限
/**
* 检查是否有android.permission.PACKAGE_USAGE_STATS权限
*
* @param context 上下文
* @return true有查询事件的能力,否则没有
*/
public static boolean checkUsageStatsPermission(Context context) {
AppOpsManager appOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
int mode;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.Q) {
mode = appOps.unsafeCheckOpNoThrow(AppOpsManager.OPSTR_GET_USAGE_STATS, android.os.Process.myUid(), context.getPackageName());
} else {
mode = appOps.checkOpNoThrow(AppOpsManager.OPSTR_GET_USAGE_STATS, android.os.Process.myUid(), context.getPackageName());
}
if (mode == AppOpsManager.MODE_DEFAULT && Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
return (context.checkCallingOrSelfPermission("android.permission.PACKAGE_USAGE_STATS") == PackageManager.PERMISSION_GRANTED);
} else {
return (mode == AppOpsManager.MODE_ALLOWED);
}
}
// 跳转到设置界面进行打开开关
startActivityForResult(new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS),1,null);
有了权限以后,获取下拉起我们进程的前面一个 进程名称
/**
* 获取拉起我们进程的应用包名
*
* @param context 上下文
* @return 返回获取拉起我们进程的应用包名,默认返回为空
*/
public static String getPreProcessPackageName(Context context) {
// 获取最近两秒的事件
long end = System.currentTimeMillis();
long start = end - 2000;
UsageStatsManager usageStatsManager = (UsageStatsManager) context.getSystemService(Context.USAGE_STATS_SERVICE);
UsageEvents usageEvents = usageStatsManager.queryEvents(start, end);
UsageEvents.Event event = new UsageEvents.Event();
String cuPackageName = context.getPackageName();
Stack<String> packageStack = new Stack<>();
while (usageEvents.hasNextEvent()) {
usageEvents.getNextEvent(event);
packageStack.push(event.getPackageName());
}
while (!packageStack.empty()) {
String pop = packageStack.pop();
if (pop != null && pop.equals(cuPackageName)) {
break;
}
}
if (packageStack.empty()) {
return "";
}
return packageStack.pop();
}
看代码也很清晰,我们进程启动的时候,向usage 服务查询下最近的两秒的应用包名,哪个应用在我们前面,高概率就是这个应用拉起了我们。 这个在有界面的拉起场景是可以的,其他的一些场景,不太准。 我尝试从源码里面来找一些捷径,待更新。有建议的话,请留言 liugstick@163.com