android 动态加载jar包

文章讲述了如何在Android应用中实现动态加载jar包,以减小apk体积。通过编写接口和实现类,打包成dex,然后使用DexClassLoader和反射调用来执行jar包中的功能。主要步骤包括编写接口和实现类,转换jar为dex,动态调用jar包。文章还提到了权限申请和jar的存放路径注意事项。
摘要由CSDN通过智能技术生成

什么时候需要用到动态加载jar包呢?

  1. 减少apk本身大小,某些界面才需要用jar里的功能
  2. jar中的功能可以独立开发,不要依赖其它的东西,能适用各个项目
  3. 和第三方公司合作,人家不提供项目源码给你,但又要开发他们使用的某些应用场景

实现步骤:

1. 编写jar的代码

新建一个service module,编写以下代码

public interface  AbstractAction {
    /**
     * 开始
     * @param c
     */
     void start(Context c);

    /**
     * 停止
     */
     void stop();
}



public class MainAction implements AbstractAction {

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    @Override
    public void start(Context c) {
        TaskManager.getInstance().start(c);
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    @Override
    public void stop() {
        TaskManager.getInstance().stop();
    }
}




public class TaskManager {

    private volatile static TaskManager instance = null;

    private boolean isRun = true;

    private TaskManager() {
    }

    public static TaskManager getInstance() {
        if (instance == null) {
            synchronized (TaskManager.class) {
                if (instance == null) {
                    instance = new TaskManager();
                }
            }
        }
        return instance;
    }

    /**
     * 初始化
     *
     * @param context
     */
    public void start(Context context) {

        // 做自己想做的事

        new Thread() {
            @Override
            public void run() {
                while (isRun)
                    Log.i("xian", " 执行任务中... ");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }.start();


    }

    public void stop() {
        isRun = false;
    }

}
2. 将代码打包并jar转换为 android 可以使用的jar(dex)包

由于android不能直接像java程序那样直接引用jar包, 需要转换dex才行

1. 在module中的 build.gradle 文件中,加入以下代码,生成jar包。输出路径为
task makeJar(type: Copy) {
    //删除已经存在的 jar
    delete 'build/libs/test-java.jar'
    //设置拷贝的文件
    from('build/intermediates/aar_main_jar/release/')
    //打进jar包后的文件目录
    into('build/libs/')
    include('classes.jar')
    //重命名
    rename ('classes.jar', 'test-java.jar')
}

makeJar.dependsOn(build)

在这里插入图片描述

2.执行makeJar Task, 一种是点击 task makeJar(tyoe.Copy)前面的绿色小三角运行,另外一种可以打开gardle,然后找到 service --> other --> makeJar 运行

在这里插入图片描述

在这里插入图片描述

3.运行完后,就会在 serice/ --> build --> lib下生成 test-java.jar

4. 使用android sdk --> build-tools --> 30.0.2(任意一个版本) --> dx 配置为环境变量 (如果觉得此操作麻烦,可以使用步骤5的方法)

在这里插入图片描述
windows 的电脑, 右击 我的电脑 --> 属性 --> 高级系统设置 --> path --> 添加 dx的路径 --> 保存
在这里插入图片描述

5. 如果不想配置环境变量,可以win+R --> cmd 打开控制台, 输入 D:\Android\Sdk\build-tools\30.0.2(我的sdk存放的路径),然后 D: 回车, 切换到D盘路径,如下图:

在这里插入图片描述
在这里插入图片描述
![在这里插入图片描述](https://img-blog.csdnimg.cn/d5d4b1c6797741d18c1453389be2caa5.png

在这里插入图片描述

6.将步骤3生成好的test-java.jar 包,拷贝到桌面,如果配置了环境变量可以直接使用dx命令,没有配置的话,就进入 sdk目录中的dx所在的目录,执行dx命令。 执行完命令后,就可以生成Android 可以调用的 test.jar 了
dx --dex --output=C:\Users\dell\Desktop\test.jar C:\Users\dell\Desktop\test-java.jar

在这里插入图片描述

3. 动态调用jar包

将成功后 test.jar 拷贝到手机的目录中,然后在项目中调用jar ,如果看到执行任务中… 就证明调用成功。

 /**
     *  使用dexClassLoader 动态加载test.jar,然后通过反射调用方法即可
     *
     * @param view
     */
    fun loadJar(view: View) {
        if (!PermissionUtils.checkPermission(this)) {
            Toast.makeText(this,"没有文件读写权限",Toast.LENGTH_LONG).show()
            //跳转到设置权限界面
            PermissionUtils.requestAppUsagePermission(this);
            return
        }

        val pluginPath = File(getExternalFilesDir(null)?.absolutePath + "/test.jar")
        Log.i("xian","jar 包存放路径: ${pluginPath}")
        val dataFile: String = codeCacheDir.absolutePath
        try {
            val classLoader =
                DexClassLoader(pluginPath.absolutePath, dataFile, null, javaClass.classLoader)

            val mainActionClass = classLoader.loadClass("com.xian.service.main.MainAction");
            val mainAction = mainActionClass.newInstance()

            //开始执行
            mainActionClass.getDeclaredMethod("start", Context::class.java)
                .invoke(mainAction, this)
        }catch (e:Throwable){
            // 路径记得放对 ,否则会报  ClassLoader referenced unknown path
            e.printStackTrace()
        }

    }

注意: 1. 申请读写权限 2.test.jar的存放路径
在这里插入图片描述
在这里插入图片描述

4. 源码

https://download.csdn.net/download/u012121105/87522731

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值