1.插件化的形式其实有挺多种,之前项目中使用的时apk安装的方法。开发比较简单,也可以做扩展,以及两个apk间共享数据,但用户体验比较差
2.其实应该比较正规的方法应该是classloadder进行动态加载。
下面是使用dexClassLoader进行动态加载的例子(需要注意的一点是:4.1系统上需要做一些特殊处理)
(笔记来源:
http://blog.zhourunsheng.com/2011/09/探秘腾讯android手机游戏平台之不安装游戏apk直接启动法/?utm_source=rss&utm_medium=rss&utm_campaign=%25e6%258e%25a2%25e7%25a7%2598%25e8%2585%25be%25e8%25ae%25afandroid%25e6%2589%258b%25e6%259c%25ba%25e6%25b8%25b8%25e6%2588%258f%25e5%25b9%25b3%25e5%258f%25b0%25e4%25b9%258b%25e4%25b8%258d%25e5%25ae%2589%25e8%25a3%2585%25e6%25b8%25b8%25e6%2588%258fapk%25e7%259b%25b4%25e6%258e%25a5%25e5%2590%25af%25e5%258a%25a8%25e6%25b3%2595
http://blog.csdn.net/yangjunjiezai/article/details/8668265)
//第一个应用,为主程序,进行正常安装,并调起要下载的插件/mnt/sdcard/TestB.apk
public class MainActivity extends Activity {
private static final String TAG = "MainActivity";
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button btn = (Button) findViewById(R.id.btn);
btn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Bundle paramBundle = new Bundle();
paramBundle.putBoolean("KEY_START_FROM_OTHER_ACTIVITY", true);
String dexpath = "/mnt/sdcard/TestB.apk";
String dexoutputpath = "dex";
LoadAPK(paramBundle, dexpath, dexoutputpath);
}
});
}
public void LoadAPK(Bundle paramBundle, String dexpath, String dexoutputpath) {
ClassLoader localClassLoader = ClassLoader.getSystemClassLoader();
DexClassLoader localDexClassLoader;
if(Build.VERSION.SDK_INT == 16){
File dexOutputDir = MainActivity.this.getDir(dexoutputpath, 0);
localDexClassLoader =
new DexClassLoader(dexpath, dexOutputDir.getAbsolutePath(), null, ClassLoader.getSystemClassLoader().getParent());
}else
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(TAG, "activityname = " + activityname);
Class localClass = localDexClassLoader.loadClass(activityname);
Constructor localConstructor = localClass
.getConstructor(new Class[] {});
Object instance = localConstructor.newInstance(new Object[] {});
Log.d(TAG, "instance = " + 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, new Object[] { paramBundle });
}
return;
} catch (Exception ex) {
ex.printStackTrace();
}
}
第二个应用不安装,直接下载即可,以下是代码:
private static final String TAG = "TestBActivity";
private Activity otherActivity;
@Override
public void onCreate(Bundle savedInstanceState) {
boolean b = false;
if (savedInstanceState != null) {
b = savedInstanceState.getBoolean("KEY_START_FROM_OTHER_ACTIVITY", false);
if (b) {
this.otherActivity.setContentView(new TBSurfaceView(
this.otherActivity));
}
}
if (!b) {
super.onCreate(savedInstanceState);
// setContentView(R.layout.main);
setContentView(new TBSurfaceView(this));
}
}
public void setActivity(Activity paramActivity) {
Log.d(TAG, "setActivity..." + paramActivity);
this.otherActivity = paramActivity;
}
</pre>注意4.1上的特殊处理:<p></p><p></p><p></p><pre code_snippet_id="432800" snippet_file_name="blog_20140722_4_9787005" name="code" class="java">if(Build.VERSION.SDK_INT == 16){
File dexOutputDir = MainActivity.this.getDir(dexoutputpath, 0);
localDexClassLoader =
new DexClassLoader(dexpath, dexOutputDir.getAbsolutePath(), null, ClassLoader.getSystemClassLoader().getParent());
}else
localDexClassLoader = new DexClassLoader(dexpath,
dexoutputpath, null, localClassLoader);