如何在 React Native 应用程序的 iOS 后台运行 socket.io?
Posted
技术标签:
【中文标题】如何在 React Native 应用程序的 iOS 后台运行 socket.io?【英文标题】:How to run socket.io in the background on iOS in a React Native app? 【发布时间】:2016-05-29 06:23:28 【问题描述】:我在ios React Native(v0.20) app
中使用socket.io
。该应用程序跟踪我的位置,当我的位置发生变化时,它会向服务器发出一条消息。如果套接字连接丢失,服务器会发送一封电子邮件通知我。
我在后台使用react-native-location 进行位置跟踪,但我无法让socket.io
工作。每当我更改应用程序或关闭屏幕时,应用程序会一直跟踪我的位置,但我会失去套接字连接。
有没有办法像位置跟踪一样在后台运行socket.io
?除此之外,是否有一些本机代码可以让我在后台维护client/server connection
?
我知道有一个WebSocket alternative,但我看不到让它在后台运行的方法。
更新:
我仔细检查了我的Info.plist
,它已经为react-native-location 设置了必要的背景值。我不知道这是否重要,但套接字工作和位置跟踪是在同一个组件中完成的。
LocationComponent.js
window.navigator.userAgent = 'react-native';
const io = require('socket.io-client/socket.io');
const socket = io(url, jsonp: false);
import React, Text, View, DeviceEventEmitter from 'react-native';
import RNLocation from 'NativeModules';
export default GeolocationExample = React.createClass(
componentDidMount: function()
RNLocation.requestAlwaysAuthorization();
RNLocation.startUpdatingLocation();
RNLocation.setDistanceFilter(3.0);
DeviceEventEmitter.addListener('locationUpdated', locationObject =>
this.props.newPosition( longitude: locationObject.coords.longitude, latitude: locationObject.coords.latitude );
);
,
render: function()
const lastPosition, distance = this.props;
socket.emit('newPos', longitude: lastPosition.longitude, latitude: lastPosition.latitude, distance, time: Date() );
return (
<View>
<Text> distance </Text>
</View>
);
);
【问题讨论】:
在 iOS 和 android 上的行为是否相似,还是仅限 iOS 的问题? 我没试过安卓。这是我的第一个 React Native 应用程序,我想专注于为 iOS 构建,以便可以在手机上使用它。 您找到解决方案了吗? @ChrisAndersson 不,我没有。我能找到的最好的建议是构建一个包,它将我需要运行的 javascript 与可以运行它的本机代码连接起来。我实际上还不知道该怎么做。 @EasilyBaffled 我发现了这个,但还没有让它工作。 gist.github.com/liamzebedee/67e1b2c53c6c5edcf8ec 【参考方案1】:你不可能以“正确的方式”做到这一点。
编辑
来自 Apple 的official documentation:
实现长时间运行的任务
对于需要更多执行时间来执行的任务,您必须 请求特定权限以在后台运行它们,而无需 他们被停职。在 iOS 中,只允许特定的应用类型 在后台运行:
在后台向用户播放可听内容的应用, 比如音乐播放器应用
在游戏中录制音频内容的应用 背景
让用户随时了解其位置的应用 时间,例如导航应用程序
支持互联网协议语音 (VoIP) 的应用程序
需要定期下载和处理新内容的应用
从外部配件接收定期更新的应用
实现这些服务的应用必须声明它们所使用的服务 支持和使用系统框架来实现相关方面 那些服务。声明服务让系统知道哪个 您使用的服务,但在某些情况下,它是系统框架 实际上可以防止您的应用程序被暂停。
话虽如此,有一种工作技术可以让你的套接字保持打开:
播放静音并将背景模式设置为音频。检查this article 以获取有关此事的更多信息(它有点旧但仍然有效)。这将允许您保持您的套接字打开假装音频应用程序。您的 info.plist 应该更新以允许音频在后台运行。
UIBackgroundModes
应该设置为audio
(查看docs了解更多信息)
【讨论】:
我已经在后台运行位置检查。正如我所展示的,我在 info.plist 中设置了它。那不应该已经解决了吗?【参考方案2】:iOS 对when an app is backgrounded 允许的进程类型有相当的限制。
socket.io 客户端issue tracker 上似乎有一些讨论。
如果将后台模式设置为audio
,似乎有人让套接字连接保持活动状态。 YMMV
确保您在 Info.plist 文件的 UIBackgroundModes 部分中设置了正确的值。 How to do this in XCode
【讨论】:
我已经在 Info.plist 中为react-native-location
设置了值,正如我在问题中提到的,位置跟踪有效。我在问题中添加了一张 Info.plist 值的图片。【参考方案3】:
我知道有一些技巧可以完成这项工作(即audio
hack),但 iOS 不允许在后台长时间运行任务是有原因的 - 请重新考虑您的设计以提供更好的产品。
使用日志运行任务会耗尽电池。如果您需要数据更新,请注册以使用 Apple 推送服务获取推送通知(如果您直接进行,或者这是我上次处理类似问题,则它是免费的)。
具体来说,位置跟踪是允许的后台系统服务,请考虑为此使用本机 API。
至于将数据推送到服务器,您将无法(并且可能不应该)与服务器保持长期的连接。
考虑每隔一段时间收集数据并将收集的批次上传到服务器 - 最好在重新打开应用时进行,这样您就不会在后台浪费资源,也不会让人们对电池寿命和数据消耗感到不安。
【讨论】:
目前我不担心电池寿命。在我先有一个应用程序的工作示例之后,我宁愿解决这个问题。该应用程序的重点是分享实时更新的赛车手,每个人都需要不断交流。如果我等太久才报告跑步者的位置,那么每个人都会失败。 您不必担心,但 Apple 是在设计 API 时,因此存在限制......也许赛车手可以将应用程序保持在前台。 虽然这在基础级别上有效,但远非理想。当我跑步时,我会打开音乐并关闭手机屏幕,因此我无法将应用程序留在前台。【参考方案4】:在你的Info.plist图片中,它只允许以下三个background modes:
后台获取
位置更新
远程通知
您应该允许“音频和 AirPlay”模式,并且看起来像“应用程序使用 Airplay 播放音频或流式传输音频/视频”。
【讨论】:
以上是关于如何在 React Native 应用程序的 iOS 后台运行 socket.io?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 IOS 中从我的 React-Native 应用程序打开外部应用程序?
如何在 React-Native 应用程序中检索 iOS 状态栏高度?
可下载内容如何在 iOS 的 react-native 应用程序中工作?