# iOS 上的 VOIP 应用，如何能够更省电？

- 作者：shallon
- 发布时间：2012-02-29 18:30
- 分类：公司
- 原文：https://www.ifanr.com/75641

[![](https://s3.ifanr.com/wp-content/uploads/2012/02/132.jpg "1")](https://s3.ifanr.com/wp-content/uploads/2012/02/132.jpg)

近日在网上看到一个文章，介绍 iPhone、Android 上的热门的 VOIP 应用 Viber ，曰：

> 它可以完全运行在后台，且不会耗电，即便是不运行在后台，你照样可以拨打免费电话和发免费短信。

应该说，这些说法从技术上看并不严谨。首先，从这段文字能得到一个模糊的印象，一个在后台运行的程序，并且不会耗电；其次，“程序即便是不运行在后台，照样可以拨打免费电话和发短信”，这如何理解呢？程序运行在前台能否拨打免费电话？程序压根不运行时能否拨打电话？

VOIP 应用是一种必须实现为“多任务”的业务，这种业务通常是耗电的大户。因此这段文字背后引出其中一个有趣的技术问题，智能设备上的多任务的业务如何能够“不会耗电”？

让我们先看看智能手机上的电池电量限制与多任务需求的关系。

**智能手机上电池电量限制与多任务需求**

智能手机与桌面电脑的根本区别在于智能手机本身的硬件尺寸与电池电量大小，电池电量对智能手机来说是关键而致命的限制，人们要求手机越来越轻薄，功能越来越强大，然而待电时间却要求越来越长，这不是“又要马儿跑又要马儿不吃草”的事情么！为此，智能手机上的电池电量正如沙漠中的水，一点一滴都不可以浪费。

为了节约电池的电量，智能手机上的操作系统的一个基本策略是，尽量减少正在运行的程序，这个道理很简单，运行的程序越多，需要耗费的 CPU 计算时间就越多，电量就省不下来。下面的图是苹果 iOS 设备应用程序调度状态图，事实上苹果设备是除了用户正在操作的程序，其他打开的程序进程尽可能都放到“挂起（Suspended）”的状态下。在“挂起”的状态下面，程序进程处在休眠状态，不耗费 CPU 计算能力。当用户没有对设备进行操作的时候，整个系统处在休眠的低电状态。（这里进程的意思是：程序运行实例）

[![high&#95;level&#95;flow](https://s3.ifanr.com/wp-content/uploads/2012/02/high_level_flow_thumb.jpg)](https://s3.ifanr.com/wp-content/uploads/2012/02/high_level_flow.jpg)

 智能手机上的 VOIP，作为一种多任务型的业务，却恰恰踩在耗电的雷区上。VOIP 类的应用需要实现为多任务原因是需要维持应用应用与服务器之间的长期的网络连接，当网络侧的来电呼叫到达的时候，提示用户进行接听。因此程序有“长期存活”的“待机”需求，后台长期存活的程序仅仅能处在“后台（Background）”的状态下面，这个状态下的程序进程，需要耗费 CPU 计算能力和电量。为何叫做“多任务”型的业务呢，意思是由于此业务的存在，除了用户交互的程序进程，还存在另外的“存活”进程。

**苹果 iOS 设备的 VOIP 实现**

正是由于对程序耗电量的锱铢必较，苹果公司曾经拒绝实现“真正”的多任务，使用“快速程序切换”来缓解用户对大部分“多任务”的需求，如今，相信苹果的研发团队是在做了艰难的平衡之后，决定允许**部分业务**实现为“多任务”。这些业务主要是上文提到的后台的音乐播放、后台的 GPS 定位服务、新闻订阅业务的后台定期更新、VOIP 应用等等，并为后台业务实现提供严格的开发指引。VOIP类的业务正是苹果公司强制管理的一种“多任务”业务，如果开发团队不遵守架构限制，软件将不能通过审核和在苹果应用商城上发布，而 Viber，在 iOS 平台上，应该是遵循了该架构。

让我们来看看苹果公司为VOIP实现，这种架构下如何可能达到省电的目标。

下面描述的文字非开发指引，仅仅为了帮助理解 VOIP 应用进程的调度过程（需要一定的软件开发背景来理解）：

1、VOIP 应用需要在 Info.plist 里配置 UIBackgroundModes 的值为 “VOIP” ，告知系统，此乃 VOIP 应用。

2、程序配置用于 VOIP 业务的网络连接（Socket），告知系统，在程序进程被调度到“挂起（Suspended）”状态时该特殊的网络连接需要被系统接管，因此，此时网络连接仍然是活动的。当网络连接有新的数据到达的时候，程序将从“挂起（Suspended）” 状态被唤醒到“后台 （Background）”状态，如果是个来电事件，VOIP应用则发起一个本地提醒事件，此时用户可以在设备的界面上看到来电提醒，如果用户选择接听来电，则 VOIP 应用被调度到前端的“活动 （Active）”状态直接与用户交互，否则，回退到低电的“挂起（Suspended）”状态。下图可以看到左图是传统的 VOIP 应用，在“待机”状态下整个程序都运行在耗电的“后台 （Background）”状态，右图是苹果的 VOIP 实现，仅仅网络连接运行在耗电的“后台 （Background）”状态。其余系统部分运行在低电的“挂起（Suspended）”状态。

[![image](https://s3.ifanr.com/wp-content/uploads/2012/02/image_thumb2.png)](https://s3.ifanr.com/wp-content/uploads/2012/02/image2.png)

3、安装 Keep-Alive 的处理函数维持与服务器端的长连接。VOIP应用将被周期性从“挂起（Suspended）”状态调度到“后台 （Background）”，使 Keep-Alive 的处理函数能够定期向网络服务器发送“心跳”的网络包。

[![power-saving2](https://s3.ifanr.com/wp-content/uploads/2012/02/power-saving2_thumb.png)](https://s3.ifanr.com/wp-content/uploads/2012/02/power-saving2.png)

总结：在 iOS 实现的 VOIP 方案中，应用进程可以看作两部分，一部分是需要系统内核看管的网络连接和系统的定期唤醒服务，另一部分是 VOIP 的程序逻辑，在 VOIP 的状态下，后一部分被放到了低电的“挂起（Suspended）”状态，最少的使用了 CPU，因此可以达到省电的效果。

**为何能够更省电**

然后，回到关于Viber的问题，如何“程序即便是不运行在后台，照样可以拨打免费电话和短信”？据考究，实际上应为“**即便程序不运行，照样可以接听电话和短信**”。原因是，拨打电话和短信，肯定必须有用户的交互操作，程序只能处在“活动（Active）状态”，不可能是不运行的。根据Viber的网站的资料，Viber 使用了苹果的 APNs（Apple Push Notification Service）功能，当用户有电话拨入或者短信发送过来的时候，此时才加载 Viber 应用。APNs 服务是一种 Apple 公司的网络端服务，用来向苹果设备推送消息，通常也用来实现邮件推送等功能。

![A remote notification from a provider to a client application](https://developer.apple.com/library/mac/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Art/remote_notif_simple.jpg)

当然，使用 APNs 的方式提醒用户来电和短信，可以更加省电，在“待机”期间，Viber 程序可以根本没有运行，仅仅当有来电和短信的时候借用了系统提供的 APNS 服务来唤醒和加载应用。

**终极的省电方式**

当然，无论如何优化，这种 VOIP 应用相比起传统语音实现来说仍然是耗电的，因为整个系统（智能手机的 AP 部分）不能休眠。在是传统的非 VOIP 话音业务中，如果没有来电和用户操作，整个系统是休眠的，仅仅是基带芯片（智能手机的 CP 部分）在工作，负责维护与电信运营商基站的连接，这无疑是最省电的一种工作方式。

题图来自 [socialbarrel](http://socialbarrel.com/viber-now-has-50mn-users-on-android-and-ios-devices/32248/)
