首页 > 测试圈 >技术>详情

终端应用开发指南

时间:2016-01-15 10:29   作者:中国移动终端公司

 

一、前言

4G移动网络的商用为移动互联网的蓬勃生长提供了肥沃的土壤,并协同国内外众多互联网厂商及终端厂商共同引领了中国移动互联网翻天覆地的发展与创新。

1.1 中国移动4G用户增长趋势

2014年以来移动4G用户数目显著提升,拉动了全网用户的流量增长,同时随着流量资费的下降,运营商将与优秀APP互助互惠:更充足更宽带宽的数据业务促进用户对移动终端APP的使用,而优秀的APP则会拉动移动互联网流量的进一步增长。

2016年中国智能手机用户预计将达6亿以上,智能手机已经并将进一步渗透至人们生活中的方方面面。根据2014年数据,中国移动终端用户平均安装34款应用,单台终端平均每日下载应用3款以上,打开应用可达20款,用户每日使用APP的时间也持续增加。作为移动互联网的入口,APP的质量优秀与否已成为用户对移动互联网体验的重要影响因素。

2014,GooglePlay商店的应用数量已达143万,开发者数量已达38.8万。如此规模巨大的市场吸引大量开发者及团队的加入,带来了空前的繁荣与竞争。如何在规模成百上千的竞品当中脱颖而出,一方面需要优秀的运营团队及策略,而更能起到决定性作用的是APP本身的品质。《终端应用开发指南》将从网络、终端与APP协同工作的角度出发,基于Android平台,对如何开发出优质的APP从而为用户提供更卓越的互联网使用体验给出参考建议。

 

二、如何定义优秀的APP

   

对于一款优秀的APP,“可用”是基本前提,“好用”是脱颖而出的必要条件,安全则是保护用户权益的根本保障。

“可用”:移动终端设备尤其是Android手机的高度碎片化给应用的兼容性带来了巨大挑战。这一碎片化既包括硬件配置如芯片平台、显示屏幕等,更涉及了极为丰富多样的操作系统。完善的兼容性成为了保证用户使用体验、提升APP质量的重要因素。

“好用”:相比于PC等传统终端设备,移动终端设备能力虽然已得到极大的提升,但内存、电量等资源依然格外宝贵。在各类APP层出不穷的当下,一款APP仅仅做到“可用”还远远不够。

“安全”:移动应用迅速覆盖了包括出行就餐、日常起居、甚至金融理财等各个领域。然而凡事有利有弊,Android漏洞、APP安全早已饱受诟病。应用安全已经成为用户挑选应用产品甚至挑选应用商店的决定因素。如何保护用户的数据安全及权限安全成为了开发者需要研究的重要课题。

移动终端产品与时俱进,已成为普罗大众眼中高新科技的代言词,也渐渐成为大众日常使用的最具科技感的个人电子设备。在“可用”“好用”“安全”的基础上,应用开发者们应不断扩展视野,并充分整合已有的最新资源,在广度上覆盖更多的移动终端产品,在深度上不断挖掘移动终端的各项能力,为用户提供更多。

本文将主要围绕着“可用”“好用”“安全”“新技术”四方面展开。第三章从操作系统版本、屏幕分辨率等方面对常见的问题进行了阐述,并抛砖引玉,给出了解决部分问题的参考建议。第四章将分别从系统资源、功耗、网络性能以及APP的交互设计等几个方面对已有的问题进行阐述并提供建议。第五章强调了安全的重要性以及如何去保证安全,将从数据安全、权限安全以及内容安全等方面对问题进行阐述并给出相应问题可供参考的解决办法。第六章主要从终端新能力、网络新技术以及终端新趋势三个方向进行介绍。

 

三、让APP能被每一个用户使用

 

终端市场发展迅速,蓬勃的市场带来了市面上千百款终端巨大的差异性。一方面,用户需求变更及科技的快速发展推进终端的硬件及操作系统的迭代更新;另一方面,各终端厂商为打造自身品牌体现产品的差异化,对外观及操作系统进行大量的、深度的个性化定制。显著的差异化给APP开发者的适配工作带来了巨大的挑战,完善的兼容性成为了保证用户使用体验、提升APP质量的基本要素。

3.1 丰富多样的操作系统

根据最新统计,2014年至2015年第三季度国内销售智能终端各操作系统占比如下图所示。

3.1 2014年至2015年三季度销售终端操作系统占比

2015第三季度销售的iOS及Android终端占比之和已超过95%。2015年Android占比虽有所下降,但依然占据主导地位,占比高达80%以上。

为了充分开发硬件能力、满足用户需求并提升用户体验,Google周期性推出新操作系统版本更新,并不定期进行小版本升级。相对而言,由于终端硬件的不支持或用户基于自身喜好不倾向于更新系统,终端产品无法保证操作系统同步更新至最新版本,这导致了市面上同时存在多个操作系统版本的问题。相比于iOS,Android由于其开放特性,使越来越多的终端厂商加入其阵营当中,愈发加剧了Android系统的碎片化。2015年第三季度在网终端产品及国内销售终端产品Android版本占比分别如下所示:

3.2 2015年三季度在网终端Android版本占比(左)及销售终端Android版本占比(右)

目前在网Android手机搭载的操作系统中小版本多达20个以上,其中大版本仍以4.X为主,但2015年第三季度销售的Android手机搭载的操作系统中5.0版本已占较大比例,4.4及5.0二者占比共计76.74%。

Android阵营的碎片化不只体现在系统版本,更体现在了各终端厂商及互联网公司定制化系统的多样性。2015年以来国内销售终端搭载的定制系统多达36款,如MIUI、EmotionUI、Flyme等,若考虑个人爱好者开发的相对小众的产品,定制系统的种类将更是数不胜数。厂商因为各种各样的原因修改了Android系统的API,带来部分APP无法安装、运行出错、强制退出等问题,给APP的适配带来了极大困难。

