首页 > 解决方案 > 如何在运行时从 Android 应用程序读取 jar 文件中保存的 3rd 方资源列表

问题描述

我正在调查citeproc在我当前的 Android 应用程序中的使用

api 'de.undercouch:citeproc-java:2.0.0'
implementation 'org.citationstyles:styles:20.11'
implementation 'org.citationstyles:locales:20.11'

使用它工作正常

   // https://repo1.maven.org/maven2/com/eclipsesource/j2v8/j2v8/6.2.0/
    implementation(name: 'j2v8-6.2.0', ext: 'aar')

然而,当我在 Android 操作系统上运行时,CSL 静态方法

CSL.getSupportedStyles()

返回一个空列表。

该方法的底层代码如下:-

private static Set<String> getAvailableFiles(String prefix,
        String knownName, String extension) throws IOException {
    Set<String> result = new LinkedHashSet<>();

    // first load a file that is known to exist
    String name = prefix + knownName + "." + extension;
    URL knownUrl = CSL.class.getResource("/" + name);
    if (knownUrl != null) {
        String path = knownUrl.getPath();
        // get the jar file containing the file
        if (path.endsWith(".jar!/" + name)) {
            String jarPath = path.substring(0, path.length() - name.length() - 2);
            URI jarUri;
            try {
                jarUri = new URI(jarPath);
            } catch (URISyntaxException e) {
                // ignore
                return result;
            }
            try (ZipFile zip = new ZipFile(new File(jarUri))) {
                Enumeration<? extends ZipEntry> entries = zip.entries();
                while (entries.hasMoreElements()) {
                    ZipEntry e = entries.nextElement();
                    if (e.getName().endsWith("." + extension) &&
                            (prefix.isEmpty() || e.getName().startsWith(prefix))) {
                        result.add(e.getName().substring(
                                prefix.length(), e.getName().length() - 4));
                    }
                }
            }
        }
    }

    return result;
}

是否可以列出getAvailableFiles在 Android 操作系统上工作的 get 方法?

以下方法不起作用

   val name: String = "$prefix$knownName.$extension"
   val knownUrl: URL? = CSL::class.java.classLoader.getResource("$name")

我所需要的只是.cslEclipse java 项目中显示为驻留在styles-20.11.jar文件中的“”文件列表

当我提取我的应用程序 APK 文件时,“ .csl”文件都单独列出

我哪里错了?

如何获取.cslCSL 可用的所有“”文件的列表?

标签: androidclasspath

解决方案


您提供的详细信息指导我找到解决方案。这足以apk在检查条件中定义。

class CLSHelper {

    public static Set<String> getSupportedStyles() throws IOException {
        return getAvailableFiles("", "ieee", "csl");
    }

    /**
     * Customizing this function to able run in Android environment
     */
    private static Set<String> getAvailableFiles(String prefix,
                                                 String knownName, String extension) throws IOException {
        Set<String> result = new LinkedHashSet<>();

        // first load a file that is known to exist
        String name = prefix + knownName + "." + extension;
        URL knownUrl = CSL.class.getResource("/" + name);
        if (knownUrl != null) {
            String path = knownUrl.getPath();
            // get the jar or apk file containing the file
            if (path.endsWith(".jar!/" + name) || path.endsWith(".apk!/" + name)) { // changing this line
                String jarPath = path.substring(0, path.length() - name.length() - 2);
                URI jarUri;
                try {
                    jarUri = new URI(jarPath);
                } catch (URISyntaxException e) {
                    // ignore
                    return result;
                }
                try (ZipFile zip = new ZipFile(new File(jarUri))) {
                    Enumeration<? extends ZipEntry> entries = zip.entries();
                    while (entries.hasMoreElements()) {
                        ZipEntry e = entries.nextElement();
                        if (e.getName().endsWith("." + extension) &&
                                (prefix.isEmpty() || e.getName().startsWith(prefix))) {
                            result.add(e.getName().substring(
                                    prefix.length(), e.getName().length() - 4));
                        }
                    }
                }
            }
        }

        return result;
    }
}

输出:

CSL.getSupportedStyles()        // []
CLSHelper.getSupportedStyles()  // [dependent/annals-of-occupational-and-environmental-medicine, dependent/photoacoustics, dependent/statistical-science, twentieth-century-music, dependent/aims-medical-science, dependent/cell-systems, dependent/nursingplus-open, dependent/computer-science-review,...]

PS:要在 AndroidStudio 上运行,我必须在其中添加这些行build.gradle

android{
    ...
    packagingOptions {
        exclude 'META-INF/truffle/language'
    }
}

推荐阅读