给定VectorDrawable的字节数组,如何从中创建VectorDrawable的实例?

时间:2019-11-24 21:45:54

标签: android apk androidx android-vectordrawable

背景

My app在设备存储区中找到APK文件,显示有关它们的信息并允许对其执行操作。

问题

自从Google添加了有关存储的新限制以来,我一直在寻找有关如何在未经存储许可的情况下解析APK文件的解决方案(因为该框架只能处理文件路径)。现在,我使用special legacy flag(requestLegacyExternalStorage)到allow me来处理文件路径,但这是直到下一版Android的临时解决方案。

我尝试和发现的东西

当前,使用workaroundlibrary(链接here),我成功获取了基本信息和应用名称,但对于图标却变得混乱了:错误的限定符,可以返回PNG而不是VectorDrawable,而VectorDrawable只是一个字节数组...

但是,即使我忽略了它的问题,我也尝试着查看各种VectorDrawable函数以及它的android-x函数(实际上是looked very promising),以尝试根据自己的能力创建一个实例。由于某种原因,我尝试的每个功能都无济于事。

问题

是否可以从字节码动态加载VectorDrawable?现在,我打算使用this library自己解析APK(因为可悲的是Google计划增加对文件的访问限制,以使用可怕的SAF),但可悲的是,对于VectorDrawable,它只有一个字节数组。 ..

请明确说明:我说的是从SAF访问APK文件(未安装文件,因为获取此信息仍然可以正常工作)。有了存储权限,它就可以正常工作(当然也可以与已安装的应用程序一起使用)。参见here。当您尝试在常规框架中使用SAF时,会得到不好的结果:一个字符串,其中包名称为app-name,默认图标为app-icon(或更糟糕的是:一个异常)。 另请注意:我知道我可以将文件复制到我自己的应用程序的存储中并仅使用框架,但这不是一个好的解决方案,因为如果我想在设备上显示有关所有APK文件的信息,那将是浪费时间和空间,只是为了获得图标和应用程序名称...我需要一种更直接的方法。一种处理速度最快的应用程序。

1 个答案:

答案 0 :(得分:1)

如果向量drawable的字节数组具有二进制XML形式,那么您应该可以通过将数组传递给我从previous answer采取的以下方法来创建它:

/**
 * Create a vector drawable from a binary XML byte array.
 * @param context Any context.
 * @param binXml Byte array containing the binary XML.
 * @return The vector drawable or null it couldn't be created.
 */
public static Drawable getVectorDrawable(@NonNull Context context, @NonNull byte[] binXml) {
    try {
        // Get the binary XML parser (XmlBlock.Parser) and use it to create the drawable
        // This is the equivalent of what AssetManager#getXml() does
        @SuppressLint("PrivateApi")
        Class<?> xmlBlock = Class.forName("android.content.res.XmlBlock");
        Constructor xmlBlockConstr = xmlBlock.getConstructor(byte[].class);
        Method xmlParserNew = xmlBlock.getDeclaredMethod("newParser");
        xmlBlockConstr.setAccessible(true);
        xmlParserNew.setAccessible(true);
        XmlPullParser parser = (XmlPullParser) xmlParserNew.invoke(
                xmlBlockConstr.newInstance((Object) binXml));

        if (Build.VERSION.SDK_INT >= 24) {
            return Drawable.createFromXml(context.getResources(), parser);
        } else {
            // Before API 24, vector drawables aren't rendered correctly without compat lib
            final AttributeSet attrs = Xml.asAttributeSet(parser);
            int type = parser.next();
            while (type != XmlPullParser.START_TAG) {
                type = parser.next();
            }
            return VectorDrawableCompat.createFromXmlInner(context.getResources(), parser, attrs, null);
        }

    } catch (Exception e) {
        Log.e(TAG, "Vector creation failed", e);
    }
    return null;
}

我还没有测试过它,但是我不明白为什么如果您的字节数组确实是矢量可绘制对象的二进制XML(即XmlPullParser和{{1 }}希望解析。

编辑:我尝试使用XmlPullParser创建这样的可绘制对象:

VectorDrawable

但是,此操作失败并发生以下异常:java.lang.ClassCastException:android.util.XmlPullAttributes无法转换为android.content.res.XmlBlock $ Parser。因此,这根本不可能回答您的评论。

相关问题