文档章节

Android 之动态加载代码

MrXI
 MrXI
发布于 2016/05/22 12:50
字数 1386
阅读 419
收藏 13
点赞 2
评论 0

一、前言

        在项目研发中会遇到部分功能经常变更,经常升级app会对用户产生反感,造成体验很差。

项目中有这样一个功能:下载到本地的视频需要在播放时加载字幕,但是某些视频我们的服务器中不存在字幕,经过调研发现字幕库网站能通过影片名查询到相应的字幕,并下载下来。但是问题是字幕库没有公开的字幕查询接口,只能通过一些逆向分析后,对页面进行解析捕获到了字幕的下载路径,字幕下载路径是嵌套在html代码中,这样只有通过JSoup技术(不懂得可以查百度,这儿就不细说)对html页面进行动态解析,拿到字幕的下载地址,之后再下载到我们的服务器上面,开发的都知道使用第三方的总是不稳定,都说吃人嘴软,拿人手短,还是不如自己的,第三方的网页布局变化了,那么使用jsoup解析的地址就全部出错了,但是不能因为这个就去对app进行重新打包发布新版本,这样对用户的体验不好,那么我们就要使用动态加载技术去改变这样的频繁打包工作。

解决思路:把经常变化的放在服务器上面,每次启动app的时候就从服务器上面下载下来逻辑,再动态的加载到app的包里面,动态打包我们的app的,实例化对象,如果字幕库发生变化,我们就只需要更新服务器上面的解析代码,重新下载相应的逻辑加载到app。

二、使用方式

如何实现动态加载的流程?

第一:制作dex文件。

第二:把制作的dex文件发布到服务器上面,从服务器上面下载dex文件之后动态打包到app中

制作的工具类:

 

 

public class JsoupUtils {

    public static String html2Url(String html) {
        return "url" + html;
    }
}

 

 

①、制作dex文件

然后编译之后再androidstudio的build/intermediates/classes/debug/  下面会看到你的包名生成的字节码,之后使用Java打包命令:jar  -cvf把指定的字节码打包成jar文件,如下:

出现这个表示打包成功,

 

然后再把jar文件打包成dex文件,现在就要使用dex命令,dx.bat文件,在build目录下,或者配置环境变量:

出现以下表示打包成功:

 

至此dex文件打包成功

 

②、把制作的dex文件发布到服务器上面,从服务器上面下载dex文件之后动态打包到app中

 

在此演示则不去服务器下载,省略下载的步骤,直接放在assets目录下面:

 

先把assets目录下的utils_dex.jar拷贝到sd卡上面

三、加载器

以下就是类加载器:

使用反射与类加载器

android中的类加载器主要有三个:

(1)、URLClassLoader  

只能用于加载jar文件,但是由于dalvik不能直接识别jar文件,所以android中无法使用这个类加载器

(2)、PathClassLoader 

它只能加载已经安装的apk,因为PathClassLoader只会读取/data/dalvik-cache/目录下的dex文件,

例如安装一个apk的时候,就会在这个目录下面的x86目录下生成每个apk对应的dex文件:

使用PathClassLoader加载apk时,它就会在这个目录下面去查找对应的DEX文件,如果apk没有安装,则会报错,ClassNotFoundException

 

(3)、DexClassLoader 

        是最理想的加载器,它的构造函数包括四个参数

1、dexPath:目标类所在的APK或jar文件的路径,类加载器将从该路径中寻找指定的目标类,该类必须是apk或者jar的全路径,如果包含多个路径,路径之间必须使用特定的分隔符分隔,特定的分隔符可以使用System.getProperty("path.separtor")获得;

2、dexOutputDir:由于dex文件被包含在apk或者jar文件中,因此在装载目标类之前需要先从apk或jar文件中解压出dex文件,该参数就是定制解压出的dex文件存放的路径,在Android系统中,一个应用程序一般对应一个Linux用户,应用程序仅对属于自己的数据目录路径有写的权限,因此,该参数可以使用该程序的数据路径

3、libPath:指目标类中使用的C/C++库存放的路径

