参阅《Android内核剖析》 —— 柯元旦
目标:实现一个Apk调用另外一个apk内部普通类的普通方法。
关键步骤:
1) 首先创建两个Android工程 一个为Plugin(插件),另一个为Host(宿主)
2)在工程Plugin中编写类PluginClass
package com.example.plugin;
import android.util.Log;
public class PluginClass {
public PluginClass(){
Log.i("Plugin", "PluginClass clint initialized");
}
//要调用的方法
public int function1(int a,int b){
return a+b;
}
}
在Host(宿主)工程作为启动项的Activity中调用方法 useDexClassLoader();
该方法的实现如下:
public void useDexClassLoader(){
Intent intent = new Intent("com.example.plugin",null);
PackageManager pm = getPackageManager();
List<ResolveInfo> plugins = pm.queryIntentActivities(intent, 0);
ResolveInfo rinfo = plugins.get(0);
ActivityInfo ainfo = rinfo.activityInfo;
//String div = System.getProperty("path.separator");
String packageName = ainfo.packageName;
String dexPath = ainfo.applicationInfo.sourceDir;
String dexOutputDir = getApplicationInfo().dataDir;
String libPath =ainfo.applicationInfo.nativeLibraryDir;
DexClassLoader classLoader = new DexClassLoader(dexPath, dexOutputDir, libPath, this.getClass().getClassLoader());
try {
Class<?> clazz =classLoader.loadClass(packageName+".PluginClass");
Object obj = clazz.newInstance();
Class[] params = new Class[2];
params[0] =Integer.TYPE;
params[1] =Integer.TYPE;
Method action = clazz.getMethod("function1", params);
Integer ret = (Integer) action.invoke(obj, 15,18);
Log.i("计算结果:", ret+"");
} catch (Exception e) {
e.printStackTrace();
}
3)注意事项
Intent intent = new Intent("com.example.plugin",null);其中的第一个参数,自己随便定义个字符创或者使用PluginClass类所在 的包名,但是须在Plugin工程的AndroidManifest.xml 中作为启动的Activity添加一个IntentFilter ,示例如下:
<activity
android:name=".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.example.plugin"/>
</intent-filter>
</activity>