“天高云淡,望断南飞雁。不到长城非好汉,屈指行程二万。六盘山上高峰,红旗漫卷西风。今日长缨在手,何时缚住苍龙?”——《清平乐·六盘山》。假期里把《中国诗词大会》从头看到尾,最后发现要论诗词的气势,作者绝对是数一数二的。新的一年,第一篇博文就选这首诗吧,愿在新的一年里,能够早日“缚住苍龙”!
在做项目的时候,很多人都想把自己写的Module或者Libs或者Utils分享出来,一来可以在其他项目中方便用到之前写的东西,二来可以帮助提高效率。其中一个常用的办法就是采用jar包,jar包具有占用空间比较小,传输速度快,不易丢失文件等优点。
1、生成jar包
生成jar包,首先要对Module的build.gradle进行修改。
第3步,在main目录下创建assets文件夹,用于存放需要打包的资源文件,比如图片等;并将其放入assets文件夹中。当然,如果没有需要打包的资源文件,则直接跳过此步骤。
第4步,向android内添加方法代码,但是在实际过程中发现直接添加到最外面也可以。不需要打包资源文件的代码如下:
task makeJar(type: Copy) {
//删除存在的
delete 'build/libs/myjar.jar'
//设置拷贝的文件
from('build/intermediates/bundles/debug/')
//打进jar包后的文件目录
into('build/libs/')
//将classes.jar放入build/libs/目录下
//include ,exclude参数来设置过滤
//(我们只关心classes.jar这个文件)
include('classes.jar')
//重命名
rename ('classes.jar', 'myjar.jar')
}
makeJar.dependsOn(build)
需要打包资源文件的代码如下:
def SDK_BASENAME = "TestSdk";
def SDK_VERSION = "_V1.0";
def sdkDestinationPath = "build";
def zipFile = file('build/intermediates/bundles/release/classes.jar')
task deleteBuild(type: Delete) {
delete sdkDestinationPath + SDK_BASENAME + SDK_VERSION + ".jar"
}
task makeJar(type: Jar) {
from zipTree(zipFile)
from fileTree(dir: 'src/main',includes: ['assets/**'])//将assets目录打入jar包
baseName = SDK_BASENAME + SDK_VERSION
destinationDir = file(sdkDestinationPath)
}
makeJar.dependsOn(deleteBuild, build)
注意jar包的生成目录。
此时jar包中的代码访问jar包assets文件夹中的文件的方式需要进行修改。输出Bitmap时应该为:
BitmapFactory.decodeStream(context.getClass().getClassLoader().getResourceAsStream("assets/" + "previous.png"))
输出Drawable时应该为:
new BitmapDrawable(BitmapFactory.decodeStream(ctx.getClassLoader().getResourceAsStream("assets/" + "person.png")))
第5步,生成jar包。点击屏幕右侧的Gradle,找到makeJar并双击即可。
常见报错:(1)生成过程中,可能会由于代码中有switch-case语句和R.id.×××结合使得程序报错,只需将switch-case语句改为if-else语句即可。选中“switch”,按下Alt+Enter,选择replace with if-else即可。 (2)Error:与元素类型 "item" 相关联的 "name" 属性值不能包含 '<' 字符——不必理会,再试一次即可!
最后,jar包生成成功!
2、jar包的合并
遗憾的是,当一个项目有多个模块时,我们并不能将整个工程生成一个jar包导出,而只能一个一个地生成多个jar包。这样就使得新的项目需要进入jar包的数量很多,给以后的其他工作造成麻烦。这个困难可以采用合并jar包的方式来解决。多个jar包合并成一个jar包是使用Apache的Ant,它是一个基于Java的生成工具。这个工具的全名是another neat tool,可以到官网(https://ant.apache.org/bindownload.cgi)下载。
下载好了之后接下来就是解压和配置环境变量。
在命令框中输入ant 如果提示如下就表示你已经安装成功了
C:\Users\user>ant
Buildfile: build.xml does not exist!
Build failed
接下来开始使用。注意:ant默认运行build.xml文件,这个文件到目前为止是不存在的 需要我们创建。如果不想命名为build.xml,运行时可以使用 ant -buildfile test.xml 命令指明要运行的构建文件。build.xml 文件的格式如下:
<?xml version="1.0" encoding="utf-8"?>
<project
name="lzg_dlna"
basedir="D:\Android\android_tool\ant_test"
default="makeSuperJar" >
<target
name="makeSuperJar"
description="description" >
<jar destfile="lzg_dlna.jar" >
<zipfileset src="cdi-api.jar" />
<zipfileset src="http-2.2.1.jar" />
<zipfileset src="httpclient-4.2.2.jar"/>
<zipfileset src="httpcore-4.2.3.jar" />
<zipfileset src="javax.annotation_1.0.jar" />
<zipfileset src="javax.inject.jar" />
<zipfileset src="javax.servlet-3.0.0.v201103241009.jar" />
<zipfileset src="jetty-client-8.1.9.v20130131.jar" />
<zipfileset src="jetty-continuation-8.1.9.v20130131.jar" />
<zipfileset src="jetty-http-8.1.9.v20130131.jar" />
<zipfileset src="jetty-io-8.1.9.v20130131.jar" />
<zipfileset src="jetty-security-8.1.9.v20130131.jar" />
<zipfileset src="jetty-server-8.1.9.v20130131.jar" />
<zipfileset src="jetty-servlet-8.1.9.v20130131.jar" />
<zipfileset src="jetty-util-8.1.9.v20130131.jar" />
<zipfileset src="seamless-http-1.0-alpha2.jar" />
<zipfileset src="seamless-util-1.0-alpha2.jar" />
<zipfileset src="seamless-xml-1.0-alpha2.jar" />
<zipfileset src="slf4j-api-1.6.1.jar" />
<zipfileset src="slf4j-jdk14-1.6.1.jar" />
</jar>
</target>
</project>
其中,name : 表示的是你即将合成的jar包的名字 可以随便写;basedir : 表示你存放jar包的目录(D:\Android\android_tool\ant_test这个目录下放的是你当前需要合并的所有jar 和build.xml文件)。
以上都转备好之后开始运行ant -buildfile命令:ant -buildfile D:\Android\android_tool\ant_test\build.xml
3、jar包的导入与删除
导入时将jar包放入模块下libs文件夹中,右键->Add As Library或者在File->Project Structure中添加,如图所示:
删除时,操作顺序正好相反。
新年第一篇博客,就写到这里吧。祝大家新的一年里工作顺利,身体健康。
4、补充
最近查阅资料发现可以将资源文件放入项目中,在jar包中添加反射类,进而实现jar包的代码访问资源文件。反射率如下:
public class MResource {
public static int getIdByName(Context context, String className, String resName) {
String packageName = context.getPackageName();
int id = 0;
try {
Class r = Class.forName(packageName + ".R");
Class[] classes = r.getClasses();
Class desireClass = null;
for (Class cls : classes) {
if (cls.getName().split("\\$")[1].equals(className)) {
desireClass = cls;
break;
}
}
if (desireClass != null) {
id = desireClass.getField(resName).getInt(desireClass);
}
} catch (Exception e) {
e.printStackTrace();
}
return id;
}
}
使用方法如下:
setContentView(MResource.getIdByName(this, "layout", "jar_layout"));
ImageView mPlayerLogo = (ImageView) this.findViewById(MResource.getIdByName(this, "id", "logo"));
mPlayerLogo.setImageResource(MResource.getIdByName(this, "drawable", "ic_launcher"));
参考:
1、https://blog.csdn.net/qq_20328181/article/details/84333750
2、https://blog.csdn.net/xiayiye5/article/details/79639044
3、https://blog.csdn.net/asan855/article/details/48027563
4、https://blog.csdn.net/rightrat/article/details/4334046
5、https://blog.csdn.net/renwudao24/article/details/69071410