4、classload是指该装载器的父装载器,一般为当前执行类的装载器

直接上代码:

package com.parse.dex;

import android.content.Context;
import android.os.Bundle;
import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.widget.Toast;

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

import dalvik.system.DexClassLoader;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initLoadDex();
    }

    private void initLoadDex() {
        FileUtils.copyAssetsJarToFile(this, "utils_dex.jar", "utils_dex.jar");
        File file = new File(Environment.getExternalStorageDirectory().toString() + File.separator + "utils_dex.jar");
        File optimizedDexOutputPath = getDir("dex", Context.MODE_PRIVATE);
        DexClassLoader dexClassLoader = new DexClassLoader(file.getAbsolutePath(), optimizedDexOutputPath.getAbsolutePath(), null, getClassLoader());
        try {
            Class loadClass = dexClassLoader.loadClass("com.parse.dex.JsoupUtils");
            Method html2Url = loadClass.getMethod("html2Url", String.class);
            String s = (String) html2Url.invoke(loadClass, "解析html文件");
            Toast.makeText(this, s, Toast.LENGTH_SHORT).show();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}

整个动态加载类的流程就是这样的

 

四、开源代码库

最后再分享一个自己积攒很久的代码库,只有你想不到,没有用不到的,欢迎star

https://github.com/xijiufu

由于github服务器在美国,有时访问很慢,还提供了开源中国地址库,2个仓库代码均同步更新:

http://git.oschina.net/xijiufu

 

© 著作权归作者所有

共有 人打赏支持
MrXI
粉丝 26
博文 16
码字总数 33406
作品 0
成都
程序员
Android动态加载——加载未安装APK中的类

前言   近期做换肤功能,由于换肤程度较高,受限于平台本身,实现起来较复杂,暂时搁置了该功能,但也积累了一些经验,将分两篇文章来写这部分的内容,欢迎交流!   关键字:Android动态...

亭子happy
2014/03/27
0
0
Android动态加载jar、apk的实现

前段时间到阿里巴巴参加支付宝技术分享沙龙,看到支付宝在Android使用插件化的技术,挺好奇的。正好这几天看到了农民伯伯的相关文章,因此简单整理了下,有什么错误希望大神指正。 核心类 1....

mingxun
2014/06/03
0
3
浅谈Android虚拟机的动态加载技术

Android虚拟机的动态加载技术分为两种:一种是加载基于NDK的so库;另一种是加载用java语言开发的zip包。我今天主要讨论后者。 先简单说明一下so库加载。NDK的执行效率很高,加密性很好,但同...

KingJerry
2013/03/04
0
1
Android 自定义组合控件小结

引言 接触Android UI开发的这段时间以来,对自定义组合控件有了一定的了解,为此小结一下,本文小结内容主要讨论的是如何使用Android SDK提供的布局和控件组成一个功能完整组合控件并将其封装...

程序袁_绪龙
2014/09/24
0
0
有关Android插件化的一些总结思考

最近几年移动开发业界兴起了「 插件化技术 」的旋风,各个大厂都推出了自己的插件化框架,各种开源框架都评价自身功能优越性,令人目不暇接。随着公司业务快速发展,项目增多,开发资源却有限...

技术小能手
昨天
0
0
滴水穿石 某APK中使用了动态注册BroadcastReceiver,Launcher中动态...

在某APK中,通过如下方法动态注册了一个BroadcastReceiver,代码参考如下: @Override Launcher要动态加载此APK(动态加载APK的目的和实现思路,参见我的这个文章: Launcher中动态加载其它A...

LiSteven
2013/10/23
0
1
Android零基础入门第85节:Fragment使用起来非常简单

Fragment创建完成后并不能单独使用,还需要将Fragment加载到Activity中,在Activity中添加Fragment的方式有两种:静态加载和动态加载,接下来分别进行学习。 一、静态加载 静态加载Fragment非...

鑫鱻
2017/10/27
0
0
Android插件化开发,初入殿堂

好久没有写博客了,这次准备写写我这几天的研究成果——Android插件化开发框架CJFrameForAndroid。 背景交代 首先,你需要知道什么是插件化开发。就拿最常见的QQ来说,在第三个界面动态那里有...

kymjs张涛
2014/10/12
0
9
(android开源库android-gif-drawable)第二篇 加载网络gif图片

大家好, 今天给大家带来如何使用 android开源库android-gif-drawable来 加载网络gif图片 同样的DEMO下载地址在 最后 请大家去下载 。 如果gif图片地址无效 了。 请大家自行到网上去寻找一个...

乱取名字
2014/11/15
0
5
Android插件化开发,运行未安装apk中的Service

如果你还不知道什么叫插件化开发,那么你应该先读一读之前写的这篇博客:Android插件化开发,初入殿堂 上一篇博客主要从整体角度分析了一下Android插件化开发的几个难点与动态加载没有被安装...

kymjs张涛
2014/10/15
0
5

没有更多内容

加载失败,请刷新页面

加载更多

下一页

idea tomcat 远程调试

tomcat 配置 编辑文件${tomcat_home}/bin/catalina.sh,在文件开头添加如下代码。    CATALINA_OPTS="-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=7829" Idea端配......

qwfys
今天
1
0
遍历目录下的文件每250M打包一个文件

#!/usr/bin/env python # -*- utf-8 -*- # @Time : 2018/7/20 0020 下午 10:16 # @Author : 陈元 # @Email : abcmeabc@163.com # @file : tarFile.py import os import tarfile import thr......

寻爱的小草
今天
1
0
expect同步文件&expect指定host和要同步的文件&构建文件分发系统&批量远程执行命令

20.31 expect脚本同步文件 expect通过与rsync结合,可以在一台机器上把文件自动同步到多台机器上 编写脚本 [root@linux-5 ~]# cd /usr/local/sbin[root@linux-5 sbin]# vim 4.expect#!/...

影夜Linux
今天
1
0
SpringBoot | 第九章:Mybatis-plus的集成和使用

前言 本章节开始介绍数据访问方面的相关知识点。对于后端开发者而言,和数据库打交道是每天都在进行的,所以一个好用的ORM框架是很有必要的。目前,绝大部分公司都选择MyBatis框架作为底层数...

oKong
今天
12
0
win10 上安装解压版mysql

1.效果 2. 下载MySQL 压缩版 下载地址: https://downloads.mysql.com/archives/community/ 3. 配置 3.1 将下载的文件解压到合适的位置 我最终将myql文件 放在:D:\develop\mysql 最终放的位...

Lucky_Me
今天
2
0
linux服务器修改mtu值优化cpu

一、jumbo frames 相关 1、什么是jumbo frames Jumbo frames 是指比标准Ethernet Frames长的frame,即比1518/1522 bit大的frames,Jumbo frame的大小是每个设备厂商规定的,不属于IEEE标准;...

问题终结者
今天
1
0
expect脚本同步文件expect脚本指定host和要同步的文件 构建文件分发系统批量远程执行命令

expect脚本同步文件 在一台机器上把文件同步到多台机器上 自动同步文件 vim 4.expect [root@yong-01 sbin]# vim 4.expect#!/usr/bin/expectset passwd "20655739"spawn rsync -av ro...

lyy549745
今天
1
0
36.rsync下 日志 screen

10.32/10.33 rsync通过服务同步 10.34 linux系统日志 10.35 screen工具 10.32/10.33 rsync通过服务同步: rsync还可以通过服务的方式同步。那需要开启一个服务,他的架构是cs架构,客户端服务...

王鑫linux
今天
1
0
matplotlib 保存图片时的参数

简单绘图 import matplotlib.pyplot as pltplt.plot(range(10)) 保存为csv格式,放大后依然很清晰 plt.savefig('t1.svg') 普通保存放大后会有点模糊文件大小20多k plt.savefig('t5.p...

阿豪boy
今天
3
0
java 8 复合Lambda 表达式

comparator 比较器复合 //排序Comparator.comparing(Apple::getWeight);List<Apple> list = Stream.of(new Apple(1, "a"), new Apple(2, "b"), new Apple(3, "c")) .collect(......

Canaan_
昨天
1
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部