暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

android插件化开发

WTech 2018-03-19
242

        前阵子,在面试过程中,了解到android的插件化开发。今天将它大概的思路整了一下。阿里巴巴开源了一个插件化开发框架Atlas,淘宝就是用这个搭建起来,地址:http://atlas.taobao.org/docs/principle-intro/Apk_architecture.html


插件化开发基本思路:

1、第一步:写好插件(就像写一个完整的apk差不多,爱写什么都可以,只要是java写的就行),并生成dex文件。编写好的java文件,打出来的jar文件,在android上是运行不了的,因为打成的jar文件里的字节码,只能在java JVM中运行,而android手机的应用是运行在Dalvik VM上的,它只能运行dex格式的字节码文件,所以再用dx命令,将jar文件转换成dex文件,压缩格式可以是jar、apk、dex。

例如:把ShowStringClass.java文件打包生成showStringClass.jar文件,然后把文件放到sdk目录下的build-tools下的23.0.1目录下,然后用下面命令把showStringClass.jar生成showStringClass_imle.jar的dex文件:


dx --dex --output=showStringClass_impl.jar showStringClass.jar


2、第二步:将dex文件放上手机sdcard中:

adb push showStringClass_impl.jar /sdcard/

3、第三步:使用DexClassLoader加载类

  DexClassLoader是一个类加载器,可以用来从.jar和.apk文件中加载class。可以用来加载执行没有和应用程序一起安装的那部分代码。它构造函数是DexClassLoader(String dexPath, String optimizedDirectory, String libraryPath, ClassLoader parent)

参数说明:

dexPath: dex文件的路径,就是第二步上传到sdcard中的jar文件路径,不能为空。

optimizedDirectory:解压后的.dex文件的存储路径(从jar文件、apk文件解压出来后,得到的.dex文件存放路径),不能为空。强烈建议使用应用程序的私有路径,不要放到sdcard上,否则代码容易被注入攻击。

libraryPath:os库的存放路径,可以为空,若有os库,必须填写。

parent:父亲加载器,一般为context.getClassLoader(),使用当前上下文的类加载器。


代码如下:

File dexOpt = this.getDir("dexOpt", MODE_PRIVATE); //在app的包名下创建一个dexOpt目录,返回路径。这是放.dex文件的  

final DexClassLoader classloader = new DexClassLoader(                    apkPath,       //加载dex文件        

dexOpt.getAbsolutePath(),      

null,               

this.getClassLoader());     

Class<?> classToLoad = (Class<?>)     classloader.loadClass("com.wong.mytestapp.ShowStringClass");     //加载特定类

Object instance = classToLoad.newInstance();         //类的实例化

Method method = classToLoad.getMethod("method");    //获得类的方法

method.invoke(instance);//调用类的方法


注意,第二步:

  如果dex文件放在android的资源目录asset中,那么准确的做法时。要把asset里的dex、jar、apk文件读出到一个目录下,如应用程序的私有路径。然后再进行第三步及后续操作。

  将asset文件读出到应用程序的私有路径:

private final String DexPath = "dex";

    private final String ASSETJAR = "plugins/ShowStringClass_impl.jar";

    private final String EXPORTJARNAME = "ShowStringClass.jar";

    private void copyDex(String DexPath) throws IOException {

        File dexPath = getDir(DexPath,0);

        File jarFile = new File(dexPath,EXPORTJARNAME);

        if(jarFile.exists()) {

                boolean b = jarFile.delete();

        }

            //打开asset中的输入流

            InputStream ins = getAssets().open(ASSETJAR);

            //将输入流写入文件

            FileOutputStream fos = new FileOutputStream(jarFile);

        byte[] arrayOfByte = new byte[1024];

        for(;;){

            int i = ins.read(arrayOfByte);

            if(i==-1) break;

            fos.write(arrayOfByte,0,i);

            fos.flush();

        }

    }


文章转载自WTech,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论