您的位置:首页 > 移动开发 > Android开发

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

2012-12-26 14:30 405 查看
因项目要求需要做类似于维信或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();
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: