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游戏的代码在打包時进行了混淆,所以没有仔细分析源代码,感兴趣的朋友可以自己研究下具体是怎么加载资源的