react-native-ble-plx: can't make background mode work

My app is supposed to send a message to a specific BLE device when that device is in range. Ideally this should work even when the app is closed/in background mode. I used the simplest restoreStateFunction I could think of: it just makes a fetch request to an endpoint on my server. However, this is never called once the app goes to background. I created a sample repo to quickly replicate the problem, and here’s the relevant code. Tested on android/ios, debug/release and nothing works. Any idea about what I’m doing wrong?

Also, I only want the app to be turned on only if a specific device is in range, and I see this is configured only in startDeviceScan. Will the background mode take this into account, or the app will be turned on anytime a new ble device is in range?

import React from 'react';
import {BleManager} from "react-native-ble-plx";
import {PermissionsAndroid, Platform} from 'react-native';

export class BleComponent extends React.PureComponent {
    constructor() {
        super();
        if (Platform.OS === 'android') {
            PermissionsAndroid.request(PermissionsAndroid.PERMISSIONS.ACCESS_COARSE_LOCATION)
                .then(granted => {
                    if (granted !== 'granted') {
                        console.log('BLUETOOTH denied')
                    }
                    else {
                        this.initializeManager();
                    }
                })
        } else {
            this.initializeManager();
        }

    }

    initializeManager() {
        this.manager = new BleManager({
            restoreStateIdentifier: 'testBleBackgroundMode',
            restoreStateFunction: bleRestoredState => {
                fetch('http://restoreStateFunctionWasCalled.com')
            }
        });
        const subscription = this.manager.onStateChange((state) => {
            if (state === 'PoweredOn') {
                this.scanAndConnect();
            }
        }, true);
    }

    scanAndConnect() {
        console.log(('scan and connect'));
        this.manager.startDeviceScan(["0000fefb-0000-1000-8000-00805f9b34fb"], null, (error, device) => {
            if (error) {
                console.log(("BLE error"));
                return
            }
            console.log(device);
        });
    }

    render() {
        return null;
    }
}

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Reactions: 3
  • Comments: 17 (2 by maintainers)

Most upvoted comments

@7772 It’s great to hear form you that it’s worked. Even to put correct serviceUUID it doesn’t work. Can you please make a proper documentation on background mode os scan and can share, I think it will be help ful for lot of people. That will be grateful though 😃 Or someone can say it never work 😦

I have trouble on scanning device on background, but solved it.

  1. make sure turn on background mode on Xcode.
  2. make sure that properly pass service uuids parameter in startDeviceScan

I noticed what I should do after reading on this

The problem is the difference in scanning in foreground and background. 
When you are scanning for devices in the foreground you can scan for anything. 
In the background you must specify the actual service UUID you are scanning for. 
Ok, this isn't actually a problem as you know the UUID you are looking for.

@adyanced Well mostly it is a job of this library 😃

On iOS background mode is tricky. Just adding special permission in XCode project allows you to do background work. There is one special case when system is taking control of your BLE connection and kills your application. Restoration function is used to allow to restore your BLE state after application relaunch (when user is going to foreground after long period in background mode). Personally I only tested if connection is kept in this situation. You can simulate this behaviour by sending SIGKILL signal to your iOS process from lldb debugger.

1). That’s probably a bug which should be fixed. 2). I didn’t test scanning functionality. Would love contributions. 3). react-native-ble-plx gives base64 to user because it is the only way to send binary data between native code and JS. There were attempts to add support for ArrayBuffer, but I guess it wasn’t implemented in RN.

@good-illy There is no easy solution, until apple changes its policies. The only option is reverse engineering, as described here: https://crownstone.rocks/2018/06/27/ios-advertisements-in-the-background

Did any one get the solution for connecting and scanning bluetooth device in background for iOS app? @grigored @adyanced @Cierpliwy @konradrodzik

@grigored I think what you want is not a job of react-native-ble-plx. I only need ble scanning in the background. But after a half day’s test, I’m considering to turn to another ble project because of three reasons:

  1. react-native-ble-plx always lose first several notification data chunks, but another one not. I reported this issue which makes it unusable for me.
  2. react-native-ble-plx can only scan 25 minutes in the background, but that one can scan so long as app is live.
  3. react-native-ble-plx gives base64 data to user, but that one transmits binary array. It means a little bit more faster cause I have about 3000 notification bytes after connected. Anyway react-native-ble-plx is still a awesome project.