• Android动态加载技术初探


    一、前言:

            现在,已经有实力强大的公司用这个技术开发应用了,比如淘宝,大众点评,百度地图等,之所以采用这个技术,实际上,就是方便更新功能,当然,前提是新旧功能的接口一致,不然会报Not Found等错。

    二、原理:

        2.1 JAR文件:

            Android使用动态加载的方法,和Java加载类似,都是加载.jar文件来实现,只不过,不同的是,这两者的虚拟机不同,导致.jar的格式也不同。

            Android只认识.dex格式的.class文件,因为,需要做的是:

            1. 正常的方法Export出一个.jar文件;

            2. 使用命令将.jar转成.dex格式的.jar文件;

            命令: dx --dex --output=[path]/[dest].jar [path]/[src].jar

        2.2 ClassLoader:

            Android系统提供了两种ClassLoader:

            1. DexClassLoader

                    这个可以加载jar/apk/dex,也可以从SD卡中加载,也是本文的重点。

            2. PathClassLoader

                    只能加载已经安装到Android系统中的apk文件。

    三、实战:

            3.1 创建一个Jar的空工程(这里我取名叫:DynamicLoaderLib)

                1. 新建两个.java文件,一个是IDynamicLoader.java(接口类),一个是LibDexJar.java(接口的实现类)

                

                 2. 代码

                 IDynamicLoader.java

    package com.chris.dynamic.loader;
    
    public interface IDynamicLoader {
    	public String getHelloWorld(); 
    }

                 LibDexJar.java

    package com.chris.dynamic.loader;
    
    public class LibDexJar implements IDynamicLoader {
    	@Override
    	public String getHelloWorld() {
    		return "HelloWorld! (使用动态加载方法)";
    	}
    }

                 3. 导出jar包 (Export -> jar文件)

                 

                 然后点"完成"就行了(千万不要将接口定义类也打包进去,否则在运行时会报错,只打包接口实现类就行)。

                 大家可以随意存放,不过,为了方便维护,我在当前这个工程下面建了一个jar目录来存放。

                 然后,打开命令行,输入命令:

                 dx --dex --output=[全路径]/dst.jar [全路径]/src.jar

                

                 注:大家需要把Android SDK的路径添加到系统的环境变量中,这样才能让系统找到dx工具,否则系统会报找不到。

                 

                 这样,就生成好了我们所需要的dex格式.class的jar包,然后把这个放到手机的/mnt/sdcard目录下(因为这个目录是可读写的)。

            3.2 创建一个Test工程(DynamicLoaderTest)

           

            IDynamicLoader.java就是上一个JAR工程中的接口定义类,这里只给出MainActivity.java的实现:

             @Override
    	protected void onCreate(Bundle savedInstanceState) {
    		super.onCreate(savedInstanceState);
    		setContentView(R.layout.activity_main);
    		
    		Button dloader = (Button) findViewById(R.id.dload_jar);
    		dloader.setOnClickListener(new OnClickListener(){
    			@Override
    			public void onClick(View v) {
    				File dexJar = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + 
    						File.separator + "LibDexJar.jar");
    				if(dexJar.exists()){
    					DexClassLoader dcl = new DexClassLoader(dexJar.getAbsolutePath(), 
    							Environment.getExternalStorageDirectory().toString(), 
    							null, getClassLoader());
    					try {
    						Class dloaderClass = dcl.loadClass("com.chris.dynamic.loader.LibDexJar");
    						IDynamicLoader IDloader = (IDynamicLoader) dloaderClass.newInstance();
    						Toast.makeText(MainActivity.this, "Android动态加载Demo:" + IDloader.getHelloWorld(), Toast.LENGTH_SHORT).show();
    					} catch (ClassNotFoundException e) {
    						e.printStackTrace();
    					} catch (InstantiationException e) {
    						e.printStackTrace();
    					} catch (IllegalAccessException e) {
    						e.printStackTrace();
    					}
    				}
    			}
    		});
    	}

            这里可以分为4步:

            1. 判断是否存在LibDexJar.jar文件在sdcard目录下;

            2. 使用DexClassLoader加载JAR文件;

            3. 载入Class;

            4. 获取接口类的实例;

            然后,就可以使用接口类中开放的接口了。

            附上我运行的截图:

              

           

    最后,附上我的两个工程的源码供大家下载参考:

    http://download.csdn.net/detail/qingye_love/6386981

    大家多在本文章中来讨论,多多交流,谢谢!

    另附上将导致的jar生成dex的jar(在代码的JAR目录下,这里我也贴出来):

    dexjar.bat

    @echo off
    rem 使用前请先设置自己的Android SDK路径
    set ANDROID_SDK="E:chrisAndroid_DevAndroidandroid-sdk"
    
    set path=%path%;%ANDROID_SDK%platform-tools;
    
    rem 设置jar所存放的路径
    set JAR_ROOT="E:chrisAndroid_DeveclipseworkspaceDynamicLoaderLibjar"
    
    rem 编译
    @echo on
    dx --dex --output=%JAR_ROOT%LibDexJar.jar %JAR_ROOT%dynamic.jar
  • 相关阅读:
    每天一道Rust-LeetCode(2019-06-11)
    每天一道Rust-LeetCode(2019-06-10)
    每天一道Rust-LeetCode(2019-06-08)
    每天一道Rust-LeetCode(2019-06-07)
    每天一道Rust-LeetCode(2019-06-06)
    每天一道Rust-LeetCode(2019-06-05)
    每天一道Rust-LeetCode(2019-06-04)
    linux 基本命令
    使用 DrMemory 详细教程
    C++ 虚函数表解析
  • 原文地址:https://www.cnblogs.com/suncoolcat/p/3366172.html
Copyright © 2020-2023  润新知