Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
444 views
in Technique[技术] by (71.8m points)

android - Keep 'META-INF/services'-files in apk

I have a custom charset which is already working on JavaSE.

The class of my CharsetProvider is specified in a file java.nio.charset.spi.CharsetProvider which is located in META-INF/services and everything get's loaded normally and works as expected.

However now I'm using the lib on android as well, but the charset isn't loaded in Android-App.

How can I integrate my charset, so that it can be used like expected in an Android-App?

Charset.forName("MyCS");

At the moment I'm doing a workaround like this:

public static String decode(String encoding, byte[] buffer, int offset, int length) {
    String result = "";
    try {
        result = new String(buffer, offset, length, encoding);
    } catch (UnsupportedEncodingException ex) {
        MyCharsetProvider provider = new MyCharsetProvider();
        Charset cs = provider.charsetForName(encoding);
        if (cs == null) {
            Logger.getLogger(Converters.class.getName()).log(
                    Level.SEVERE,null,ex);
            result = new String(buffer, offset, length);
        } else {
            result = cs.decode(ByteBuffer.wrap(buffer, offset, length)).toString();
        }
    }
    return result;
}

Which works, but seems ineffective to me, since everytime I try to decode like this with my own charset, an exception will be thrown and a CharsetProvider-Object will be created.

The creation of course could be reduced by singleton pattern. But the issue is to avoid the direct usage of MyCharsetProvider entirely.

EDIT :

Since META-INF/services/java.nio.charset.spi.CharsetProvider is missing in the apk I though maybe proguard removes it. I then tried the following options in proguard.cfg:

-adaptresourcefilenames **.CharsetProvider
-adaptresourcefilecontents **.CharsetProvider

But the problem still persists. so how can I get these files from META-INF/services into my apk automatically using ant (netbeans)?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

ANT

I'm using the following solution now:

I created a custom_rules.xml with the followin targets to copy files in META-INF/services into the unaligned and unsigned apk.

<target name="-post-package" depends="-custom-copy" />

<target name="-copy-custom">
    <zip destfile="${out.packaged.file}"
         update="true"
         basedir="${source.absolute.dir}"
         includes="${custom.copy}" />
</target>

And in ant.properties I added the line

custom.copy=META-INF/services/**

Now I just have to copy relevant files from libraries to the META-INF/services-folder of my own project to include them in the apk. This gives me full control over which classes to be loaded by ServiceLoader.

Remark: Currently I only load implementations that are included in external Java-SE-jars this way. Obfuscation may have to be configured if the implementations are in an android-project.


ECLIPSE-PLUGIN

Using the eclipse-plugin, there's no workaround like in ANT. The problem is the ExportHelper (line 405) which just igores everything in META-INF folders.


Android-Studio/GRADLE

According to this Bug you may define a META-INF-directory in your main project and this will be packaged into your apk. META-INF-folders of libraries are excluded, so that you are forced to specify the implementations you want to use in your own project (I think this is the intention of it).


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...