Android CommunityAndroid开发Android开发经验谈

Android动态加载dex技术初步了解

2017-09-20  本文已影响127人  Lazy1

1.概述

2.实践

public interface IShowToast {

  public int showToast(android.app.Application context);
}

public class ShowToastImpl implements IShowToast {

  @Override
  public int showToast(android.app.Application context) {
    Toast.makeText(context, "我来自另一个dex文件", Toast.LENGTH_LONG).show();
    return 100;
  }

  public void test() {
    Log.e("\"我来自另一个dex文件\"","我来自另一个dex文件");
  }
}


public class MainActivity extends AppCompatActivity {

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    try {
      File dexOutputDir = getDir("dex1", 0);
      String dexPath = Environment.getExternalStorageDirectory().toString() + File.separator + "a";
      File file = new File(dexPath);
      Log.e("MainActivity",file.length()+"");
      DexClassLoader loader = new DexClassLoader(dexPath,
          dexOutputDir.getAbsolutePath(),
          null, getClassLoader());
      Class clz = loader.loadClass("com.Company.Demo.ShowToastImpl");
      Method m1 = clz.getDeclaredMethod("test");
      Method showToast = clz
          .getDeclaredMethod("showToast", new Class[]{getApplication().getClass()});
      m1.invoke(clz.newInstance());
      showToast.invoke(clz.newInstance(),getApplication());
    } catch (Exception e) {
      Log.e("MainActivity", "error happened", e);
    }
  }
}



其实这里就是通过DexClassLoader得到sd卡的dex的ShowToastImpl对象然后通过反射即可调用器内部的方法

此处需要注意DexClassLoader的四个参数:
参数1 dexPath:待加载的dex文件路径,如果是外存路径,一定要加上读外存文件的权限(<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> ),否则会报与上面一样的错误,这点参考文章2中说这个权限可有可无是错误的。(更正下:Android4.4 KitKat及以后的版本需要此权限,之前的版本不需要权限)

           参数2 optimizedDirectory:解压后的dex存放位置,此位置一定要是可读写且仅该应用可读写(安全性考虑),所以只能放在data/data下。本文getDir("dex1", 0)会在/data/data/**package/下创建一个名叫”app_dex1“的文件夹,其内存放的文件是自动生成a.dex;如果不满足条件,Android会报的错误为:

          java.lang.IllegalArgumentException: optimizedDirectory not readable/writable: /storage/sdcard0

          java.lang.IllegalArgumentException: Optimized data directory /storage/sdcard0 is not owned by the current user. Shared storage cannot protect your application from code injection attacks.

           参数3 libraryPath:指向包含本地库(so)的文件夹路径,可以设为null

           参数4 parent:父级类加载器,一般可以通过Context.getClassLoader获取到,也可以通过ClassLoader.getSystemClassLoader()取到。
上一篇下一篇

猜你喜欢

热点阅读