通过对海量测试数据深度的收集整理与分析,这里总结了最为常见的适配问题并提出了相应的解决方案:

1. 在低版本Android系统上调用高版本API导致应用Crash

在不断升级的过程中,Android为支持新的功能和特性需增添新的API。开发者如果在应用内调用了此类API,同时没有限定应用最低支持版本,则在低版本上运行时会出现崩溃异常。

当Android发布新版本,开发者一方面要重点关注Google新增的功能,另一方面要关注新增功能所使用的API是否为新增。如果应用在迭代升级的过程中使用了新增功能或函数,那么应用开发过程中一定要注意新增功能在低版本Android系统上实现的兼容性。

2. 使用Android官方废弃函数导致应用不兼容新版本

在Android版本更新的过程中,不仅仅会增加新的函数,也会由于需求的变更或基于执行效率的考虑而删除部分函数。开发者在APP开发过程中,如果未能及时跟进和更新应用中相应功能实现,应用在新版本系统上调用已经删除的函数,运行时候就会出现崩溃异常。

3. 由于厂商定制系统导致的不兼容问题

Android系统的开放性吸引了大量的终端厂商加入其阵营当中。基于产品的差异化需求,直接使用Android原生系统的终端厂商寥寥无几,很多厂商在定制系统中对应用程序框架层有或多或少的改动。

如部分厂商在定制系统时修改存储卡的挂载点,如果APP开发代码中使用硬编码定义存储卡路径就会出现无法读取和保存文件的情况。应尽量避免使用硬编码定义存储卡路径,使用Environment.getExternalStorageDirectory()等对应API获取。

3.2 千差万别的屏幕

 

屏幕分辨率发展迅速,在2014年下半年2K屏幕已经成为了各厂商旗舰机的主流配置。更清晰的屏幕给用户呈现更丰富的内容,也带来了更惊艳的视觉享受。短短5年,手机屏幕分辨率从800×480骤增至2560×1440。当前主流的屏幕分辨率包括WVGA(800×480)、qHD(960×540)、HD(1280×720)、FHD(1920×1080)、WQHD(2560×1440)等。2014年至2015年第三季度销售终端的屏幕分辨率的占比如下:

3.3 2014年至2015年三季度销售终端屏幕分辨率占比

由上图可以看出,在屏幕分辨率保持多样性的同时,FHD、WQHD等高分辨率屏幕的占比正在提高,针对高分辨率屏幕开发高清APP已是目前趋势。

为确保APP对不同分辨率屏幕的良好兼容,应着手于AndroidManifest.xml文件及res目录下文件的配置。

1. AndroidManifest.xml设置

在AndroidManifest中添加子元素android:anyDensity="true"后,应用程序安装在不同密度的终端上时,程序会分别加载xxhdpi、xhdpi、hdpi、mdpi文件夹中的资源,其中dpi表示屏幕像素密度,指每英寸上的像素点数。之前还有ldpi,但是随着移动设备配置的不断升级,现在适配时不需考虑。mdpi、hdpi、xhdpi、xxhdpi用来修饰Android中的drawable文件夹及values文件夹,用来区分不同像素密度下的图片和dimen值。

在开发过程中,应将合适大小的图片放在合适的文件夹中,对于五种主流的像素密度(MDPI、HDPI、XHDPI、XXHDPI和XXXHDPI)应按照 1:1.5:2:3:4的比例进行缩放:

1. 横屏竖屏目录区分

在开发过程中,应分别对横屏及竖屏建立不同的目录,放置适用于横屏及竖屏的图片及布局文件,适应横竖屏的切换。如在res目录下建立layout-port和layout-land两个目录,里面分别放置竖屏和横屏两种布局文件。

2. 关于布局的适配建议

1) 尽量不使用绝对布局。

2) 尽量使用match_parent而不是fill_parent。

3) 使用layout_weight属性按屏幕比例布局,这样可以保证在屏幕上面展示的时候有合适的大小。不要使用像素单位的硬编码,需要的话在dimens定义使用。

4) 设置android:layout_width和android:layout_height的值时,dp比px更好,文字大小应该使用sp来定义。

5) 为适应不同屏幕分辨率,在res目录下创建不同的layout文件夹,比如:layout-1280x720、layout-1920x1080等,Android系统会根据屏幕的分辨率大小选择合适的layout进行使用。

3.3 版本迭代的兼容

 

用户的需求不断革新,快速迭代已成为APP成功的因素之一。根据测试数据,移动应用平均每月会进行一次新版本的升级。如此频繁的版本升级使得高低版本间的兼容性尤为重要。

若要保证高低版本间不出现兼容性问题,首先要设置好版本号(VersionCode)的值。VersionCode是一个Integer类型的值,在第一次发布应用到市场时,版本取值为1(VersionCode=1),这也是目前典型和普遍的做法。然后,发布更新版本时可以递增VersionCode的值。。

APP版本迭代时,新功能需求引起数据库的变动,需要重写SQLiteHelper的update方法对数据库进行增量更新,避免删除所有数据表再重新创建。

另外,在APP升级过程中要确保旧版本的可用性,保留服务端旧版本接口相关代码支持。对于过于老旧的计划不再支持的版本,要推送消息指引用户主动进行版本更新。

 

四、让手机更轻松,增强用户体验

 

相比于PC等传统终端设备,移动终端设备的资源更加宝贵:系统及硬件资源决定了用户使用体验;续航已成为影响用户挑选终端的重要指标;复杂的网络环境也让用户对流量格外关注。

是否可以通过降低APP占用的系统及硬件资源有效延长终端使用时间?是否能够在保证提供有效服务的同时降低流量的消耗?是否可以为用户提供更顺畅更快捷的操控体验?以上已成为APP从“可用”到“好用”的分水岭,也成为衡量开发者及团队是否专业的重要标志。

