如何将已存在的APK项目作为资源引用

文章链接:http://www.liuschen.com

android开发中,调用外部引用的方法分为三种:

  • 引入jar包文件
  • 把项目整体作为依赖
  • 通过maven或是gradle直接配置依赖

基本上,项目如果要开发更简洁,引入外部的依赖是不可避免的,这些引入的方法都很简单,不多加详述,现在我主要探究的是如何通过已有的apk拓展源,来制作可用的依赖。

关于这点有两点设想

  1. 反编译apk,修改清单文件,重新打包,将apk作为插件供新程序调用。
  2. 反编译apk,将反编译出的class文件打成jar包,供新程序调用,引入资源文件,修改映射关系

反编译,重打包

将apk反编译后会解出一个smali文件夹和res文件夹以及一个解码过的清单文件,如果单纯的解压apk,得到的则是dex文件和resources.arsc文件以及没有解码的res和清单文件,将反编译后的文件夹重新打包,会生成一个build文件夹,里面的内容和解压apk得到的文件类似。也就是说,其实反编译得到的代码是一个完整的开发工程,只是不是Java而已。

反编译 apktool d -f -.apk,会生成一个apk的同名文件夹

重打包 apktool b -f 反编译得到的文件夹,然后会在该文件夹下的dist目录中得到未签名的apk

这时,包是没有签名的,没有签名的apk是不能安装到手机上的,所以,先简单说一下签名

每个程序在安装前都需要签名,即是是调试的apk也不例外,发布到市场上的apk一般会单独生成一个keystore,而一般调试用的是系统里面的一个debug.keystore

keytool(jdk的bin目录下)是用来生成keystore的,eclipse和studio里面有图形化的生成方式其实也是调用的这个命令
keytool -genkeypair -alias - debug.keystore -keyalg RSA -validity  100
-keystore debug.keystore
命令说明如下:
 -genkeypair  :指定生成数字证书
-alias :指定生成数字证书的别名
-keyalg:指定生成数字证书的算法  这里如RSA算法
-validity:指定生成数字证书的有效期
-keystore :指定生成数字证书的存储路径。  (这里默认在keytool.exe 目录下)


jarsigner(jdk的bin目录下)命令是用来签名的,调试的时候就是用这个命令签入debug.keystore的
jarsigner -verbose -keystore debug.keystore -signedjar
dst.apk src.apk debug.keystore 
以上命令的说明:
-verbose:指定生成详细输出
-keystore:指定数字证书存储路径
-signedjar:该选项的三个参数为  签名后的apk包  未签名的apk包  数字证书别名

我的debug.keystore在用户目录下的.android文件夹中

查看证书信息keytool -list -keystore debug.keystore
默认密码为:android

debug.keystore签名的别名为androiddebugkey

如果用debug.keystore来签名:

jarsigner -verbose -keystore C:\Users\用户.android\debug.keystore -signedjar dst.apk src.apk androiddebugkey

正在添加: META-INF/MANIFEST.MF
正在添加: META-INF/ANDROIDD.SF
正在添加: META-INF/ANDROIDD.RSA
正在签名: AndroidManifest.xml
正在签名: classes.dex
正在签名: res/anim/calendar_push_left_in.xml
正在签名: res/anim/calendar_push_left_out.xml
正在签名: res/anim/calendar_push_right_in.xml
正在签名: res/anim/calendar_push_right_out.xml
正在签名: res/anim/push_bottom_in.xml
正在签名: res/anim/push_bottom_in2.xml
			。
			。

利用这一流程,来做若干测试:

  1. 修改反编译后的清单文件(比如为activity添加入口,去掉入口,修改包名等等),打包,签名,安装运行程序,程序能如预期的修改效果。
  2. 修改反编译后的资源文件(如替换图片),程序也能如期产生对应效果。
  3. 修改smali

    Dalvik字节码Dalvik是google专门为Android操作系统设计的一个虚拟机,经过深度的优化。虽然Android上的程序是使用java来开发的,但是Dalvik和标准的java虚拟机JVM是不同的。Dalvik VM是基于寄存器的,而JVM是基于栈的;Dalvik有专属的文件执行格式dex(dalvik executable),而JVM则执行的是java字节码。Dalvik VM比JVM速度更快,占用空间更少。打包成apk的过程就是将java编译成class文件,然后将class文件封装成dex打包入apk的过程。

