- Notifications
You must be signed in to change notification settings - Fork38
Android library scanning BLE beacons nearby with RxJava
License
pwittchen/ReactiveBeacons
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
Current Branch | Branch | Artifact Id | Build Status | Maven Central |
---|---|---|---|---|
RxJava1.x | reactivebeacons | |||
☑️ | RxJava2.x | reactivebeacons-rx2 |
This isRxJava2.x branch. To see documentation for RxJava1.x, switch toRxJava1.x branch.
Android library scanning BLE (Bluetooth Low Energy) beacons nearby with RxJava
Library was tested with Estimote and Kontakt beacons.
This library has limited functionality, but its API is simple:
ReactiveBeacons(context)booleanisBleSupported()booleanisBluetoothEnabled()booleanisLocationEnabled(context)booleanisAtLeastAndroidLollipop()voidrequestBluetoothAccess(activity)voidrequestLocationAccess(activity)Observable<Beacon>observe()Observable<Beacon>observe(ScanStrategyscanStrategy)
JavaDoc is available at:http://pwittchen.github.io/ReactiveBeacons/RxJava2.x
min SDK = 9, but if you are using API level lower than 18, don't forget tocheck BLE support on the device.
- Usage
- Good practices
- Examples
- Compatibility with different Android versions
- Beacon class
- Filter class
- Download
- Tests
- Code style
- Static code analysis
- References
- License
InitializeReactiveBeacons
object:
privateReactiveBeaconsreactiveBeacons;@OverrideprotectedvoidonCreate(BundlesavedInstanceState) {reactiveBeacons =newReactiveBeacons(this);}
Create subscribtion:
privateDisposablesubscription;@OverrideprotectedvoidonResume() {super.onResume();if (!reactiveBeacons.isBleSupported()) {// optional, but recommended step// show message for the user that BLE is not supported on the devicereturn; }// we should check Bluetooth and Location access here// if they're disabled, we can request access// if you want to know how to do it, check next sections// of this documentation and sample appsubscription =reactiveBeacons.observe() .subscribeOn(Schedulers.computation()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(newConsumer<Beacon>() {@Overridepublicvoidcall(Beaconbeacon) {// do something with beacon } });}
Unsubscribe subscription inonPause()
method to stop BLE scan.
@OverrideprotectedvoidonPause() {super.onPause();if (subscription !=null && !subscription.isDisposed()) {subscription.dispose() }}
Please note: Library may emit information about the same beacon multiple times. New emission is created everytime when RSSI changes. We can distinguish several beacons by their MAC addresses withbeacon.device.getAddress()
method.
Add<uses-feature .../>
tag inside<manifest ...>
tag inAndroidManifest.xml
file in your application if you support Android devices with API level 18 or higher. You can skip this, if you are supporting lower API levels.
<uses-featureandroid:name="android.hardware.bluetooth_le"android:required="true" />
Check BLE support if you are supporting devices with API level lower than 18.
if (!reactiveBeacons.isBleSupported()) {// show message for the user that BLE is not supported on the device}
If BLE is not supported, Observable emitting Beacons will be always empty.
UserequestBluetoothAccess(activity)
method to ensure that Bluetooth is enabled.If you are supporting devices with API level lower than 18, you don't have to request Bluetooth access every time.
if (!reactiveBeacons.isBluetoothEnabled()) {reactiveBeacons.requestBluetoothAccess(activity);}
Since API 23 (Android 6 - Marshmallow), Bluetooth Low Energy scan, requiresACCESS_COARSE_LOCATION
orACCESS_FINE_LOCATION
permissions.Moreover, we need to enable Location services in order to scan BLE beacons. You don't have to worry about that if your apps are targeted to lower APIs than 23.Nevertheless, you have to be aware of that, if you want to detect beacons on the newest versions of Android. Read more at:https://code.google.com/p/android/issues/detail?id=190372. UserequestLocationAccess(activity)
method to ensure that Location services are enabled. If you are supporting devices with API level lower than 18, you don't have to request Location access every time.
if (!reactiveBeacons.isLocationEnabled(activity)) {reactiveBeacons.requestLocationAccess(activity);}
Since Android M (API 23), we need to request Runtime Permissions.If we want to scan for BLE beacons, we need to request forACCESS_COARSE_LOCATION
orACCESS_FINE_LOCATION
permission.For more details, check sampleapp
.
With API methods, we can create the following code snippet:
privatebooleancanObserveBeacons() {if (!reactiveBeacons.isBleSupported()) {Toast.makeText(this,"BLE is not supported on this device",Toast.LENGTH_SHORT).show();returnfalse; }if (!reactiveBeacons.isBluetoothEnabled()) {reactiveBeacons.requestBluetoothAccess(this);returnfalse; }elseif (!reactiveBeacons.isLocationEnabled(this)) {reactiveBeacons.requestLocationAccess(this);returnfalse; }elseif (!isFineOrCoarseLocationPermissionGranted() &&Build.VERSION.SDK_INT >=Build.VERSION_CODES.M) {requestCoarseLocationPermission();returnfalse; }returntrue;}
You can adjust this snippet to your needs or handle this logic in your own way.
After that, we can perform the following operation:
if(canObserveBeacons()) {// observe beacons here}
Exemplary application is located inapp
directory of this repository.
If you want to know, how to use this library with Kotlin, checkapp-kotlin
sample.
BLE scanning is available from Android 4.3JELLY_BEAN_MR2
(API 18).You can use this library on lower versions of Android, but you won't be able to scan BLE devices,you should handle that situation in your app and notify user about that. SeeGood practices section.Since Android 5.0LOLLIPOP
(API 21), we have different API for BLE scanning.That's why this library has two different BLE scanning strategies:
PreLollipopScanStrategy
used for pre-Lollipop devices (from API 18 to 20)LollipopScanStrategy
used for Lollipop devices (API 21 or higher)
Library automatically chooses proper strategy withisAtLeastAndroidLollipop()
method,which checks version of the system installed on a device and uses selected strategy inObservable<Beacon> observe()
method from the library.Moreover, you can force using one of the existing strategies or your own custom scanning strategywith the following method available in the library:
Observable<Beacon>observe(ScanStrategyscanStrategy)
ScanStrategy
is an interface with the following method:
Observable<Beacon>observe();
Beacon
class represents BLE beacon and has the following attributes:
BluetoothDevicedevice;intrssi;byte[]scanRecord;inttxPower;
All of the elements are assigned dynamically, buttxPower
has default value equal to-59
.It works quite fine for different types of beacons.
Beacon class has alsogetDistance()
method, which returns distance from mobile device to beacon in meters andgetProximity()
method, which returnsProximity
value.
Proximity
can be as follows:
IMMEDIATE
- from 0m to 1mNEAR
- from 1m to 3mFAR
- more than 3m
Beacon class has also staticcreate(...)
method responsible for creating Beacon objects.
Filter
class provides static filtering methods, which can be used with RxJavafilter(...)
method inside specific subscription.
Currently the following filters are available:
proximityIsEqualTo(Proximity)
proximityIsNotEqualTo(Proximity)
distanceIsEqualTo(double)
distanceIsGreaterThan(double)
distanceIsLowerThan(double)
hasName(String)
hasMacAddress(String)
Of course, we can create our own custom filters, which are not listed above if we need to.
Exemplary usage
In the example below, we are filtering all Beacons withProximity
equal toNEAR
value.
reactiveBeacons.observe() .filter(Filter.proximityIsEqualTo(Proximity.NEAR)) .subscribe(newConsumer<Beacon>() {@Overridepublicvoidcall(Beaconbeacon) {beacons.put(beacon.device.getAddress(),beacon);refreshBeaconList(); } });
You can depend on the library through Maven:
<dependency> <groupId>com.github.pwittchen</groupId> <artifactId>reactivebeacons-rx2</artifactId> <version>0.6.0</version></dependency>
or through Gradle:
dependencies { compile'com.github.pwittchen:reactivebeacons-rx2:0.6.0'}
Tests are available inlibrary/src/test/java/
directory and can be executed without emulator or Android device from CLI with the following command:
./gradlew test
Code style used in the project is calledSquareAndroid
from Java Code Styles repository by Square available at:https://github.com/square/java-code-styles. Currently, library doesn't have checkstyle verification attached. It can be done in the future.
Static code analysis runs Checkstyle, FindBugs, PMD and Lint. It can be executed with command:
./gradlew check
Reports from analysis are generated inlibrary/build/reports/
directory.
- Bluetooth Low Energy on Wikipedia
- android-bluetooth-demo repository
- Converting callbacks to RxJava Observables
- Transmission power range and RSSI
- What are Broadcasting Power, RSSI and other characteristics of beacon's signal?
- Estimating beacon proximity/distance based on RSSI - Bluetooth LE
- RSSI (Received Signal Strength Indication) on Wikipedia
- Specification for Eddystone, an open beacon format from Google
- Bluetooth Low Energy on Android Developer Guide
- Beacons/BLE
- Bluetooth
Copyright 2015 Piotr WittchenLicensed under the Apache License, Version 2.0 (the "License");you may not use this file except in compliance with the License.You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0Unless required by applicable law or agreed to in writing, softwaredistributed under the License is distributed on an "AS IS" BASIS,WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.See the License for the specific language governing permissions andlimitations under the License.
About
Android library scanning BLE beacons nearby with RxJava