4.1 良好的编程习惯

 

在资源使用方面,如果打开了资源,要记得关闭资源。要尽量晚地获取,尽量早地释放。如果使用了底层的设备服务时更应如此。当不再需要这些信息时要取消获取最新信息的注册。这将帮助避免不必要地耗费设备电池电量或占用系统资源。

另外,作为一名优秀的开发者,也要学会充分利用调优工具。

Android SDK随带了许多工具,可用来对应用程序进行分析,比如:

Android Lint:Android Lint是SDK Tools 16 (ADT 16)之后才引入的工具,通过它对Android工程源代码进行扫描和检查,可发现潜在的问题,以便程序员及早修正。由于Android Lint在最初设计时就考虑到了独立于IDE,所以它可以很方便的与项目中的其他自动系统(配置/Build/测试等)集成。

TraceView:这款图形化工具可以帮助调试和找到应用程序中的性能瓶颈。

学会使用这些SDK提供的调优工具可以在开发工作中起到事半功倍的作用。

4.2 更低的系统资源占用

 

CPU与内存是决定终端性能的最重要的两部分硬件。手机芯片的处理能力飞速提升,从2012年到2014年两年的时间内走完了PC从1999年到2006年的历程。虽然移动终端的性能提升显著,但终端的硬件资源依然有限。随着高CPU及内存占用率的APP层出不穷,给终端带来了更大的负担,容易造成手机运行卡顿等现象,因此用户越发重视APP对CPU及内存的占用率。降低Android系统及单个APP的资源占用以获取更充裕的空闲资源,可以给用户提供更丰富的功能与服务并带来更流畅的操控体验。

2015年,移动终端芯片产品开始进入64位时代,核心数目越发集中于四核及八核。相比于芯片的性能,厂商越发重视能效,即在性能平稳提升的同时更重视能耗的降低。

市场销售终端CPU主频变化趋势如下图所示:

 

4.1 2014年至2015年三季度销售终端CPU主频占比

由上图可以看出,CPU主频提高的趋势依然存在,但变化已渐平缓。芯片厂商将更多的精力用于架构与工艺的提升。市场主流销售终端的CPU核心数目变化趋势如下:


图4.2 2014年至2015年三季度销售终端CPU核心数目占比

8核处理器的市场占比逐月提升,部分8核处理器采用big.LITTLE架构模式,通过两种架构双四核的合理调度有效降低功耗。

2014至2015年第三季度,国内市场销售终端内存占比如下:

4.3 2014年至2015年三季度销售终端RAM大小占比

目前市场主流内存大小从14年的1GB及2GB增长至2015年的2GB及3GB。由于手机产品的精品化趋势,2GB及2GB以上的内存大小已在2015年成为主流,各大终端厂商的旗舰机型则相继使用3GB甚至更大的内存。

RAM在任何软件开发环境中都是很宝贵的资源。开发者以及普通用户们越发认识到降低APP资源占用的必要性。在Android系统中,每个程序都会有可使用的内存上限,即堆大小(Heap Size)。随着硬件设备的升级,堆大小也随之提高。在开发应用程序时所使用的内存不能超出限制,否则会出现OutOfMemoryError。

虽然Android系统具有GC操作且在绝大多数情况下我们并不需要主动通知系统进行GC,但这并不意味着可以忽视内存分配与释放的时机与地点。

为了降低终端硬件资源的占用,以下建议可供参考:

1. 珍惜Services资源

如果应用需要在后台使用Service,除非它被触发并执行一个任务,否则Service都应该是停止状态。另外需要注意当Service完成任务之后,因为停止Service失败而引起的内存泄漏。当启动一个Service,系统会倾向为了保留这个Service而一直保留Service所在的进程,系统无法把Service所占用的RAM空间腾出来让给其他组件。另外,Service不能被paged out,这减少了系统能够存放到LRU缓存当中的进程数量,它会影响APP之间的切换效率,甚至会导致系统内存使用不稳定。

限制Service的最好办法是使用IntentService,它会在处理完交代给它的intent任务之后尽快结束自己。

2. 当UI隐藏时释放内存

当用户切换到其它应用并且原应用 UI不再可见时,应该释放原应用UI上所占用的所有内存资源。在这个时候释放UI资源可以显著的增加系统缓存进程的能力,它会对用户体验有着很直接的影响。

3. 当内存紧张时释放部分内存

在APP生命周期的任何阶段,通过onTrimMemory的回调方法同样可以得知整个设备的内存资源已经开始紧张。应该根据onTrimMemory回调中的内存级别来进一步决定释放哪些资源。

4. 使用优化的数据容器

利用AndroidFramework里优化的容器类,如SparseArray、SparseBooleanArray与LongSparseArray。通常的HashMap的实现方式更加消耗内存,因为它需要一个额外的实例对象来记录Mapping操作。另外,SparseArray更加高效,这在于他们避免了对key与value的autobox自动装箱,并且避免了装箱后的解箱。

5. 为序列化的数据使用nanoprotobufs

Protocol buffers是由Google为序列化结构数据而设计的,一种语言无关、平台无关、具有良好扩展性的协议,类似XML却比XML更加轻量、快速、简单。如果需要为数据实现协议化,应该在客户端的代码中使用nano protobufs。

6. 谨慎使用第三方Library

很多开源的library代码都不是为移动网络环境而编写的,如果运用在移动设备上效率并不高。当使用一个第三方library的时候,应该针对移动网络做繁琐的迁移与维护。即使是针对Android而设计的library,也可能是很危险的,因为每一个library所做的事情都不同。

7. 使用ProGuard来精简代码

ProGuard能够通过移除不需要的代码,重命名类、域与方法等对代码进行压缩、优化与混淆。

8. 对最终的apk使用zipalign

在编写完所有代码,并通过编译生成apk之后,需要使用zipalign对apk进行重新校准。

