`
scliu0718
  • 浏览: 52342 次
  • 性别: Icon_minigender_1
  • 来自: 成都
文章分类
社区版块
存档分类
最新评论

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,只是在主程序中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();
	}
}




分享到:
评论

相关推荐

    Android动态加载未安装apk

    在Android开发中,有时我们需要实现一个功能,即在运行时动态加载未安装的APK文件。这主要应用于插件化开发、热更新或者模块化的应用架构。动态加载未安装的APK可以让应用在不更新主应用程序的情况下添加或更新功能...

    Android动态加载之DexClassLoader学习

    例如,我们可以在运行时下载一个包含新功能的APK,从中提取出.dex文件,然后使用DexClassLoader加载这个.dex,实现新功能的动态加载。同时,为了防止加载冲突,通常需要对加载的类进行命名空间隔离,这可以通过实现...

    Android动态加载(下)——加载已安装APK中的类和资源

    Android系统默认使用DexClassLoader来加载应用中的类,但如果我们想加载外部APK中的类,我们需要自定义ClassLoader。首先,我们需要获取到目标APK的路径,这可以通过Context.getPackageCodePath()或者File类来完成。...

    Android 免安装动态加载APK

    在Android开发中,"免安装动态加载APK"是一种高级技术,它允许应用程序在运行时动态地下载并加载新的功能模块,而无需用户手动安装额外的APK文件。这种技术通常被称为插件化或者模块化开发,对于更新、扩展应用功能...

    Android App调用没有安装的apk

    2. **DexClassLoader**:Android系统使用DexClassLoader加载.dex(Dalvik Executable)文件,这是Android应用的字节码格式。在插件化开发中,我们需要创建自定义的ClassLoader子类,比如DexPathList,来指定加载插件...

    apk动态加载研究(1)

    在Android开发领域,APK动态加载是一项关键技术,它允许应用程序在运行时动态地加载和执行代码,从而提高软件的灵活性和可维护性。本研究主要关注如何实现这一技术,以及其在实际应用中的优势和挑战。 动态加载的...

    Android 通过反射启动未安装的APK中的Activity

    3. **加载类**:有了Activity的类名后,我们可以使用ClassLoader(通常是DexClassLoader)加载APK中的类。ClassLoader能从特定的 Dex 文件(包含Dalvik字节码)中加载类。 4. **创建对象**:使用反射的`Class.for...

    android动态运行已安装和未安装apk中的方法

    在Android平台上,动态加载APK的能力是一项非常实用的技术,它允许程序在运行时根据需要加载新的功能或插件。这通常涉及到对Android的类加载机制、 DexClassLoader 和反射API的深入理解。标题“android动态运行已...

    DexClassLoader自定义加载Assets目录下的dex、jar文件

    在Android中,通常每个应用都有一个默认的ClassLoader,它会加载APK内的classes.dex文件。然而,如果我们需要在运行时加载额外的.dex或.jar,我们可以创建一个新的DexClassLoader实例,并指定额外的 DexPathList,这...

    Android动态加载插件apk

    在Android平台上,动态加载插件apk是一种常见的技术,它允许应用程序在运行时加载和执行未在主应用包中编译的代码。这种技术的核心在于实现应用程序的模块化,提高更新效率,减少应用体积,以及增强安全性。下面我们...

    android动态加载class文件(DexClassLoader可从SD卡加载)(android插件开发)

    标题中的"android动态加载class文件(DexClassLoader可从SD卡加载)"指的是利用Android的DexClassLoader类来实现从外部存储(如SD卡)加载Dalvik执行文件(.dex)的能力。这一技术在开发过程中能显著提升应用的灵活...

    插件化动态加载apk

    在Android开发领域,插件化动态加载apk是一种高级技术,它允许应用程序在运行时加载和卸载未预先安装的apk,以实现功能扩展或者界面皮肤更换等效果。这种技术极大地提高了应用的灵活性和可维护性,同时减少了用户...

    ClassLoader动态加载dex

    当Android系统启动一个应用时,会通过PathClassLoader加载APK中的`classes.dex`文件,这个文件包含了应用的大部分类。但是,如果我们的目标是动态加载额外的.dex文件,那么就需要自定义ClassLoader,比如继承...

    动态加载apk demp

    在Android开发中,动态加载APK(Dynamic APK Loading)是一种重要的技术,它允许应用程序在运行时下载并安装额外的模块,而无需用户手动更新整个应用。这种技术在提高用户体验、节省存储空间以及实现热修复等方面...

    安卓插件机制相关-Android免安装动态加载APK.rar

    本资料"安卓插件机制相关-Android免安装动态加载APK.rar"主要探讨了这一主题,虽然文件可能并未全部验证其可用性,但仍然可以作为参考学习的重要资源。 1. **动态加载原理**:Android系统的动态加载通常基于...

    Android中的动态加载机制(折腾版) 源码

    DexClassLoader可以加载APK、.jar或包含.dex的.zip文件,非常适合于动态加载。 3. DexOpt:在Android中,当.dex文件被加载时,系统会进行dex优化,将其转换为OAT(Optimized Android bytecode)文件,以提高执行...

    动态加载Apk、Jar

    1. **创建自定义ClassLoader**:你需要继承dalvik.system.DexClassLoader或者dalvik.system.PathClassLoader,重写其findClass()方法,以便根据需要加载Apk中的类。 2. **获取Apk的Dex文件**:使用 DexFile 或者 ...

    从内存卡中选择 apk 动态加载apk

    在Android系统中,动态加载APK是一项重要的技术,它允许应用程序在运行时加载和执行新的功能模块,而无需用户更新整个应用。这种技术的核心在于利用Android的ClassLoader机制,它可以加载在运行时找到的新APK文件,...

    Android插件化动态加载 APK 文件中(Activity,Servicer,Broadcast)等一些资源

    总的来说,Android插件化动态加载APK文件涉及到类加载机制、组件动态启动、资源加载等多个方面,需要深入理解Android系统的工作原理和反射机制。通过这样的设计,我们可以构建出更加灵活、可扩展的应用架构,适应...

    android动态加载jar

    在Android开发中,动态加载JAR(Java Archive)文件是一种常见的技术,它允许应用程序在运行时加载和执行不在原始APK文件中的代码。这种技术有多种应用场景,例如更新功能、热修复、插件化框架等。下面将详细介绍...

Global site tag (gtag.js) - Google Analytics