Android 动态加载DEX-阿里云开发者社区

开发者社区> 开发与运维> 正文

Android 动态加载DEX

简介: 1). 新建项目并创建Dynamic接口 /** * 接口 * Created by mazaiting on 2018/6/26. */ public interface Dynamic { String say(); } 2).
1). 新建项目并创建Dynamic接口
/**
 * 接口
 * Created by mazaiting on 2018/6/26.
 */

public interface Dynamic {
  String say();
}
2). 创建接口的实现类DynamicImpl
/**
 * 动态实现类
 * Created by mazaiting on 2018/6/26.
 */

public class DynamicImpl implements Dynamic {
  @Override
  public String say() {
    return "mazaiting";
  }
}
3). 编译

Build -> Make Project, 生成的文件位于


img_58562ba82f274afcd06ae6521b26e0fa.png
图1.png
4). Gradle任务创建

在app/build.gradle文件中追加

// 删除dynamic.jar包任务
task clearJar(type: Delete) {
    delete('libs/dynamic.jar')
}

// 打包任务
task makeJar(type: org.gradle.api.tasks.bundling.Jar) {
    // 指定生成jar名称
    baseName 'dynamic'
    // 打包文件的位置
    from('build\\intermediates\\classes\\debug\\com\\mazaiting\\dynamicjar\\')
    // 打包到jar后的目录结构
    into('com/mazaiting/dynamicjar/')
    // 去掉不需要打包的目录和文件
    exclude('text/','Dynamic.class','R.class','BuildConfig.class')
    // 去掉R$开头的文件
    exclude { it.name.startsWith('R$') }
}

makeJar.dependsOn(clearJar, build)
5). 在Terminal控制台运行
# 查看所有任务
gradlew tasks --all
# 执行任务
gradlew makeJar
6). 生成jar
img_ec883e1e26e9c89054bc0214b6b5c570.png
图2.png
7). dex打包

将打包好的jar文件拷贝到android的安装目录中的\sdk\build-tools\26.0.1\目录下,使用dx --dex --output=dynamic_temp.jar dynamic.jar进行压缩
这条命令首先将dynamic.jar编译成dynamic.dex文件,然后再将dynamic.dex文件压缩成dynamic_temp.jar,当然也可以压缩成.zip格式或者直接编译成.apk文件都可以。

8). 将生成的dynamic_dex.jar文件导入Android工程的assets文件夹下,并删除Dynamic接口的实现包
img_dc5da4f8a310b3d007e5002c39d44fa8.png
图3.png
9). 使用
public class MainActivity extends AppCompatActivity {
  /**缓存文件夹*/
  private File mCacheDir;
  /**目标文件*/
  private String mInternalPath;
  
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    copyFile();
    setContentView(R.layout.activity_main);
  }
  
  /**
   * 拷贝文件
   */
  private void copyFile() {
    // 获取缓存路径
    mCacheDir = FileUtil.getCacheDir(getApplicationContext());
    // 获取dex文件存储路径
    mInternalPath = mCacheDir.getAbsolutePath() + File.separator + "dynamic.jar";
    File file = new File(mInternalPath);
    // 判断文件是否存在
    if (!file.exists()) {
      try {
        // 创建新文件
        file.createNewFile();
        // 拷贝文件
        FileUtil.copyFiles(this, "dynamic_dex.jar", file);
      } catch (IOException e) {
        e.printStackTrace();
      }
    }
  }
  
  /**
   * 动态加载按钮,布局文件只有一个按钮
   */
  public void loadDex(View view) {
    loadDex();
  }
  
  /**
   * 动态加载
   */
  private void loadDex() {
    // 新建DexClassLoader
    // 第一个参数:dex压缩文件的路径
    // 第二个参数:dex解压缩后的文件路径
    // 第三个参数:C/C++依赖的本地库文件
    // 第四个参数:上一级的类加载器
    DexClassLoader dexClassLoader = new DexClassLoader(
            mInternalPath, mCacheDir.getAbsolutePath(), null, getClassLoader());
    try {
      // 加载的类名为jar文件中的完整类名
      Class clazz = dexClassLoader.loadClass("com.mazaiting.dynamicjar.impl.DynamicImpl");
      Dynamic dynamic = (Dynamic) clazz.newInstance();
      if (null != dynamic) {
        Toast.makeText(this, dynamic.say(), Toast.LENGTH_SHORT).show();
      }
    } catch (ClassNotFoundException | IllegalAccessException | InstantiationException e) {
      e.printStackTrace();
    }
  }
}
10). 运行项目
img_54069a1fac2f7ae7d960c4881a7a88ff.png
图4.png
代码下载

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

分享:
开发与运维
使用钉钉扫一扫加入圈子
+ 订阅

集结各类场景实战经验,助你开发运维畅行无忧

其他文章