关于QQ游戏大厅的插件启动运行模式的讨论

天高空 发布于 2013/01/28 10:46
阅读 1K+
收藏 0
如果大家有这方面的经验,希望大家不吝赐教,畅所欲言

以下是问题补充:

@天高空:这个帖子可不能沉了 (2013/01/28 15:22)
@天高空:希望能人志士们 解答 (2013/01/28 15:23)
@天高空:红薯哥哥 呢? (2013/01/28 16:34)
@天高空:还有没有人在 说说? (2013/01/29 18:59)
加载中
0
天高空
天高空

关于类似QQ大厅的实现模式有一个参考:http://www.tidroid.com/article_108.html

Android手机上的QQ游戏大厅,下载一个游戏后不需要安装就可以直接启动运行。通过分析手机SD卡里.QQGame文件夹里的文件,可以发现 下载下来的具体游戏是一个apk安装包,而在/data/app目录下并没有该apk的安装信息,也就是说这个apk并没有安装。我们知道android 中要启动一个应用程序,首先需要安装这个应用程序,那么QQ游戏是怎么启动这个apk的呢?

带着前面的问题,來找答案吧。Java里可以通过反射机制來启动一个jar文件中的类,而jar文件就是一个特殊的zip压缩文件,其实apk文件 也是一个特殊的zip压缩文件,只不过apk里面的java类文件,都打包在classes.dex文件里了,这么看用反射机制就不行了。其实不然,我们 可以去看下Android的文档,在dalvik.system包下有一个类DexClassLoader,这个类就是用来从apk文件加载类的方法了, 而且这个类的父类的父类就是java.lang.ClassLoader。这样就大致能猜想到,QQ游戏的启动应该是这种方式启动的。

不过通过反射來启动的话,就不能由系统自动管理应用的生命周期了,这是一个问题,那么QQ游戏会怎么做呢,目前不得而知。不过我们可以通过反编译看 一下QQ游戏的具体实现机制,以下反编译基于最新版的QQ游戏大厅qqhall1.0_androidhvga_build0028.apk以及一个小游 戏俄罗斯方块qqrussia1.0_androidhvga_build0006.apk,俄罗斯方块的apk是在游戏大厅下载后,从sd卡上 的.QQGame目录下拷贝出来的。反编译qqhall1.0_androidhvga_build0028.apk后,使用JD-GUI打开反编译后的 jar文件,找到com.tencent.qqgame.client.game这个包,在这个包下有两个类PortraitGameActivity和 LandScapeGameActivity,分别用来启动竖屏和横屏的游戏,两个类的代码差不多,只看其中一个就行了。以 PortraitGameActivity为例,这个类实现了onCreate、onDestroy、onKeyDown、onPause、 onRestart、onResume、onStart等方法,每一个方法都是通过反射机制來启动游戏的Activity对应的方法,这说明具体游戏的生 命周期,是通过这个Activity來进行管理的。

还有一个问题,就是虽然通过反射可以启动类,但是由于没有Context,资源文件就没办法获得,QQ游戏用了那么多图片资源,总是需要加载的吧。 其实QQ游戏的所有资源文件都放在了assets文件夹里,具体加载時应该是通过直接读文件来加载的,因为QQ游戏的代码在打包時进行了混淆,所以没有仔 细分析源代码,感兴趣的朋友可以自己研究下具体是怎么加载资源的。

0
天高空
天高空

我的实现想法一:不同于腾讯的实现,意思就是假实现

我们在App1中检查App2是否安装

App2中我们在主页面的manifest.xml中去掉 <category android:name="android.intent.category.LAUNCHER" /> 加入<category android:name="android.intent.category.APP_BROWSER" />

这样在桌面上是看不到App2的图标的,但是在程序管理中能看到。

在程序中我们这样去做:

if(安装App2){

启动程序();

}else{

下载程序并安装();

}


/**
	 *  检测某一个apk是否安装
	 * @param pak
	 * @return
	 */
	protected boolean checkInstall(String pak) {

		boolean install = false;
		PackageManager pm = getPackageManager();
		try {
			PackageInfo info = pm.getPackageInfo(pak, PackageManager.GET_ACTIVITIES);
			if (info != null && info.activities.length > 0) {
				install = true;
				
			}
		} catch (NameNotFoundException e) {

			
		}
		return install;
	}
