如何识别拉起应用的包名

500 阅读2分钟

应用安全总是一个绕不过的话题,识别哪些应用拉起了我们,可以为我们做很多事情哦。这里对如何识别拉起我们应用的来源方案预研做个记录。

介绍下: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