因项目要求需要做类似于维信或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 逆向】类加载器 ClassLoader ( 使用 DexClassLoader 动态加载字节码文件 | 准备 DEX 字节码文件 ) https://hanshuliang.blog.csdn.net/article/details/121776627 博客源码
DexClassLoader学习源码,使用时,请删除Lib.Java文件,否则会出现loadClass错误。
DexClassLoader自定义加载Assets目录下的dex、jar文件,对Assets目录下jar、dex进行加载
(2)Android动态加载APK文件(代理模式) (3)Hook技术动态加载APK文件中的Activity 二、Android 动态加载dex文件 1.反射方式加载(较麻烦,不介绍),需要反射出具体的方法等 2.接口编程的方式加载(以下重点介绍...
通过对ClassLoader中两个子类加载dex,来熟悉安卓中的apk加载流程
android-custom-class-loading-sample,源码。需要使用ant进行编译。编译之后可以动态的使用DexClassLoader加载代码并执行。
Android DexClassLoader调用其他apk中的函数 实现动态加载
NULL 博文链接:https://flycatdeng.iteye.com/blog/2100653
一个动态加载android 的class框架, 过程是先解压一个完全的apk,然后创建自己的dexclassloader,然后动态加载指定的activity的过程
主要介绍了Android开发中类加载器DexClassLoader的简单使用讲解,DexClassLoader可以看作是一个特殊的Java中的ClassLoader,需要的朋友可以参考下
Android dexclassLoader 热更demo,详细讲解请看 https://blog.csdn.net/zhou3299136/article/details/105796479
首先第一个是 jar 文件的制作,Java 里面直接把 .class 文件打包到 .jar 文件里面就可以了,但是 Android 的 Dalvik VM 是不认 Java ...要动态加载其它类,可以用的 Class Loader 有: DexClassLoader,PathClassLoader
使用Android的classloader加载器实现热更新,通过反射机制获取到源码的Elements数组替换classes.dex实现更新,只能重启软件进行更新,无法实现实时更新。
android_dex Android DexClassLoader
加载一个Activity肯定不会像加载一般的类那样,因为activity作为系统的组件有自己的生命周期,有系统的很多回调控制,所以自定义一个DexClassLoader类加载器来加载插件中的Activity肯定是不可以的。 首先不得不了解...
实现安卓的多 dex 加载和 dex 加解密,学习了解APP的加固原理。 理解APP动态加载原理。
DexClassloader 这个一个demo,用来实现加载class文件,如果在实际项目中可以...2: DexClassloader: Android 用来加载 jar/apk/dex 文件 3: URLClassloader: 可以加载java的jar包,但是Dalvik 虚拟机不支持这种加载方式
普通的Android程序Dalvik虚拟机都是从一个默认的地方载入程序需要的类文件(dex文件),而Dalvik虚拟机还提供了从其他地方载入类的能力(比如从设备的内部存储空间以及...开始使用获取到的动态类对象~\(≧▽≦)/~啦啦啦
1. Dalvik下DexClassLoader动态加载关键函数链(基于Android4.4) 2. Art下DexClassLoader动态加载关键函数链(基于Android8.0) 3. Art下InMemoryDexClassLoader动态加载关键函数链(基于Android8.0) 4. Dalvik下...