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

因项目要求需要做类似于维信或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,

        也就是说它已经没有了Android中Activity的特性,它只是在主程序中Activity上画Apk中Activity的View。

这是调用的Activity:

package com.beyondsoft.activity;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import dalvik.system.DexClassLoader;
import android.app.Activity;
import android.content.pm.PackageInfo;
import android.os.Bundle;
import android.util.Log;

public class PlugActivity extends Activity {

	private Class mActivityClass;
	private Object mActivityInstance;
	Class localClass;
	private Object instance;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		Bundle paramBundle = new Bundle();
		paramBundle.putBoolean("KEY_START_FROM_OTHER_ACTIVITY", true);
		paramBundle.putString("str", "PlugActivity");
		String dexpath = "/sdcard/FragmentProject.apk";
		String dexoutputpath = "/mnt/sdcard/";
		LoadAPK(paramBundle, dexpath, dexoutputpath);
	}

	@Override
	protected void onStart() {
		super.onStart();
		Method start;
		try {
			start = localClass.getMethod("onStart");
				start.invoke(instance);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	@Override
	protected void onResume() {
		// TODO Auto-generated method stub
		super.onResume();
		Method resume;
		try {
			resume = localClass.getMethod("onResume");
			resume.invoke(instance);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	@Override
	protected void onPause() {
		super.onPause();
		Method pause;
		try {
			pause = localClass.getMethod("onPause");
			pause.invoke(instance);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	@Override
	protected void onStop() {
		super.onStop();
		try {
			Method stop = localClass.getMethod("onStop");
			stop.invoke(instance);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	@Override
	protected void onDestroy() {
		// TODO Auto-generated method stub
		super.onDestroy();
		try {
			Method des = localClass.getMethod("onDestroy");
			des.invoke(instance);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public void LoadAPK(Bundle paramBundle, String dexpath, String dexoutputpath) {
		ClassLoader localClassLoader = ClassLoader.getSystemClassLoader();
		DexClassLoader localDexClassLoader = new DexClassLoader(dexpath, dexoutputpath, null, localClassLoader);
		try {
			PackageInfo plocalObject = getPackageManager().getPackageArchiveInfo(dexpath, 1);

			if ((plocalObject.activities != null) && (plocalObject.activities.length > 0)) {
				String activityname = plocalObject.activities[0].name;
				Log.d("sys", "activityname = " + activityname);

				localClass = localDexClassLoader.loadClass(activityname);//结果:"com.example.fragmentproject.FristActivity"
				mActivityClass = localClass;
				Constructor localConstructor = localClass.getConstructor(new Class[] {});
				instance = localConstructor.newInstance(new Object[] {});
				Log.d("sys", "instance = " + instance);
				mActivityInstance = instance;

				Method des = localClass.getMethod("test");
				des.invoke(instance);
				
				Method localMethodSetActivity = localClass.getDeclaredMethod("setActivity", new Class[] { Activity.class });
				localMethodSetActivity.setAccessible(true);
				localMethodSetActivity.invoke(instance, new Object[] { this });

				 Method methodonCreate = localClass.getDeclaredMethod("onCreate", new Class[] { Bundle.class });
				 methodonCreate.setAccessible(true);
				 methodonCreate.invoke(instance, paramBundle);
			}
			return;
		} catch (Exception ex) {
			ex.printStackTrace();
		}
	}

}


这是被调用的Activity:

public class FristActivity extends Activity{

	private Button fragment;
	private Button listFragment;
	private Button controlFragment;
	private Button viewFlipper;
	private Button viewPager;
	private Activity otherActivity;

	public void test() {
		Log.i("sys", "测试方法执行了");
	}

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		 // 测试DexClassLoader 动态加载未安装Apk中的类
		TextView t = new TextView(otherActivity);
		t.setText("我是测试");
		otherActivity.setContentView(t);// R.layout.frist_activity_main

		Log.i("sys", "Fragment项目启动了");
	}

	public void setActivity(Activity paramActivity) {
		Log.d("sys", "setActivity..." + paramActivity);
		this.otherActivity = paramActivity;
	}

	@Override
	public void onSaveInstanceState(Bundle outState) {
		super.onSaveInstanceState(outState);
		Log.i("sys", "OnSaveInstance被调了");
	}

	@Override
	public void onStart() {
		Log.i("sys", "onStart被调了");
		// TODO Auto-generated method stub
		super.onStart();
	}

	@Override
	public void onResume() {
		Log.i("sys", "onResume被调了");
		// TODO Auto-generated method stub
		super.onResume();
	}

	@Override
	public void onPause() {
		Log.i("sys", "onPause被调了");
		// TODO Auto-generated method stub
		super.onPause();
	}

	@Override
	public void onStop() {
		Log.i("sys", "onStop被调了");
		// TODO Auto-generated method stub
		super.onStop();
	}

	@Override
	protected void onDestroy() {
		Log.i("sys", "onDestroy被调了");
		// TODO Auto-generated method stub
		super.onDestroy();
	}
}




评论 23
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值