/**
	 * 加载另一个应用
	 * @param pak
	 */
	protected void 启动程序(String pak) {
		// 代码启动
		try {
			Context ctxTestB = getTestContext(pak);
			Class cls = ctxTestB.getClassLoader().loadClass(pak+".MainActivity");
			MainActivity.this.startActivity(new Intent(ctxTestB, cls));
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (NameNotFoundException e) {
			
			e.printStackTrace();
			
		}
	}
这里用DexClassLoader去加载class,然后启动,这样就ok了,如果App2没有安装的话,下载完后必须安装上,而腾讯的是没经过安装,把apk给解压了,直接用的反射机制去加载的,因为文档上是这样说的:

A class loader that loads classes from .jar and .apk files containing a classes.dex entry. This can be used to execute code not installed as part of an application.

This class loader requires an application-private, writable directory to cache optimized classes. Use Context.getDir(String, int) to create such a directory:

   File dexOutputDir = context.getDir("dex", 0);

Do not cache optimized classes on external storage. External storage does not provide access controls necessary to protect your application from code injection attacks.

天高空
天高空
纠正下:我这里用的是classloader 而腾讯用的DexClassLoader
0
天高空
天高空

引用来自“天高空”的答案

关于类似QQ大厅的实现模式有一个参考:http://www.tidroid.com/article_108.html

Android手机上的QQ游戏大厅,下载一个游戏后不需要安装就可以直接启动运行。通过分析手机SD卡里.QQGame文件夹里的文件,可以发现 下载下来的具体游戏是一个apk安装包,而在/data/app目录下并没有该apk的安装信息,也就是说这个apk并没有安装。我们知道android 中要启动一个应用程序,首先需要安装这个应用程序,那么QQ游戏是怎么启动这个apk的呢?

带着前面的问题,來找答案吧。Java里可以通过反射机制來启动一个jar文件中的类,而jar文件就是一个特殊的zip压缩文件,其实apk文件 也是一个特殊的zip压缩文件,只不过apk里面的java类文件,都打包在classes.dex文件里了,这么看用反射机制就不行了。其实不然,我们 可以去看下Android的文档,在dalvik.system包下有一个类DexClassLoader,这个类就是用来从apk文件加载类的方法了, 而且这个类的父类的父类就是java.lang.ClassLoader。这样就大致能猜想到,QQ游戏的启动应该是这种方式启动的。

不过通过反射來启动的话,就不能由系统自动管理应用的生命周期了,这是一个问题,那么QQ游戏会怎么做呢,目前不得而知。不过我们可以通过反编译看 一下QQ游戏的具体实现机制,以下反编译基于最新版的QQ游戏大厅qqhall1.0_androidhvga_build0028.apk以及一个小游 戏俄罗斯方块qqrussia1.0_androidhvga_build0006.apk,俄罗斯方块的apk是在游戏大厅下载后,从sd卡上 的.QQGame目录下拷贝出来的。反编译qqhall1.0_androidhvga_build0028.apk后,使用JD-GUI打开反编译后的 jar文件,找到com.tencent.qqgame.client.game这个包,在这个包下有两个类PortraitGameActivity和 LandScapeGameActivity,分别用来启动竖屏和横屏的游戏,两个类的代码差不多,只看其中一个就行了。以 PortraitGameActivity为例,这个类实现了onCreate、onDestroy、onKeyDown、onPause、 onRestart、onResume、onStart等方法,每一个方法都是通过反射机制來启动游戏的Activity对应的方法,这说明具体游戏的生 命周期,是通过这个Activity來进行管理的。

还有一个问题,就是虽然通过反射可以启动类,但是由于没有Context,资源文件就没办法获得,QQ游戏用了那么多图片资源,总是需要加载的吧。 其实QQ游戏的所有资源文件都放在了assets文件夹里,具体加载時应该是通过直接读文件来加载的,因为QQ游戏的代码在打包時进行了混淆,所以没有仔 细分析源代码,感兴趣的朋友可以自己研究下具体是怎么加载资源的。

缺点就是apk包得按照你的规则来编写。与外表交互就很麻烦。如果加载资源的话,游戏是放在assas中用pak压缩了,但是应用程序必须用到laout.xml文件,所以这个如何获取资源还是一个门槛,如果实现了,那么应用也可以这样做了。
0
alu
alu
现在好多动态加载框架都能处理资源加载了,但是一般都需要apk按某种规则来编写,一般是依赖框架提供的API,有一个开源项目,可加载不依赖规则的apk : android-pluginmgr 小弟开发的 还在完善中 欢迎star fork
返回顶部
顶部