zoukankan      html  css  js  c++  java
  • 动态加载dex

    动态加载dex

    1. 新建一个工程

    2. 新建一个类,在类中加一个方法,添加一个 TextView 调用

      package com.example.myloaddex;

      import androidx.appcompat.app.AppCompatActivity;

      import android.os.Bundle;

      public class MainActivity extends AppCompatActivity {

          @Override
          protected void onCreate(Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
              setContentView(R.layout.activity_main);
              // 调用
              LoadDex.createView(this);
         }
      }

      MyLoadDex

      package com.example.myloaddex;

      import android.app.Activity;
      import android.view.Gravity;
      import android.widget.FrameLayout;
      import android.widget.TextView;

      public class LoadDex {
          // 一个静态方法
          public static void createView(Activity ac){
              // 创建一个TextView
              TextView tv= new TextView(ac);
              // 创建布局设置参数
              FrameLayout.LayoutParams params=new FrameLayout.LayoutParams(
                      FrameLayout.LayoutParams.WRAP_CONTENT,
                      FrameLayout.LayoutParams.WRAP_CONTENT
             );
              // 设置控件到顶点
              params.topMargin=0;
              // 设置控件的位置
              params.gravity= Gravity.TOP|Gravity.CENTER_HORIZONTAL;
              tv.setText("MyTestActivity Textview!");
              // 添加TextView到Activity
              ac.addContentView(tv,params);
         }
      }
    3. 编译成 apk 1570429664735

    4. 反编译 apk,将新建的类的 smali 文件提取出来

    5. 单独将一个 smali 文件转成 dex 文件 E:MyLoadDexappuildintermediatesjavacdebugclasses

      整个文件夹复制出来,因为要保留路径,不然会出错(版本不同路径可能不同,直接在文件夹下搜classes文件夹)

      然后用./d2j-jar2dex.bat LoadDex.class -o test.dex命令将LoadDex.class文件转成test.dex

    1570428171277

    1. 将 dex 文件放到 assets 文件夹中,assets自己右键新建

    1570428189167

    1. 把原本的那个类代码删除,进文件夹直接删除文件夹里面的那个类文件就可以

    2. 写代码动态加载 dex,让程序正常跑起来

    调用

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            // 1. 拷贝dex到安装目录下
            String path = copyDex("test.dex");
            // 2. 使用DexClassLoader,加载dex
            DexClassLoader dex = loadDex(path);
            // 3. 使用返回的dex对象,加载类,获取方法对象,调用方法
            useClass(dex);
       }

    使用Java反射机制,动态加载dex,并调用

    // 使用Java反射机制,动态加载dex,并调用
        public void useClass(DexClassLoader dex) {
            try {
                // 获取加载的类信息
                // 包名+工程名+类名
                Class TestDex = dex.loadClass("com.bluelesson.app34_3.MyTestActivity");
               // 参数为构造方法参数数组
                // 获取成员方法
                Method methodTest = TestDex.getDeclaredMethod("createView",     // 方法名称
                        new Class[]{Activity.class});   // 方法参数类型数组
                // 取消java访问检查,提高反射速度
                methodTest.setAccessible(true);
                // 调用方法,this指针传进去
                methodTest.invoke(null,        // 类对象
                        new Object[] { this });   // 方法参数数组
           } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
           }
       }
       

    获得指定文件的dex加载器

    // 获得指定文件的dex加载器
        public DexClassLoader loadDex(String path) {
            // 创建dex文件的类加载器,返回DexClassLoader对象
            DexClassLoader dex = new DexClassLoader(
                    path,       // dex路径
                    getCacheDir().toString(),   // 优化之后的文件的路径
                    null,      // 原生库路径
                    getClassLoader());          // 父类加载器
            return dex;
       }

    拷贝指定的文件从assets目录中到/data/data/包名/files中

        // 拷贝指定的文件从assets目录中到/data/data/包名/files中
        String copyDex(String dexName) {
            // 获取assets目录管理器
            AssetManager as = getAssets();
            // 合成路径
            // getFilesDir返回的就是/data/data/包名/files
            String path = getFilesDir() + File.separator + dexName; // File.separator 分隔符
            Log.i("15pb-log", path);
            try {
                // 创建文件流
                FileOutputStream out = new FileOutputStream(path);
                // 打开文件
                InputStream is = as.open(dexName);
                // 循环读取文件,拷贝到对应路径
                byte[] buffer = new byte[1024];
                int len = 0;
                while ((len = is.read(buffer)) != -1) {
                    out.write(buffer, 0, len);
               }
                // 关闭文件
                out.close();

           } catch (IOException e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
                return "";
           }
            return path;
       }
  • 相关阅读:
    http-Content-Type
    ip地址和端口号
    node中的js-核心模块
    http-url 发送请求
    http 发送请求
    node http核心模块
    node 写文件
    bzoj-3170 3170: [Tjoi 2013]松鼠聚会(计算几何)
    codeforces 710E E. Generate a String(dp)
    codeforces 710C C. Magic Odd Square(构造)
  • 原文地址:https://www.cnblogs.com/ltyandy/p/11630631.html
Copyright © 2011-2022 走看看