Android动态加载技术初探

来源:互联网 发布:tcp ip协议c语言实现 编辑:程序博客网 时间:2024/04/30 01:24

分类: Android 418人阅读 评论(0) 收藏 举报
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

[java] view plaincopy
  1. package com.chris.dynamic.loader;  
  2.   
  3. public interface IDynamicLoader {  
  4.     public String getHelloWorld();   
  5. }  

             LibDexJar.java

[java] view plaincopy
  1. package com.chris.dynamic.loader;  
  2.   
  3. public class LibDexJar implements IDynamicLoader {  
  4.     @Override  
  5.     public String getHelloWorld() {  
  6.         return "HelloWorld! (使用动态加载方法)";  
  7.     }  
  8. }  

             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的实现:

[java] view plaincopy
  1.         @Override  
  2. protected void onCreate(Bundle savedInstanceState) {  
  3.     super.onCreate(savedInstanceState);  
  4.     setContentView(R.layout.activity_main);  
  5.       
  6.     Button dloader = (Button) findViewById(R.id.dload_jar);  
  7.     dloader.setOnClickListener(new OnClickListener(){  
  8.         @Override  
  9.         public void onClick(View v) {  
  10.             File dexJar = new File(Environment.getExternalStorageDirectory().getAbsolutePath() +   
  11.                     File.separator + "LibDexJar.jar");  
  12.             if(dexJar.exists()){  
  13.                 DexClassLoader dcl = new DexClassLoader(dexJar.getAbsolutePath(),   
  14.                         Environment.getExternalStorageDirectory().toString(),   
  15.                         null, getClassLoader());  
  16.                 try {  
  17.                     Class dloaderClass = dcl.loadClass("com.chris.dynamic.loader.LibDexJar");  
  18.                     IDynamicLoader IDloader = (IDynamicLoader) dloaderClass.newInstance();  
  19.                     Toast.makeText(MainActivity.this"Android动态加载Demo:" + IDloader.getHelloWorld(), Toast.LENGTH_SHORT).show();  
  20.                 } catch (ClassNotFoundException e) {  
  21.                     e.printStackTrace();  
  22.                 } catch (InstantiationException e) {  
  23.                     e.printStackTrace();  
  24.                 } catch (IllegalAccessException e) {  
  25.                     e.printStackTrace();  
  26.                 }  
  27.             }  
  28.         }  
  29.     });  
  30. }  

        这里可以分为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

[plain] view plaincopy
  1. @echo off  
  2. rem 使用前请先设置自己的Android SDK路径  
  3. set ANDROID_SDK="E:\chris\Android_Dev\Android\android-sdk"  
  4.   
  5. set path=%path%;%ANDROID_SDK%\platform-tools;  
  6.   
  7. rem 设置jar所存放的路径  
  8. set JAR_ROOT="E:\chris\Android_Dev\eclipse\workspace\DynamicLoaderLib\jar"  
  9.   
  10. rem 编译  
  11. @echo on  
  12. dx --dex --output=%JAR_ROOT%\LibDexJar.jar %JAR_ROOT%\dynamic.jar  
更多0
0 0
原创粉丝点击