探秘腾讯Android手机游戏平台之不安装游戏APK直接启动法
前言相信这样一个问题,大家都不会陌生,
“有什么的方法可以使Android的程序APK不用安装,而能够直接启动”。
发现最后的结局都是不能实现这个美好的愿望,而腾讯Android手机游戏平台却又能实现这个功能,下载的连连看,五子棋都没有安装过程,但是都能直接运行,这其中到底有什么“玄机”呢,也有热心童鞋问过我这个问题,本文就为大家来揭开这个谜团。
实践
我实现了一个小小的Demo,麻雀虽小五脏俱全,为了突出原理,我就尽量简化了程序,通过这个实例来让大家明白后台的工作原理。
下载demo的apk程序apks,其中包括了两个apk,分别是A和B
这两个APK可分别安装和运行,A程序界面只显示一个Button,B程序界面会动态显示当前的时间
下面的三幅图片分别为直接启动运行A程序(安装TestA.apk),直接启动运行B程序(安装TestB.apk)和由A程序动态启动B程序(安装TestA.apk,TestB.apk不用安装,而是放在/mnt/sdcard/目录中,即SD卡上)的截图,细心的同学可以停下来观察一下他们之间的不同
后两幅图片的不同,也即Title的不同,则解释出了我们将要分析的后台实现原理的机制
实现原理
最能讲明白道理的莫过于源码了,下面我们就来分析一下A和B的实现机制,首先来分析TestA.apk的主要代码实现:
@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 = "/mnt/sdcard/";
LoadAPK(paramBundle, dexpath, dexoutputpath);
}
});
}
@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 = "/mnt/sdcard/";
LoadAPK(paramBundle, dexpath, dexoutputpath);
}
});
}
代码解析:这就是OnCreate函数要做的事情,装载view界面,绑定button事件,大家都熟悉了,还有就是设置程序B的放置路径,因为我程序中代码是从/mnt/sdcard/TestB.apk中动态加载,这也就是为什么要让大家把TestB.apk放在SD卡上面的原因了。关键的函数就是最后一个了LoadAPK,它来实现动态加载B程序。
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(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();
}
}
public void LoadAPK(
补充:移动开发 , Android ,