Android使用DexClassLoader动态加载未安装Apk

时间:2022-02-07 19:38:48
因项目要求需要做类似于维信或Q游这样插件化的开发模式,在网上也查了很多资料整理了一下并记在这里,可用两种方式:


1. 通过后台安装,由于默认的安装是通过PackageInstallActivity界面去执行安装的,此界面有一个Dialog和一个ProcessBar,不能更改,想做些手脚一直没找到方法,所以有了下面这一出。

方法:反射出sdk中的隐匿类PackageInstaller类,然后调用安装方法instatllBatch(String),

                  Class<?> clz = Class.forName("com.android.util.PackageInstaller");
                  Method method = clz.getMethod("instatllBatch");
                  method.invoke(clz, path);

           可惜的是添加权限<uses-permission android:name="android.permission.INSTALL_LOCATION_PROVIDER" />,这玩意儿是系统进程方可有权限。所以最后结果就是没有结果。


2. 不安装apk,通过动态加载dex包中的类,也属于通过反射的方式来然后手动的创建Activity。

注意:这种方式跟系统创建的Activity是不一样的,没有系统创建的Activity的特性。而且R也找不到(也就是说无法通过layout来画UI).而且运行的并不是Apk中的Activity,只是在主程序中Activity上画Apk中Activity的View。

这是调用的Activity:

[java]  view plain copy
  1. package com.beyondsoft.activity;  
  2.   
  3. import java.lang.reflect.Constructor;  
  4. import java.lang.reflect.InvocationTargetException;  
  5. import java.lang.reflect.Method;  
  6.   
  7. import dalvik.system.DexClassLoader;  
  8. import android.app.Activity;  
  9. import android.content.pm.PackageInfo;  
  10. import android.os.Bundle;  
  11. import android.util.Log;  
  12.   
  13. public class PlugActivity extends Activity {  
  14.   
  15.     private Class mActivityClass;  
  16.     private Object mActivityInstance;  
  17.     Class localClass;  
  18.     private Object instance;  
  19.   
  20.     @Override  
  21.     protected void onCreate(Bundle savedInstanceState) {  
  22.         super.onCreate(savedInstanceState);  
  23.   
  24.         Bundle paramBundle = new Bundle();  
  25.         paramBundle.putBoolean("KEY_START_FROM_OTHER_ACTIVITY"true);  
  26.         paramBundle.putString("str""PlugActivity");  
  27.         String dexpath = "/sdcard/FragmentProject.apk";  
  28.         String dexoutputpath = "/mnt/sdcard/";  
  29.         LoadAPK(paramBundle, dexpath, dexoutputpath);  
  30.     }  
  31.   
  32.     @Override  
  33.     protected void onStart() {  
  34.         super.onStart();  
  35.         Method start;  
  36.         try {  
  37.             start = localClass.getMethod("onStart");  
  38.                 start.invoke(instance);  
  39.         } catch (Exception e) {  
  40.             // TODO Auto-generated catch block  
  41.             e.printStackTrace();  
  42.         }  
  43.     }  
  44.   
  45.     @Override  
  46.     protected void onResume() {  
  47.         // TODO Auto-generated method stub  
  48.         super.onResume();  
  49.         Method resume;  
  50.         try {  
  51.             resume = localClass.getMethod("onResume");  
  52.             resume.invoke(instance);  
  53.         } catch (Exception e) {  
  54.             // TODO Auto-generated catch block  
  55.             e.printStackTrace();  
  56.         }  
  57.     }  
  58.   
  59.     @Override  
  60.     protected void onPause() {  
  61.         super.onPause();  
  62.         Method pause;  
  63.         try {  
  64.             pause = localClass.getMethod("onPause");  
  65.             pause.invoke(instance);  
  66.         } catch (Exception e) {  
  67.             e.printStackTrace();  
  68.         }  
  69.     }  
  70.   
  71.     @Override  
  72.     protected void onStop() {  
  73.         super.onStop();  
  74.         try {  
  75.             Method stop = localClass.getMethod("onStop");  
  76.             stop.invoke(instance);  
  77.         } catch (Exception e) {  
  78.             e.printStackTrace();  
  79.         }  
  80.     }  
  81.   
  82.     @Override  
  83.     protected void onDestroy() {  
  84.         // TODO Auto-generated method stub  
  85.         super.onDestroy();  
  86.         try {  
  87.             Method des = localClass.getMethod("onDestroy");  
  88.             des.invoke(instance);  
  89.         } catch (Exception e) {  
  90.             // TODO Auto-generated catch block  
  91.             e.printStackTrace();  
  92.         }  
  93.     }  
  94.   
  95.     public void LoadAPK(Bundle paramBundle, String dexpath, String dexoutputpath) {  
  96.         ClassLoader localClassLoader = ClassLoader.getSystemClassLoader();  
  97.         DexClassLoader localDexClassLoader = new DexClassLoader(dexpath, dexoutputpath, null, localClassLoader);  
  98.         try {  
  99.             PackageInfo plocalObject = getPackageManager().getPackageArchiveInfo(dexpath, 1);  
  100.   
  101.             if ((plocalObject.activities != null) && (plocalObject.activities.length > 0)) {  
  102.                 String activityname = plocalObject.activities[0].name;  
  103.                 Log.d("sys""activityname = " + activityname);  
  104.   
  105.                 localClass = localDexClassLoader.loadClass(activityname);//结果:"com.example.fragmentproject.FristActivity"  
  106.                 mActivityClass = localClass;  
  107.                 Constructor localConstructor = localClass.getConstructor(new Class[] {});  
  108.                 instance = localConstructor.newInstance(new Object[] {});  
  109.                 Log.d("sys""instance = " + instance);  
  110.                 mActivityInstance = instance;  
  111.   
  112.                 Method des = localClass.getMethod("test");  
  113.                 des.invoke(instance);  
  114.                   
  115.                 Method localMethodSetActivity = localClass.getDeclaredMethod("setActivity"new Class[] { Activity.class });  
  116.                 localMethodSetActivity.setAccessible(true);  
  117.                 localMethodSetActivity.invoke(instance, new Object[] { this });  
  118.   
  119.                  Method methodonCreate = localClass.getDeclaredMethod("onCreate"new Class[] { Bundle.class });  
  120.                  methodonCreate.setAccessible(true);  
  121.                  methodonCreate.invoke(instance, paramBundle);  
  122.             }  
  123.             return;  
  124.         } catch (Exception ex) {  
  125.             ex.printStackTrace();  
  126.         }  
  127.     }  
  128.   
  129. }  


