创建支持多种屏幕尺寸的apk

tndroid 2013-07-04

原文自:http://android.eoe.cn/topic/ui

 

创建对两种以上屏幕尺寸的多apk支持(Creating Multiple APKs with 2+ Dimensions)

为了在开发android应用程序的时候加以利用google安卓市场的多apk支持特性,刚开始就采取一些良好的措施去增加对多apk的支持,是非常重要的,这样可以在将来开发的过程中减少不必要的麻烦。这一节将向您展示如何为你的app创建多apk支持--不同的apk支持不同的屏幕大小。还将获得一些维护多apk代码库尽可能的简单的工具。

确认您是否需要多apk支持


当你试图创建一个支持跨多android设备的应用程序时,很自然的你希望你的应用程序可以在所有的设备上都看起来最好。你既想利用大屏幕的空间,也希望能在小屏幕上运行,想利用新api的特征,也想在最新设备上的看到的纹理特征同时能在旧设备上同样可以看到。
刚开始的时候认为通过创建多个apk去支持多设备是最好的解决方案,但是往往不是这样。而是使用单个的apk去替代多个apk,开发指南中有去完成这个目标有用的信息,包括如何使用支持库的信息。还可以学习到如何写只能运行在特定api版本的代码的方法,而不去使用像反射这样的非常消耗资源的技术。

如果你能让你的应用程序只使用一个apk,将有如下几点好处:

  • * 发布和测试简单
  • * 只需维护一个代码库
  • * 应用程序可以适应不同配置的设备
  • * App可以跨设备运行
  • * 你不必考虑market的要求,apk的升级或者apk属于哪类设备

假设您已经研究了这个文档,已经学习了链接页面的内容,并且确定多apk支持的程序是你需要的,那么请继续看下面的小节。

画出你的需求


首先创建一个简单的图表来快速确定你需要多少个APK, 每个Apk覆盖的屏幕尺寸范围。虽然刚开始听起来非常容易,但是每个pai版本的apk去实现目标有是比较困难的,特别是经常有重叠的部分。幸运的是,通过本方法,你会很容易绘制出你的需求,供以后开发参考。让我们先讨论一下如何根据屏幕尺寸和api版本,为apk划分对应的设备范围。首先是创建一个图表,行和列对应一个值,并且都用颜色填充,每种颜色代表一个apk。
创建支持多种屏幕尺寸的apk

上面的例子有四个apk,蓝色的是为所有的small/normall屏幕设备的开发的,绿色的是为所有的large屏幕设备开发的,红色的是为xlarge设屏幕设备开发的,这三种apk对应的API范围是3-10。紫色的是一个特例,它可以适应所有的屏幕大小,但是仅支持API11或者以上系统。更重要的一点是,当你瞅一眼这个图表的时候,你能快速的看出来哪个apk对应什么API,对应什么屏幕大小。此外你还可以为每一个apk起一个非常拉风的开发代号。当我们的团队成员问我们,“我们是不是该测试红色的那个apk了”,而不是说“我们是不是该测试这个支持API3-10,支持xlarge屏幕,并且不是在摩托的Xoom平板上的apk了”,显然,前一种方式更容易理解。还有,把这个需求图表打印下来,分发给每一个团队成员。

把所有的共用代码和共用资源放在同一个库工程里( Put All Common Code and Resources in a Library Project)


无论你是修改一个已经存在的Android应用程序还是开始创建一个新的程序,首先最重要的任务就是创建一个共用代码库(如标题所说的库工程)。把那些只需更新一次就可以减少项目的开发时间,减少项目错误的代码或者资源放进这个库工程里(比如可以放在代码库里的像本地化语言字符串,颜色主题,共用bug的修复等)。

注意: 如何创建库项目的细节,不是本节要讲解的范围,您可以通过下面的链接快速的了解如何创建库工程:

如果你想把已有的应程序转成多apk的支持,需要重新组织你的代码中的所有的本地化字符串文件,值列表,颜色主题,菜单图标,布局文件,这些跨apk的不会改变的资源文件,并把他们放到库工程里。还有把那些不会改变太多的代码放到库工程里。这样你将会发现,你可以从一个apk继承另一个apk那些类的,扩展一到两个方法(函数)。

如果你刚开始创建一个新应用程序,首先要尽量在一个库工程中写代码,如果必要的情况下做成一个独立的apk。这样在以后长时间的开发过程中,长远看来是非常容易管理的,可以一点一点的添加共用代码和资源,并在数月之后指出这些代码或者资源在不经修改的情况下是否该移动到库里。