9. 合理使用多进程

通过把APP组件切分成多个组件,运行在不同的进程中,可以有效提高内存管理的灵活度及效率。这个技术必须谨慎使用,因为如果使用不当,它会显著增加内存的使用,而不是减少。

4.3 更低的耗电量

 

终端的性能经历了翻天覆地的提升,移动互联网的发展也让终端承载了越来越多的任务,然而随着终端各项业务对能耗需求的增加,移动终端限于体积却无法大量地提升电池的容量。电池容量虽有所提升,但在日常使用中依然捉襟见肘,手机续航问题长久以来困扰着终端厂商与用户。下图为2014年至2015年第三季度国内市场销售终端的电池容量占比变化情况:


图4.5 2014年至2015年三季度销售终端电池容量大小占比

 

由4.2节对芯片发展趋势的分析可以看出,为了降低终端的耗电量,硬件厂商已经做出了切实的努力。与此同时,目前市面大多数的移动终端产品所搭载的操作系统也都带有省电模式:通过降低屏幕亮度、CPU限频、关闭后台等方式降低电量消耗。

硬件及操作系统都已为移动终端的能耗降低做出了贡献,在应用层级也应采取必要的方式节省能耗。

1. 合理安排任务

可以通过BatteryHistorian Tool查看详细的电量消耗,如果发现APP有电量消耗过多的问题,可以使用JobScheduler API来对一些任务进行定时处理,如把任务重的操作等到手机处于充电状态,或是连接到WiFi的时候来处理。

2. 汇集零散的网络请求统一进行操作

触发网络请求的操作,每次都会保持无线信号持续一段时间,可以把零散的网络请求打包进行一次操作,避免过多的无线信号引起的电量消耗。

3. 减少网络传输的数据量

在没有必要的情况下不要联网进行操作,合理使用ImageLoader,使用增量更新,或者在满足质量的情况下,对数据进行一定的压缩 (和缓存合并)。

4. 优化APP心跳机制

APP应通过自适应等方式优化心跳机制,减少不必要的心跳。这将有利于终端电量的节省。关于心跳机制的具体内容将在4.4节做更详细的阐述。

4.4 更优的网络性能

 

2014年以来4G的网络建设和商用为用户带来更高速的数据通讯体验,而绝大多数用户限于费用而对应用产生的流量较为敏感,尤其是对于后台流量更是谨而慎之。

2015年9月在网用户月均使用流量243.37MB,逾75%的用户每月使用流量在200MB以下。相对而言,为了保证用户使用体验,一些APP开发者以耗费不必要的网络流量为代价,频繁交互信息或过度强化心跳机制,导致用户的流量费用和电量均损耗较大。如何在消耗较少流量的同时提供有效服务并对后台流量进行有效控制成为了开发者、终端厂商以及运营商共同关注的重要课题。

为了降低流量并提高网络性能,可以从优化心跳机制及数据获取过程两方面着手:

1. 优化心跳机制

不同类别应用的心跳周期存在差别,而同一类别下不同应用的心跳周期也不尽相同。

根据测试,某终端待机底电流为4.9mA,后台同时运行微信、QQ、飞信这三个典型即时通信应用,55分钟待机时间内有47次心跳包,心跳间隔不均匀,平均心跳包间隔70s,平均待机电流22mA,接近待机底电流的5倍。

智能终端普遍会同时运行多个应用,由于各应用独立发送心跳包,导致心跳包非常密集,从而带来终端电量和流量的大量消耗。

心跳一方面影响终端的功耗,更对运营商的网络存在影响。下图是一次业务心跳导致的信令交互过程,空闲状态时的业务心跳包触发终端发起服务器请求过程,引起随机接入→安全模式→无线资源重配→无线链路释放等过程。

4.6 业务心跳信令交互流程示意图

 

单用户同时有多应用程序在后台运行时,每个应用业务都各自维护心跳包,导致心跳包间隔相对单应用来说大大缩短。假设应用业务心跳包间隔60s,则每60s单用户发送8条RRC信令,占用12-16次物理下行链路控制信道(PDCCH),占用5-8次物理混合ARQ指示信道(PHICH),至少占用一次随机接入信道(PRACH)。以下是关于信道承载能力的分析:

计算基于如下现网常用配置:20M系统带宽,上下行配比3DL:1UL,特殊时隙配比10:2:2,PCFICH取值3,PHICHNg参数取值1/6,PRACH配置为10ms一个PRACH资源,公共preamble个数配置为52。

1) PDCCH:以平均聚合等级为4估算,10ms内可用PDCCH个数为6(常规子帧)*21+2(特殊子帧)*13=152个,则每秒能够承载的PDCCH个数为15200次,每60秒能够承载的PDCCH个数为912000次。

2) PRACH:每10ms共有1次PRACH资源,每PRACH资源可复用52个用户,不考虑冲突,则每秒支持用户数为5200,每60s支持用户数为312000。

3) PHICH:PHICH组复用用户数按最大值8估算,则每子帧支持PHICH用户数为24,则每秒支持用户数为4800,每60s支持用户数为288000。

此外频繁的心跳包还可能导致终端一直处于RRC连接态,耗费系统的PUCCH(CQI、SR)、SRS等资源,导致系统容量下降,同时也会导致终端耗电增加。

智能终端各类软件所引发的无线信令流量是传统非智能终端的10倍以上,这进一步增加了智能手机产生的信令。同时,必然会影响终端与网络之间的空中接口的信令处理能力,那么一旦信令信道发生拥塞,就会导致空口资源的调度失控。这时即便空口资源是空闲的,终端也无法使用。也很容易引发雪崩效应,当终端申请不到空口资源或链接不上网络就会不断重试,导致信令信道更加拥塞。对用户来说,这将会导致用户掉话率提高、发送消息延迟、甚至无法接听拨打电话。

