Android Studio 打包Jar
2017-07-17 17:43
274 查看
晨鸣的博客–Android Studio 打包Jar
最近公司一个新需求,需要将项目中某一个模块打包成SDK提供给第三方公司使用。打包SDK?我只会用啊!!没办法,硬着头皮也得上!
选择打包方式
说干就干,撸起袖子就Google。。。通过Google可以确定常见的几种打包SDK的方式
直接以Library Module的方式引入
优点简单方便,直接把模块抠出来放进一个Library中扔给第三方公司用就行了
缺点
只能适合于Android Studio开发的项目,假如第三方公司用的是Eclipse,那不就懵逼了.
不安全,相当于把源码完全暴露给第三方。泄露资料事小,代码写的差被嘲笑事大啊!!
以aar包的方式引入
优点生成简单,Android Studio的项目在编译完成后,Library Module 的build目录中会自动生成 aar包,不用做额外操作
缺点
还是比较适合Android Studio开发的项目,虽然Eclipse 也能引入aar包,但是比较复杂,我可不想写一堆接入文档,还不一定说的清。
以jar包的方式引入
优点接入方便,是个Android开发应该都会引入jar包吧。。
缺点
打包比较麻烦,而且Jar包中关于一些资源文件的引用比较麻烦
经过一番比较,最终我选择以Jar包的形式提供一个对外的SDK。毕竟是给别人使用的东西,用户的使用体验最重要,通过jar包方式可以以最简单的方式集成SDK,减少接入SDK的成本以及时间。
打包Jar
相关知识
Android Studio 生成Jar包,还是需要借助 Library Module来操作。创建一个Library Module ,然后在主项目中依赖这个Module,当项目经过编译后,我们会发现在Library Module 的build/intermediates/bundles/default/目录下会有一个
class.jar文件
我们生成Jar文件就是需要将这个
class.jar文件进行打包处理
操作
将项目中需要生成SDK的模块分离出来,单独放入一个Module中,并将这个Module切换为Library,使主项目依赖这个Library。在Library Module 的build.gradle 文件的最后添加如下代码
//打jar包 def SDK_BASENAME = "*****"; //打包后的名称 def sdkJarPath = "build"; //打包输出目录 def zipFile = file('build/intermediates/bundles/default/classes.jar') //将编译生成的classes.jar文件打包 task makeJar(type: Jar) { from zipTree(zipFile) from fileTree(dir: 'src/main', includes: ['assets/**']) //需要保留的资源文件 baseName = SDK_BASENAME destinationDir = file(sdkJarPath) } makeJar.dependsOn(build)
rebuild 项目,确保
build/intermediates/bundles/default/目录下存在
class.jar文件。
打开Terminal命令行,或者直接用系统命令行进入项目目录,输入
gradlew makeJar回车,开始进行打包。第一次进行打包,可能会需要下载一些文件,需要一些时间,请耐心等待。
当出现
BUILD SUCCESSFUL时代表打包完成,打开输出目录就会有打包生成的jar包。
一些问题及注意事项
如果Jar包中包含Activity,在项目中引入这个Jar后,还需要在项目的AndroidManifest.xml中声明这个Activity,以及添加一些必要的权限声明。
打包时可以选择保留项目中的资源文件,但仅仅只有assets下的资源文件在jar包中可以正常使用。其他的资源文件,如drawable、layout等,都不可以用常见的方法引用。我们在正常使用某一个资源文件时,是通过
R.**.**方法引用,而打包Jar时并不会保留资源文件id对应的映射R文件,所以这些资源文件就不能正常调用了。
如果Jar包中需要使用一些资源文件,可以将需要的资源文件,例如图片、布局等单独拿出来,项目中引入Jar时,同时添加这些必需的资源文件(类似友盟、腾讯等第三方jar的引入),这样Jar包中可以通过反射读取项目中资源文件。反射读取资源文件的代码如下:
/** * **************************************************************** * Author: LCM * Date: 2017/6/2 上午11:09 * Desc: 通过反射获取资源文件 * ***************************************************************** */ public class MResource { /** * * @param context 上下文 * @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; } /** * 从Assets中读取图片 */ public static Bitmap getImageFromAssetsFile(Context context, String fileName) { Bitmap image = null; AssetManager am = context.getResources().getAssets(); try { InputStream is = am.open(fileName); image = BitmapFactory.decodeStream(is); is.close(); } catch (IOException e) { e.printStackTrace(); } return image; } }
//代码中调用 setContentView(MResource.getIdByName(getApplicationContext(), "layout", "layout_demo")); tvTitle = (TextView) findViewById(MResource.getIdByName(getApplicationContext(), "id", "demo_tv_title"));
额外发现
生成一个Jar,还需要另外提供一些资源文件给别人,对我这种有代码洁癖的人来说是不能忍的。我的理想状态是,就一个jar包,你想用的都在里面,干净简洁。本着不作死就不会死的精神,竟然真的被我发现了一种从assets中加载布局文件的方式!!!!!!
我们知道生成布局文件一般有两种方式
findViewById
直接new一个布局文件,代码中添加属性
其实还有一种容易被我们忽略的方法
LayoutInflater,我们常在ListView或者RecyclerView 的Adapter中通过
Layoutinflater加载Item项的布局,那么能不能通过它来加载一个Activity的布局呢?
我们通常使用的是这两个
public View inflate(@LayoutRes int resource, @Nullable ViewGroup root, boolean attachToRoot)
public View inflate(@LayoutRes int resource, @Nullable ViewGroup root)
方法来加载布局
但其实
LayoutInflater还有两个重载的方法
public View inflate(XmlPullParser parser, @Nullable ViewGroup root, boolean attachToRoot)
public View inflate(XmlPullParser parser, @Nullable ViewGroup root)
看见
XmlPullParser是不是感觉到希望了呢?
没错!
XmlPullParser可以用来解析Xml文件,这样我们就不用通过R文件来映射资源文件,而是直接通过解析Xml文件来加载布局。
解析资源布局文件需要用
XmlResourceParser类
public static XmlResourceParser getIsFromAssetsFile(Context context, String fileName) { AssetManager am = context.getResources().getAssets(); XmlResourceParser xmlResourceParser = null; try { xmlResourceParser = am.openXmlResourceParser("assets/" + fileName); } catch (IOException e) { e.printStackTrace(); } return xmlResourceParser; }
LinearLayout layout = (LinearLayout) LayoutInflater.from(this).inflate(MResource.getIsFromAssetsFile(this, "layout_demo.xml"), null,false); setContentView(layout);
把布局文件扔进assets目录,来来来!接下来就是见证奇迹的时刻!
f**k ………
淡定淡定。。发现问题还是要解决问题嘛。。。
经过一番艰苦卓越的google ,发现这里
XmlResourceParser解析的布局必需是编译过后的布局文件。
那么怎么获取编译后的布局文件呢,很简单也很无脑,把你需要的布局文件放到任意一个正常项目的layout目录下,编译项目,在
build/output/apk文件夹中会有一个 apk包,解压就可在layout目录下获得编译后的布局文件
重新将编译后的布局文件扔到assets目录中,运行
布局文件能找到,那么布局中的控件呢,肯定不能
findViewById了,别担心,android中还有另一个findview的方法
findViewByTag,你可以在布局中给每一个控件添加一个
android:tag=""属性,然后你就可以通过
findViewByTag方法来找到指定的控件了。
终于我成功的将SDK封装的只剩一个Jar包!!
然鹅!!我最终还是放弃了这种方式!!!因为这种方式打包的jar包在Android Studio中可以正常使用,但是在Eclipse中不能使用!!!解析不了这个布局!!!!网上关于这方面的资料又比较少,我只能猜测这是因为Eclipse 与Android Studio 的加载机制不同导致的。。
相关文章推荐
- Android studio 打包Jar
- android studio 打包jar
- android Studio 混淆打包jar,已经添加其他文件到jar
- Android Studio将module打包成.jar包
- Android studio 之 打包 model 成 jar (xutils 数据库升级版本校验问题)
- android studio 使用gradle 导出jar包,并打包assets目录
- Android Studio使用Gradle将.java文件打包成jar包
- Android Studio 使用 Gradle 打包 Jar
- Android Studio 取消打包某一个Jar包
- Android Studio 使用 Gradle 打包 Jar-IT蓝豹
- Android studio修改源码之后打包成jar包
- android studio 如何打包成jar包
- Android Studio 打包Jar
- 运用插件直接Android studio打包jar
- Android Studio打包jar及aar包的方法
- Android Studio 使用 Gradle 打包 Jar
- 在Android Studio 取消打包某一个Jar包
- android studio 使用gradle 导出jar包,并打包assets目录
- Android studio3.1.3 打包jar,混淆
- Android Studio 将moudle打包成jar