android动态加载已安装apk中的方法

在android开发中,有很多时候是需要用到动态加载的,今天学习在android中动态加载已安装的apk中的方法。

首先,我们需要新建一个用来被加载的android工程,暂且给他取名叫做:plugproj

在plugproj中新建一个类Dynamic,在这个类中,我们新建一些方法,等会我们会分别在该工程安装和没有安装的情况下加载这些方法,Dynamic.java如下:

package com.example.plugproj;

import android.app.Activity;
import android.widget.Toast;

public class Dynamic {
	Activity mActivity = null;
	public void init(Activity activity) {
		// TODO Auto-generated method stub
		mActivity = activity;
	}
	public void showDialog() {
		// TODO Auto-generated method stub
		Toast.makeText(mActivity, "show dialog test gaga",Toast.LENGTH_LONG).show();
	}
	public void showWindow() {
		// TODO Auto-generated method stub
		Toast.makeText(mActivity, "show window test gaga",Toast.LENGTH_LONG).show();
	}
	public int addMethod(int a, int b) {
		// TODO Auto-generated method stub
		return a + b;
	}

}

可以看到init方法中,我们为其mActivity赋值,这是为了得到context对象,好让toast可以执行。

这里还需要注意,我们需要为plugproj工程的启动的activity中配置一个action,好让我们可以通过这个action来加载对应的包,如下:

 <activity
       android:name="com.example.plugproj.MainActivity"
       android:label="@string/app_name" >
       <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
        <intent-filter>
            <action android:name="com.haha.android.plugin"/>
        </intent-filter>
 </activity>

安装plugproj工程。