绝大多数移动应用都是通过TCP长连接来进行Push消息的,TCP长连接存活,消息Push就及时。

为了保证接收消息的及时性,当APP处于前台活跃状态时,建议使用统一的固定心跳。而当应用进入后台时,建议使用不同于前台运行时的周期更长的心跳策略。通常情况下,建议在后台自适应计算心跳周期,根据自身产品的特点和当前的网络环境选择合适的心跳范围。

1) 统一心跳包的发送

理论上即时通讯类应用所需的心跳周期是最短的,当前即时通讯类应用心跳周期在4min左右。

建议将最小需求4min作为基础周期,各应用心跳包发送周期设置为基础周期的整数倍,如8min、12min,如此基本满足大多应用需求。以终端上的时钟为参考系,当分针指向0、4、8、…56时,需要发送心跳的应用将心跳包统一发送。

2) 优化心跳包发送周期

用户可根据需求自主选择心跳发送周期,允许用户在省电、及时等多个场景间切换。根据网络环境、用户使用情况试探性地动态调整发送周期,如从4分钟试探调整至8分钟、12分钟、16分钟。终端休眠时应用的心跳发送周期应延长,如调整至亮屏状态时的二倍。

2. 优化数据获取

在获取数据的过程中,建议的优化策略包括:

1) 连接复用。通过如开启keep-alive的方式节省建立时间。对于Android来说默认情况下HttpURLConnection和HttpClient都开启了keep-alive。

2) 请求合并。即将多个请求合并为一个进行请求。

3) 减小请求数据大小。为了减小请求数据的大小,可以尝试使用对请求头进行压缩的方式。而对于POST请求,Body也可以做Gzip压缩。

4) CDN缓存静态资源。缓存常见的图片、JS、CSS等静态资源。

5) 减小返回数据大小。为了减小返回数据的大小,一般可以采用对返回数据进行压缩的方式。另外使用JSON代替XML、WebP代替其他图片格式等精简数据格式的方式也可以减小返回数据的大小。对于不同的设备及不同的网络环境要有区别地返回内容:如不同分辨率的图片。需要数据更新时,可以考虑增量更新,如常见的服务端进行bsdiff,客户端进行bspatch。

6) 数据缓存缓存获取的数据在一定的有效时间内再次请求可以直接从缓存读取。

除上述几种方法,预连接、预取数据以及建立多连接的方式均可有效提高网络性能。分优先级,将不重要的请求延迟,既可以削减峰值并减少并发,又可以与后面的请求进行合并。

4.5 更优的交互设计

 

APP内容的加载时间往往是影响用户满意度的重要因素。内容加载时间主要取决于用户所在的网络环境,而通过良好的交互设计尤其是加载页面的设计,可以有效降低用户的等待感,让用户“不烦躁”地等待。

1. 用非模态的加载方式

尽量使用非模态的加载方式,就是加载的过程是不打断用户,不需要等待加载完就可以进行其他操作,如下示意:


图4.7 模态加载与非模态加载

用非模态的加载方式,用户可以利用做其他事情来打发等待的时间,而不用一直等待数据加载完成,大大降低了等待的焦躁感。即便是模态的加载,也要给一个取消的选项,当用户不耐烦的情况下可以取消。

2. 情趣化的加载动画

加载的过程如此枯燥乏味,有创意的设计师们可以设计了各种有创意的加载动画。这些加载动画让等待的过程变成了一种享受,用户能感受到设计师的情怀,体会新鲜有趣的等待过程。提升了产品情趣化的设计语言,让等待的焦躁感一扫而空。

3. 漫长加载告知进度

如果是时间较长的加载过程,最好能清晰的告知过程进度,这时候就需要采用有进度的加载设计。浏览器的进度条是一种较为常见的进度告知设计,通过这个进度告知,让用户有了更加明确的知情权,也能更好的预期到加载完成的时间。

4. 尽量提前加载

尽可能的利用预加载或有WiFi的情况下离线缓存的方式,把内容提前加载下来,这样能做到最大限度的降低加载给用户带来的卡顿感。如果能判断出来用户下一步要做的事情,提前帮用户加载相应的内容,肯定是最符合需求场景的事情。

4.6 其他注意点

1. 注意避免发生ANR问题

ANR: Application Not Responding,即应用无响应。为了尽量避免ANR错误,在编码上有以下三点建议:

1) UI线程尽量只做跟UI相关的工作,避免在主线程(UI线程)上进行复杂耗时的操作,比如说进行大量的计算/操作数据库/读写文件等。这类复杂耗时的操作可以通过使用AsyncTask或者使用多线程来实现。

2) BroadCastReceiver要进行复杂操作时,可以在onReceive()方法中启动Service来处理。

3) 在设计及代码编写阶段避免出现同步/死锁或者错误处理不恰当等情况。

2. 避免过度绘制

1) 太多重叠的背景:检查在布局和代码中设置的背景,有些背景是被隐藏在底下而永远不可能显示。这种没必要的背景一定要移除,因为它很可能会严重影响到APP的性能。

2) 太多重叠的view:必要的时候尽可能动态地加载布局,只有用到重叠的view的时候才进行加载,推迟加载的时间,而不是所有的都通过SetVisiblity函数来控制。

3) 复杂的Layout层级:添加到应用中的每一个控件和布局文件都需要经过初始化、排列位置和绘制三个过程,因此使用嵌套的线性布局可能导致布局层级变得十分冗余。复杂的布局,既会提高我们的设计难度,也会降低代码效率,因此,不妨多使用一下相对布局。建议使用HierarchyViewer工具来分析和优化布局,要尽量减少布局中的枝叶,减少父母层级,避免过深的布局层级。

3. 避免空指针

空指针引起的原因主要有调用空对象的方法、访问或更新空对象的变量、获取空集合的长度、访问或更新空集合中的内容、抛出空的Throwable对象、同步空对象等。为避免空指针,应当在使用之前确保对其做了适当的初始化。

 

