Android implements obtaining IntentFilter information of other apps

Android does not provide the function of obtaining intentFilter information of the four major components, such as obtaining action definitions in activities of other applications, etc., because the IntentFilter field is deleted from the ComponentInfo returned by the system. If you want to obtain this information, you can only use other methods. Two methods are introduced here. One is to call the getAllIntentFilters method in PackageManager and return a List<IntentFilter> collection. This is the system api and can only be called reflectively. However, it returns all intentfilters and there is no component information in it, so I don’t know. Which component is it under? The other is to call the system PackageParser class through reflection and manually parse the apk to obtain all the application information. The third method is to directly parse AndroidManifest.xml. This can be implemented using a third-party plug-in, or by calling the system's AssetManager class (for information about AssetManager parsing xml, please refer to another article I wrote "Android Decompiling XML Resource Files"). The code for the second method is given below:

There is no need to reflect the call information here. We directly create a system subclass and fill in the required information. First, create the package android.content.pm in the java directory, and then create the following two classes to obtain the final information:

public class PackageParser$Package {
    //用到的字段
    public final ArrayList<PackageParser$Component> activities = new ArrayList<>(0);
    public final ArrayList<PackageParser$Component> receivers = new ArrayList<>(0);
    public final ArrayList<PackageParser$Component> providers = new ArrayList<>(0);
    public final ArrayList<PackageParser$Component> services = new ArrayList<>(0);

    //可以在这里添加其它字段,参考系统源码PackageParser.Package类
    //...
}

public class PackageParser$Component {
    public ArrayList<IntentFilter> intents;  //这个就是我们要的数据
    public String className; //这个类名也要有

    public Bundle metaData;
    public Package owner;

    public int order;

    ComponentName componentName;
    String componentShortName;
}

Finally, the specific implementation code:

public class PackageUtils {

    //根据包名获取Package信息
    public static PackageParser$Package getPackageInfo(Context context, String packageName) {
        ApplicationInfo info = null;
        try {
            info = context.getPackageManager().getApplicationInfo(packageName, 0);
            if (info.sourceDir != null) {
                return getPackageInfo(new File(info.sourceDir));
            }
        } catch (Exception e) {
            Log.e("walx", e.toString());
        }
        return null;
    }

    public static PackageParser$Package getPackageInfo(File apkFile) {
        try {
            Class<?> clazz = Class.forName("android.content.pm.PackageParser");
            Object packageParser = newInstance(clazz, null, null);
            PackageParser$Package pkg = (PackageParser$Package) invokeMethod(packageParser, "parsePackage", new Class[]{File.class, int.class}, new Object[]{apkFile, 0});
            return pkg;
        } catch (Exception e) {
            Log.e("walx", e.toString());
        }
        return null;
    }

    private static Object newInstance(Class clazz, Class[] argsType, Object[] args) {
        Object instance = null;
        try {
            Constructor constructor;
            if (argsType == null) {
                constructor = clazz.getConstructor();
                constructor.setAccessible(true);
                instance = constructor.newInstance();
            } else {
                constructor = clazz.getConstructor(argsType);
                constructor.setAccessible(true);
                instance = constructor.newInstance(args);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return instance;
    }

    private static Object readField(Object object, String name) {
        try {
            Field field = object.getClass().getField(name);
            field.setAccessible(true);
            return field.get(object);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    private static Object invokeMethod(Object object, String name, Class[] argsType, Object[] args) {
        try {
            Method method = object.getClass().getMethod(name, argsType);
            method.setAccessible(true);
            return method.invoke(object, args);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}
//调用测试

PackageParser$Package pkgInfo = PackageUtils.getPackageInfo(this, "com.android.settings");
if (pkgInfo != null) {
	Log.i(TAG, "activities:" + pkgInfo.activities.size());
	Log.i(TAG, "receivers:" + pkgInfo.receivers.size());
	Log.i(TAG, "providers:" + pkgInfo.providers.size());
	Log.i(TAG, "services:" + pkgInfo.services.size());
	
	//...
}

Guess you like

Origin blog.csdn.net/zzmzzff/article/details/130719451