如何在运行时从 Android 应用程序读取 jar 文件中保存的第三方资源列表

How to read list of 3rd party resources held in jar files from Android Application at runtime

我正在调查 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 OS CSL 静态方法

CSL.getSupportedStyles()

returns 一个空列表。

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

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

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

以下方法无效

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

我只需要在 Eclipse java 项目中显示为驻留在 styles-20.11.jar 文件

中的“.csl”文件列表

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

我哪里错了?

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

你提供的详细信息指导我找到解决方案。这足以在检查器条件中定义 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,...]

P.S:要在 AndroidStudio 上 运行,我必须在 build.gradle

中添加这些行
android{
    ...
    packagingOptions {
        exclude 'META-INF/truffle/language'
    }
}