学习自
https://blog.csdn.net/fwt336/article/details/53336810
他的才是加载apk里的内容,想看加载外源apk的可以去这个链接里看。我这里图方便,直接加载dex里的东西了。
熟悉ClassLoader的朋友都知道,PathClassLoader仅仅能加载已安装的APK中的类,DexClassLoader就灵活度很高了,许多压缩文件他都可以进行一个加载。
所以我们可以在程序运行的时候,动态加载某个压缩文件中的class然后进行一个调用。我们今天要做的就是这样一件事。
现在我有这样一个dex,里面有一个类,我调用他的方法就可以得到一段文字,然后我把这段文字更新到UI上,这是我打算实现的。
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); final Button bt = findViewById(R.id.bt); bt.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { try { bt.setText(get()); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } } }); } private String get() throws ClassNotFoundException, IllegalAccessException, NoSuchMethodException, InvocationTargetException { String path = Environment.getExternalStorageDirectory().getAbsolutePath()+"/classes2.dex"; File oDexFile = new File(getDir("odex", Context.MODE_PRIVATE).getAbsolutePath()); ClassLoader dexClassLoader = new DexClassLoader(path,// dexPath oDexFile.getAbsolutePath(),// optimizedDirectory null, getClassLoader()); Class c = dexClassLoader.loadClass("com.example.myapplication.WantFix"); Method method = c.getDeclaredMethod("get"); String s= (String) method.invoke(null); Log.i("xbh", "get: " + s); return s; } }
这里的代码成功搞定,也很简单,就不多赘述了。
但是如果本地已经有一样的类的了话,会率先加载本地的类,这就让人很蛋疼了。因为这个DexClassLoader不仅会搜索自己管辖的dex下的内容,更是会率先把任务交给BaseClassLoader来搜索。找不到再自己进行一个搜索。所以我们需要进行一个同名类的替换,不过这就是热修复的话题了。而且正常情况下不会有相同类。