创建新的APK工程(Create New APK Projects)


对于需要发布的每个APK,要分别为每个APK创建Android工程。为了便于管理,把库工程和所有相关的APK工程放在相同的父目录下,同时需要记住每个APK需要相同的包名,虽然他们在这个库里不必须去共享他们的包名。比如,如果你有4个APK,正如前面的规则所描述的,你的根目录会像这样:

1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
alexlucas:~/code/multi-apks-root$ ls

foo-blue

foo-green

foo-lib

foo-purple

foo-red

一旦这个工程创建之后,把这个库工程引用到每个APK工程,如果可以的话,在库工程里定义启动Activity,并在APK工程里继承这个Activity。有了这个在库工程中定义的启动Activity,可以把你的所有应用程序的初始化工作放在一个地方,这样一来每个一个单独的APK就不需要重新实现这些像初始化分析,运行许可检查等其他的一些初始化工作,不用一个个APK的去写,维护起来也会简单好多。

调整Manifests文件(Adjust the Manifests)


当用户从google安卓市场下载对多APK支持的程序时,正确的APK使用两个简单规则:

1.maifest已经表明这个APK是合格的

2.对于所有的合格APK,支持的Android API版本号最高者优先被发现。

下面我们将以举例的方式讲解,首先,假设我们已经了解了前面所述的多APK的描述,并且这些apk支持所有的屏幕尺寸,而不是仅仅只支持目标尺寸的屏幕,让我们重新看一下前面的表格:
Since it’s okay for coverage to overlap, we can describe the area covered by each APK like so:
创建支持多种屏幕尺寸的apk

因为他们有重合的部分,我们可以像下面一样去描述每个apk

    • 蓝色的覆盖所有的屏幕尺寸,最低支持sdk是3
    • 绿色的覆盖大屏幕或者更大的屏幕,最低的sdk是3。
    • 红色的覆盖的是超大屏幕的(平常的平板),最低支持sdk9
    • 紫色的覆盖所有的屏幕尺寸,支持最低sdk11

请注意,在上述的规则中有很多重合的地方。举个例子,一个xlarger屏幕的设备,系统版本是API11,这个4个apk全都可以在这个设备上运行,我们根据最高版本优先被搜到的原则,我们可以把他们的优先级列出来:

紫色 ≥ 红色 ≥ 绿色 ≥ 蓝色

为什么允许重叠呢?
现在我们进一步假设,紫色的apk需要一些必须的东西,而其他的两种apk不需要有。google安卓市场的开发者指南页面上列出了所有的可能过滤掉你的程序的罪魁祸首。为了更好的讲解例子,我们继续假设,紫色的apk需要前置摄像头,关键点就在于,必须要求有前置摄像头,但是并不是所有的API11或以上设备上都配有前置摄像头,是不是很恐怖。

幸运的是,如果用户在google安卓市场使用这样的设备浏览软件的时候,安卓市场的引擎首先会到manifest文件里面去查看是否必须要有的前置摄像头,如果必须要求有前置摄像头,因为紫色的apk和设备不匹配,这个紫色的apk将会被忽略掉;然后再查看红色的apk,因为红色的apk即支持xlarger屏幕,对前置摄像头也没有硬性的要求,google play会认为红色的apk可以和设备匹配,程序就可以从google play上下载下来试用了,因为至少有一个支持这个设备的apk。

为了把所有的apk分别处理,设定一个好的版本号使用规则特别重要,在开发者指南上有推荐的版本号规则Version Codes。这一部分还是比较值得阅读的,基本要点是为一组apk设定规则,我们用两个数字代表最低支持的系统版本号,用两个数字代表支持的最大或者最小屏幕大小,另外的三个数字代表自己的程序的版本。通过这种方式,当设备的系统升级的时候,比如从10升级到11,apk升级的时候,在所有的apk中,优先被升级的apk是当前安装在设备上的那个apk。下面是一个版本号使用规则的一个例子,可以定义成如下格式,

蓝色: 0304001, 0304002, 0304003...

绿色: 0334001, 0334002, 0334003

红色: 0344001, 0344002, 0344003...

紫色: 1104001, 1104002, 1104003...

这三种在程序的manifests文件中定义分别如下:
蓝色:

