Android随笔:关于生成jar包的问题

背景:工作中需要开发一个广告插件,并提供给其它人使用。这里就需要把自己的插件程序,打成jar来提供给他人引用。
但是遇到一个问题:插件程序中无法使用资源文件。

试过以下几种方式解决:

1、从插件程序中导出jar包
论坛上有人说导出的jar包中无法包含Drawable等资源文件,一些图片等数据,需要放到Assert文件中使用。
其实,关于这个问题,我做了尝试:
首先,需要说明导出jar包含什么文件是由你导出时选择来决定的,比如下图:
Android随笔:关于生成jar包的问题_第1张图片
如果你选择了res文件夹,则打包出的jar文件是可以包含res文件到。

但是包含文件并不代表可以使用。如果你想当然在插件程序中使用R.drawable.XXXX等方式获取
资源会报错!
当然别人通过R.XX.XX也只能看到自己的资源文件,而无法获取jar中的资源文件。

2、获取jar包中的文件

虽然无法直接引用资源文件,但是如果外边程序想获取某个资源文件时,也是可行的。
其原理是以数据流读取jar中指定的文件。
比如读取Assert文件下的icon.jpg文件:
你可以在插件中封装一个对外的方法:
public static Drawable getAssertDrawable(Context context,String fileName){
try {
InputStream inStream=context.getAssets().open(fileName);
return new BitmapDrawable(BitmapFactory.decodeStream(inStream));
} catch (IOException e) {
Log.e(LOG_TAG, "Assert中"+fileName+"不存在");
}
return null;
}
直接使用该方法可以得到文件。
后来又尝试在外部程序,直接使用context.getAssets().open(fileName)方法获取jar中文件,
让人喜出望外的是竟然成功了。呵呵!
后来分析,外部程序编译时,其实连同jar包中内容一起混编。jar包中的Assert文件会同外部程序的Assert一起
由AssertManager管理。
所以当你jar包中Assert内部文件和外部Assert中的文件有命名冲突时,编译器会报错的。

另外,还有人提供另外一种方法来读取诸如Drawable等文件夹下的文件。
public static Drawable getDrawableForJar(String resName,Class class){
InputStream inStream=class.getResourceAsStream(resName);
return new BitmapDrawable(BitmapFactory.decodeStream(inStream));
}
使用class.getResourceAsStream()方法读取,注意这里resName是文件的相对路径,比如jar根目录下res/drawable/icon.png,
则调用方法为:class.getResourceAsStream(/res/drawable/icon.png);

这里主要是采用ClassLoader的下面几个方法来实现:

  public URL getResource(String name);

  public InputStream getResourceAsStream(String name)

  public static InputStream getSystemResourceAsStream(String name)

  public static URL getSystemResource(String name)

  后两个方法可以看出是静态的方法,这几个方法都可以从Jar中读取图片资源,但是对与动画的gif文件,笔者在尝试过程中发现,存在一些差异。

  String gifName为Gif文件在Jar中的相对路径。

  (1)使用了两个静态方法

  BufferedImage image = ImageIO.read(ClassLoader.getSystemResourceAsStream(gifName));

  或者

  Image image = Toolkit.getDefaultToolkit().getImage(ClassLoader.getSystemResource(gifName));

  这两种方式可以成功地读取gif文件,但是对于gif动画,显示出来地是静态的。

  (2)使用其他两个方法

  Image image = Toolkit.getDefaultToolkit().getImage( this .getClass.getClassLoader()
.getResource(gifName));

  再这种方式下动画可以正常显示了。


3、使用library方法加载资源文件

在论坛中看到帖子讲述如何把工程作为libarary,让其他工程添加library,编译后会自动生成jar,然后在哪来使用。
当时看到此贴,喜出望外,所以赶紧尝试下!

方法:选择插件工程,右键选择属性,选择Android,勾选下面Is Liabrary选项。
然后,选择我们现有的工程,右键属性,选择Android,在library下add 相应的库。你会看到,刚才我们设置的插件项目,就在其中。最后,点击应用,完成。

详细步骤:

按如下方法设置:

1. 假设要引用的android工程叫LibProject,引入到的工程叫MainProject;

2. 设置LibProject,右键->Properties->Android,将Is library项选中,然后Apply;

3. 设置MainProject,右键->->Properties->Android, 在Library中,点击Add按钮,将LibProject工程加入,Apply即可。



你会看到我们的工程中多出插件工程的引用,而且可以使用R.XXX.XXX获取资源文件。

以为可以解决了,但是发现并没有生成想要的jar文件。在插件工程中,倒是有编译的class文件,却没有jar包。
而我们往往是不能像这样把原工程给别人直接引用的。
经过多次试验,始终没有生成jar,非常奇怪别人怎么弄得。。。

另外,拿以前通过这种方式生成的jar文件看,里面也不包含资源文件夹。。

所以最终确定,这种方式无法实现需求。

你可能感兴趣的:(Android,随笔)