android jar包插件化以及远程更新jar包思路

来源:互联网 发布:淘宝开店充话费流程 编辑:程序博客网 时间:2024/06/07 20:33

首先介绍一下要实现的效果:静默更新所有客户端应用程序中的jar包。

产生这个需求的原因:当做好的jar包发布出去,开发者已经在使用的情况下,有一天我们发现jar包中有个bug,这是我们就要去更新jar包,但是如果开发者需要更新jar包的话,那代价无疑是巨大的。出于减少开发者更新jar包的代价的目的。我们想到了使用这种方式来解决。整个项目的结构如下图:


插件管理框架工作流程:

客户端app启动时,插件管理框架读取本地所有插件信息,例如插件版本,提供者等等,并将该信息发送到插件管理服务端,在服务端监测是否有新的插件需要更新。如果有新的插件插件管理框架负责下载等操作。

具体的实现的话,为了统一,我们在插件管理框架中定义好接口,所有插件都要实现该接口,实现该接口的插件,我们就认为它是一个合法的插件。这样在application中我们就可以通过插件管理框架中的方法来调用插件中的方法。

插件管理框架主要模块:

1.插件管理:读取插件信息和服务端交互,根据返回判断是否下载新的插件。

2.调用插件中的方法。

       关于第一点就不多少了,就是一些网络访问和下载的东东。我们主要说一下调用插件中的方法。在使用jar包的使用我们知道如果是放在lib目录下,通过build path 加载到项目中,我们可以直接通过import导入使用jar包中的类和方法。但是插件的类和方法该怎么使用呢?这是我们就要使用到android的类加载器。android中有两种类加载器 DexClassLoader和PathClassLoader,两者的区别就是PathClassLoader只能加载已经安装到android系统中的apk文件,也就是/data/app/下的apk文件,加载其他位置的文件会报ClassNotFoundException ,DexClassLoader可以加载apk、jar和dex文件,而且可以加载sdcard下的文件。

先介绍一下我们的插件项目,该项目就是简单的做个加法运算。

package com.apkplug;public class plugClass {    public plugClass() {            }    public int  add(int a, int b){        return a+b;            }    }

  在下面的介绍中我们使用DexClassLoader.首先我们来打包jar包并转换成dex文件,首先将写好的jar包导出,Export->java jarfile ->Next 然后选择jar的存放目录。然后我们将jar包转成dex格式,为了方便我们将jar包放到SDK的安装目录plarform-tools下,DOS进入这个目录,执行命令: dx --dex -ouput=classes.jar  Myplug.jar 这样我们就将Myplugin.jar转成了dex格式,我们将classes.jar 放到SDcard目录。下面在程序中我们使用DexClassLoader来加载classes.jar中的类

package com.apkplugtest;import android.os.Bundle;import android.app.Activity;import android.view.Menu;import android.widget.TextView;import java.lang.reflect.Method;import dalvik.system.DexClassLoader;import dalvik.system.PathClassLoader;public class MainActivity extends Activity {    TextView tv = null;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        tv = (TextView) findViewById(R.id.tv);        useDexClassLoader();    }    private void useDexClassLoader() {               String dexPath = "/mnt/sdcard/classes.jar";        String dexOutputDir = "/data/data/com.apkplugtest";        DexClassLoader pathClassLoader = new DexClassLoader(dexPath, dexOutputDir, null, this                .getClass().getClassLoader());        // dexPath 目标jar或apk的路径 ; dexOutputDirdex 文件路径 ;null 目标类中使用的c/c++库存放的路径        // ; 第四个参数 父装载类        try {            Class<?> class1 = pathClassLoader.loadClass("com.apkplug.plugClass");            Object object = class1.newInstance();            Class[] params = new Class[2];            params[0] = Integer.TYPE;            params[1] = Integer.TYPE;            Method action = class1.getMethod("add", params);            Integer ret = (Integer) action.invoke(object, 12, 13);            tv.setText("method : " + action.getName() + ", return :" + ret);        } catch (Exception e) {            // TODO: handle exception        }    }   }

程序运行结果如下图:


同时我们看到在data/data/com.apkplugtest下生成了.dex 文件如下图:



整个思路就是这样了。

0 0
原创粉丝点击