五、千万别忽视安全

2015年,中国移动互联网用户数已突破9亿。随着移动互联网的高速发展,智能手机、平板电脑以及智能穿戴设备等已经充斥了人们的生活,移动应用迅速覆盖了包括出行就餐、日常起居、金融理财等各个领域。

然而凡事有利有弊,Android漏洞、APP安全早已饱受诟病。2015年第二季度,工业和信息化部组织对40余家手机应用商店的应用软件进行技术检测,发现存在问题的应用软件达80款,涉及违规收集用户个人信息、恶意扣费、强行捆绑推广其他无关应用软件等问题。安全性成为了用户选择APP的重要参考条件。

5.1 保护用户的数据

与iOS相比,Android提供了一种开放的环境,在获得了灵活性、可以满足各种定制需求的同时,也损失了部分安全性。APP开发团队通常将精力集中在产品设计、功能实现、用户体验和系统效率等,而忽略了安全问题,导致数据存储以及通信过程中存在漏洞,给恶意攻击者们留下了可乘之机。

1. 数据存储安全

APP的存储区域分为外部(SD卡)和内部(NAND闪存)两种。除了大小和位置不同之外,两者在安全权限上也有很大的区别。外部存储的文件没有读写权限的管理,所有应用软件都可以随意创建、读取、修改、删除位于外部存储中的文件,仅仅需要申明READ_EXTERNAL_STORAGE和WRITE_EXTERNAL_STORAGE权限。内部存储则为每个软件分配了私有区域,并有基于Linux的文件权限控制,其中每个文件的所有者ID均为Android为该软件设立的一个用户ID。通常情况下,其他软件无权读写这些文件。

为了保护用户存储数据的安全,有以下建议可供参考:

1) 避免将数据明文保存在外部存储

APP可能将系统数据及用户数据存储在外部存储(SD卡)上。当这些数据是直接明文保存的,攻击者可以对这些数据进行读取,造成隐私信息泄露。若恶意软件读取了系统数据则可能会展开进一步的攻击。

更好的处理方法是对这些数据进行加密,相对敏感的信息如密码保存在内部存储,由系统托管或者由用户使用时输入。

2) 将软件运行时依赖的数据保存在内部存储

若软件将配置文件存储在SD卡上,然后在运行期间读取配置文件,根据其中数据进行工作,攻击者编写的软件可以修改这些配置文件,从而控制软件的运行。

对于此类配置文件,更为安全的方法是保存到内部存储;如果必须存储到SD卡,则应在每次使用前判断它是否被篡改,如与保存在内部的文件哈希值进行匹配。

3) 将软件安装包或者二进制代码保存在内部存储或使用前进行校验

部分软件会推荐用户下载并安装其他软件:用户点击后,会下载另一个软件的apk,保存到SD卡然后安装。有一些软件为了实现功能扩展,选择动态加载并执行二进制代码。如果在安装或加载前,该部分数据被篡改或伪造,就会出现安全问题。攻击者可以使用“重打包”(re-packaging)方法加入恶意代码、改变软件的数据或指令,而软件原有功能和界面基本不会受到影响,用户难以察觉。

为了避免此类问题,软件应该在安装或加载位于SD卡的任何文件之前,对其完整性做验证,判断其与实现保存在内部存储中的(或从服务器下载来的)哈希值是否一致。

4) 内部文件避免全局可读写

使用openFileOutput(Stringname, int mode)方法创建内部文件时,若第二个参数设为Context.MODE_WORLD_READABLE或Context.MODE_WORLD_WRITEABLE,就会让这个文件变为全局可读或全局可写的。攻击者编写的恶意软件也将拥有这一权限。

如果要跨应用共享数据,一种较好的方法是实现一个Content Provider组件,提供数据的读写接口,并为读写操作分别设置一个自定义权限。5) 避免内部敏感文件被root权限软件读写

在引进SEAndroid安全机制之前,一旦手机被root,用户获得了su权限,就可以对系统文件和其他应用进行操作。Android 5.0版本全面启用了Android系统安全强化套件,SEAndroid (Security-Enhanced Android),将Linux上的MAC强制访问控制套件SELinux移植并增加安全功能到Android平台上。在SEAndroid中,每一个进程和文件都会关联一个安全上下文,由用户、角色、类型、安全级别四个部分组成。系统管理员基于安全上下文制定安全访问策略,用来规定什么样的进程可以访问什么样的文件。在这种体系的限制下,进程只能访问那些在其任务中所需文件,恶意APP即使篡得了较高的Root权限,仍然被安全访问策略有限的控制着而不能为所欲为。

6) 在配置文件中android:allowBackup配置为false

Android系统提供了为APP数据的备份恢复功能,其开关决定于AndroidManifest.xml文件中的allowBackup属性的值,默认为true。当allowBackup标志为true时,用户即可通过adbbackup和adb restore来进行对应用数据的备份和恢复,这可能会带来一定的安全风险:adb backup容许任何一个能够打开USB调试开关的用户从Android手机中复制应用数据到外设,一旦应用数据被备份之后,所有应用数据都可被用户读取;adb restore容许用户指定一个恢复的数据来源(即备份的应用数据)来恢复应用程序数据的创建。攻击者可通过adb backup和adb restore进行恢复新安装的同一个应用来查看聊天记录等敏感信息。

因此,除非非常有必要,开发者应将allowBackup属性值设置为false,从而关闭应用程序的备份和恢复功能,以免造成信息泄露和财产损失。

2. 组件通信安全

Android系统包含四类组件:Activity、Service、Broadcast receiver和Content provider。前三种组件使用intent相互调用.

下面是组件间通信时应注意的安全事项:

1) 最小化组件暴露

