android 如何使用Dexdex ClassLoader加载一个dex文件?

yhived7q  于 2023-03-16  发布在  Android
关注(0)|答案(1)|浏览(115)

我尝试使用DexClassLoader类动态加载包含android活动类的dex文件,使用以下代码。

try {
File file = File.createTempFile("input",".dex");
InputStream reader = getResources().openRawResource(R.raw.classes);
OutputStream writer = new FileOutputStream(file.getAbsolutePath());

while(true){ int x = reader.read(); if(x == -1) break; writer.write(x);}

DexClassLoader loader = new DexClassLoader(file.getAbsolutePath(),null,null,MainActivity.this.getClassLoader());

Class<?> c = loader.loadClass("com.example.myapplication2.MainActivity");
Intent intent = new Intent(MainActivity.this.getApplicationContext(),c);
startActivity(intent);
}

catch(Exception e){
e.printStackTrace();
}

但是,在执行前面的代码后,应用程序崩溃,并出现以下异常

android.content.ActivityNotFoundException: Unable to find explicit activity class{com.example.myapplication/com.example.myapplication2.MainActivity}; have you declared this activity in your AndroidManifest.xml?
 at android.app.Instrumentation.checkStartActivityResult(Instrumentation.java:2005)
 at android.app.Instrumentation.execStartActivity(Instrumentation.java:1673)
 at android.app.Activity.startActivityForResult(Activity.java:4586)
 at androidx.activity.ComponentActivity.startActivityForResult(ComponentActivity.java:728)
 at android.app.Activity.startActivityForResult(Activity.java:4544)
 at androidx.activity.ComponentActivity.startActivityForResult(ComponentActivity.java:709)
 at android.app.Activity.startActivity(Activity.java:4905)
 at android.app.Activity.startActivity(Activity.java:4873)
 at com.example.myapplication.MainActivity$1.onClick(MainActivity.java:82)
 at android.view.View.performClick(View.java:6597)
 at com.google.android.material.button.MaterialButton.performClick(MaterialButton.java:1219)
 at android.view.View.performClickInternal(View.java:6574)
 at android.view.View.access$3100(View.java:778)
 at android.view.View$PerformClick.run(View.java:25885)
 at android.os.Handler.handleCallback(Handler.java:873)
 at android.os.Handler.dispatchMessage(Handler.java:99)
 at android.os.Looper.loop(Looper.java:193)
 at android.app.ActivityThread.main(ActivityThread.java:6669)
 at java.lang.reflect.Method.invoke(Native Method)
 at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
 at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)

另外,我注意到大多数示例dex文件包含普通的java类而不是活动类,所以我想知道我正在尝试做的是否适用,以及异常之外的原因

lp0sw83n

lp0sw83n1#

下面的解决方案对我很有效,它的灵感来自blog post

File file = File.createTempFile("input",".dex");
          InputStream reader = getResources().openRawResource(R.raw.classes);
          OutputStream writer = new FileOutputStream(file.getAbsolutePath());

while(true){ int x = reader.read(); if(x == -1) break; writer.write(x);}

Context context = this;
DexClassLoader dexloader = new DexClassLoader(file.getAbsolutePath()
                             ,null,
                              null,
                              context.getClassLoader());

Field f = BaseDexClassLoader.class.getDeclaredField("pathList");
f.setAccessible(true);
Object dexPathObjNew = f.get(dexloader); // get the pathList of dexloader that hold the loaded dex file path 
f.set(context.getClassLoader(), dexPathObjNew); // set the pathlist of current context classloader to the pathList of dexloader
Class c = context.getClassLoader().loadClass("com.example.myapplication2.helloActivity");

Intent i = new Intent(context,c);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);

现在,当前上下文的类加载器可以看到加载的dex。

相关问题