使用DexClassLoader的简单例子

因为项目需要,分析了DexClassLoader相关的源码实现,为了看看实际效果,参考网上例子,做了一个apk,使用DexClassLoader来做类加载器。


参考文章:

http://blog.csdn.net/u013478336/article/details/50734108


1,制作一个被调用的dex文件


1.1  按照建helloworldapk的方法新建一个android项目就行,包名或在建立的时候按下面代码来建,或者在已有项目新建下面的包名


文件1,

IShowToast.java

package com.example.testdextoast;


import android.content.Context;  


public interface IShowToast {  
    public int showToast(Context context);  
}  


文件2,

IShowToast.java

package com.example.testdextoast;


import android.content.Context;  
import android.widget.Toast;  
  
public class ShowToastImpl implements IShowToast {  
  
    @Override  
    public int showToast(Context context) {  
        Toast.makeText(context, "我来自另一个dex文件", Toast.LENGTH_LONG).show();  
        return 100;  
    }  
}  


1.2   对IShowToast.java文件,在Eclipse工程右键->Export->Java->Jar file,导出一个jar包,如命名origin.jar


1.3  在android的SDK目录下,找到类似目录Android\sdk\build-tools\22.0.1, 找到dx.bat


1.4 在命令行下,进入dx所在目录,将jar文件拷到该目录下,执行dx --dex --output=output.jar origin.jar,得到内含class.dex的output.jar

      因为使用level24的工具报错,所以暂使用22.0.1的

C:\Users\sssAppData\Local\Android\sdk\build-tools\24.0.0>dx --dex --output=out
put.jar origin.jar
Exception in thread "main" java.lang.UnsupportedClassVersionError: com/android/d
x/command/Main : Unsupported major.minor version 52.0
        at java.lang.ClassLoader.defineClass1(Native Method)
        at java.lang.ClassLoader.defineClass(ClassLoader.java:800)
        at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:14
2)
        at java.net.URLClassLoader.defineClass(URLClassLoader.java:449)
        at java.net.URLClassLoader.access$100(URLClassLoader.java:71)
        at java.net.URLClassLoader$1.run(URLClassLoader.java:361)
        at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:412)
        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
        at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:482)



1.5 将output.jar文件放到SD卡下adb push output.jar sdcard/output.jar



2. 制作一个主控apk,来动态加载dex


2.1 也是按照建helloworldapk的方法新建一个android项目就行


2.2 主代码如下

package com.example.testshowtoastdex;


import android.view.Menu;
import android.view.MenuItem;


import java.io.File;  


import com.example.testdextoast.IShowToast;  
  
import dalvik.system.DexClassLoader;  
import android.app.Activity;  
import android.os.Bundle;  
import android.os.Environment;  
import android.util.Log;  
  
public class MainActivity extends Activity {  
  
    @Override  
    protected void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.activity_main);  
          
        File dexOutputDir = getDir("dex1", 0);  
        String dexPath = Environment.getExternalStorageDirectory().toString() + File.separator + "output.jar";  
        Log.d("TEST111", "showToast"+dexPath);  
        DexClassLoader loader = new DexClassLoader(dexPath,   
                dexOutputDir.getAbsolutePath(),   
                null, getClassLoader());  
        try {  
            Class clz = loader.loadClass("com.example.testdextoast.ShowToastImpl");  
            IShowToast impl = (IShowToast) clz.newInstance();  
            impl.showToast(this);  
            Log.d("TEST111", "showToast");  
        } catch (Exception e) {  
            Log.d("TEST111", "error happened", e);  
        }  
    }  
}  


2.3 因为要访问SD卡,所以要在manifest加权限<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.testshowtoastdex"
    android:versionCode="1"
    android:versionName="1.0" >


    <uses-sdk
        android:minSdkVersion="14"
        android:targetSdkVersion="21" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />


                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>


</manifest>


如果没加权限,会出现如下报错

09-20 23:48:26.599: D/TEST111(4440): Suppressed: java.lang.ClassNotFoundException: Didn't find class "com.example.testdextoast.ShowToastImpl" on path: DexPathList[[zip file "/data/app/com.example.testshowtoastdex-1/base.apk"],nativeLibraryDirectories=[/data/app/com.example.testshowtoastdex-1/lib/arm, /vendor/lib, /system/lib]]
09-20 23:48:26.599: D/TEST111(4440): at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)
09-20 23:48:26.599: D/TEST111(4440): at java.lang.ClassLoader.loadClass(ClassLoader.java:511)
09-20 23:48:26.599: D/TEST111(4440): at java.lang.ClassLoader.loadClass(ClassLoader.java:504)


2.3  按IShowToast.java的原来的路径,将它复制到新工程,不要改变文件


编译、安装到手机,就能看到toast。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值