这是被调用的Activity:

[java]  view plain copy
  1. public class FristActivity extends Activity{  
  2.   
  3.     private Button fragment;  
  4.     private Button listFragment;  
  5.     private Button controlFragment;  
  6.     private Button viewFlipper;  
  7.     private Button viewPager;  
  8.     private Activity otherActivity;  
  9.   
  10.     public void test() {  
  11.         Log.i("sys""测试方法执行了");  
  12.     }  
  13.   
  14.     @Override  
  15.     public void onCreate(Bundle savedInstanceState) {  
  16.         super.onCreate(savedInstanceState);  
  17.          // 测试DexClassLoader 动态加载未安装Apk中的类  
  18.         TextView t = new TextView(otherActivity);  
  19.         t.setText("我是测试");  
  20.         otherActivity.setContentView(t);// R.layout.frist_activity_main  
  21.   
  22.         Log.i("sys""Fragment项目启动了");  
  23.     }  
  24.   
  25.     public void setActivity(Activity paramActivity) {  
  26.         Log.d("sys""setActivity..." + paramActivity);  
  27.         this.otherActivity = paramActivity;  
  28.     }  
  29.   
  30.     @Override  
  31.     public void onSaveInstanceState(Bundle outState) {  
  32.         super.onSaveInstanceState(outState);  
  33.         Log.i("sys""OnSaveInstance被调了");  
  34.     }  
  35.   
  36.     @Override  
  37.     public void onStart() {  
  38.         Log.i("sys""onStart被调了");  
  39.         // TODO Auto-generated method stub  
  40.         super.onStart();  
  41.     }  
  42.   
  43.     @Override  
  44.     public void onResume() {  
  45.         Log.i("sys""onResume被调了");  
  46.         // TODO Auto-generated method stub  
  47.         super.onResume();  
  48.     }  
  49.   
  50.     @Override  
  51.     public void onPause() {  
  52.         Log.i("sys""onPause被调了");  
  53.         // TODO Auto-generated method stub  
  54.         super.onPause();  
  55.     }  
  56.   
  57.     @Override  
  58.     public void onStop() {  
  59.         Log.i("sys""onStop被调了");  
  60.         // TODO Auto-generated method stub  
  61.         super.onStop();  
  62.     }  
  63.   
  64.     @Override  
  65.     protected void onDestroy() {  
  66.         Log.i("sys""onDestroy被调了");  
  67.         // TODO Auto-generated method stub  
  68.         super.onDestroy();  
  69.     }  
  70. }