背景
在移动端应用使用中,iOS或者Android设备通常作为客户端和服务器通讯,当应用打开时就去连接服务器获取数据显示操作页面。由服务器确保server的稳定性,设备端做异常断连的重连。
但最近的物联网项目中,需要移动端作为server,提供服务给服务器端使用。服务器端来主动连接移动端设备。
问题
移动端由于具有可交互性,用户可能会手动退出程序,此时服务就会不稳定。
用户的异常操作通常有以下几种:
- 退出应用
- 直接退回桌面
- 直接锁屏
异常操作下socket的工作情况
测试使用的server由dart来实现:juejin.cn/post/717388…
| 平台 | 模式 | 操作 | 服务情况 | |
|---|---|---|---|---|
| iOS | release | 关掉 | 断开 | |
| 锁屏 | TCP 服务会立即断开 | |||
| 后台 | TCP 服务会工作一段时间,后断开 | |||
| debug | 关掉 | 断开 | ||
| 锁屏 | TCP 服务会工作一段时间,后断开 | |||
| 后台 | TCP 服务会工作一段时间,后不处理消息 | |||
| Android | release | 关掉 | 断开 | |
| 锁屏 | TCP 服务会工作一段时间,后不处理消息 | |||
| 后台 | TCP 服务会工作一段时间,后不处理消息 | |||
| debug | 关掉 | 断开 | ||
| 锁屏 | TCP 服务正常工作 | |||
| 后台 | TCP 服务正常工作 |
分析
通过上表我们可以发现,程序在进入后台后,一段时间都不会正常操作,我们需要移动端程序在进入前台后,重启服务。 但没做测试之前我的理解是:程序在进入前台是判断一下socket有没有存在,没存在则重启一下服务。我的判断方法是:
- 判断socket是否为空。这种没有效果,因为程序里面写了socket断开后会先置空,后重启,正常情况下不会为空,异常情况下置空的代码不会执行
- 判断socket的clien是否为空。这种也没有效果,理由与1一样,异应用挂起后,置空的代码不会执行 由此,还是在程序进入前台时重启一些程序会比较稳定有效
还有一种方案是,程序进入前台后尝试给client发送一次消息,收到发送异常则重启server.这种方式可以保证程序短时间进入后台,再次进入前台不重启server
此外注意建立server和client的双向心跳机制,最大保证服务的稳定性
如何判断程序锁屏
Flutter 的 WidgetsBindingObserver可监听程序是否进入后台前台但不能判断是锁屏进入后台还是Home键进入后台。
尝试的测试方法有:
- 可以判断屏幕亮度,后台屏幕亮度不为0,锁屏后亮度为0。不能解决Home键后,再锁屏的操作。
- 通过文件的读写权限,创建一个NSFileProtectionCompleteUnlessOpen权限的文件,当app进入后台时来进行读写,读写失败表明处于锁屏,否则表明未锁屏。锁屏后权限未生效,此方法不可用
- iOS使用系统回调,iOS,Android未测试
- (void)applicationProtectedDataWillBecomeUnavailable:(UIApplication *)application
{
}
- (void)applicationProtectedDataDidBecomeAvailable:(UIApplication *)application
{
}