接下来看看另一个主工程,即加载plugproj的工程,主要代码如下:

              //创建一个意图,用来找到指定的apk
		Intent intent = new Intent("com.haha.android.plugin", null);
		//获得包管理器
		PackageManager pm = getPackageManager();
		List<ResolveInfo> resolveinfoes =  pm.queryIntentActivities(intent, 0);
		//获得指定的activity的信息
		ActivityInfo actInfo = resolveinfoes.get(0).activityInfo;    

		//获得包名
		String pacageName = actInfo.packageName;
		//获得apk的目录或者jar的目录
		String apkPath = actInfo.applicationInfo.sourceDir;
		//dex解压后的目录,注意,这个用宿主程序的目录,android中只允许程序读取写自己
		//目录下的文件
		String dexOutputDir = getApplicationInfo().dataDir;  

		//native代码的目录
		String libPath = actInfo.applicationInfo.nativeLibraryDir;
		//创建类加载器,把dex加载到虚拟机中
		DexClassLoader calssLoader = new DexClassLoader(apkPath, dexOutputDir, libPath,
				this.getClass().getClassLoader());   

		try {
			clazz = calssLoader.loadClass(pacageName+".Dynamic");
			obj = clazz.newInstance();
			Method initMethod = clazz.getDeclaredMethod("init",Activity.class);
			initMethod.invoke(obj,MainActivity.this);

		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (InstantiationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (NoSuchMethodException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} 

接下来是执行上面三个方法的onclick事件:

        @Override
	public void onClick(View arg0) {
		// TODO Auto-generated method stub
		try {
			switch (arg0.getId()) {
			case R.id.id_dialog:
				Method dialogMethod = clazz.getDeclaredMethod("showDialog",null);
				dialogMethod.invoke(obj, null);
				Log.d("Tag","show dialog runs ...");
				break;
			case R.id.id_window:
				Method windowMethod = clazz.getDeclaredMethod("showWindow",null);
				windowMethod.invoke(obj,null);
				Log.d("Tag","show window runs ...");
				break;
			case R.id.id_plus:
				Class[] param = new Class[2];
	            param[0] = Integer.TYPE;
	            param[1] = Integer.TYPE;
				Method method = clazz.getDeclaredMethod("addMethod",param);
				int result = (Integer) method.invoke(obj, 22,33);
				Toast.makeText(MainActivity.this,"result is :"+result,Toast.LENGTH_SHORT).show();
				Log.d("Tag","add  runs ...");
				break;
			default:
				Toast.makeText(MainActivity.this,"no property id",Toast.LENGTH_LONG).show();
			}
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		}
	} 

这样就实现了加载已经安装的apk中的方法。

接下来看看加载已经打包成为jar文件的方式:

首先需要将plugproj导出为jar文件,我们这里导出为plugproj.jar,注意这时候的jar文件在android手机上是不能直接加载的,我们需要将他转换成dex文件,怎么转换呢,在sdk下有一个dx工具,可以用它来实现,将plugproj.jar拷贝到拥有dx文件的目录下,一般是在platform_tool有时在build_tools文件夹下,然后用命令进入该文件下:

执行如下命令:

dx --dex --output 优化过的jar  没有优化过的jar

此时就会生成一个优化过的jar文件,这个jar文件就是我们的android手机可以直接加载的。将该jar文件拷贝到手机指定的目录下:

以下是关键代码:

                String path = "/storage/sdcard0/183/mydynamic_help.jar";
		dexPath = getDir("dex", Context.MODE_PRIVATE).getAbsolutePath();
		dexClassLoader = new DexClassLoader(path, dexPath, null, getClassLoader());
		try {
			clazz = dexClassLoader.loadClass("com.example.plugproj.Dynamic");
			try {
				obj = clazz.newInstance();
				Method method = clazz.getDeclaredMethod("init",Activity.class);
				method.invoke(obj, MainActivity.this);
				Log.d("Tag","dynamic init runs ...");
			} catch (InstantiationException e1) {
				e1.printStackTrace();
			} catch (IllegalAccessException e1) {
				e1.printStackTrace();
			} catch (NoSuchMethodException e) {
				e.printStackTrace();
			} catch (IllegalArgumentException e) {
				e.printStackTrace();
			} catch (InvocationTargetException e) {
				e.printStackTrace();
			}
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}

为按钮绑定onclick事件:

public void onClick(View arg0) {
// TODO Auto-generated method stub
try {
	switch (arg0.getId()) {
	case R.id.id_dialog:
		Method method = clazz.getDeclaredMethod("showDialog",null);
		method.invoke(obj, null);
		Log.d("Tag","show dialog runs ...");
		break;
	case R.id.id_window:
		method = clazz.getDeclaredMethod("showWindow",null);
		method.invoke(obj, null);
		Log.d("Tag","show window runs ...");
		break;
	case R.id.id_plus:
	<span style="white-space:pre">	</span>Class[]param = new Class[2];
		param[0] = Integer.TYPE;
		param[1] = Integer.TYPE;
		method = clazz.getDeclaredMethod("addMethod",param);
		int result = (Integer) method.invoke(obj,23,25);
	<span style="white-space:pre">	</span>Toast.makeText(MainActivity.this,"result is :"+result,Toast.LENGTH_SHORT).show();
		Log.d("Tag","add  runs ...");
		break;
	<span style="white-space:pre">	</span>default:
		Toast.makeText(MainActivity.this,"no property id",Toast.LENGTH_LONG).show();
	}
} catch (NoSuchMethodException e) {
	e.printStackTrace();
} catch (IllegalAccessException e) {
	e.printStackTrace();
} catch (IllegalArgumentException e) {
	e.printStackTrace();
} catch (InvocationTargetException e) {
	e.printStackTrace();
}
}

最后千万要记住,添加读写sd卡的权限。

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

源码下载

动态加载jar

时间: 2025-01-10 04:54:20

android动态加载已安装apk中的方法的相关文章

android动态加载已安装和未安装的apk资源

在android开发中动态加载已安装和未安装的apk资源,是很有用的,可以用来实现换肤功能等等.今天我们来学习. 首先新建一个工程plugpicinstall,我们需要往该工程的asset目录和drawable目录下拷贝一些呆会需要加载的图片.运行该工程,即安装. 我们先看看如何实现加载已经安装的apk中的资源: 我们需要先写两个方法,用来获取对应的已安装的apk的context对象和resource对应的id,如下: /** * 该方法用来获取已经安装的apk对应的context对象 * @r

Android动态加载框架DL的架构与基本原理解析

转载请注明出处,本文来自[ Mr.Simple的博客 ]. 我正在参加博客之星,点击这里投我一票吧,谢谢~ 前言 最近这一两年,Android App使用插件化技术开发的数量越来越大,其实还是业务地快速膨胀导致,需求越来越多,App越来越臃肿.虽然手机的内存空间不断地的增大,但是太大的安装包给用户也造成了心理压力.于是大家都会想到插件化的开发方式,把App做成一个平台,而不是一个独立的app.平台上可以集成各种各样的功能,功能模块也插件的形式添加进来,这些插件不需要安装,只需要用户按需下载到某个

Android动态加载jar/dex

http://www.cnblogs.com/over140/archive/2011/11/23/2259367.html 前言 在目前的软硬件环境下,Native App与Web App在用户体验上有着明显的优势,但在实际项目中有些会因为业务的频繁变更而频繁的升级客户端,造成较差的用户体验,而这也恰恰是Web App的优势.本文对网上Android动态加载jar的资料进行梳理和实践在这里与大家一起分享,试图改善频繁升级这一弊病. 声明 欢迎转载,但请保留文章原始出处:) 博客园:http:/

实现Android 动态加载APK(Fragment or Activity实现)

尊重原创:http://blog.csdn.net/yuanzeyao/article/details/38565345 最近由于项目太大了,导致编译通不过(Android对一个应用中的方法个数貌似有限制),所以一直琢磨着能否将某些模块的APK不用安装,动态加载,通过在网上查找资料和网友的帮助,终于实现了APK的动态加载,网络上介绍APK动态加载的文章非常多,但是我觉得写得非常好的就是这位大牛的,我基本上就是使用他的这种方案,然后加入了自己的元素.这位大牛是通过Activity实现的,我稍作修改

Android动态加载ListView中的Item

我这周上网看到动态增加listview的每一项item的布局,今天抽空自己写了一个,方便自己日后使用,这个效果还是很不错的,用到了Adapter的notifyDataSetChanged()方法,当点击每一个Item的时候,就通知adapter更新getView,系统得到通知就相应的加载一遍布局,就达到了动态加载item布局的效果.希望给大家带来点启迪,有问题或想要代码的可以留言,欢迎大家留言谈论listview的一些知识,以求共同进步,转载请标明出处: http://blog.csdn.net

Android动态加载那些事儿

基础 1.Java 类加载器 类加载器(class loader)是 Java?中的一个很重要的概念.类加载器负责加载 Java 类的字节代码到 Java 虚拟机中.本文首先详细介绍了 Java 类加载器的基本概念,包括代理模式.加载类的具体过程和线程上下文类加载器等,接着介绍如何开发自己的类加载器,最后介绍了类加载器在 Web 容器和 OSGi?中的应用. 2.反射原理 Java 提供的反射機制允許您於執行時期動態載入類別.檢視類別資訊.生成物件或操作生成的物件,要舉反射機制的一個應用實例,就

Android动态加载技术三个关键问题详解

编者按:InfoQ开设新栏目“品味书香”,精选技术书籍的精彩章节,以及分享看完书留下的思考和收获,欢迎大家关注.本文节选自任玉刚著<Android开发艺术探索>中的章节“Android的动态加载技术”,探讨了Android动态加载的三个关键问题. 动态加载技术(也叫插件化技术)在技术驱动型的公司中扮演着相当重要的角色,当项目越来越庞大的时候,需要通过插件化来减轻应用的内存和CPU占用,还可以实现热插拔,即在不发布新版本的情况下更新某些模块.动态加载是一项很复杂的技术,这里主要介绍动态加载技术中

android动态加载(二)

上一篇说了android中的动态加载,即在android工程中动态加载经过dx操作以后的jar文件和没有安装的apk文件,今天我们来看看怎么执行已经安装的apk中的类中的方法. 所以,我们会需要两个工程,一个是plugone,这个是我们暴露给外面的方法的一个android工程.另外一个我们暂且给他起名为useplugone吧. 先来看看plugone工程,我们在plugone工程中有这样一个类,用来暴露给调用者一个方法: package com.example.plugone; public c

Android动态加载Dex机制解析

1.什么是类加载器? 类加载器(class loader)是 Java?中的一个很重要的概念.类加载器负责加载 Java 类的字节代码到 Java 虚拟机中. Java 虚拟机使用 Java 类的方式如下:Java 源程序(.java 文件)在经过 Java 编译器编译之后就被转换成 Java 字节代码(.class 文件).类加载器负责读取 Java 字节代码,并转换成java.lang.Class类的一个实例.每个这样的实例用来表示一个 Java 类.通过此实例的 newInstance()