因项目要求需要做类似于维信或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文件。这主要应用于插件化开发、热更新或者模块化的应用架构。动态加载未安装的APK可以让应用在不更新主应用程序的情况下添加或更新功能...
例如,我们可以在运行时下载一个包含新功能的APK,从中提取出.dex文件,然后使用DexClassLoader加载这个.dex,实现新功能的动态加载。同时,为了防止加载冲突,通常需要对加载的类进行命名空间隔离,这可以通过实现...
Android系统默认使用DexClassLoader来加载应用中的类,但如果我们想加载外部APK中的类,我们需要自定义ClassLoader。首先,我们需要获取到目标APK的路径,这可以通过Context.getPackageCodePath()或者File类来完成。...
在Android开发中,"免安装动态加载APK"是一种高级技术,它允许应用程序在运行时动态地下载并加载新的功能模块,而无需用户手动安装额外的APK文件。这种技术通常被称为插件化或者模块化开发,对于更新、扩展应用功能...
2. **DexClassLoader**:Android系统使用DexClassLoader加载.dex(Dalvik Executable)文件,这是Android应用的字节码格式。在插件化开发中,我们需要创建自定义的ClassLoader子类,比如DexPathList,来指定加载插件...
在Android开发领域,APK动态加载是一项关键技术,它允许应用程序在运行时动态地加载和执行代码,从而提高软件的灵活性和可维护性。本研究主要关注如何实现这一技术,以及其在实际应用中的优势和挑战。 动态加载的...
3. **加载类**:有了Activity的类名后,我们可以使用ClassLoader(通常是DexClassLoader)加载APK中的类。ClassLoader能从特定的 Dex 文件(包含Dalvik字节码)中加载类。 4. **创建对象**:使用反射的`Class.for...
在Android平台上,动态加载APK的能力是一项非常实用的技术,它允许程序在运行时根据需要加载新的功能或插件。这通常涉及到对Android的类加载机制、 DexClassLoader 和反射API的深入理解。标题“android动态运行已...
在Android中,通常每个应用都有一个默认的ClassLoader,它会加载APK内的classes.dex文件。然而,如果我们需要在运行时加载额外的.dex或.jar,我们可以创建一个新的DexClassLoader实例,并指定额外的 DexPathList,这...
在Android平台上,动态加载插件apk是一种常见的技术,它允许应用程序在运行时加载和执行未在主应用包中编译的代码。这种技术的核心在于实现应用程序的模块化,提高更新效率,减少应用体积,以及增强安全性。下面我们...
标题中的"android动态加载class文件(DexClassLoader可从SD卡加载)"指的是利用Android的DexClassLoader类来实现从外部存储(如SD卡)加载Dalvik执行文件(.dex)的能力。这一技术在开发过程中能显著提升应用的灵活...
在Android开发领域,插件化动态加载apk是一种高级技术,它允许应用程序在运行时加载和卸载未预先安装的apk,以实现功能扩展或者界面皮肤更换等效果。这种技术极大地提高了应用的灵活性和可维护性,同时减少了用户...
当Android系统启动一个应用时,会通过PathClassLoader加载APK中的`classes.dex`文件,这个文件包含了应用的大部分类。但是,如果我们的目标是动态加载额外的.dex文件,那么就需要自定义ClassLoader,比如继承...
在Android开发中,动态加载APK(Dynamic APK Loading)是一种重要的技术,它允许应用程序在运行时下载并安装额外的模块,而无需用户手动更新整个应用。这种技术在提高用户体验、节省存储空间以及实现热修复等方面...
本资料"安卓插件机制相关-Android免安装动态加载APK.rar"主要探讨了这一主题,虽然文件可能并未全部验证其可用性,但仍然可以作为参考学习的重要资源。 1. **动态加载原理**:Android系统的动态加载通常基于...
DexClassLoader可以加载APK、.jar或包含.dex的.zip文件,非常适合于动态加载。 3. DexOpt:在Android中,当.dex文件被加载时,系统会进行dex优化,将其转换为OAT(Optimized Android bytecode)文件,以提高执行...
1. **创建自定义ClassLoader**:你需要继承dalvik.system.DexClassLoader或者dalvik.system.PathClassLoader,重写其findClass()方法,以便根据需要加载Apk中的类。 2. **获取Apk的Dex文件**:使用 DexFile 或者 ...
在Android系统中,动态加载APK是一项重要的技术,它允许应用程序在运行时加载和执行新的功能模块,而无需用户更新整个应用。这种技术的核心在于利用Android的ClassLoader机制,它可以加载在运行时找到的新APK文件,...
总的来说,Android插件化动态加载APK文件涉及到类加载机制、组件动态启动、资源加载等多个方面,需要深入理解Android系统的工作原理和反射机制。通过这样的设计,我们可以构建出更加灵活、可扩展的应用架构,适应...
在Android开发中,动态加载JAR(Java Archive)文件是一种常见的技术,它允许应用程序在运行时加载和执行不在原始APK文件中的代码。这种技术有多种应用场景,例如更新功能、热修复、插件化框架等。下面将详细介绍...