react-native-beacons-manager icon indicating copy to clipboard operation
react-native-beacons-manager copied to clipboard

Beacon notification is always showing in Android

Open phoenix377 opened this issue 4 years ago • 7 comments

Version

1.4.9

Platform

Android

OS version

android 9

Steps to reproduce

  1. install react-native-beacons-manager
  2. open your app
  3. close your app

Expected behavior

No beacons notification.

Actual behavior

Beacons notification is active all the time even if I close my app or if I don't use 'react-native-beacons-manager' (like 'startMonitoringForRegion') in app's code.

screenshot

phoenix377 avatar Sep 23 '19 14:09 phoenix377

While you're scanning, that thing will appear there. You can avoid it by scanning at an interval. (check WhatsApp's live location sharing implementation).

iamandiradu avatar Sep 23 '19 15:09 iamandiradu

@iamandiradu Issue is that it's appearing though you are not scanning. Beacon notification is active all the time even if I close my app or if I don't use 'react-native-beacons-manager' (like startMonitoringForRegion) in app's code.

phoenix377 avatar Sep 23 '19 15:09 phoenix377

I recognize the "Scanning for Beacons" string from @ newoceaninfosys fork. I also made a fork after that fork (double fork?) and implemented a toggle logic for the Beacon Service. I can provide an usage example tomorrow, if it's not too late.

(look at startBeaconService and stopBeaconsService in the sources for Android)

iamandiradu avatar Sep 23 '19 17:09 iamandiradu

@iamandiradu That will be great if you can provide it tomorrow. Thanks.

phoenix377 avatar Sep 23 '19 17:09 phoenix377

componentDidMount() {
    this._beaconsInit();
}

_beaconsInit = async () => {
    // function that checks is Bluetooth and Location services are enabled
    const proximityCapabilities = await this._proximityCapabilities();
    if (this.props.beaconsEnabled && proximityCapabilities) {
        // Beacons listener
        this.beaconEnterListener = Beacons.BeaconsEventEmitter.addListener(
            'regionDidEnter',
            data => this._beaconListener(data));

        if (Platform.OS === 'ios') {
            // iOS cold start listener
            this.beaconMissedListener = Beacons.BeaconsEventEmitter.addListener(
                'onMissedBeacon',
                data => {
                    if (data) {
                        this._beaconListener(data);
                    }
                },
            );
            // iOS on cold start tends to send the beacon event before the JS is loaded, thus 'missing' the beacon
            // I've added in the library a method that stores the beacon data if no listener is attached and send it when getMissedBeacon is called
            Beacons.getMissedBeacon();
        }

        this._startBeaconService();
    } else {
        this.props.disableBeacons();
        this._stopBeaconService();
    }
}

_startBeaconService = (toggled = false) => {
    if (Platform.OS === 'ios') {
        Beacons.allowsBackgroundLocationUpdates(false);
        this._monitorForRegions(false);
        Beacons.startUpdatingLocation();
        // Adds the listener in case the service was toggled and was not initiated on app start
        if (toggled) {
            this.beaconEnterListener = Beacons.BeaconsEventEmitter.addListener(
                'regionDidEnter',
                data => this._beaconListener(data));
        }
    } else {
        // Start the fresh service
        Beacons.addIBeaconsDetection()
            .then(() => Beacons.startBeaconService(toggled))
            .then(() => this._monitorForRegions(false))
            .catch(error => {
                console.warn('Error at Service start: ' + error);
            });
    }
};
_stopBeaconService = (toggled = false) => {
    if (Platform.OS === 'android') {
        this.beaconsServiceDidConnect && this.beaconsServiceDidConnect.remove();
        Beacons.removeIBeaconsDetection().catch(error =>
            console.warn(`Something went wrong during Beacon detection removal: ${error}`),
        );
    } else {
        Beacons.allowsBackgroundLocationUpdates &&
            Beacons.allowsBackgroundLocationUpdates(false);
        Beacons.startUpdatingLocation && Beacons.stopUpdatingLocation();
    }

    this._monitorForRegions(true);
    this.beaconEnterListener && this.beaconEnterListener.remove();
    if (Platform.OS === 'android') {
        Beacons.stopBeaconService(toggled)
            .then()
            .catch(error => {
                console.warn('Error at Service stop: ' + error);
            });
    }
};
_beaconListener = data => {
    const detectedBeacon =
        R.filter(beacon => beacon.id === Number(data.identifier), this.props.beacons)[0] ||
        false;
    const detectedBeaconTag = this.props.beaconTags[detectedBeacon.tag];

    console.log(detectedBeacon); /* do something with the detected beacon */
};
_monitorForRegions = (stop = false) => {
    R.forEach(eachRegion => {
        const generatedRegion = {
            identifier: `${eachRegion.id}`,
            uuid: eachRegion.beaconId,
        };
        // Monitor for beacons inside the region
        if (!stop) {
            Beacons.startMonitoringForRegion(generatedRegion)
                .then()
                .catch(error => {
                    console.warn(`Beacons monitoring not started: ${error}`);
                });
        } else {
            Beacons.stopMonitoringForRegion(generatedRegion)
                .then()
                .catch(error => console.warn(`Beacons monitoring not stopped: ${error}`));
        }
    }, this.props.beacons); // an object that contains our registered beacons
    /* 
    "beacons": [
        {
            "id": 1,
            "tag": "tag1",
            "beaconId": "8323fff7-82fa-4e74-a7dd-cc5fe64f7461",
        },
    ],
    "beaconTags": {
            "tag1": {
            "title": "title 1",
            "message": "message 1"
        },
    ]
    */
};

_proximityCapabilities = async () => {
    const bluetoothEnabled = await BluetoothStatus.state();
    const locationEnabled = await SystemSetting.isLocationEnabled();
    return bluetoothEnabled && locationEnabled;
}

What you need in order for that permanent notification to dismiss is to call stopBeaconService() and pass 'true' if the service was active on app launch and toggled later.

This happens because @newoceaninfosys started the notification channel/service in the init function of the library, so I just split it in 2 methods: start and stop. :)

iamandiradu avatar Sep 24 '19 06:09 iamandiradu

@iamandiradu What version of RN are you using? I am using RN 0.60 and not finding the beacons.

ielonclesio avatar Oct 13 '19 15:10 ielonclesio

@ielonclesio, also 0.60.

iamandiradu avatar Mar 04 '20 10:03 iamandiradu