Android动态加载类

这篇博客介绍了Android中如何动态加载class文件为dex并进行使用。首先,利用dx工具将class打包成dex,然后将dex文件放置到手机特定路径。接着,通过DexClassLoader来加载dex中的类。在实施过程中,遇到JDK版本高于9导致的问题,解决方法是修改dx.bat脚本中的参数。此外,还解决了Android高版本中在外部存储加载dex文件报错的问题,建议将dex文件存放在应用内部的缓存目录。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.把class文件打包成dex文件。

在android-sdk/build-tool下有个dx脚本工具,可以将class文件打包成dex文件。

dx --dex --no-strict --output <输出dex路径> <class文件路径>

2.将dex文件放入手机中的某个路径下。

3.使用DexClassLoader加载dex文件中的类。

Activity代码:

package com.champion.loaddexdemo;

import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Environment;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;

import junit.framework.Assert;

import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import dalvik.system.DexClassLoader;

public class MainActivity extends AppCompatActivity {
    int storageRequestCode = 1;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        if(PackageManager.PERMISSION_DENIED == checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE)){
            requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, storageRequestCode);
        }
        findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //本例中是将out.dex放在sdcard根目录下
                File dexFile = new File(Environment.getExternalStorageDirectory(), "out.dex");
                if(!dexFile.exists()){
                    System.out.println("dexFile not exists");
                    return;
                }
                File odexDir = getDir("odex", Context.MODE_PRIVATE);
                if(!odexDir.exists()){
                    System.out.println("odexDir not exists");
                    odexDir.mkdir();
                }
                //新建一个DexClassLoader,以dex文件的路径为参数,传入一个放置odex文件的文件夹路径
                DexClassLoader dexClassLoader = new DexClassLoader(dexFile.getAbsolutePath(),
                        odexDir.getAbsolutePath(), null, getClassLoader());
                try {
                    //使用dexClassLoader进行加载dex文件中的类
                    Class clazz = dexClassLoader.loadClass("com.champion.loaddexdemo.dynanmicLoadedTest");
                    Object object = clazz.newInstance();
                    //调用类中的方法
                    Method method = clazz.getMethod("load");
                    method.invoke(object);
                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (InstantiationException e) {
                    e.printStackTrace();
                } catch (NoSuchMethodException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                }
            }
        });
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if(requestCode == storageRequestCode){
            System.out.println("request code success!!!!!");
        }
    }

}

被加载的测试类代码:

package com.champion.loaddexdemo;

public class dynanmicLoadedTest {
    static {
        System.out.println("static load success!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
    }
    public void load(){
        System.out.println("load+++++++++++++++++++++++++++++++++");
    }
}

 高版本JDK导致的问题:-Djava.ext.dirs=C:\Users\zhangjb\AppData\Local\Android\Sdk\build-tools\28.0.0\lib is not supported

原因:JDK大于9,新增了--class-path,不支持原来的-Djava.ext.dirs属性

解决方法:打开dx.bat,将-Djava.ext.dirs替换为--class-path

高版本Android导致的问题:java.io.IOException: No original dex files found for dex location (arm64) /sdcard/lib.dex

原因:不知道,Android有意限制不能在不属于应用的外部存储中吧

解决方法:把dex文件或者apk放到应用内部存储空间,如应用cache ,通过getExternalCacheDir获取

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值