另类获取安装列表的方式

直接上代码

public class HookGetAllPackages {
    // 有泄露 用application 防止多次注册代理
    static Context context;

    //获取安装列表检测
    public static void hookDelegate(Context scontext) throws Exception {
        if (context == scontext) {
            return;
        } else {
            context = scontext;
        }
        Log.e("loadContext", "successed 2");
        final PackageManager packageManager = context.getPackageManager();
        final Object iPackageManager = getBinderObject(packageManager);
        Class IPackageManagercls = Class.forName("android.content.pm.IPackageManager");
        Object iPackageManagerProxy = Proxy.newProxyInstance(packageManager.getClass().getClassLoader(), new Class[]{IPackageManagercls}, new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//                    if(!method.getName().equals("toStirng")){
//                        XposedHookUtilOPPOFindxFix.printStackLog(method.getName());
//                    }
//                    Log.e("loadContext",method.getName());
                Log.e("loadContext", method.getName());
                return method.invoke(iPackageManager, args);
            }
        });
        Field sServiceFiled = packageManager.getClass().getDeclaredField("mPM");
        sServiceFiled.setAccessible(true);
        sServiceFiled.set(packageManager, iPackageManagerProxy);
        Log.e("loadContext", "successed 3");
    }

    public static Object getBinderObject(final PackageManager packageManager) throws Exception {
        return getFieldValue(packageManager, "mPM");
    }

    public static Object getFieldValue(Object object, String fieldName) throws IllegalAccessException, NoSuchFieldException {
        Field field = getDeclaredField(object, fieldName);

        if (field == null) {
            throw new IllegalArgumentException("Could not find field [" + fieldName + "] on target [" + object + "]");
        }

        makeAccessible(field);

        Object result = null;

        result = field.get(object);
        return result;
    }

    public static void makeAccessible(Field field) {
        if (!Modifier.isPublic(field.getModifiers())) {
            field.setAccessible(true);
        }
    }

    public static Field getDeclaredField(Object object, String filedName) throws NoSuchFieldException {
        for (Class superClass = object.getClass(); superClass != Object.class; superClass = superClass.getSuperclass()) {
            return superClass.getDeclaredField(filedName);

        }
        return null;
    }

    //获取已安装列表 方法
    public static ArrayList getAllPackages(final Context context) {
        final ArrayList packages = new ArrayList<>();
        final PackageManager packageManager = context.getPackageManager();
        try {
            //高版本需要  hidden api 绕过
            final List allPackages = (List)
                    invokeMethod(getBinderObject(packageManager), "getAllPackages", null, null);
            packages.ensureCapacity(allPackages.size());
            for (final String packageName : allPackages) {
                Log.i("loadContext", packageName);
//                try {
//                    final PackageInfo info = packageManager.getPackageInfo(packageName, PackageManager.MATCH_UNINSTALLED_PACKAGES);
//                    Log.i(TAG, info.packageName);
//                    packages.add(info);
//                } catch (final PackageManager.NameNotFoundException e) {
//                    Log.e(TAG, "NameNotFoundException" + packageName);
//                } catch (final Exception e) {
//                    Log.e(TAG, packageName, e);
//                }
            }
        } catch (final InvocationTargetException e) {
            Log.e("loadContext", e.getTargetException().getMessage());
            packages.addAll(packageManager.getInstalledPackages(PackageManager.MATCH_UNINSTALLED_PACKAGES));
        } catch (final Exception e) {
            e.printStackTrace();
        }
        return packages;
    }

    public static Object invokeMethod(Object object, String methodName, Class[] parameterTypes,
                                      Object[] parameters) throws InvocationTargetException {
        Log.i("loadContext", object.getClass().getName());
        Method method = getDeclaredMethod(object, methodName, parameterTypes);
        if (method == null) {
            throw new IllegalArgumentException("Could not find method [" + methodName + "] on target [" + object + "]");
        }
        method.setAccessible(true);
        try {
            return method.invoke(object, parameters);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static Method getDeclaredMethod(Object object, String methodName, Class[] parameterTypes) {

        for (Class superClass = object.getClass(); superClass != Object.class; superClass = superClass.getSuperclass()) {
            try {
                return superClass.getDeclaredMethod(methodName, parameterTypes);
            } catch (NoSuchMethodException e) {
                //Method 不在当前类定义, 继续向上转型
            }
        }
        return null;
    }
}

你可能感兴趣的:(另类获取安装列表的方式)