Android Eclipse 导入 AS Gradle AAR 库手冊
序言
这是一篇半技术类文章。众所周知如今Google主推Android Studio开发工具。而Eclipse已经被闲置一阵子了,可是Eclipse项目却还有非常多没有迁移到AS中。而如今一些新的库都是採用AS Gradle打包并公布到公共仓库中。而这些库Eclipse 并不能直接使用。在本篇文章中将解说怎样导入一个或者多个库到Eclipse中使用。
目的
Eclipse基本算是荒废的状态了。这并非说Eclipse就不好。毕竟都是Eclipse过来的;仅仅能说一个个是新欢一个旧情人了。
旧情人肯定是有她特殊的韵味的,所以如今并非所有的都迁移到AS了,还有非常大一部分处于Eclipse上的项目。
这里就有问题了,很多的开发人员在AS上的库一般来说都不是打包为Jar包。而是直接生成AAR库,随后公布到公共仓库中,AS的使用者呢就使用一句简单的代码就能使用这个库了,其下载-载入-编译-执行都用Gradle搞定了。而Eclipse就不乐意了~~
Eclipse 就面临着尴尬的局面想要用新的库,可是却没法用~~
在本篇文章中。将会解说怎样在Eclipse中使用一个公共仓库中的库。
Gradle 公布流程
仓库简单介绍
在AS中公布库都是採用Gradle公布到相应的公共仓库中进行使用,仓库有非常多。你也能够自己使用server搭建仓库;而公共仓库中有两个特别OK的:
在最初google框架中默认使用的仓库是:mavencentral 。可是由于mavencentral 仓库的公布流程较为严格并且操作上不够人性化所以后来改为了:jcenter。
所以推荐使用jcenter,当然假设你在mavencentral中公布了你的库,那么这个库在公布成功后的24小时内会被同步到jcenter中,而jcenter中公布的库也能够通过一键式操作公布到mavencentral仓库中。
由于有上面的仓库差别,所以假设你使用的是AS将会在配置中看见诸如这种配置:
repositories {
jcenter()
}
repositories {
jcenter {
url "http://jcenter.bintray.com/"
}
}
repositories {
mavenLocal()
}
这就是在告诉你的项目中使用的库的来源。AS将会更加库的标识去寻找须要的文件,当然两个仓库能够同一时候写入到项目配置中。
公布到仓库
在我的文章中有一篇关于公布到mavencentral仓库的文章:[Publish AAR To Maven] 使用 Gradle 公布 AAR 到 Maven 仓库
上面所介绍的是公布到mavencentral仓库的流程,而jcenter的流程也基本相似,仅仅只是把文件加密的过程放到了server上去完毕。
总体来说:
- 首先我们须要有一份库的代码
- 编译源代码得到Jar, R, JNI, xml等源代码文件。
- 打包所有文件为一个aar的文件
- 签名
- 公布到仓库
- 校验并公布
怎样使用
而使用这个库,则也非常easy下载相应版本号的AAR文件,加入到项目中,并编译进项目。
从这里就能够看出一点,实际的android使用中就是使用的aar文件,仅仅只是此时的aar文件会被解包编译。
在AS的项目配置中我们加上这样一句:
dependencies {
compile 'net.qiujuer.genius:ui:1.3.0'
}
在编译后,我们查看一下项目的Build文件夹:
在这里我们能够看见实际的使用中的确如我们所想的一般。
当然这里之所以会出现“res“包,是由于“genius-ui“包中默认引用了“genius-res“包,所以当我们使用“UI“包的时候就会同步下载“res“包。具体能够见开源项目:Genius-Android
OK, 一个库的简单流程我们说好了;那么来看看怎样在Eclipse中使用。
问题
从上面的库的流程中能够看出一个AAR库中能够包含:jar, aidl, assets, res, R 文件等数据。而Eclipse中默认引用库的时候仅仅能引用jar文件。
假设我们仅仅是把jar文件放到eclipse中的话将会无法正常使用相应的资源文件。那么是不是仅仅要同一时候把资源文件放到eclipse中也就攻克了这个问题?并非的!
众所周知,一个资源文件在编译的时候会在R文件里生成一个int 值与之相相应。而实际代码中所有使用这个int值取代;那么上面加入的资源文件所有会生成一份新的值与之相应。那么在库的jar中依旧无法找到与之相应的资源,终于将会导致APP崩溃。
此时有一个办法能够解决,那就是固化资源相应的INT值,让改资源在编译的时候每次都生成我们指定的INT值。
在这里我们使用一个android中特有的文件:“public.xml“
public.xml: 用于固化资源所相应的INT值。
实施
下载
首先我们须要准备一份相应的aar文件,在这里我使用 genius-android 库的 UI 包来完毕该操作。
下载点有:
我们进入mavencentral,并搜索 genius ,找到 ui 包:
由于UI包中引用了res包。所以我们同一时候下载ui和res包。
解包
更改后缀为zip,并解压:
- AndroidManifest.xml :含有权限-服务声明-广播注冊-activity声明等信息。直接将当中的数据复制到自己的项目中就OK。
- aidl:这个中一般都是独立服务的东西。在项目中依照相应的地方建立好文件就好。
- assets:这个中通常是字体。html等数据
- classes.jar 这个就是我们须要直接使用的jar包了
- R.txt 这个就是资源相应的int值了,我们须要做的主要工作就是把其转换为 public.xml 文件
- Res 文件夹中的内容能够原封不动的复制到项目的res文件夹中。
创建项目
为了避免该项目与自己的项目相冲突。我们首先须要建立项目:
在这里起名为:GeniusUI,并指定包名为:”net.qiujuer.genius.ui”
为什么呢?由于上面解压后的AndroidManifest.xml中有指定包名:
假设这里未指定包名,那么就算后面我们写好了 public.xml文件,其尽管能固化INT值,可是却没法相应到我们的包名上。换句话说我们的 jar 文件里依旧无法找到相应的资源文件。
进入项目属性(Properties)-Android-勾选上(Is Library) 使其成为库项目。
请记住在这里我们并不为RES包单独创建项目;由于UI库中引用了RES包中的资源。那么在UI库生成的时候将会又一次计算一份新的Res库的资源INT值。
在这里之所以要下载Res包,仅仅是仅仅须要当中的资源文件而已。
同一时候打开 Res包中的 R文件(左边)与UI包中的R文件(右边):
能够看出UI包中同样含有颜色相应的INT值。可是其值与原Res包中并不同样。
复制文件
我们依照图片所看到的把现有的文件所有拷贝进项目中:
此时编译一次项目。一般来说仅仅要文件所有拷贝正确了,那么是不应该报错了,并且此时应该生成了一份R文件,仅仅只是此时的R文件与原来库中的值并不全然同样(有可能有部分同样,这也就导致有部分资源能够正常使用)。
对照
此时我们对照项目生成的R文件与库中的R文件:
能够发现不尽同样。当然你的也也许全然同样。比方:
这意味着什么?意味着这个项目中的资源能够全然使用。可是什么情况下会不同?
我们在 Res 项目中的 values.xml 文件里加上一个颜色:
<color name="a">#ffecb3</color>
这句话将会带来什么?带来兴许的ID所有相应失败的问题:
这也就是我说的资源无法正常相应的问题。
这个同样和不同样都是随机的,也许原来的库刚刚巧合了那么也就同样了。
Public.xml 固化
此时我们在 项目的 values 文件夹中创建 public.xml 文件,并加上:
<?
xml version="1.0" encoding="utf-8"?>
<resources>
<public id="0x7f020000" name="amber_100" type="color" />
<public id="0x7f020001" name="amber_200" type="color" />
<public id="0x7f020002" name="amber_300" type="color" />
<public id="0x7f020003" name="amber_400" type="color" />
</resources>
编译项目,此时我们再次查看 R 文件:
在这里能够看出我们写了的部分已经OK了,从第5个開始又出现故障了,所以啊,我们须要把所有的R相应的INT值都固化到Public中。
好了,如今知道Public文件的魅力了。可是想要固化一整个文件并非那么的如意;我一打开UI库的R文件的时候是崩溃的。
我擦,500多汗~~
坑爹呢不是。。
并且大概看了一下有颜色-数字-style-TM 还有 styleable 这是什么> 鬼?假设你写过自己定义控件那么应该知道这个是:自己定义属性。可是,可是这个怎么固化?500多行。等弄好菜都凉了。
代码化
我们是程序猿,我们都非常懒,所以我们用程序来解决。
在这里我们写一个从 R.txt 转换到 public.xml 的小程序就好。
格式
首先来看看R.txt 文件里转换到 XML 时相应的格式。
- 颜色、数字、数组、ID、String、drawable能够直接转换
int color black 0x7f04000e
int dimen font_10 0x7f050000
int array loading 0x7f030000
int id all 0x7f080009
int string g_font_file 0x7f060000
int drawable background 0x7f020000
<public type="color" name="black" id="0x7f04000e" />
<public type="dimen" name="font_10" id="0x7f050000" />
<public type="array" name="loading" id="0x7f030000" />
<public type="id" name="all" id="0x7f080009" />
<public type="string" name="g_font_file" id="0x7f060000" />
<public type="drawable" name="background" id="0x7f020000" />
- style 须要替换“_“为“.“
int style Genius_Widget_BalloonMarker 0x7f070000
<public type="style" name="Genius.Widget.BalloonMarker" id="0x7f070000" />
- attr属性须要抛弃styleable部分
int attr gAllowTrackClickToDrag 0x7f010022
...
int[] styleable AbsSeekBar { 0x7f01000c, 0x7f010019, 0x7f01001a, 0x7f01001b, 0x7f01001c, 0x7f01001d, 0x7f01001e, 0x7f01001f, 0x7f010020, 0x7f010021, 0x7f010022, 0x7f010023, 0x7f010024, 0x7f010025, 0x7f010026, 0x7f010027, 0x7f010028, 0x7f010029, 0x7f01002a, 0x7f01002b, 0x7f01002c }
int styleable AbsSeekBar_gAllowTrackClickToDrag 10
要得到 gAllowTrackClickToDrag
所代表的INT值,两种办法,直接从第一句中转换得到。
第二个办法,读取到 styleable AbsSeekBar
时存储后面的数组,然后读取到 int styleable AbsSeekBar_gAllowTrackClickToDrag 10
时,依照 10 这个下标去取得值 0x7f010022
。
<public type="attr" name="gAllowTrackClickToDrag" id="0x7f010022" />
代码
实体类
static class PublicLine implements Comparable<PublicLine> {
public String type;
public String name;
public String id;
public PublicLine() {
}
public PublicLine(String type, String name, String id) {
this.type = type.trim();
this.name = name.trim();
this.id = id.trim();
}
public String getKey() {
return type + "_" + name;
}
@Override
public String toString() {
return "<public type=\"" + type + "\" name=\"" + name + "\" id=\"" + id + "\" />";
}
@Override
public int compareTo(PublicLine o) {
int i = this.type.compareTo(o.type);
if (i == 0)
return this.name.compareTo(o.name);
else
return i;
}
}
- 实现 compareTo 是用于后面排序,避免输出的内容乱糟糟的。
- “getKey()“ 方法是为了存储到Map中的主键值而准备。避免反复。
- “toString()“这是为了输出日志而准备。
总体流程
public static void main(String[] args) throws IOException {
File in = new File("R.txt");
File out = new File("public.xml");
if (!in.exists()) {
throw new NullPointerException("R.txt is not null.");
}
try {
out.createNewFile();
} catch (IOException e) {
e.printStackTrace();
return;
}
System.out.println(in.getAbsolutePath());
System.out.println(out.getAbsolutePath());
InputStreamReader read = new InputStreamReader(new FileInputStream(in));
BufferedReader bufferedReader = new BufferedReader(read);
OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(out));
BufferedWriter bufferedWriter = new BufferedWriter(writer);
Map<String, PublicLine> xml = new HashMap<>();
buildXml(bufferedReader, xml);
List<PublicLine> lines = new ArrayList<>();
lines.addAll(xml.values());
Collections.sort(lines);
saveFile(lines, bufferedWriter);
close(bufferedReader);
close(bufferedWriter);
System.out.println("End.");
}
整个流程非常easy,直接使用当前文件夹生成两个文件。R.txt 为输入源,public.xml 则是输出文件。该文件每次执行都又一次生成新文件。
然后输出一次两个文件的文件夹信息到控制台。
然后初始化Buffer,在这里经过2层的分装,终于得到的是:BufferedReader 与 BufferedWriter,才有这两个的目的主要是为了一行行的读取,终于也一行行的输出。
然后声明一个 Map 变量。用于存储读取并转换为实体的集合。之所以採用Map是为了实现避免反复内容的出现。
再后面我们又声明了一个 List 变量。并把Map的值存储到List中,这一步主要是为了排序整个集合;Map本身是无序的,并且假设直接对Map排序就相当复杂,所以这里我们填充到 List 后再进行排序。
然后则是输出到Public文件里,然后关闭流的操作。
读取集合
public static void buildXml(BufferedReader reader, Map<String, PublicLine> xml) {
while (true) {
String line;
try {
line = reader.readLine();
if (line == null || line.trim().length() == 0)
return;
} catch (IOException e) {
e.printStackTrace();
continue;
}
if (line.contains("styleable")) {
// skip styleable array
continue;
} else {
// convert other xml
String[] split = line.split(" ");
if (split.length == 0)
continue;
String type = split[1];
String name = split[2];
String id = split[3];
if (type.contains("style"))
name = name.replace("_", ".");
saveToMap(xml, new PublicLine(type, name, id));
}
}
}
- 循环读取每一行,当读取到某行空的情况下则退出循环
- 在这里我们对attr的转换採用过滤的方式。所以凡事具有“styleable“ 标示的行都能够直接抛弃掉。
- 正常情况下。我们读取一行,并按空格划分开;然后分别读取到 type 、name、id 的值。
- 假设当前类型为 style 类型。那么我们的名称须要把 “_” 替换为 “.” 。
- 把当前识别到的信息存储到 Map 中。
假设这里对 attr 的识别採取的是读取 styleable 数组中的信息。然后再按索引找寻相应INT值的话,代码就应该是这样:
public static void buildXml(BufferedReader reader, Map<String, PublicLine> xml) {
while (true) {
String line;
try {
line = reader.readLine();
if (line == null || line.trim().length() == 0)
return;
} catch (IOException e) {
e.printStackTrace();
continue;
}
String[] split = line.split(" ");
if (split.length == 0)
continue;
if (line.contains("int[]")) {
// convert attr xml
String name = split[2].trim();
line = line.substring(line.indexOf("{") + 1, line.lastIndexOf("}"));
System.out.println(line);
String[] ids = line.split(",");
if (ids.length > 0) {
readStyleableXml(reader, xml, ids, name);
}
} else {
// convert other xml
String type = split[1];
String name = split[2];
String id = split[3];
if (type.contains("style"))
name = name.replace("_", ".");
saveToMap(xml, new PublicLine(type, name, id));
}
}
}
@SuppressWarnings("unused")
public static void readStyleableXml(BufferedReader reader, Map<String, PublicLine> xml, String[] ids, String name) {
for (String id : ids) {
String line;
try {
line = reader.readLine();
if (line == null)
continue;
} catch (IOException e) {
e.printStackTrace();
continue;
}
String[] split = line.split(" ");
String lName = split[2].substring(split[2].indexOf(name) + name.length() + 1);
String lId = ids[Integer.parseInt(split[3].trim())];
saveToMap(xml, new PublicLine("attr", lName, lId));
}
}
在这里我们就须要多一个方法,在这种方法中我们依照当前控件的数组长度进行循环读取其后相应数组长度的行,然后再解析并存储。
存储
public static void saveToMap(Map<String, PublicLine> xml, PublicLine line) {
try {
xml.putIfAbsent(line.getKey(), line);
System.out.println(">>>: " + line.toString());
} catch (Exception e) {
e.printStackTrace();
}
}
存储方法相对简单,我们採用 Map 的 “putIfAbsent“ 方法。该方法有一个作用,就是会推断当前 KEY 是否存在,假设不存在则存储。
存储
public static void saveFile(List<PublicLine> lines, BufferedWriter writer) throws IOException {
// write head
writer.append("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
writer.append("\n");
writer.append("<resources>");
writer.append("\n");
for (PublicLine line : lines) {
try {
writer.append(" ");
writer.append(line.toString());
writer.append("\n");
writer.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
// write footer
writer.append("</resources>");
writer.flush();
}
存储过程分为存储头部。存储集合数据。以及存储底部来完毕。
关闭流
public static void close(Closeable closeable) {
try {
closeable.close();
} catch (IOException e) {
e.printStackTrace();
}
}
关闭流的方法就更加简单了,无非就是单独出来了而已。
效果
此时我们把R文件放到根文件夹,执行一次代码,控制台将会输出:
此时已经生成了一份 public 文件。与R文件相应看一下:
能够看出效果是相当不错。把public文件复制到库中直接投入使用。
预览
为了測试是否成功,我依照开源库 Genius-Android 中的 sample 项目代码在 Eclipse 中完毕了一份界面布局。
所有控件与资源都能正常使用。
最后
在这里我把代码生成了一份 jar 文件,你能够下载该文件,并把 R.txt 文件放到同一文件夹,执行该 jar 文件既可得到 public 文件。
同一时候我把所有的源文件与代码都上传到了 GtiHub 的 BeFoot 项目中;以后的所有样例也都会更新到该项目中。
假设有哪里不正确,或者说的不够清楚还请多多不吝赐教。
========================================================
作者:qiujuer
博客:blog.csdn.net/qiujuer
站点:www.qiujuer.net
开源库:github.com/qiujuer/Genius-Android
开源库:github.com/qiujuer/Blink
转载请注明出处:http://blog.csdn.net/qiujuer/article/details/50084345
—— 学之开源,用于开源;刚開始学习的人的心态,与君共勉!
========================================================
Android Eclipse 导入 AS Gradle AAR 库手冊的更多相关文章
- 在Android Eclipse 开发如何 使用 (*.aar)文件
http://www.cnblogs.com/shortboy/p/4424944.html 开场白:其实这篇文章有点白费心机. 详细说明是:http://blog.csdn.net/qiujuer/ ...
- Android eclipse导入项目后出现Unable to resolve target 'android-17'解决方法
eclipse导入项目后出现Unable to resolve target 'android-17'解决方法.在最后附带还有一种编译逻辑不成功情况解决方法. 一.问题情况 二.解决的方法 1.改动项 ...
- Android Studio -导入项目 gradle处理
如果导入 android studio 项目, 那么一定要注意 需要合适的gradle版本,具体方法为: 首先导入步骤: 打开android studio ==> File ==> New ...
- 迅为-IMX6开发板Android Eclipse 导入Led应用程序工程
本小节给大家详细讲解如何导入 Android 应用的工程文件.先解压迅为“iTOP-IMX6-Android4.4-LED 测试程序 r”压缩包.如下图所示,解压出ledtest 文件夹.<ig ...
- android eclipse 导入idea项目
将以下代码复制到.project中 <?xml version="1.0" encoding="UTF-8"?> <projectDescri ...
- Eclipse导入Oracle/MySQL数库驱动包教程
在操作数据库时除了import相关的SQL类外,还得在项目中导入数据库的驱动才能连接和操作数据库. 而数据库驱动jar包在默认Java的lib里是没有的,要自己到官网下载导入:本教程以Oracle为例 ...
- 4418之Android Eclipse导入应用程序在开发板上调试
由于在开发板上 LEDtest 应用已经默认安装了,所以在开发板上调试已安装应用的时候,需要做一下处理才能够正常连接.基于迅为iTOP4418开发板如下图所示,在打开工程“ledtest”,打开“bi ...
- Eclipse导入到最新版Android Studio详解
说到使用AndroidStudio,除了新建的项目,我们都会面临的问题是原先Eclipse的代码该怎么导入到AndroidStudio中使用.这方面相关的资料还比较少,自己摸索了一下,总结出这篇博客, ...
- 从 Eclipse 导入项目到 Android Studio
ADT已经有些过时了,现在比较流行的安卓开发工具是Android Studio,毕竟是谷歌一直在推广的. 最近装了as,从之前的adt迁移项目到as上,遇到了不少坎. 主要注意以下两点: (1)文件路 ...
随机推荐
- maven项目打包 编码gbk的不可映射字符
中文系统默认gbk编码格式,你的代码是utf8格式的.所以报错 <build> <plugins> <plugin> <groupId>org.apac ...
- SpringBoot基础之MockMvc单元测试
SpringBoot创建的Maven项目中,会默认添加spring-boot-starter-test依赖.在<5分钟快速上手SpringBoot>中编写的单元测试使用了MockMvc.本 ...
- <编程精粹:编写高质量C语言代码> 读书笔记
0.规则<The Elements of Programming Style><The Elements of Style> 1.假想的编译程序(1)使用编译器提供的所有的可选 ...
- 定位 UNIX 上常见问题的经验总结
本文主要对 UNIX 平台常见的问题进行了分类,介绍一些常见问题分析时使用的方法和命令,对以下三种常见问题的分析方法做了简单介绍:UNIX 下 Crash 问题的分析方法.UNIX 下内存泄露问题的分 ...
- build android on macOS
http://blog.csdn.net/loften_93663469/article/details/51503293 @import url(http://i.cnblogs.com/Load. ...
- Vue中的computed 解读
computed相当于属性的一个实时计算,如果实时计算里关联了对象,那么当对象的某个值改变的时候,同事会出发实时计算.比如: <body id="content"> & ...
- 仓鼠找sugar(lca)
洛谷——P3398 仓鼠找sugar 题目描述 小仓鼠的和他的基(mei)友(zi)sugar住在地下洞穴中,每个节点的编号为1~n.地下洞穴是一个树形结构.这一天小仓鼠打算从从他的卧室(a)到餐厅( ...
- jenkins集群节点构建maven(几乎是坑最多的)
业务量变大时,单台的jenkins进行自动化构建部署,就显得没那么灵活,jenkins的集群并非像web服务器.mysql集群那样,jenkins的集群无需在额外的主机安装jenkins,但是用于ja ...
- [ONTAK2010]Peaks
题目大意: 一个图上有$n(n\leq100000)$个带权点,$m(m\leq500000)$条带权边.有$q(q\leq500000)$组询问,每次询问从点$v$出发,只经过权值小于等于$x$的边 ...
- chrome mac 快捷键
⌘-N 打开新窗口. ⌘-T 打开新标签页. ⌘-Shift-N 在隐身模式下打开新窗口. 按 ⌘-O,然后选择文件. 在 Google Chrome 浏览器中打开计算机中的文件. 按住 ⌘ 键,然后 ...