Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to run socket.io in the background on iOS in a React Native app?

I am using socket.io in an iOS React Native(v0.20) app. The app tracks my location, and when my position changes it emits a message to a server. If the socket connection is lost the server sends an email to notify me.

I have the location tracking working in the background with react-native-location, but I can't get socket.io to work. When ever I change apps or turn off the screen, the app keeps tracking my location but I lose the socket connection.

Is there a way to run socket.io in the background like location tracking ? Short of that is there some native code that will allow me to maintain a client/server connection while in the background?

I know there is a WebSocket alternative but I can't see a way to get it to run in the background.

UPDATE: I doubled checked my Info.plist, it has the necessary background values set already for react-native-location. I don't know if it matters but the socket work and location tracking are done in the same component.

enter image description here

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>
    );
  }
});
like image 612
EasilyBaffled Avatar asked Feb 17 '16 13:02

EasilyBaffled


People also ask

Is it possible to run a React Native app in the background?

React Native background service library for running background tasks forever in Android & iOS. Schedule a background job that will run your JavaScript when your app is in the background or foreground.

Does socket IO work on iOS?

Socket.IO is a framework that makes it easy to implement Socket and the available for iOS, Android, back-end and front-end. In this article you will find some code in Swift (iOS) and Javascript (Web) for implementing the client and NodeJS for implementing the back-end.

How do I get the React Native app to work in the background?

In React Native, performing a task in the background might seem daunting at first. It is not as simple as writing a function in JavaScript, where the function is executed even after the activity is killed. Instead, React Native uses Headless JS to execute JavaScript code in the background.

Can socket IO be used with React Native?

You need to use socket. io-client on the react-native client side of things. The latest version of socket.


3 Answers

There is no way you can do this "the right way".

Edit

From Apple's official documentation :

Implementing Long-Running Tasks

For tasks that require more execution time to implement, you must request specific permissions to run them in the background without their being suspended. In iOS, only specific app types are allowed to run in the background:

Apps that play audible content to the user while in the background, such as a music player app

Apps that record audio content while in the background

Apps that keep users informed of their location at all times, such as a navigation app

Apps that support Voice over Internet Protocol (VoIP)

Apps that need to download and process new content regularly

Apps that receive regular updates from external accessories

Apps that implement these services must declare the services they support and use system frameworks to implement the relevant aspects of those services. Declaring the services lets the system know which services you use, but in some cases it is the system frameworks that actually prevent your application from being suspended.

This being said, there is a working technique exist to keep your socket open :

Play a silent sound and set the background mode to audio. Check this article for more information on the matter (it's a bit old but still valid). This will allow you to keep your socket open faking an audio app. Your info.plist should be updated to allow audio to run in the background. UIBackgroundModesshould be set to audio (check the docs for more information)

like image 119
G. Hamaide Avatar answered Sep 22 '22 02:09

G. Hamaide


iOS is fairly restrictive on the kind of processes it allows when an app is backgrounded.

There seems to be some discussion around this on the socket.io client issue tracker.

It seems someone got the socket connection to remain active if they set the background mode to audio. YMMV

Make sure you're setting the correct values in the UIBackgroundModes section of the Info.plist file. How to do this in XCode

like image 25
frank Avatar answered Sep 20 '22 02:09

frank


I know there are hacks to get this done (i.e. the audio hack), but there's a reason iOS doesn't allow long running tasks in the background - please rethink your design to allow a better product.

Using log running tasks will deplete the battery. If you need data updates, register to get push notifications using the Apple push service (it's free, if your doing it directly, or it was last time I dealt with a similar issue).

Location tracking, specifically, is an allowed background system service, consider using the native API for this.

As to pushing the data to the server, you won't be able to (and probably shouldn't) maintain a long lasting connection with the server.

Consider collecting data and uploading to the server the collected batch every once in a while - preferably when the app is reopened, so you don't waste resources in the background and get people upset about their battery life and their data consumption.

like image 31
Myst Avatar answered Sep 23 '22 02:09

Myst