不参与跨应用调用的组件添加android:exported="false"属性,这个属性说明它是私有的,只有同一个应用程序的组件或带有相同用户ID的应用程序才能启动或绑定该服务。

2) 设置组件访问权限

参与跨应用调用的组件或者公开的广播、服务设置权限,设置权限时,组件添加android:permission属性并且声明属性,调用组件者声明

3) 运行时权限检测

Android提供各种 API 来在运行时检查、执行、授予和撤销权限。这些API是android.content.Context 类的一部分,这个类提供有关应用程序环境的全局信息。可以调用Context类的checkCallingOrSelfPermission方法在运行时验证权限是否获取成功。

3. 网络通信安全

1) 加密传输敏感数据

最危险的是直接使用HTTP协议登录账户或交换数据。如攻击者在自己设置的钓鱼网络中配置DNS服务器,将软件要连接的服务器域名解析至攻击者的另一台服务器;这台服务器就可以获得用户登录信息,或者充当客户端与原服务器的中间人,转发双方数据。

这类问题的解决方法是对敏感数据采用基于SSL/TLS的HTTPS进行传输

2) SSL通信检查证书有效性

移动软件大多只和固定的服务器通信,因此可以在代码中更精确地直接验证是否某张特定的证书,这种方法称为“证书锁定”(certificatepinning)。实现证书锁定的方法有两种:一种是实现X509TrustManager接口,另一种则是使用KeyStore。

3) 安全使用WebView

如果程序不需要直接调用JavaScript,不应调用setJavaScriptEnabled(),使用addJavaScriptInterface()时应特别小心,推荐只暴露给自己apk内部的JavaScript。

4. 服务器数据安全

如今网络安全环境异常严峻,几乎每年都有知名互联网厂商服务器端暴露出安全性问题,造成了大量用户信息的泄露,甚至直接影响了用户的经济利益。为了保护服务器端的数据安全,通常可采取以下办法:

1) 定时检查服务器工作状态

定时检查服务器的网络连接状况、定时检查服务器操作系统运行状况、定时检查服务器系统日志、定时检查磁盘剩余空间以确保有充足的空间存储数据。

2) 合理设计备份

通过合理设计备份工作为数据带来较高的安全性保障,一旦其中一个硬盘发生故障,仍可通过备份硬盘读出有效数据。数据备份记录也要做好,以便恢复时使用。记录里面应包含:备份时间点、备份保存、备份方法、备份工具、操作人员、备份完成时间、备份检测、备份开始时间等。

3) 删除不必要的软件并停止不必要的服务

删除在服务器上的不需要的软件并停止不必要的服务,从而减少黑客攻击的机会。

4) 开启强密码保护

要尽量以最小的权限来执行管理任务。同样,具有管理员权限的其他所有账户,即是使用密码策略也仍需强制执行强密码保护。

5) 应用防火墙

由于大多数服务器都是需要连接到整个互联网的,所以应使用防火墙限制外部访问服务器所在的局域网。

6) 及时更新补丁

即使服务器没有连接到互联网,仍然要保证软件系统的更新。可以通过网络上的另一个服务器运行服务器更新策略服务来完成。

5.2 代码安全

对于需要保护代码的Android客户端应特别注意代码安全,如保护技术难点、核心代码等。目前代码安全主要依靠代码混淆、Dex加壳、so加固等技术。

1. 代码混淆

Android上的APP绝大部分是使用Java语言开发,编译时会编译成Dalvik字节码(即dex文件),运行时由Android自带的Dalvik虚拟机解释执行。由于Java开发的APP很容易被逆向破解,目前市面上已有的Java程序反编译工具有baksmali、jd-gui、apktool等。为防止APP被逆向破解,最常见方法是代码混淆。

2. 注意开发工具的安全

开发者应使用正版的开发工具并通过正规渠道获取SDK,防止所开发的APP被人为加入后门,给用户和开发者带来较大的风险。

3. 正规的证书

开发者应使用正规的、带有开发者身份信息的证书对APP进行签名。

4. 自校验加固

为APP添加运行时的校验机制,在用户首次打开APP时进行自校验,判断apk是否已被攻击者篡改。若存在被篡改的情况,则主动提示用户卸载软件。

5.3 权限安全

当手机用户在对某APP进行下载、更新甚至使用时,常常会遇到要求用户向APP开放各类手机权限的情形,而其中经常包括用户通讯录、短信、相册、地理位置等涉及用户隐私的权限。关于用户手机涉及的隐私权限众多,Android平台所涉及的隐私权限达30多项,而每个应用厂商对于权限的定义都不同。

应用在开发之时应声明其将会调用的最少必要功能组,对于没有声明过的调用,应用软件不得调用,对于不需使用的功能,应用软件不得声明。

客户端应向用户清晰明确地对需调用的基础权限进行提示。

1. 提示框标题要求

使用积极和热情的提示语对话框标题,“温馨提示”或“欢迎使用XX客户端”。

2. 权限使用提示内容要求

每项权限要求作为一条单列,并在向用户要求某项权限前,说明能给用户带来的作用、影响等。提示语应清晰、明确,不能出现“可能”等模糊词语。

3. 隐私保护申明要求

申明清晰明了,推荐使用“没有经过用户的允许,本软件绝对不会收集用户的各种隐私数据,也不会泄漏用户的个人信息。”方式。

4. 用户确认操作要求

在用户可见区域设置不再提醒选项。

涉及用户隐私的特殊权限(通讯录、短信、位置信息等)在用户使用到具体功能时再进行提示授权,用户确认后可使用,不确认则不再使用该功能。

对于可能造成费用或有大量流量产生情况,应主动对用户进行“二次确认”

六、用新技术给用户提供更多

 

移动终端产品与时俱进,已成为普罗大众眼中高新科技的代言词,也渐渐成为大众日常使用的最具科技感的个人电子设备。寄托着用户的期待,移动终端产品有义务、有能力也有需要将时下的新技术与新概念带给广大群众,并充分整合已有的最新资源,为用户提供更多。

