Android implementa la obtención de información IntentFilter de otras apps

Android no proporciona la función de obtener la información de intentFilter de los cuatro componentes principales, como obtener las definiciones de acciones en las actividades de otras aplicaciones, porque el campo IntentFilter se elimina de ComponentInfo devuelto por el sistema. información, sólo puede utilizar otros métodos. Aquí se presentan dos métodos. Uno es llamar al método getAllIntentFilters en PackageManager y devolver una colección List<IntentFilter>. Esta es la API del sistema y solo se puede llamar de forma reflexiva. Sin embargo, devuelve todos los filtros de intención y no hay información de componentes en ella. Entonces no lo sé. ¿En qué componente se encuentra? El otro es llamar a la clase PackageParser del sistema a través de la reflexión y analizar manualmente el apk para obtener toda la información de la aplicación. El tercer método es analizar directamente AndroidManifest.xml. Esto se puede implementar mediante un complemento de terceros o llamando a la clase AssetManager del sistema (para obtener información sobre el análisis xml de AssetManager, consulte otro artículo que escribí "Descompilación XML de Android Archivos de recursos"). El código para el segundo método se proporciona a continuación:

No es necesario reflejar la información de la llamada aquí. Creamos directamente una subclase del sistema y completamos la información requerida. Primero, creamos el paquete android.content.pm en el directorio de Java y luego creamos las dos clases siguientes para obtener el resultado final. información:

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;
}

Finalmente, el código de implementación específico:

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());
	
	//...
}

Supongo que te gusta

Origin blog.csdn.net/zzmzzff/article/details/130719451
Recomendado
Clasificación