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

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

2016-02-02 10:50 477 查看
因项目要求需要做类似于维信或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 plaincopy

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:

[java] view plaincopy

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();

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: