多APK支持是 Android Market 的一个新特性,它允许您为同一款应用对应不同的设备API Level 创建不同的APK,Android Market 会自动进行管理,通过识别用户设备的系统等级,比如2.2,2.3,4.0等等,然后会选择适合该设备的APK来让用户安装。
为不同的API Level设计的APK,可以进行特别的优化设置,比如GL纹理设置, API级别,屏幕尺寸,或其中的多个组合。
本节课就带领大家熟悉一下多APK的设计思路,您可以从中找到必要的开发工具和开发维护多个版本APK的方法。
确认您需要多个APKs
当您设计一款应用程序,为了满足多版本多设备之间的需求,在不牺牲向后兼容性的情况下,又可以利用最新版本的新特性,似乎多APK支持是个不错的解决方案。但事实并非如此,您可以通过阅读资料《Using Single APK Instead 》和《this article》来学习怎样在单一APK中实现上面提到的功能需求,以及怎样利用我们的支持库,同时也可以了解一下如何来编码实现。
使用单一APK有如下优势:
- 发布和测试更容易
- 只需要维护一个代码库
- 应用程序能够自适应设备配置的变化
- 应用恢复功能跨设备通用
- 应用升级容易
本文的余下章节,假定您已经认为您确实需要多APKs的解决方案,而不使用单一 APK 的方法。
图示化需求
可以通过创建一个简单的图表来确定需要几个APK来支持,以及每个APK与之对应的API Level范围。您可以在Android 平台版本的信息页面(Platform Versions )中找到有用的参考资料,通过这种方法可以快速确定需要的APK个数和每个APK对应的API Level范围,尤其在出现API Level范围有重叠情况的时候更加有效,同时也方便了日后参考。
创建一个水平的列表来表示出当前已经发布的Android 版本号,在列表的最后一个位置放置一个+号来代表未来发布的版本。
3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | + |
对上面的列表进行着色,每一种颜色对应一个APK,之后您的团队就可以以此来进行讨论还开发。
3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | + |
设计公共库
无论是修改已有的代码做二次开发,还是从头开发一个新的应用,第一件事情就是提取公共的代码库,这些代码可以被不同的应用使用,并且只需要在一处编写和维护,比如多语言支持(language-localized strings),颜色主题(color themes),bug修复代码等,提供公共代码可以大大提高开发效率和节省开发时间,以及降低更新代码时引入的错误。
注:如何提取和创建公共的代码库,可参照下面的文章
如果您打算将已开发的单一APK转化为多APK支持,那么以下资源通常可以放置到公共代码库中,比如字符串资源文件(localized string file),常量值(list of values),颜色定义(theme colors),菜单图标(menu icons )和可共用的布局文件(layout )。或者,您打算从头开发一个应用,这时候也应该先开发公共的代码库,然后将各个APK不同的特定代码部分移动到具体的APK中,便于代码的管理和以后的扩展,当开发过一段时间之后,您可以逆向从各个不同的APK中再提取公共的部分来更新公共代码库。
建立工程项目
每一个独立的APK对应于一个独立的工程文件夹,为了方便代码的组织和管理,所有APK项目的工程文件夹和公共项目文件夹应该放在同一个根目录下面,并且所有的APK项目应该是相同的包名(package name)。示例代码展示了建立上面列举的3个独立APK的项目文件夹,组织结构如下:
alexlucas:~/code/multi-apks-root$ ls foo-blue foo-green foo-lib foo-red
工程目录建立好以后,每个独立的APK项目都可以引用公共项目库,一般将启动Activity(starting Activity )放在公共项目库中,然后独立的APK工程中可以继承和扩展该Activity,这样便于将初始化代码集中在一个地方,例如 initializing Analytics, running licensing checks, and any other initialization procedures。
配置 Manifests 文件
当用户通过Android Market下载支持多APK的应用时,Market过滤器会依据如下的规则来选择合适的APK版本:
- manifest 中声明的版本号必须匹配
- manifest 中声明匹配的所有版本号中最大者优先
用我们前面讨论过的例子来进行说明,假如 manifest 中未设置支持的最大API等级(max API level) 选项,则每一个APK对应的API Level 如下:
3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | + |
3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | + |
3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | + |
minSdkVersion 越大则代表支持越高版本的代码,那么如上图 red ≥ green ≥ blue,则上图可以合并如下:
3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | + |
现在,假如 Red APK 使用了一种其他APK没有的新功能,比如前置相机,API Level 11以后支持。当用户设备通过Android Market进行程序下载的时候,Market Filters就会检测设备的信息,看是否是Level 11以上,是否有前置相机,如果不符合条件的话,Red APK就不会列在下载清单中,用户也就没法下载。事实上,目前仍有很多的设备还没有达到Level 11,也没有配置前置相机,那么如何解决此类问题呢。
幸运的是,Android Market会自动处理这种情况,它发现当前设备与Red APK的manifest 文件声明不符,会简单忽略它,然后继续检测Green APK,因为 Green APK没有设置maxSdkVersion 选项,本身又向前兼容,这样不管设备的版本是不是Level 11以上,也不管设备是否有前置摄像头,Green APK 仍然可用,用户也可以下载。
为了便于管理所有的APKs,应该合理设置版本号(version code scheme)。推荐阅读指南《Version Codes》,我们的例子中有3个独立的APK,每一个可以设置1000的版本号范围,前几位的数字(minSdkVersion )用来标志不同的APK,每次更新程序依次递增。示例如下:
Blue: 03001, 03002, 03003, 03004... Green: 07001, 07002, 07003, 07004... Red:11001, 11002, 11003, 11004...
综合以上,您的 Android Manifests 文件可能如下:
Blue:
<manifest xmlns:android="<a href="http://schemas.android.com/apk/res/android">http://schemas.android.com/apk/res/android</a>" android:versionCode="03001" android:versionName="1.0" package="com.example.foo"> <uses-sdk android:minSdkVersion="3" /> ...
Green:
<manifest xmlns:android="<a href="http://schemas.android.com/apk/res/android">http://schemas.android.com/apk/res/android</a>" android:versionCode="07001" android:versionName="1.0" package="com.example.foo"> <uses-sdk android:minSdkVersion="7" /> ...
Red:
<manifest xmlns:android="<a href="http://schemas.android.com/apk/res/android">http://schemas.android.com/apk/res/android</a>" android:versionCode="11001" android:versionName="1.0" package="com.example.foo"> <uses-sdk android:minSdkVersion="11" /> ...
发布前的检测清单
在将您的应用发布到Android Market之前,请仔细检查下面清单中列举的项目。请记住这些检查只适用于多APKs的程序设计,本文无法列出要发布到Android Market程序的所有检测项目。
- 所有的APKs拥有相同的包名
- 所有的APKs必须使用相同的签名文件
- 如果多个APKs的平台兼容版本有重叠,那么拥有较高minSdkVersion版本的APK必须拥有较高的版本号(version code)
- 检查manifest配置文件中的filter,防止出现矛盾的地方(例如,APK声明为只支持屏幕类型为XLARGE的cupcake版本,那么此APK将不能被任何设备下载)
- 每一个APK的manifest配置文件必须是唯一的,至少支持一种类型的屏幕,OpenGL纹理,或者Android固件版本
- 每一个APK都至少在一个平台上做过测试,开发环境中可以建立多个不同类型自定义的模拟器,请尽量做完整的测试
利用 Aapt (the Android Asset Packaging Tool) 工具来做最后的打包和检查工作,有效防止意外的小错误导致您的应用无法在Android Market的下载清单中正常显示出来。
>aapt dump badging package: name='com.example.hello' versionCode='1' versionName='1.0' sdkVersion:'11' uses-permission:'android.permission.SEND_SMS' application-label:'Hello' application-icon-120:'res/drawable-ldpi/icon.png' application-icon-160:'res/drawable-mdpi/icon.png' application-icon-240:'res/drawable-hdpi/icon.png' application: label='Hello' icon='res/drawable-mdpi/icon.png' launchable-activity: name='com.example.hello.HelloActivity' label='Hello' icon='' uses-feature:'android.hardware.telephony' uses-feature:'android.hardware.touchscreen' main supports-screens: 'small' 'normal' 'large' 'xlarge' supports-any-density: 'true' locales: '--_--' densities: '120' '160' '240'
仔细检查aapt工具的输出,看看有没有设置有矛盾的地方,尤其是关于支持的屏幕类型(supports-screens )和兼容的屏幕类型( compatible-screens),没有预期之外的多余的用户功能(uses-feature)权限,在上面的示例中,该APK在很多设备中都不可见。
什么原因导致的呢?因为上面的APK配置文件中加入了发信息(SEND_SMS)权限,android.hardware.telephony 特性就被隐式自动添加了。API 11 是Honeycomb (专门为平板设计的系统),而该设备没有支持电话的硬件(telephony hardware),Android Market就会将此APK过滤掉,导致 Honeycomb 设备没法下载和安装该APK,直到未来的设备APK Level升级,加入了支持电话的硬件,这个APK才能被下载安装。
幸运的是,我们可以只简单的修改一下配置文件即可解决这个问题:
<uses-feature android:name="android.hardware.telephony" android:required="false" />
完成了以上的检查工作,提交APKs到Android Market。经过审核后,您就可以在Android Market中下载和安装这些应用到您的测试设备中,确保所有的APKs都正确匹配配置文件中声明的设备类型,APK在预期的设备平台上会正常工作,到此为止,恭喜您,多APK设计的工作就完成了。
参考文摘:
http://developer.android.com/training/multiple-apks/api.html
博主,来看你了。