1
2
3
4
5
6
7
8
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    android:versionCode="0304001" android:versionName="1.0" package="com.example.foo">
    <uses-sdk android:minSdkVersion="3" />
    <supports-screens android:smallScreens="true"
        android:normalScreens="true"
        android:largeScreens="true"
        android:xlargeScreens="true" />
    ...

绿色:

1
2
3
4
5
6
7
8
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    android:versionCode="0334001" android:versionName="1.0" package="com.example.foo">
    <uses-sdk android:minSdkVersion="3" />
    <supports-screens android:smallScreens="false"
        android:normalScreens="false"
        android:largeScreens="true"
        android:xlargeScreens="true" />
    ...

红色:

1
2
3
4
5
6
7
8
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    android:versionCode="0344001" android:versionName="1.0" package="com.example.foo">
    <uses-sdk android:minSdkVersion="3" />
    <supports-screens android:smallScreens="false"
        android:normalScreens="false"
        android:largeScreens="false"
        android:xlargeScreens="true" />
    ...

紫色:

1
2
3
4
5
6
7
8
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    android:versionCode="1104001" android:versionName="1.0" package="com.example.foo">
    <uses-sdk android:minSdkVersion="11" />
    <supports-screens android:smallScreens="true"
        android:normalScreens="true"
        android:largeScreens="true"
        android:xlargeScreens="true" />
    ...

注意一下,在技术上,一个apk要么有支持的特定屏幕的标记,要么有兼容性的屏幕的标记,支持的屏幕是优先考虑的。但是如果同时有这两个标记是很不好的做法,这样会增加额外的复杂性,增加机会性错误。同时还要注意,不要使用默认的值(small和normal默认情况下总是true),在manifesets中应该明确指定屏幕大小的值。这样会减少以后的麻烦---顺便举个例子,manifest的目标sdk要求小于9,如果使用默认值,xlarge自动设置为false,xlarge的屏幕将不会支持,因此最好要明确指定。

发布前的检查(Go Over Pre-launch Checklist)


往google play上上传程序之前,一定要根据下面的条目仔细的检查下程序。记住,这些条目与多apk支持关系非常密,但是这里并没有列出所有的需要检查清单。

  • * 所有的apk必须有相同的包名
  • * 所有的apk必须用相同的数字证书签名
  • * 如果这些apk有系统版本重合的地方,最低系统版本号最大的那个apk必须有一个更高版本号(If the APKs overlap in platform version, the one with the higher minSdkVersion must have a higher version code)
  • * 任何一种你将有支持的屏幕大小都要在manifest中设置成true,如果不想支持的就设置成false。
  • * 仔细检视manifest的过滤条件是否有冲突的地方(比如,一个apk只支持xlager的屏幕的设备,就不要被所有的设备看到)
  • * 每一个apk的menifest必须至少支持一种屏幕,openGL texture或者系统版本。
  • * 每一个apk至少在一个种设备上测试过。除非你是为定制的设备开发程序。

把程序提交到google市场之前,还要对编译过的程序进行检查,确保没有一些其他的明显的问题而影响你的程序在google市场上被发现。使用aapt(Android Asset Packaging Tool,是生成和打包android应用程序的重要构建工具)这个工具进行编译检查特别的简单便利。

1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
>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的输出时,确保支持的屏幕和兼容的屏幕的值不冲突,不要在manifest中的"uses-feature"添加一些你并不需要的系统权限.如上面的例子,这个apk不会被很多的设备看到。

为什么呢?例子中显示,增加了SEND_SMS的权限要求,这个特征需要增加android.hardware.telephony硬件支持。从api11 Honeycomb开始是针对平板电脑的系统,没有打电话的硬件支持,Google play将会过滤掉不支持打电话的设备,只有API版本匹配,同时支持打电话的硬件支持才不会被过滤掉。

可以非常容易的在manifest中修复这个问题:

1
<uses-feature android:name="android.hardware.telephony" android:required="false" />

android.hardvare.touchscreen 权限要求也本不正确的加进去了,如果你想你的apk能被没有触碰功能的android系统的智能电视也能在市场上搜索到,进行如下设置:

1
<uses-feature android:name="android.hardware.touchscreen" android:required="false" />v

当你完成了发布前的检查,你就可以向google play上提交你的apk了。发布完之后再去google play做最后一点检查,去上面搜索你的程序,下载下来,以确保你的目标设备可以搜到,并能使用。恭喜您,现在您已经完成了本节课程!!!

相关推荐