主要整理一般加载jar相关的流程:jar混淆打包乃至加密,加载以及解密,调用。
1.打包发布相关
jar打包很简单,可以使用eclipse等工具,也能直接使用命令。
使用eclipse的话,右键工程,有个Export,然后选择打包的文件类型,选择java下的jar file,然后选择下打包的文件和存放路径。但是这个好像是没混淆的,目前还不确定怎么将混淆文件添加到jar打包的路径去。
使用指令:jar cvf dst src,然后使用proguard.jar混淆,java -jar proguard.jar @proguard.pro
其中proguard.pro是混淆配置文件,可以下载标准的文件修改,或者参照下面的使用语法自己添加,在这个文件的开头加上以下语句来定义dst和src文件。
-injars ./out/a.jar
-outjars ./out/b.jar
这样就得到了jar,但是这个android不识别,需要转化成dex文件,使用以下指令:
dx --dex --output=dst src
然后可以对dex文件加密,这样就准备好了需要的插件包。
附部分混淆语法
# 保持哪些类不被混淆
-keep public class * extends android.app.Activity
# 保持接口不被混淆
-keepclassmembers class * extends android.app.Activity
{
public <methods>;
}
#去除log信息
-assumenosideeffects class android.util.Log{
public static *** d(...);
public static *** i(...);
}
-flattenpackagehierarchy #包结构扁平化
2.加载jar包
File dexOutputDir = context.getDir("dex", 0); //dex文件输出目录
DexClassLoader mClassLoader = new DexClassLoader(jarFile.getAbsolutePath(), dexOutputDir.getAbsolutePath(), null,
ClassLoader.getSystemClassLoader());
上面是加载dex文件,当然如果加密的话,需要先解密,然后就是反射调用接口了。
3.反射调用
if(mClassLoader != null){
try{
mgrClass = mClassLoader.loadClass(完整的包名+类名);
Log.i(TAG, "~~try load jar---ok");
}catch(ClassNotFoundException e){
}
}
获取类的构造方法和对象
Constructor<?> jarConstructor = mgrClass.getConstructor(Context.class,String.class);
mgrInstance = jarConstructor.newInstance(context);
然后获取他的方法
Method entry = mgrClass.getMethod("entry",int.class);
调用方法
int cmd = 3;
try {
entry.invoke(mgrInstance, cmd);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
上面举例的构造方法是public xxx(Context,String),反射的方法带个int参数。
假如需要使用jar包里的资源文件,可以使用Class通过路径得到资源文件
getClass().getResourceAsStream("xxx");
最后,就可以使用动态加载来实现插件化开发了,jar可以从服务器下载从而实现不同的功能。