6.1 充分发挥终端的各项能力

 

每次Android新版本升级,除了增加新的特性,还会伴随着一件事,就是将原来只有系统有的能力开放给了开发者,开发者可以用这些新特性/能力来建设不一样的应用。

以Android5.0为例:

1. Material Design

在Android 5.0的宣传中强调最多的一个亮点就是Material Design,从设计语言来讲,这个特点是能在将整个素材铺平的同时还遵循一定的物理材质的需求。这样的设计可以让应用感觉更活泼、具有更丰富的颜色,有无处不在的阴影,以及动画效果更真实等等。

2. Fingerprint Support

这项功能允许用户进行指纹解锁设备或进行购买支付操作,所有开发者都可以通过API把指纹识别功能接入到自己的APP中。这对Android Pay的安全性提供了十分重要的支持。

6.2 混合式应用

 

对于快速更迭的移动互联网来说,应用模块的持续更迭、致命问题的修复,无疑都需要重新进行应用的发布及审核。此时,开发一个基于原生应用+web网页方式的混合式移动应用无疑是个不错的选择。

1. Web与原生系统交互

使用Android浏览器对象LoadUrl,addJavaScriptInterface等方法实现WebView与原生类的绑定时,实现前端JS与后端Java类的数据交互。可以将功能简单但会频繁更新的一部分业务考虑使用网页来实现,最后在Android应用中嵌入网页。

2. 挖掘HTML5的潜力

目前HTML5规范已集成了打电话、发短信、拍照、通信、缓存、webSql等一系列新的本地功能调用API,使用此类API,将会大大降低开发难度,提升开发效率,并从用户角度上感觉与原生应用并无差距。

3. 使用联调测试

采用混合应用进行产品开发的另一个好处是可以分开进行开发测试,最终进行联调测试。Web网页测试调试时的consle.log同样也会输出在Android调试窗口LogCat中,对于CSS样式的测试,建议使用chrome手机版,配合终端上的远程调试工具,如Weinre,可以在PC上实时更改手机上对应网页的元素、样式表,或是查看JavaScript变量,同时还可以看到手机上页面的错误和警告信息。

同时建议开发者在开发时使用响应式布局框架,避免在PC上开发完成后运行在终端的效果大相径庭。

6.3 多形态终端与智能穿戴

 

工业和信息化部发布报告,截至2015年3月底,中国移动电话用户总数达到12.9亿。截至2015年底,智能手机用户数有望突破6亿大关。智能穿戴产品的广阔市场将使其成为智能终端发展的另一个重要方向,也将成为各大终端厂商以及互联网厂商热血厮杀的新的主战场。根据第三方市场报告分析,2015年及2016年智能穿戴产品发展趋势如下图所示:

6.1 智能穿戴产品发展趋势预测

随后两年,智能穿戴产品的销量将成指数增长,2016年全年销量预计可达6000万以上,且基于中国这一广阔市场基础,将持续其迅猛的发展势头。层出不穷的可穿戴产品在中国以及全世界范围内引领了消费者对可穿戴设备的认知程度。

6.2 消费者对智能穿戴产品的认知程度

对智能穿戴产品的认知度在随着时间提高的同时也伴随着年轻化与高端化,25到39岁的消费者鉴于其对新技术良好的接受能力及乐于尝新的生活态度,成为了智能穿戴产品最主要的消费人群。

相比于手机,智能穿戴产品在信息输入输出过程中显得更加不便。目前主流的解决方式有两种:一、配合手机等产品使用,将输入及信息展示功能交给手机客户端,智能穿戴产品利用其集成的各类传感器主要负责信息收集功能,通过蓝牙等通信技术将所收集的信息传输至智能手机,智能手机对数据进行处理后,以友好全面的方式呈现给用户;二、如Apple Watch,其为穿戴产品设计了更为简单的操作模式,通过设置简单的按钮及手势降低了操作难度并减少误操作。在文字输入过程中采用语音输入等方式极大提高了信息输入的便捷性。

另外,由于智能手环及智能手表等产品的尺寸较小,无法装载较大的电池,其较短的待机时间也是亟待解决的问题。目前解决该问题一方面要依赖穿戴产品本身的优秀的电源管理,另一方面要依赖特殊设计的产品架构,将采集的原始数据或简单加工的数据在需要时传输至智能手机或云端服务器,由智能手机或服务器端完成相关运算。

广大用户群体对于智能穿戴产品各项功能的着重点存在不同,各个不同的年龄段更是泾渭分明,如图6.3:年轻人更加注重穿戴产品与智能手机产品的协同功能,而中老年则更偏好于健康。如16到24岁的年轻人相对更在意蓝牙通话功能以及来电/短信提醒功能,并不在意监测体温/血压/血糖,而该项正是30岁以上人群更在意的功能点。以上都是智能穿戴产品及其APP开发过程中所需要考量的重要因素。


6.3 不同年龄段消费者对智能穿戴产品功能偏好

智能穿戴产品及各种多形态终端承载着用户的需求,将在不远的将来全方位地覆盖人们生活的健康、医疗、交通、饮食等各个领域,协同物联网及云技术的成熟发展,形成无处不在、无所不能的智能生态体系。APP作为其生态体系中的重要一环,承担着举足轻重的责任,也必然会为用户带来生活各方面的便捷与革命。

七、结束语

 

移动互联网的用户是网络运营商的用户,是终端厂商的用户,也是移动应用的用户。终端、应用与网络平台形成一个闭环,相互配合共同为用户提供优秀的移动互联网使用体验。中国移动通信集团终端有限公司持续以来致力于成为联接三者的纽带,加强运营商、终端厂商与应用厂商的互助与信息互通,携手为用户创造更加丰富多彩的移动生活。

 



线