Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android BLE proximity notifications

I've been working on developing an application that interacts with BLE devices. Everything works great, I can scan, connect, and consume services.

I've been reading through all the docs and I do not see anything that gives the developer the option of listening for BLE devices. Basically I would like to trigger a broadcast receiver when the devices enters the range of a BLE device.

I know I could continually scan for this, but battery use is way too high and I would like this to be invoked even when my application is not being used.

Is this feature not supported or am I missing a section of the docs that discuss this?

like image 703
Bobbake4 Avatar asked Jul 22 '14 18:07

Bobbake4


2 Answers

I have done a project recently, and from what I read in your question it has some similarity to what I did.

I know I could continually scan for this but battery use is way too high and I would like this to be invoked even when my application is not being used.

Regarding battery problem, having Bluetooth on all the time is power consuming, but at the same time you can not detect BLE with out having Bluetooth on.

What I did is two experiments and both are useful but are different and I can not say which one is best, but you need to test it so it fits your requirement.

  1. Having Thread running that turns Bluetooth on and listen to iBeacon and off (with sleeping time) for while programmatically. It can be done many ways.

  2. Using a package called Altbeacon, has a lot of useful features, one of those features is Auto Battery Saving with example code:

    public class MyApplication extends Application implements BootstrapNotifier {
        private BackgroundPowerSaver backgroundPowerSaver;
    
        public void onCreate() {
            super.onCreate();
            // Simply constructing this class and holding a reference to it
            // in your custom Application class
            // enables auto battery saving of about 60%
            backgroundPowerSaver = new BackgroundPowerSaver(this);
        }
    }
    

We need a broadcast event, that wakes up our app once a BLE-device with a certain Service-UUID is in reach. Maybe now there is a better BLE API available than 2 years ago. The most energy saving and most precise method gets rewarded.

Your other part, it is called triggering actions at a specific distance. I still use the Altbeacon to check beacon range and triggering action. A sample code is something like

@Override
public void didRangeBeaconsInRegion(Collection<Beacon> beacons, Region region) {
    for (Beacon beacon : beacons) {
        if (beacon.getDistance() < 5.0) {
            Log.d(TAG, "I see a beacon that is less than 5 meters away.");
            // Perform distance-specific action here
        }
    }
}

So when that said, you can also get distance of specific UUID I build a method based on Altbeacon, looks like this (Look inside the for loop and if statement):

private void startRangeNotifier() {
    Log.i(TAG, "Starting range notifier...");
    beaconManager.setRangeNotifier(new BeaconRangeListener() {
        @Override
        public void didRangeBeaconsInRegion(Collection<Beacon> beacons, Region region) {

            if (beacons.size() > 0) {
                for (Beacon beacon : beacons) {
                    Log.d(TAG, "uuid's: " + beacon);
                    Log.d(TAG, "uuid id1: " + beacon.getId1());
                    if (beacon.getId1().toString()
                            .equals("b9407f30-f5f8-466e-aff9-25556b57fe6d")) {
                        Log.d(TAG, "uuid id1 distance: " + beacon.getDistance());
                    }
                }

            }
        }
    });

    try {
        beaconManager.startRangingBeaconsInRegion(
                new Region(BEACON_MONITORING_ID, null, null, null));
    } catch (RemoteException e) {
        e.printStackTrace();
    }
}

My log output:

D/Main activity:: uuid's: id1: b9407f30-f5f8-466e-aff9-25556b57fe6d id2: 31807 id3: 59251
D/Main activity:: uuid id1: b9407f30-f5f8-466e-aff9-25556b57fe6d
D/Main activity:: uuid id1 distance: 0.2108658568686884

In my answer I wanted to present the concept I used, Beacons project need patience in general. As the other answer mentioned it is also possible to combine the solution here with Geofences and ActivityRecognition.

Note: Since the nature of bluetooth beacon, the distance is proximity and not absolute, and some time even the bluetooth beacon is 1 meter a way it might show 2 meter or 0.5 meter, so have that in mind

Link reference:

  • https://altbeacon.github.io/android-beacon-library/distance-triggering.html
  • https://altbeacon.github.io/android-beacon-library/samples.html
  • https://altbeacon.github.io/android-beacon-library/eddystone-how-to.html
  • https://github.com/AltBeacon/android-beacon-library-reference
like image 93
Maytham Avatar answered Sep 21 '22 00:09

Maytham


BLE scanning on Android is pretty battery intensive, and it's definitely not something you want to do in the background all the time. If you are working on a background application with stationary bluetooth devices (à la ibeacons) that you know the location of, you can use Geofences to turn scanning on and off when you think you are in the approximate proximity of a device. If you are not careful geofencing can also drain battery.

If you don't know the location of your bluetooth devices I guess you can also play tricks with ActivityRecognition, i.e only scan periodically when the user is walking and stopping it if the user is stationary/running/biking/in vehicle. Again, the activity recognition stuff also takes battery so you are going to have to be judicious.

like image 32
James Avatar answered Sep 22 '22 00:09

James