您的位置:首页 > 移动开发 > Android开发

Android含资源文件引用的项目打包成jar包

2016-03-18 11:44 393 查看

一、发现问题

最近一个项目临到收尾,就差最后一步打包了~~但却遇到了一些小问题。这个项目里面用到Notification,用过notification的人都知道,notification必须设置小图标setSmallIcon(int icon),参数icon就是资源文件的Id。于是很简单,我把需要的资源文件一起打包成jar包就可以了;可是老大说,我们是产出SDK给第三方用的,而第三方可以把notification资源文件换成第三方自己的应用图标,意思就是我不能把资源文件一起打包;还是很简单,我只打包jar文件,不包含资源文件,到时候第三方在自己项目中添加对应名称的资源文件就OK啦~~可是,测试运行jar包,发现找不能资源文件。为什么??

二、分析问题

原来,问题出现在下面这句简单的代码:
builder.setSmallIcon(R.id.small_icon);
      这个代码我们常写,会有什么问题呢?问题就出现在R这个类。熟悉Eclipse项目结构的人都知道,会在 " /gen/包名/"  下面自动生成一个R.java类,例如:/gen/com.mobisummer.ads.banner/R.java 。而这个R类有点像数据库的索引表,把资源文件和ID对应起来,开发者可以通过id直接找到资源文件。所以,上面的代码是省略的,实际可以看成下面这样:
builder.setSmallIcon(com.mobisummer.ads.banner.R.id.small_icon);
所以,当在第三方项目中引用jar包,把资源文件直接放在第三方项目中,那么上面的代码当然找不到对应的资源了,因为jar包的包名和第三方项目的包名不一样,即是索引ID的包名和资源实际的包名不一致。那么,就没有办法了吗? 有,当然有。。。

三、方法一

这种方法的原理也很简单:上面说到出错原因是ID和资源的包名不一致,所以我们就婉转一点,不引用绝对的ID地址,而把ID改成相对的,即 “getPackageName().R.id.small_icon” 的形式,这样,不管第三方的包名是什么,都能索引到正确的包下面的资源了。当然,上面的形式是不符合代码格式的,所以android提供了专门的接口:
builder.setSmallIcon(getResources().getIdentifier("small_icon", "drawable", getPackageName()));
其中,第一个参数是资源的名字,第二个参数是资源的类型,例如drawable/ layout/ string等,第三个参数是目标项目的包名。这个实际就是,利用反射根据资源名字获取资源ID。当然,为了项目的模块化和结构优化,我们可以搞一个专门的类实现该功能,代码很简单,应该都能读懂,不多做分析,至于参数,代码里面有说明:
package com.mobisummer.ads.banner.util;import android.content.Context;import android.util.Log;public class MResource {/*** 根据资源的名字获取其ID值** @param context*            目标应用程序,一般通过getApplication()取得* @param className*            资源类型,如layout/id/drawable等* @param name*            资源的名称* @return*/public static int getIdByName(Context context, String className, String name) {String packageName = context.getPackageName();Class r = null;int id = 0;try {r = Class.forName(packageName + ".R");Class[] classes = r.getClasses();Class desireClass = null;for (int i = 0; i < classes.length; ++i) {if (classes[i].getName().split("\\$")[1].equals(className)) {desireClass = classes[i];break;}}if (desireClass != null)id = desireClass.getField(name).getInt(desireClass);} catch (ClassNotFoundException e) {e.printStackTrace();} catch (IllegalArgumentException e) {e.printStackTrace();} catch (SecurityException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();} catch (NoSuchFieldException e) {e.printStackTrace();}return id;}}
调用代码如下:
		builder.setSmallIcon(MResource.getIdByName(mContext.getApplicationContext(), "drawable", "small_icon"));
很简单吧~~~

四、方法二

这个方法的原理也很简单: 当自己的项目是为自己所用,或者代码可以公开给第三方时,将项目设置为引用库,在其他项目中添加这个库的引用即可。具体的操作就不自己写了, 直接从网上摘抄过来的,摘抄链接: http://blog.csdn.net/jia635/article/details/44004079 根据Android的官方文档,将其中一个项目设置为引用库,在另一个项目中添加这个库的引用。简单的做法是在被引用项目TestJar中的project.properties中添加一行
android.library=true
在引用的项目TestMain的project.properties中添加
 android.library=falseandroid.library.reference.1=../TestJar
其中1表示引用包的序号,“../TestJar”表示引用项目的路径在Eclipse中操作具体做法如下:把普通的android project设置成库项目库项目也是一个标准的Android项目,因此你先创建一个普通的Android项目,这个项目可以起任何的名称,任何的包名,设置其他需要设置的字段等。接着把项目设置成库项目,步骤如下:1)在Package Explorer中,鼠标右键项目文件夹(TestJar),点击Properties。2)在Properties窗口选择”Android“,Library属性显示在右下边。3)把”is Library“单选框选上,在点击Apply。4)点击OK关闭Properties。这时,这个项目就变成库项目了,当然纯的java项目也可以变成库项目,非常简单,执行上面四步就OK了。其他程序项目就可以引用这个库项目了。引用库项目如果你开发的应用程序想要调用库项目中的代码和资源,也easy哦,引用步骤如下:1)在Package Explorer中,鼠标右键项目文件夹(TestMain),点击Properties。2)在Properties窗口选择”Android“,Library属性显示在右下边。3)点击Add,打开了Project Selection对话框。4)从可用的库项目列表中选择要添加的库项目,点击OK。5)对话框关闭之后点击Apply,(在Properties窗口)。6)点击OK,关闭Properties窗口。完成以上六步,Eclipse会重建项目,把库项目中的内同包含进去。如果你想增加多个库项目的引用,使用up和down可以设置他们的相对的优先级和合并顺序。工具在合并引用的库的时候顺序是从低优先级(列表的下面)到高优先级(列表的上面)。 如果不只一个库定义了相同的资源ID,这个工具选择资源时会选择高优先级的资源。应用程序自身拥有最高的优先级。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: