解密ADT第五篇-案例分析

前言

本来此篇当作最终篇,但是一下子写说多了,说着说着就占了很多的篇幅了,于是把这篇分拆开来当作案例分析,本篇使用的案例是联想SDK,具体的请看我的github地址…可能我写的那么多乱且没什么朋友看,但是我自己也当作是一种记录与训练,怎么把我知道的对的或者错的展现给第二个人 这是我迫切需要锻炼的能力.


Let`s going on

下面将一步一步针对ADT进行DIY,以下是一些事先需要准备的:

配置的IDE环境:android开发环境,AIR开发环境,JAVA开发环境.

配置的环境变量:android SDK tool,JDK1.7,JRE,ADT,Apktool5.2

我使用的系统:XP,Win7,Mac

SDK版本:AIRSDK:3.5,androidSDK2.2.3

案例ANE:联想支付(https://github.com/platformanes/AndroidLenovoANE)

PS:使用联想SDK做案例,是由于联想ANE集所有问题于一身:打包文件到APK根目录,资源类库,合并jar,安卓SDK限制,资源未多语言国际化等等…

首先说说联想ANE,移步我在github写的README(https://github.com/platformanes/AndroidLenovoANE/blob/master/README.md):

也就是说整个联想ANE从编写完代码到打包成APK需要经过:

  1. 编写两端代码,配置SDK参数
  2. 整合资源
  3. 合并JAR
  4. 打包ANE
  5. 打包APK
  6. 解压APK
  7. 删除签名
  8. 放入bin文件夹
  9. 生成APK
  10. 签名APK
  11. 优化APK

整整11个步骤,任何一个步骤出错都会导致错误!!我相信在flash开发者接联想SDK的时候暂时没有任何一个人能一击即中一步到位.

而且ANE的调试比较麻烦,初学者甚至都不知道怎么调试ANE,我其实有写一款ANE调试工具的想法,但是考虑到需要手动配置的东西太多,估计写出来除了我自己没人愿意用,所以作罢.下面开始分析AIR项目在接入联想ANE之后 打包成APK的每个过程,等于是前四篇理论的细化 或者实践.

我把整个过程从以下三个细点进行分析(针对联想ANE,使用特定的SDK进行分析。下面三个小内容是我的一些认识与理解)

  • 所谓ADT打包

使用案例中的联想打包,与APK打包的具体过程。所有路径使用我本机的作为参照:

假设包名是:air.com.lenovo.ane.lenovo

编译资源:

//取airSDK中的aapt工具;
D:\FlashBuilder\Adobe Flash Builder 4.6\sdks\AIR3.5\lib\android\bin\aapt.exe,package, -z, -u,
//前面文章分析过.-J 指定输出路径
-J, C:\Users\RECT\AppData\Local\Temp\d8af65b1, 
//-M 指定配置文件
-M,C:\Users\RECT\AppData\Local\Temp\d8af65b1\AndroidManifest.xml,
//-S 全部是编译进去的资源 ;这里的是启动类资源 AIRSDK自带
-S,C:\Users\RECT\AppData\Local\Temp\d8af65b1\app_entry_res,
// ANE的资源  这里
-S,C:\Users\RECT\AppData\Local\Temp\9234f12d\res, --auto-add-overlay,
// -I 引动androidSDK资源库
-I, D:\FlashBuilder\Adobe Flash Builder 4.6\sdks\AIR3.5\lib\android\lib\resources\android-res.jar, 
--min-sdk-version, 8, --target-sdk-version, 14, --version-code, 0, --version-name, 0.0.0, 
//生成的文件 是一个资源APK
-F, C:\Users\RECT\AppData\Local\Temp\d8af65b1\resources.apk

在编译资源这一步,会生成三个文件:

一个是R.java 资源ID源码,与air.com.lenovo.ane.lenovo对应

一个是R.java编译后的 resources.jar;

另外一个是 资源图片配置文件等的压缩包 resources.apk

 

编译dex文件:

//AIRSDK中的dx工具,此工具取之于androidSDK
java, -jar, D:\FlashBuilder\Adobe Flash Builder 4.6\sdks\AIR3.5\lib\android\bin\dx.jar, --dex,
//指定输出文件,dex文件是android系统的可执行文件,类似WIN的exe文件
--output=C:\Users\RECT\AppData\Local\Temp\aa3c906c/outputDEX.dex,
//编译进去的库
C:\Users\RECT\AppData\Local\Temp\aa3c906c/inputJAR.jar,
//编译进去的库 这个是资源库 就是R.java
C:\Users\RECT\AppData\Local\Temp\d8af65b1\resources.jar,
//ANE中转库 我们的ANE函数需要通过它 的映射提交给air虚拟机
C:\Users\RECT\AppData\Local\Temp\aa3c906c/FlashRuntimeExtensions.jar,
//ANE java端代码
C:\Users\RECT\AppData\Local\Temp\9234f12d\com.lenovo.ane.jar,

在这一步 会生成dex文件:outputDEX.dex.

经过上面两步之后,我们就有了 resources.apk文件和outputDEX.dex文件,接下来的东西就没什么技术可言了,无非就是把我们的AS代码编译的swf文件打包进asset文件夹,然后使用zip压缩成一个APK,然后签名,然后优化,这就是我们用ADT打包出来的APK了,(题外话:看吧 是不是很简单?不仅仅是APK文件,即使是exe文件,ipa文件,等各种系统的文件 无非都是这几个步骤:编译-打包,我们的android程序是运行在android虚拟机Dalvik之上的,对于win系统的可执行文件PE文件 也就是exe后缀名的文件 则需要借助windows的装载器才能运行.swf文件需要falsh虚拟机才能运行,而flash程序 android程序的编译过程其实又和LLVM有关系,这个LLVM大有来头,有兴趣的同学可以自行跟进,但是万变不里其中,无论什么可执行文件 其实都是运行在特定的虚拟机之上的.)

现在我们反编译一下生成的联想APK看看里面有什么:

通过这一步,相信大家已经知道为什么我们的ANE接入SDK经常会发现找不到资源的问题了,由于SDK的资源是根据他本身的 包名路径来去R.java取的ID,而我们的AIR只编译了一个包名为air.XXX的R.java,这资源文件的路径错了,当然就会取不到资源了.我们可以反编译一下联想原生项目一看便知我说的对不对,如下图:

看到了吧,总结下:

AIR打包资源ID文件:air.com.lenovo.ane.lenovo.R.java

安卓原生打包的ID文件:com.lenovo.pay360.R.java

这包名的冲突导致了资源ID访问不了.虽然R.java的内容都是一样的.

接下来我详细说说什么是资源ID?资源ID有什么用?资源ID可以吃么?

  • 所谓资源ID

资源ID

其实就是androidSDK给资源文件(res文件夹)逐个命名所得的ID,每一个数字代表一个资源,这个资源可能是一个xml,也可能是一个png也可能是一个jpg甚至可能是一个其他什么东西.总之一句话比喻:如果我们每一个人都是一个地球的资源的话,资源名字是我们每个人的人名,资源ID就是我们的身份证号.可能很多人叫Rect 但是身份证号是:440xxxxxxxxxxx12 的可能就只有我一个人.

资源的身份证

是什么?随便解压一个APK文件,出来一个叫:resources.arsc,的文件就是资源的映射文件,等同于我们的身份证.安卓程序通过对这个arsc输入ID得到具体的资源名路径 然后去取得资源实体,相应的,警察叔叔通过我的身份证确认我是当年偷看隔壁姐姐洗澡的那个小屁孩.

关于资源与ID的更多分享

  1. 每编译一次APK 只要是增删了资源,ID都可能不一样
  2. R.java路径不对会导致ID无法取得
  3. 盲目的解压生成APK可能会导致"身份证"错乱
  4. 写ANE的时候R.java不能单单直接复制或者改包名
  5. 切记不可加入字节为0的资源,类似死了的人没销户,可能会发生错乱.

在ANE中我怎么处理资源ID?

  1. 原来写过比较麻烦但绝对靠谱的方法:传送门
  2. 打包一次APK,然后反编译复制R.java,在java端新建相应包名的R.java然后粘贴(没第1点靠谱)
  3. 修改SDK的全部取ID方式为ctx.getResourceID("xx")(靠谱但是不现实)
  4. 在ADT编译阶段再生成一个不同包名的R.java(目前为止我找到的最完美的方式,最终定制版ADT会在下一篇放出)
  • 所谓ANE

分析ANE的打包过程,还原ANE实现原理,让ANE不在神秘。

关于ANE官方的解释是:传送门,但是我觉得我们单单看了官方的解析其实对ANE并不甚了解,仅仅这些解释怎么能满足程序员呢?让我们直接深入腹地,看看ANE就是是怎样的一个鬼马六,能让大家如此深爱如此怨恨.

案例分析先到这,关于我对ANE的理解 我在另外开篇详述

 

14 评论

  1. 博主,给我邮箱发个QQ吧,估计我也要研究这东西一段时间,好交流一下(不会太打扰你的)

  2. 进过2个小时的努力,终于吧"air."前缀去掉了,小米接入成功,感谢博主给了我这个思路!

  3. 第一条的思路是什么?我吧launchMode改成standard和singleTop都不行

  4. 这个联想ANE真是奇葩啊,谢谢前辈分享经验,辛苦了。

    顺便吐槽一下loading。:)

  5. 调用SDK接口的时候不是传入 context.getActivity()

    而是改为启动一个新的activity 然后传给SDK

    如此 便可一劳永逸的解决强制后台运行,横竖切换等问题.

    更具体的实现方式请参照 传送门

  6. 再建议一条:减少运行时大小,比如"res\drawable-land-xhdpi"下的图片,可以删掉

发表评论

电子邮件地址不会被公开。 必填项已用*标注