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

插件化开发实践
本文介绍了两种插件化开发的方法:一是尝试通过反射调用隐藏的PackageInstaller类进行后台安装,但受限于权限未能实现;二是通过动态加载DEX包中的类来创建Activity,实现了在不安装APK的情况下运行其中的Activity。
因项目要求需要做类似于维信或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:

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


转自:http://blog.youkuaiyun.com/yczz/article/details/38926685




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值