As shown in title, my socket server will determine my react native app is 'dead' when my device is on lock screen or background.
What are the solution to these?
With the help of Headless JS, Native Modules, and WorkManager, it is fairly easy to create and run JavaScript tasks in React Native. In this article, we covered from beginning to end setting up and running Headless JS in React Native Android, allowing us to run tasks in the background of our application.
The latest version of socket. io-client 2.2. 0 does not work with React-Native currently apparently, so you need to install and use version 2.1.
React Native also supports WebSockets, a protocol which provides full-duplex communication channels over a single TCP connection.
After doing some reading online, the reason my socket server will determine my react native app is 'dead' is because all of the javascript code inside my app has stopped working when my device is locked or in background.
Therefore, i have figured out a solution to solve this problem.
Tools i have used:
My client side code:
import React, {useEffect, useRef} from 'react';
import {AppState} from 'react-native'
export default () => {
const appState = useRef(AppState.currentState);
var interval
const _handleAppStateChange = (nextAppState) => {
if (
appState.current.match(/inactive|background/) &&
nextAppState === "active"
) {
console.log("App has come to the foreground!");
//clearInterval when your app has come back to the foreground
BackgroundTimer.clearInterval(interval)
}else{
//app goes to background
console.log('app goes to background')
//tell the server that your app is still online when your app detect that it goes to background
interval = BackgroundTimer.setInterval(()=>{
console.log('connection status ', socket.connected)
socket.emit('online')
},5000)
appState.current = nextAppState;
console.log("AppState", appState.current);
}
useEffect (() => {
AppState.addEventListener("change", _handleAppStateChange);
return () => {
AppState.removeEventListener("change", _handleAppStateChange);
};
},[])
}
My Server side code:
io.on('connection',(socket)=>{
socket.on('online',()=>{
//do nothing
})
}
)
This solution works on my app. Now socket will not disconnect until i close the app or click disconnect button.
Although Jin Tan's answer worked for me and my socket connection remained stable, the process that I was using over the socket connection got shutdown (react-native-webrtc).
I used the ForegroundService Library to keep both the socket as well as the webrtc transport active. The combined code is as follows:
import VIForegroundService from '@voximplant/react-native-foreground-service';
import BackgroundTimer from 'react-native-background-timer';
_handleAppStateChange = (nextAppState) => {
if (this.state.appState.match(/inactive|background/) && nextAppState === 'active') {
console.log('App has come to the foreground!')
// clearInterval when the app comes back to the foreground
BackgroundTimer.clearInterval(interval)
}else{
// app goes to background
console.log('app goes to background')
// tell server that the app is still online when app goes to background
interval = BackgroundTimer.setInterval(()=>{
console.log('connection status ', socket.connected)
this.socket.emit('online')
},5000)
this.setState({appState: nextAppState});
console.log("AppState", this.state.appState);
}
}
async configureForeground(){
if (Platform.Version >= 26) {
const channelConfig = {
id: 'CallNotification',
name: `Active Call Notification`,
description: 'Active calls will be shown using this notification',
enableVibration: false,
importance: 1
};
await VIForegroundService.createNotificationChannel(channelConfig);
}
const notificationConfig = {
id: 3456,
title: 'title',
text: 'text',
icon: 'ic_notification',
priority: 1
};
if (Platform.Version >= 26) {
notificationConfig.channelId = 'voiceCallNotification';
}
await VIForegroundService.startService(notificationConfig);
}
ic_notification is an image "ic_notification.png" in all the mipmap-xxxx folders.
You can call configureForeground() to start the notification. To end the foreground service in componentWillUnmount:
AppState.removeEventListener('change', this._handleAppStateChange);
try{
VIForegroundService.stopService();
}catch(err){
// do nothing if service was never started.
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With