工作的时候有时候会在系统中增加api方法,这时候如果提供给app开发人员使用的话有两种方法:
- 打包新的android.jar
- 使用反射
这里简单的说一下第一种方法,使用反射的方法可以参照之前的文章。
其实android系统内带的framework.jar已经包含了增加的api,只需将其抽取并放到官方的android.jar内就好了,整理一下就是:
- 增加新的方法make后,拷贝出新的framework.jar
- 解压framework.jar,使用d2j-dex2jar.sh将其中的dex解压为class文件
- 解压andoid.jar文件
- 将步骤2中解压出来的class文件拷贝到步骤3解压出来文件夹的对应位置
- 打包新的andoid.jar
方便起见,写一个脚本来完成上面的工作,其中转换framework.jar用到dex2jar工具,请自行下载配置
#!/bin/sh
####################################################################################
##
## Usage: makesdk.sh framework.jar android.jar ~/Desktop
##
## 20170712 write by liuxq
##
## version 1.0
##
## used to merge platform.jar to android.jar for app
##
## ps:need dex2jar tool
##
####################################################################################
DEX2JAR_PATH="/home/liuxiuquan/SynologyDrive/ubuntu/worktest/test_shell/android_51_anrdoidjar/dex-tools-2.1/d2j-dex2jar.sh"
DEX=$1
AJAR=$2
OUT=$3
doMerge() {
echo param: DEX=${DEX} AJAR=${AJAR} OUT=${OUT}
current_time=`date '+%Y%m%d_%H%M%S'`
android_jar_name=android_${current_time}.jar
echo $android_jar_name
#1.unpack framework.jar and do d2j-dex2jar
cp $DEX framework.zip
unzip -q -o -d framework_dex_tmp framework.zip
echo "STEP ONE DONE!"
#run d2j-dex2jar
cd framework_dex_tmp
# find -maxdepth 1 -name "classes*.dex" -exec ${DEX2JAR_PATH} --force {} \; >/dev/null 2>&1
find -maxdepth 1 -name "classes*.dex" -exec ${DEX2JAR_PATH} --force {} \;
find -maxdepth 1 -name "classes*.jar" -exec unzip -q -o -d framework_jar_tmp {} \;
cd ..
#2.unpack android.jar
cp $AJAR android.zip
unzip -q -o -d android-sdk android.zip
echo "STEP TWO DONE!"
#3.merge and pack
cp -r -f framework_dex_tmp/framework_jar_tmp/* android-sdk/
cd android-sdk
# zip -q -r $OUT/android-new.jar *
jar -cf ${OUT}/${android_jar_name} .
cd ..
echo "STEP THREE DONE!"
#4.clean
rm android.zip
rm framework.zip
rm -rf android-sdk/
rm -rf framework_dex_tmp/
echo "STEP FOUR DONE!"
echo "new android.jar is locate at $OUT/${android_jar_name}"
}
usage(){
#41 background color, 37 font color
echo "Usage: \033[41;37m$0 framework.jar android.jar ~/Desktop/ \033[0m"
echo "first param is framework.jar's path"
echo "second param is android.jar's path"
echo "last param is output's path"
echo '\nDo these things:'
echo '1.unpack framework.jar and do d2j-dex2jar'
echo '2.unpack android.jar'
echo '3.merge and pack'
echo '4.clean\n'
}
if [ ! $# -eq 3 ]; then
case $1 in
-h|--help)
usage
;;
*)
#41 background color, 37 font color
echo "Usage: \033[41;37m$0 framework.jar android.jar ~/Desktop\033[0m"
echo "Try $0 -h for more information."
;;
esac
else
doMerge
fi
使用也很简单,将这段脚本存为makesdk.sh并给予可执行权限,然后使用
$ makesdk.sh framework.jar android.jar ~/Desktop/
执行完成后,即可在桌面上看到一个名为android_${current_time}.jar
的文件,这就是包含我们增加api的sdk了
备注:
一、如果执行d2j-dex2jar.sh
的时候有如下报错,则需要更新下dex2jar版本 (下载完源码后gradle build
即可)
Landroid/preference/MultiSelectListPreference$1;.onClick(Landroid/content/DialogInterface;IZ)V
java.lang.RuntimeException: can not merge I and Z
at com.googlecode.dex2jar.ir.TypeClass.merge(TypeClass.java:100)
at com.googlecode.dex2jar.ir.ts.TypeTransformer$TypeRef.updateTypeClass(TypeTransformer.java:174)
at com.googlecode.dex2jar.ir.ts.TypeTransformer$TypeAnalyze.provideAs(TypeTransformer.java:780)
at com.googlecode.dex2jar.ir.ts.TypeTransformer$TypeAnalyze.enexpr(TypeTransformer.java:659)
at com.googlecode.dex2jar.ir.ts.TypeTransformer$TypeAnalyze.exExpr(TypeTransformer.java:719)
at com.googlecode.dex2jar.ir.ts.TypeTransformer$TypeAnalyze.exExpr(TypeTransformer.java:703)
at com.googlecode.dex2jar.ir.ts.TypeTransformer$TypeAnalyze.enexpr(TypeTransformer.java:698)
at com.googlecode.dex2jar.ir.ts.TypeTransformer$TypeAnalyze.exExpr(TypeTransformer.java:719)
at com.googlecode.dex2jar.ir.ts.TypeTransformer$TypeAnalyze.exExpr(TypeTransformer.java:703)
at com.googlecode.dex2jar.ir.ts.TypeTransformer$TypeAnalyze.s1stmt(TypeTransformer.java:810)
at com.googlecode.dex2jar.ir.ts.TypeTransformer$TypeAnalyze.sxStmt(TypeTransformer.java:840)
at com.googlecode.dex2jar.ir.ts.TypeTransformer$TypeAnalyze.analyze(TypeTransformer.java:206)
at com.googlecode.dex2jar.ir.ts.TypeTransformer.transform(TypeTransformer.java:44)
at com.googlecode.d2j.dex.Dex2jar$2.optimize(Dex2jar.java:162)
at com.googlecode.d2j.dex.Dex2Asm.convertCode(Dex2Asm.java:414)
at com.googlecode.d2j.dex.ExDex2Asm.convertCode(ExDex2Asm.java:42)
at com.googlecode.d2j.dex.Dex2jar$2.convertCode(Dex2jar.java:128)
at com.googlecode.d2j.dex.Dex2Asm.convertMethod(Dex2Asm.java:509)
at com.googlecode.d2j.dex.Dex2Asm.convertClass(Dex2Asm.java:406)
at com.googlecode.d2j.dex.Dex2Asm.convertDex(Dex2Asm.java:422)
at com.googlecode.d2j.dex.Dex2jar.doTranslate(Dex2jar.java:172)
at com.googlecode.d2j.dex.Dex2jar.to(Dex2jar.java:272)
at com.googlecode.dex2jar.tools.Dex2jarCmd.doCommandLine(Dex2jarCmd.java:108)
at com.googlecode.dex2jar.tools.BaseCmd.doMain(BaseCmd.java:288)
at com.googlecode.dex2jar.tools.Dex2jarCmd.main(Dex2jarCmd.java:32)
引用下 https://github.com/pxb1988/dex2jar/issues/10 上pxb1988的回复:
the problem is caused by strict type calculation, because in java syntaxt, a boolean can not assign to an inteager. so dex2jar forbid merge type Z and I. There are two solutions:
1.modify the dex by hand and add the following code after
move-result v1
if-eqz v1, :LZERO const v1, 1 goto :Lend :LZERO const v1, 0 :Lend
2.modify the dex2jar code. return Type I when merge I and Z at
com.googlecode.dex2jar.ir.TypeClass.merge(TypeClass.java:100)
二、其实也可以直接编译android.jar,只是改动比较多。
$ source build/envsetup.sh
$ launch'what you want'
$ make update-api
$ make PRODUCT-sdk-sdk -j8
代码使用android L