通过这个方法总结出利用原始apk文件部分功能的方法

  • 修改apk入口,将之作为插件依附在新建的apk上
  • 新建项目写好需要添加的功能,然后编译成apk文件,反编译出源码,对照修改原来的smali文件和资源文件,重新打包签名

反编译,提取class文件制作jar包

之前反编译到的文件通过jd-gui读取时有很多乱序代码,所以直接抠出Java代码放在开发环境中修改将是一项相当耗时,而且需要懂其中的的业务逻辑,不然就就不可能还原其代码,那么就只能将它打成jar包在新工程中调用,如果是这样,那么就剩下了一个问题,就是如何修复class文件中的资源id和资源本身的映射关系。

通过实践可知,如果将一个android项目导出为jar包,除了不能包含清单文件和一系列配置文件外(因为配置文件外部也有,如果里面也存在就会造成冲突),资源文件并不能被正确找到。毕竟,资源文件的映射ID是随机生成的。

而Android系统将代码生成apk过程如下:

命令行方式生成APK

1、使用Android SDK提供的aapt.exe(build-tools目录)生成R.Java类文件

2、使用Android SDK提供的aidl.exe(build-tools目录)把.aidl转成.java文件

3、使用JDK提供的javac.exe(jdk的bin目录下)编译.java类文件生成class文件

4、使用Android SDK提供的dx.bat(build-tools目录)命令行脚本生成classes.dex文件

5、使用Android SDK提供的aapt.exe(build-tools目录)生成资源包文件(包括res、assets、androidmanifest.xml等)

6、使用Android SDK提供的apkbuilder.bat(老版本在sdk中tool目录下,新版是没有这个文件的)生成未签名的apk安装文件

7、使用jdk的jarsigner.exe(jdk的bin目录下)对未签名的包进行apk签名

8、安装使用的adb.exe在SDK的platform-tools目录下

android.jar里面是有资源文件的,但是通过尝试,发现引入的jar是和android.jar包不一样的,引入的jar包相当于和本地写的代码是一样的,不允许重复,清单文件资源文件还有resources.arsc文件,resources.arsc一开始我认为里面存放的应该是资源的映射关系,所以放在jar包中能有用,但是却会提示和本地生成的resources.arsc有冲突。那么就不能将这些文件一同写入jar包了,但是如果分开来src和jar包只放代码,res放资源,由于开发环境中R映射文件是动态生成的。而我现在操作的是R文件映射关系已经固定的项目,强行指定固然可以一试,但却不是好方法。

dex2jar classes.dex             //dex转jar
jar xf classes_dex2jar.jar		//解压jar
jar cvf ketroa.jar *			//打jar包

于是我又想到了第二种导入依赖的方法,项目指定,在eclipse中如果一个项目把另一个项目作为依赖,那么这个项目引用的包就会指向被引用项目的bin文件中自动生成的jar包,这个bin文件中除了有jar包,还有一个res资源文件夹,一个清单文件,和一个R.txt文件,虽然小,但是所有需要的文件都有。R.txt格式文件如下:

int dimen activity_horizontal_margin 0x7f040000
int dimen activity_vertical_margin 0x7f040001
int drawable ic_launcher 0x7f020000

这种方式虽然可行,但是也需要熟知Android生成apk的过程,对已有打包脚本进行修改才行,虽然是从两种出发点考虑,但是却和上面的强行指定是同一种路子。

关于aapt,可以通过调出命令文档可知aapt d -param apk可以查看apk的各种信息。

Loading Disqus comments...
Table of Contents