├── .github └── ISSUE_TEMPLATE.md ├── .gitignore ├── CHANGELOG.md ├── Docs ├── DOC_deviceConnection.md ├── DOC_monitoring_after_restart.md ├── DOC_monitoring_scanning.md ├── DOC_multiadvertisers.md ├── DOC_telemetry.md ├── DOC_thirdPartyLicenses.md ├── manual_installation.md ├── quick_snippets.md └── switching_to_1.0.0.md ├── LICENSE └── README.md /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## Prerequisites 2 | 3 | * [ ] Put an X between the brackets on this line if you have done all of the following: 4 | * My Android device/devices supports BLE and has Android OS version >= 4.4 5 | * My Android device/devices have Bluetooth enabled 6 | * My app has Location Permissions granted 7 | 8 | ## Basic information 9 | 10 | **Estimote SDK version:** [Paste here the SDK version that you are using (like `1.4.1`)] 11 | 12 | **Android devices affected:** [Paste here your Android device model/models that you are having problems with.] 13 | 14 | **Android OS version affected:** [Android OS version (ex. `Oreo 8.0.0`)] 15 | 16 | **Beacon hardware version:** [Paste here your beacons hardware version (you can check that in Estimote Cloud).] 17 | 18 | ## Description 19 | 20 | [Description of the issue] 21 | 22 | **(Optional) Steps to reproduce:** 23 | 24 | 1. [First Step] 25 | 2. [Second Step] 26 | 3. [and so on...] 27 | 28 | **Expected behavior:** [What you expect to happen] 29 | 30 | **Actual behavior:** [What actually happens] 31 | 32 | ## Logs and code 33 | ``` 34 | Add here any logs, stack traces, code snippets you want to attach, or any other info, like pictures for example 35 | ``` 36 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # IntelliJ IDEA 2 | .idea 3 | *.iml 4 | classes 5 | out 6 | 7 | # Gradle 8 | .gradle 9 | build 10 | local.properties 11 | gen 12 | 13 | # Mac 14 | .DS_Store 15 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | Changelog 2 | ===================== 3 | ## 1.4.5 (Aug 2, 2018) 4 | Maintenance release - Fix generic advertisers cloud synchronization issue 5 | 6 | ## 1.4.4 (26 Jun, 2018) 7 | Maintenance release. 8 | 9 | ## 1.4.2 (26 Jun, 2018) 10 | Maintenance release. 11 | - Added compatibility for new Proximity SDK. 12 | 13 | ## 1.4.1 (Dec 20, 2017) 14 | Maintenance release. 15 | - Fixed scanning on Android 7+ 16 | - Fixed scanning on devices without low power scanning features (batch scanning, hardware filters) 17 | - Fixed NPE on scanning start 18 | 19 | ## 1.4.0 (Oct 24, 2017) 20 | - Mesh Management - Mesh Gateway is now able to synchronize mesh's asset tracking report from beacons in to cloud. 21 | 22 | ## 1.3.0 (Sep 22, 2017) 23 | - Mesh Management - Mesh Gateway beta version 24 | 25 | ## 1.2.0 (Sep 08, 2017) 26 | - Push start UWB commands into mesh when connecting to the beacon 27 | - Add possibility to set up 'start UWB' command on cloud for beacons in mesh 28 | - Fix: Make it possible to set 20dBm as transmit power value when configuring advertiser 29 | 30 | ## 1.1.0 (Aug 22, 2017) 31 | - Enable Magnetometer: Synchronize Magnetometer calibration data from cloud. 32 | - FIX: Use millivolts as battery voltage level unit 33 | - FIX: EstimoteLocation - changed timestamp to be public 34 | 35 | ## 1.0.15 (Aug 16, 2017) 36 | - Revert buggy implementation for: Use average advertising time to calculate expiration time when ranging beacons 37 | 38 | ## 1.0.14 (Aug 14, 2017) 39 | - Use average advertising time to calculate expiration time when ranging beacons 40 | - Add timestamp field to all packets parsed from scanner 41 | - FIX: Ensure Here and now are synchronized to beacons with firmware 4.7.0 or newer 42 | - FIX: Use proper sdk version when communicating with cloud 43 | 44 | ## 1.0.13 (Aug 08, 2017) 45 | - Bug fix: Use region exit expiration timeout defined by the user instead of default value 46 | - Cleanup SDK manifest to make it easier to use SDK in non-java-gradle android projects 47 | - Cleanup SDK resources to make it easier to use SDK in non-java-gradle android projects 48 | 49 | ## 1.0.12 (Aug 01, 2017) 50 | - Bug fix: Ensure SDK is able to connect to the beacon without mesh network configured 51 | - Bug fix: Hardware filter for BeaconRegion for Nougat devices 52 | 53 | ## 1.0.11 (Jul 26, 2017) 54 | - Bug fixes 55 | 56 | ## 1.0.10 (Jul 21, 2017) 57 | - Add "Here and Now" feature support. Now, "Here and Now" related settings are synchronized from Cloud in to the beacon. 58 | - Synchronize GPIO settings from Cloud. 59 | - Make it possible to reflect GPIO_0 state on Beacon's embeded LED. 60 | 61 | ## 1.0.9 (Jul 19, 2017) 62 | - Old proximity beacons (D3.4) iBeacon packets are now properly scanned using `BeaconManager` 63 | - Major improvements to monitoring/ranging on Nougat. The scanning relies now on internal Android mechanism, so scanning periods may slightly differ from those you set with `setForegroundScanningPeriod` and `setBackgroundScanningPeriod`. 64 | 65 | ## 1.0.8 (Jul 4, 2017) 66 | - Added support for routed mesh immmplementation 67 | - Minor bug-fixes 68 | 69 | ## 1.0.3 (May 2, 2017) 70 | - BeaconRegion should be now properly ranged/monitored. Related to [#211](https://github.com/Estimote/Android-SDK/issues/211) 71 | - Added Mirror Access Control flag to packet. 72 | - Fixed NPE being thrown by KitKatScanScheduler on API 18 devices. 73 | 74 | ## 1.0.2 (April 19, 2017) 75 | - Fixed [#211](https://github.com/Estimote/Android-SDK/issues/211) when SecureBeacon region with null UUID thrown NPE. Also fixed problem with filtering secure regions on some devices. 76 | - Fixed [#207](https://github.com/Estimote/Android-SDK/issues/207) where Nearables and old Proximity beacons were not scanned as a ConfigurableDevice. 77 | - Fixed [#213](https://github.com/Estimote/Android-SDK/issues/213) where temperature values in Estimote Telemetry were wrongly parsed. 78 | - Added improvements for Nougat+ devices. Since Nougat, every application is allowed to start/stop BLE scan a maximum of 5 times per 30s. New improvements prevents many scan start/stop events, which resulted in "App XXX is scanning too frequently" logs. All start/stop requests are buffered and the most recent is executed after the delay time. You can play with the setting by yourself using new method in `BeaconManager` class, but we recommend using the default one (1,5s) 79 | ```Java 80 | beaconManager.setScanRequestDelay(delayInMillis); 81 | ``` 82 | 83 | ## 1.0.1 (April 11, 2017) 84 | - Fixed [#206](https://github.com/Estimote/Android-SDK/issues/206) when changing scan period after starting scan was not applied 85 | - Fixed [#205](https://github.com/Estimote/Android-SDK/issues/205) when scan results were not sorted by RSSI. 86 | - Fixed [#187](https://github.com/Estimote/Android-SDK/issues/187) when Estimote telemetry packets were reported as duplicates after getting out of beacon's range. 87 | - Fixed "ClassNotFoundException" being thrown on pre-Lollipop devices when using `ScanFilter` class. 88 | - Improved low-level filtering for Estimote devices. 89 | 90 | ## 1.0.0 (March 29, 2017) 91 | - Changed package names to clean messy things, see [migration guide](https://github.com/Estimote/Android-SDK/blob/master/Docs/switching_to_1.0.0.md) 92 | - Added new bulk updater, see [tutorial](https://github.com/Estimote/Android-SDK/blob/master/Docs/quick_snippets.md#bulk-updater-quick-start) 93 | - Added discovery, ranging and monitoring for Estimote Mirror packets 94 | - Updated [javadocs](https://estimote.github.io/Android-SDK/JavaDocs/) 95 | - Scanning for configurable devices is now a part of `BeaconManager`. See [quick start guide](https://github.com/Estimote/Android-SDK/blob/master/Docs/quick_snippets.md#connecting-to-your-devices-quick-start) for more info. 96 | - Fixed Estimote Location packets not being reported 97 | - Fixed problem with duplicated telemetry packets 98 | - Fixed access to `Vector` x,y,z fields 99 | - Fixed the problem with mesh_key when synchronising beacon data 100 | 101 | ## 0.16.0 (January 27, 2017) 102 | - Added support for mesh via MeshManager 103 | - Added firmware update through mesh 104 | - Fixed Motion Only broadcasting problems 105 | - Added minor fixes for stability and bugfixes. 106 | 107 | ## 0.15.0 (December 19, 2016) 108 | - Added minor fixes to Secure UUID resolving. 109 | - Fixed wrong parceling in EstimoteTelemetry packets 110 | 111 | Merged from beta branch: 112 | - Added fixes for NFC 113 | - Added MOTION_ADVERTISING_DELAY setting. 114 | - Added support for key-value storage on devices with firmware 4.9.0+ 115 | * You can now push your key:value map via our SDK to device in the same way as typical setting: 116 | ```Java 117 | Map map = new HashMap<>(); 118 | map.put("myKey", "myValue"); 119 | connection.settings.storage.writeStorage(map, new StorageManager.WriteCallback() { 120 | @Override 121 | public void onSuccess() { 122 | // HANDLE SUCCESS 123 | } 124 | 125 | @Override 126 | public void onFailure(DeviceConnectionException exception) { 127 | // HANDLE FAILURE 128 | } 129 | }); 130 | ``` 131 | * Reading stored values can be done without user being authorised - this will allow client apps to read stored data. For this purpose, there is a new method for quick connection to beacon: `deviceConnectionProvider.getConnectionForStorageRead(ConfigurableDevice)` 132 | * Bear in mind that the more data is stored on device the more time it takes to read it. 133 | 134 | - Improved Estimote Analytics precision and data persistence. 135 | 136 | ## 0.13.0 (September 28, 2016) 137 | - Added support for Shake-to-connect: 138 | * Enabling/Disabling this setting on device via sdk 139 | * ConfigurableDevice has now property isShaken 140 | - Added support for Near-to-connect: 141 | * Enabling/Disabling this setting on device via sdk 142 | * ConfigurableDevice has now property isClose 143 | - Added Bulk Updater functionality to ConfigurableDevicesScanner: 144 | * You can enable it via `configurableDevicesScanner.enableBulkFirmwareUpdate(BulkUpdater.BulkUpdaterCallback);` 145 | * When enabled, bulk updater will update firmware and settings to all devices around you. This will make sure your beacons are always up to date. 146 | * Availabe for use in foreground, or in background if you run your ConfigurableDevicesScanner in a service/or non-main thread. 147 | * Returns result via one callback, so you are able to be constantly notified about process. 148 | 149 | ## 0.12.0 (September 14, 2016) 150 | - Added support for monitoring and ranging on Android Nougat devices. 151 | * Due to new Android restrictions, we can only start/stop scanning no more than 5 times per 30 seconds. 152 | * It is strongly recommended, to set your foreground/background scanning periods according to the new specification. If you forgot to do so, SDK will automatically update periods to avoid scan block by Nougat. 153 | 154 | - Flag DISABLE_BATCH_SCANNING is from set to 'true' from now on. Batch scan implementation varies on many phones, and it is usually causing badly delayed scan results. If you really want to use it, just set it to 'false' in your android manifest file. 155 | - Fixed (https://github.com/Estimote/Android-SDK/issues/168) - FATAL EXCEPTION: BeaconServiceThread 156 | 157 | ## 0.11.1 (September 1, 2016) 158 | - Added Firmware version to ConfigurableDevice object 159 | - Fixed wrong NFC cloud data 160 | - Fixed Flip to Sleep problems on some devices 161 | - Fixed GPIO wrong data saving 162 | - Fixed rare bug when NPE was thrown when closing connection while connecting 163 | 164 | ## 0.11.0 (August 1, 2016) 165 | - Added NFC support for changing NFC data transmited by beacon. 166 | * You can set your own URI or Android Application Package Name as an EstimoteNdefRecord 167 | * Your data can take up to 256 bytes. 168 | * Beacon Id and Mac address are added automatically 169 | - Fixed Analytics problems with sending data (https://github.com/Estimote/Android-SDK/issues/157) 170 | 171 | ## 0.10.8 (July 6, 2016) 172 | - Fixed problems while updating firmware 173 | - Fixed old firmware version reported by SDK while checking device firmware. 174 | - Fixed "server error 200: null" bug with connecting to nearables 175 | - Removed unnecessary logs 176 | 177 | ## 0.10.7 (July 1, 2016) 178 | - Added motion only and flip to sleep as a separate settings (instead of Conditional Broadcasting) 179 | - Fixed bugs with SettingEditor 180 | - Fixed Motion Only/Flip to sleep problems on older devices 181 | - Fixed EID tx power setting 182 | - Analytics from now on is enabled by default. 183 | 184 | 185 | ## 0.10.6 (June 23, 2016) 186 | - Added support for connectiong to Nearables 187 | * There are some issues on some phones due to different implementations of bluetooth stack. We're working on it and it should be improved really soon. We recommend using Nexus devices for stable connection. 188 | - Added support for Nearables Eddystone URL 189 | - Nearables reported by scanner now have their type and color resolved (only for logged user otherwise all is UNKNOWN) 190 | - Removed some unnecessary scan logs. 191 | 192 | ## 0.10.5 (May 25, 2016) 193 | - Ranging results are now reported at exact time 194 | - Default beacon expiration time after which onExitRegion events are called is now set to 20s (was 10s). This should help with random short onExit/onEnter events. If you need to tweak this by yourself, beaconManager has new method for changing this to value from 1-60s range: 195 | ```java 196 | beaconManager.setRegionExitExpiration(TimeUnit.SECONDS.toMillis(20)); 197 | ``` 198 | Bear in mind, that high beacon advertising interval is also causing random short onEnter/onExit events. You can try lowering it to 200-300ms to gain better user experience. 199 | - Added support for Eddystone Configuration Service (ECS) 200 | - Minor optimizations 201 | 202 | ## 0.10.4 (May 11, 2016) 203 | - Fixed problems with Advertising Interval setting update on Proximity Beacons 204 | - Fixed (https://github.com/Estimote/Android-SDK/issues/151): Context problems with Analytics where NPE was thrown. 205 | 206 | ## 0.10.3 (May 4, 2016) 207 | - Added support for Analytics - can be enabled via EstimoteSDK class and offers monitoring and ranging statistics. 208 | - Fixed (https://github.com/Estimote/Android-SDK/issues/149): crash : com.estimote.sdk.internal.utils.AsyncCache$1.onFailure (AsyncCache.java:106) 209 | - Fixed rare bug where reading beacon characteristic caused crash 210 | - Fixed errors with RecoveryHelper while connecting to beacons 211 | - Optimized beacon connection 212 | - Unresolved Eddystone EID packets are now reported by scanner 213 | 214 | ## 0.10.2 (April 14, 2016) 215 | - Added support for Eddystone Ephemeral ID (EID) 216 | - 'Check for firmware updates' now properly compare firmware version values 217 | - ScanResultItem is now Parcelable 218 | 219 | ## 0.10.1 (March 17, 2016) 220 | - Added value validation for each setting 221 | - Added RSSI read from connected beacon (for Proximity & Location beacons) 222 | - Fixed enabling Secure UUID 223 | - Fixed (https://github.com/Estimote/Android-SDK/issues/144): stopRanging does not seem to stop actual ranging 224 | - Fixed duplicated listener notification while ranging/monitoring 225 | - Fixed rare crash on closing bluetooth gatt 226 | - Fixed triggering scan cycle in Doze mode (Android 6.0+) 227 | - Beacon firmware is now cached properly 228 | 229 | ## 0.10.0 (March 11, 2016) 230 | 231 | - New SDK for configuring Location and Proximity beacons 232 | * supports more sensors (temperature, motion, light) 233 | * advertising multiple packet types 234 | - Improved monitoring using batch mode and hardware filtering. 235 | - Support for observing Estimote Telemetry packets 236 | - Support for observing Estimote Location packets 237 | - More information can be found in following docs: 238 | * [Scanning and monitoring](/DOC_monitoring_scanning.md) 239 | * [Beacon connection](/DOC_deviceConnection.md) 240 | * [Multiple advertisers in Location Beacons](/DOC_multiadvertisers.md) 241 | * [Using telemetry packets](/DOC_telemetry.md) 242 | 243 | 244 | ## 0.9.7 (January 19, 2016) 245 | 246 | - Packet parser errors are logged and should not crash whole application. 247 | - Fixed threading issue that cause scanning to continue when service was stopped (on some devices). 248 | - onExitRegion should be now working on devices with pre-Lollipop Androids. 249 | - Fixed (https://github.com/Estimote/Android-SDK/issues/135): Fails getting RSSI on Android >=5.0 (Samsung Galaxies) 250 | - Fixed (https://github.com/Estimote/Android-SDK/issues/137): IllegalStateException when starting monitoring on SDK 0.9.6 251 | 252 | ## 0.9.6 (December 22, 2015) 253 | 254 | - Added ScanStatusListner to BeaconManager. This allows to find you when scanning really started and when it stopped. User may switch the Bluetooth off and then turn it on when 255 | application is running. This listener allows to track this events and react properly to them (eg. gray out device list). See ListBeaconsActivity to see sample code. 256 | ```java 257 | beaconManager.setScanStatusListener(new BeaconManager.ScanStatusListener() { 258 | @Override public void onScanStart() { 259 | // Unlock UI 260 | list.setEnabled(true); 261 | list.setAlpha(1.0f); 262 | } 263 | 264 | @Override public void onScanStop() { 265 | // Lock UI 266 | list.setEnabled(false); 267 | list.setAlpha(0.5f); 268 | } 269 | }); 270 | ``` 271 | - Fixed (https://github.com/Estimote/Android-SDK/issues/134): java.lang.NullPointerException when using SDK on Emulator 272 | 273 | 274 | ## 0.9.5 (December 8, 2015) 275 | 276 | - This version uses new Lollipop BLE scanning API. Previous API is still supported on older phones. It uses features like batch scanning and hardware filtering (if particular device supports them). No need to change your code, those features are enabled automatically. 277 | 278 | ## 0.9.4 (October 30, 2015) 279 | 280 | - This release features support for Android Marshmallow runtime permissions and helps you meet all the requirements necessary for beacon detection (Bluetooth, Location, runtime permissions). 281 | - Full description of all requirements for beacon detection are described in JavaDoc for `SystemRequirementsChecker`. 282 | - Demos have been updated to target API 23 (M) and uses `SystemRequirementsChecker` to meet all requirements. 283 | - From time to time SDK will put warning in device logs what is missing. 284 | 285 | New tools 286 | - `SystemRequirementsChecker`: use the `check` method to determine which requirements are not met for beacon detection 287 | - `SystemRequirementsChecker`: use the `checkWithDefaultDialogs` method in your activity for a convenient way to ask for all permissions and rights. It's all handled by the SDK, and should be of great help if you want to get up and running quickly. 288 | - `SystemRequirementsHelper`: a grab bag of static methods to determine status of Bluetooth, Location Services, granted required permissions 289 | 290 | Breaking changes: 291 | - `BeaconManager`: not longer included the following methods `checkPermissionsAndService`, `isBluetoothEnabled`, `hasBluetooth`. You can find them in `SystemRequirementsHelper`. 292 | 293 | ## 0.9.3 (October 20, 2015) 294 | Bug fix: 295 | - `EstimoteCloud#fetchBeaconDetails(UUID, major, minor, callback)` under certain circumstances could yield beacon not found. 296 | 297 | ## 0.9.2 (October 20, 2015) 298 | New: 299 | - Beacon *signal filtering* for smoothing [RSSI](https://en.wikipedia.org/wiki/Received_signal_strength_indication) readings. What does it mean for you? The RSSI values returned by `RangingListener#onBeaconsDiscovered` are much more stable now, which should enable you to predict proximity to a beacon more accurately and without having to write complex filtering algorithms yourself. The dinner's on us\*. 300 | 301 | \* The dinner is not really on us, but the RSSI smoothing code is. 302 | - You can add and remove multiple callbacks in `BeaconConnection` (new methods `addConnectionCallback`, `removeConnectionCallback`, `clearCallbacks`). 303 | - Added `EstimoteCloud#fetchBeaconDetails(UUID, major, minor, callback)` method to fetch details of your beacon in Estimote Cloud using UUID, major, minor values. 304 | 305 | Bug fixes: 306 | - Secure UUID introduced in `v0.9` got lots of good improvements. Fixes https://github.com/Estimote/Android-SDK/issues/127. 307 | 308 | Breaking changes: 309 | - Removed `Beacon#getName` method. It was name of the Bluetooth device and was often confused with name given to a beacon in Estimote Cloud. Beacon's name can be fetched using `EstimoteCloud#fetchBeaconDetails` method. 310 | 311 | ## 0.9.1 (September 29, 2015) 312 | - Fixes problem when not initializing SDK caused problems with ranging & monitoring. 313 | 314 | ## 0.9 (September 29, 2015) 315 | - This release brings [**Secure UUID**](https://community.estimote.com/hc/en-us/articles/201371053-What-security-features-does-Estimote-offer-How-does-Secure-UUID-work-) – a security mechanism to protect your beacons from spoofing (where someone tries to ‘impersonate’ your beacons, by broadcasting the same UUID, Major and Minor). Using _Secure UUID_, the UUID, Major and Minor values that your beacon broadcasts will change unpredictably over time. The only way to resolve the values we generate to a particular beacon is via authorized access to Estimote Cloud. 316 | 317 | - You can enable _Secure UUID_ via [Estimote app](https://play.google.com/store/apps/details?id=com.estimote.apps.main&hl=en) from Google Play or via SDK 318 | ```java 319 | connection = new BeaconConnection(...); 320 | connection.edit().set(connection.secureUUID(), true).commit(...); 321 | ``` 322 | 323 | - Ranging and region monitoring works transparently with _Secure UUID_ enabled beacons. All you need is: 324 | 325 | - Make sure you have initialised SDK with your App ID & App Token. 326 | ```java 327 | // App ID & App Token can be taken from App section of Estimote Cloud. 328 | EstimoteSDK.initialize(applicationContext, appId, appToken); 329 | ``` 330 | 331 | - Use `SecureRegion` instead of `Region` when starting ranging or monitoring. 332 | 333 | ```java 334 | // Initialise BeaconManager as before. 335 | // Find all *your* Secure UUID beacons in the vicinity. 336 | beaconManager.startRanging(new SecureRegion(“regionId”, null, null, null)); 337 | 338 | // Remember that you can also range for other regions as well. 339 | beaconManager.startRanging(new Region("otherRegion", null, null, null); 340 | ``` 341 | 342 | - **Breaking changes**: 343 | - `BeaconManager` methods for ranging & monitoring (`startRanging`, `stopRanging`, `startMonitoring`, `stopMonitoring`) no longer throws `RemoteException`. We heard that it caused lots of boilerplate code. We agree and removed it. 344 | 345 | - Formatting MAC address was always pain (`aabbccddeeff` or `AA:BB:CC:DD:EE:FF`?). That's why we removed all `String` representation of MAC address and introduced `MacAddress` class. 346 | 347 | - For the same reason we removed all usages of `String` representation [UUID](https://en.wikipedia.org/wiki/Universally_unique_identifier) and used Java's `java.util.UUID` class instead. 348 | 349 | ## 0.8.8 (September 16, 2015) 350 | - Finally support for built-in sensors: motion and temperature. 351 | - Motion sensor readout with notifications. Note that you need to make sure it is enabled (separate property do enable/disable motion) sensor. 352 | ```java 353 | connection = new BeaconConnection(...); 354 | 355 | // Make sure to enable motion sensor first. 356 | connection.edit().set(connection.motionDetectionEnabled(), true).commit(...callback...); 357 | 358 | connection.setMotionListener(new Property.Callback() { 359 | @Override public void onValueReceived(final MotionState value) { 360 | // Motion state in value argument. 361 | } 362 | 363 | @Override public void onFailure() { 364 | // Error handling. 365 | } 366 | }); 367 | ``` 368 | - Temperature sensor readout and calibration (two separate properies added to BeaconConnection). 369 | ```java 370 | // Temperature calibration (see also docs for BeaconConnection#temperatureCalibration()). 371 | connection.edit().set(connection.temperatureCalibration(), 21).commit(...); 372 | 373 | // If you want to measure temperature from beacon on demand. 374 | connection.temperature().getAsync(new Property.Callback() { 375 | @Override public void onValueReceived(final Float value) { 376 | // updateTemperatureValue(value); 377 | } 378 | 379 | @Override public void onFailure() { 380 | // Error handling. 381 | } 382 | }); 383 | ``` 384 | 385 | Bug fixes: 386 | - Negative temperature is properly interpreted in EddystoneTelemetry packet. 387 | - BeaconManager crash when there are Eddystone beacons with bad packet. 388 | 389 | **Breaking changes** 390 | - `BeaconConnection.ConnectionCallback` has been changed to indicate that that your access to beacon had been authorised (`ConnectionCallback#onAuthorized(BeaconInfo)`). 391 | 392 | ## 0.8.7 (August 25, 2015) 393 | - Finally Estimote SDK is available on Maven Central (`com.estimote:sdk:0.8.7@aar`). 394 | 395 | ## 0.8.6 (August 21, 2015) 396 | - Authentication to beacon is more robust than ever (requires updating beacon to firmware 3.2.0). 397 | 398 | ## 0.8.5 (August 20, 2015) 399 | - Security improvements in the beacon authorization mechanism. 400 | - Beacon update is more stable. 401 | 402 | ## 0.8.2 (July 24, 2015) 403 | - This is mainly a bugfix release. 404 | - Fixed (https://github.com/Estimote/Android-SDK/issues/109): Documentation Bug. 405 | - Fixed (https://github.com/Estimote/Android-SDK/issues/117): Crash after update to 0.8 version. 406 | - SDK demos are now using Material Design (h/t @RingoMckraken). 407 | 408 | ## 0.8.1 (July 15, 2015) 409 | - Small fixes for Eddystone protocol. 410 | 411 | ## 0.8 (July 14, 2015) 412 | - Say hello to [Eddystone](https://developers.google.com/beacons) - an open protocol BLE protocol from Google. 413 | - Estimote Beacons can broadcast Eddystone protocol. 414 | - In order to start playing with Eddystone you need to update firmware of your existing Estimote beacons to `3.1.1`. Easiest way is through [Estimote app on Google Play](https://play.google.com/store/apps/details?id=com.estimote.apps.main). Than you can change broadcasting scheme on your beacon to Eddystone-URL or Eddystone-UID. 415 | - *New in SDK*: 416 | - find nearby Eddystone beacons (`BeaconManager#startEddystoneScanning`) 417 | - configure Eddystone related properties: 418 | - URL property of `Eddystone-URL` (see `BeaconConnection#eddystoneUrl`) 419 | - namespace & instance properties of `Eddystone-UID` (see `BeaconConnection#eddystoneNamepsace`, `BeaconConnection#eddystoneInstance`) 420 | - configure broadcasting scheme of beacon to `Estimote Default`, `Eddystone-UID` or `Eddystone-URL` (see `BeaconConnection#broadcastingScheme`) 421 | - [SDK Examples](https://github.com/Estimote/Android-SDK/tree/master/Demos) have been updated to showcase Eddystone support. 422 | 423 | ## 0.7 (June 18, 2015) 424 | - Initial support for nearables. You can discover nearby nearables via `BeaconManager.startNearableDiscovery()`. With nearbles you can read temperature, motion, orientation without need to connect to it. Directly from discovered `Nearable` class. 425 | - You can change basic & smart power mode in your beacon via `BeaconConnection`. [Read more about power modes.](https://community.estimote.com/hc/en-us/articles/202552866-How-to-optimize-battery-performance-of-Estimote-Beacons-) 426 | - `android.hardware.bluetooth_le` feature is no longer required 427 | - You can also change conditional broadcating in beacon (Flip To Sleep). It is great for development. [Read more about Flip To Sleep.](https://community.estimote.com/hc/en-us/articles/205413787-How-to-enable-conditional-broadcasting-and-Flip-to-sleep-mode-) 428 | - **Breaking changes** (1.0 is approaching, bear with us): 429 | - most of `BeaconConnection`s write* methods are gone, they are replaced with more appropriate `Property` class 430 | 431 | ```java 432 | // Before 433 | connection.writeMajor(newMajor, callback); 434 | connection.writeMinor(newMinor, callback); 435 | 436 | // After: reading 437 | connection.minor().get() 438 | connection.major().get() 439 | 440 | // After: writing in batch 441 | connection.edit() 442 | .set(connection.proximityUuid(), newUuid) 443 | .set(connection.major(), newMajor) 444 | .set(connection.minor(), newMinor) 445 | .commit(callback); 446 | ``` 447 | 448 | ## 0.6.1 (June 2, 2015) 449 | - Fixed authentication issues (#111). 450 | 451 | ## 0.6 (May 4, 2015) 452 | - You can update update firmware in Estimote beacons from the SDK. There are several ways to do it: 453 | - Use `BeaconOta` class to perform firmware update on selected beacon. 454 | - Use `BeaconConnection#updateBeacon` which triggers update on the beacon. See updated demos to see how it works. 455 | - You can also use Estimote app from Play Store to do that. 456 | - Estimote SDK now includes also `android.permission.ACCESS_NETWORK_STATE` permission to determine internet connectivity. 457 | - **Breaking changes** (please bear with us, we are approaching stable 1.0 release): 458 | - `BeaconConnection`'s `ConnectionCallback#onAuthenticated` method does not return `BeaconCharacteristics` object any more. You can read them directly on `BeaconConnection` object. 459 | - For example read reading broadcasting power is just `connection.getBroadcastingPower()`. 460 | 461 | ## 0.5 (April 17, 2015) 462 | - From now Estimote SDK for Android is distributed as [AAR archive](http://tools.android.com/tech-docs/new-build-system/aar-format) rather than jar. That means that you do not need to change your `AndroidManifest.xml`. SDK's `AndroidManifest.xml` will be merged with your application's `AndroidManifest.xml`. See [installation guide](https://github.com/Estimote/Android-SDK#installation) how to add library to your project. 463 | - Welcome back! We have added support for [Estimote Cloud](http://cloud.estimote.com). You can access it via `EstimoteCloud` class. Remember first to provide your App ID & App Token from App section of [Estimote Cloud](http://cloud.estimote.com) via `EstimoteSDK#initialize` method. 464 | - From now all connections to beacons needs to be authorized. If a beacon is not registered to your account, you will not be able to connect to it. 465 | - Estimote SDK's `AndroidManifest.xml` uses `BLUETOOTH`, `BLUETOOTH_ADMIN` and `INTERNET` permissions. 466 | - Yes, there is single point of initialisation of the SDK. 467 | 468 | ```java 469 | // App ID & App Token can be taken from App section of Estimote Cloud. 470 | EstimoteSDK.initialize(applicationContext, appId, appToken); 471 | // Optional, debug logging. 472 | EstimoteSDK.enableDebugLogging(true); 473 | ``` 474 | - All exceptions within the SDK has been unified and exposed in `com.estimote.sdk.exception` package. 475 | 476 | - That means some **breaking changes**: 477 | - `L` class is no longer available, in order to turn on debug logging use `EstimoteSDK` class. 478 | - `BeaconConnection.ConnectionCallback` & `BeaconConnection.WriteCallback` methods have been changed to contain apropriate exception when happens. 479 | 480 | ## 0.4.3 (November 12, 2014) 481 | - Fixes https://github.com/Estimote/Android-SDK/issues/59: compatibilty with Android L 482 | 483 | ## 0.4.2 (June 24, 2014) 484 | - Fixes https://github.com/Estimote/Android-SDK/issues/55: it is safe to use library from remote process 485 | 486 | ## 0.4.1 (March 18, 2014) 487 | - *CAN BREAK BUILD*: MonitoringListener returns list of beacons the triggered enter region event (https://github.com/Estimote/Android-SDK/issues/18) 488 | - Better messaging when BeaconManager cannot start service to scan beacons (https://github.com/Estimote/Android-SDK/issues/25) 489 | - Fixed bug in SDK when other beacons are around (https://github.com/Estimote/Android-SDK/issues/27) 490 | 491 | ## 0.4 (February 17, 2014) 492 | - Introducing ability to change beacon's UUID, major, minor, broadcasting power, advertising interval (see BeaconConnection class). 493 | - Dropping Guava dependency. 494 | 495 | ## 0.3.1 (February 11, 2014) 496 | - Fixes bug when simulated beacons were not seen even when using Estimote's proximity UUID. 497 | 498 | ## 0.3 (February 11, 2014) 499 | - Background monitoring is more robust and using AlarmService to invoke scanning. 500 | - Default values for background monitoring were changed. Scanning is performed for 5 seconds and then service sleeps for 25 seconds. Those values can be changed with BeaconManager#setBackgroundScanPeriod. 501 | - Beacons reported in RangingListener#onBeaconsDiscovered are sorted by accuracy (estimated distance between device and beacon). 502 | - Bug fixes. 503 | 504 | ## 0.2 (January 7, 2014) 505 | - *IMPORTANT*: package changes BeaconService is now in `com.estimote.sdk.service service`. You need to update your `AndroidManifest.xml` service definition to `com.estimote.sdk.service.BeaconService`. 506 | - Support for monitoring regions in BeaconManager. 507 | - Region class: it is mandatory to provide region id in its constructor. This matches CLRegion/ESTBeaconRegion from iOS. 508 | - Beacon, Region classes now follow Java bean conventions (that is getXXX for accessing properties). 509 | - Debug logging is disabled by default. You can enable it via `com.estimote.sdk.utils.L#enableDebugLogging(boolean)`. 510 | 511 | ## 0.1 (December 9, 2013) 512 | - Initial version. 513 | -------------------------------------------------------------------------------- /Docs/DOC_deviceConnection.md: -------------------------------------------------------------------------------- 1 | # Connecting to beacons in Android SDK 2 | 3 | Connecting to a device lets you change its settings (Minor, Major, advertising interval etc.). 4 | To edit seetings you need to be an owner of the beacon in Estimote Cloud. 5 | Every attempt to connect with device that is not linked to your Estimote Account will fail. 6 | 7 | ## Discovering configurable devices 8 | At first, you will need to scan for configurable devices around you: 9 | 10 | ```Java 11 | BeaconManager beaconManager = new BeaconManager(this); 12 | // set foreground scan periods. This one will scan for 2s and wait 2s 13 | beaconManager.setForegroundScanPeriod(2000, 2000); 14 | // connects beacon manager to underlying service 15 | beaconManager.connect(new BeaconManager.ServiceReadyCallback() { 16 | @Override 17 | public void onServiceReady() { 18 | // add listener for ConfigurableDevice objects 19 | beaconManager.setConfigurableDevicesListener(new BeaconManager.ConfigurableDevicesListener() { 20 | @Override 21 | public void onConfigurableDevicesFound(List configurableDevices) { 22 | // handle the configurable device here. You can use it to acquire connection from DeviceConnectionProvider 23 | } 24 | }); 25 | beaconManager.startConfigurableDevicesDiscovery(); 26 | ``` 27 | 28 | Once you have your `ConfigurableDevice` object, you want to acquire `DeviceConnection` for it. To do that, you need to be connected to `DeviceConnectionProvider`. 29 | It creates simple service that lets you handle multiple connections at once. This provider is bound to your context, so you only need to connect once during your context lifetime. Here is how to do that in your activity `onCreate` method: 30 | 31 | ```Java 32 | @Override 33 | protected void onCreate(Bundle savedInstanceState) { 34 | DeviceConnectionProvider connectionProvider = new DeviceConnectionProvider(this); 35 | connectionProvider.connectToService(new DeviceConnectionProvider.ConnectionProviderCallback() { 36 | @Override 37 | public void onConnectedToService() { 38 | // Handle your actions here. You are now connected to connection service. 39 | // For example: you can create DeviceConnection object here from connectionProvider. 40 | }); 41 | } 42 | ``` 43 | Remember to call `connectionProvider.destroy()` method in your activity `onDestroy()`: 44 | 45 | ```Java 46 | @Override 47 | protected void onDestroy() { 48 | connectionProvider.destroy(); 49 | super.onDestroy(); 50 | } 51 | ``` 52 | 53 | When your Activity is connected to `ConnectionProvider`, and you got your `ConfigurableDevice` object, you can now try to establish device connection. Doing that is really easy from now on: 54 | ```Java 55 | // Pass your ConfigurableDevice to connection provider method 56 | DeviceConnection connection = connectionProvider.getConnection(device); 57 | connection.connect(new DeviceConnectionCallback() { 58 | @Override 59 | public void onConnected() { 60 | // Do something with your connection. 61 | // You can for example read device settings, or make an firmware update. 62 | Log.d("DeviceConnection", "onConnected"); 63 | } 64 | 65 | @Override 66 | public void onDisconnected() { 67 | // Every time your device gets disconnected, you can handle that here. 68 | // For example: in this state you can try reconnecting to your device. 69 | Log.d("DeviceConnection", "onDisconnected"); 70 | } 71 | 72 | @Override 73 | public void onConnectionFailed(DeviceConnectionException exception) { 74 | // Handle every connection error here. 75 | Log.d("DeviceConnection", "onConnectionFailed"); 76 | } 77 | }); 78 | ``` 79 | Now you can use `DeviceConnection` object to communicate with a configurable device. Remember that every time your connection fails, your `DeviceConnectionCallback` needs to handle that. 80 | 81 | Don't worry about connection state while switching application context - after first creation, your connection is always kept in the underlying service. Launching new activity and creating new `DeviceConnection` object for the same `ConfigurableDevice` only adds new observers to current connection. 82 | If you only want to detach your activity callbacks from connection, just use `connection.destroy()` method in your activity `onDestroy()` method: 83 | ```Java 84 | @Override 85 | protected void onDestroy() { 86 | super.onDestroy(); 87 | connection.destroy(); 88 | } 89 | ``` 90 | 91 | To completely close the underlying connection just call: 92 | ```Java 93 | connection.close() 94 | ``` 95 | From now on, if any application context holds active `DeviceConnectionCallback`, it will have it's `onDisconnected()` called. Of course, it will only happen when you haven't called `connection.destroy()` on that context. Be sure to handle that! 96 | 97 | 98 | ###### Known issues 99 | 100 | Unfortunately due to the differences between Bluetooth implementations on many Android devices, you may facem problems with achieving stable connection to devices. It often occurs as randomly thrown `BluetoothGatt error 133`. We are trying our best to find a workaround, but the issue is linked to low-level libraries we cannot modify. 101 | 102 | ## Basic operations on connected device 103 | Just after your device is connected, you can perform actions to read or write data to it. Please bear in mind that all these actions are performed **asynchronously**. For each operation you will need to define a callback object that will handle all possible results for you. 104 | 105 | ### Reading device setting 106 | You can access all reading methods via `connection.settings` object. It holds references for many objects containing device data. Feel free to choose what you need, and then call `get(SettingCallback callback)` on it. Be sure to implement callback methods! Take a look at that example: 107 | 108 | ```Java 109 | connection.settings.deviceInfo.firmware().get(new SettingCallback() { 110 | @Override 111 | public void onSuccess(final Version value) { 112 | // Handle read data here. 113 | // For example: display them in UI. This callback will be called in the same thread as connection was created (not opened). 114 | // You can use your activity method runOnUIThread(Runnable runnable) to handle that. 115 | Log.d("DeviceRead","Read firmware version: " + value.toString()); 116 | } 117 | 118 | @Override public void onFailure(DeviceConnectionException exception) { 119 | // Handle exceptions here. 120 | Log.d("DeviceRead","Reading firmware version failed."); 121 | } 122 | }); 123 | ``` 124 | ### Writing device setting 125 | Writing data to device is similar - in this case you need to call `set(SettingCallback callback)` instead of get. 126 | Keep in mind that some device settings are read only! 127 | Writing device eddystone interval example: 128 | 129 | ```Java 130 | int advertisingInterval = 1000; 131 | connection.settings.eddystone.tlm.advertisingInterval().set(advertisingInterval, new SettingCallback() { 132 | @Override 133 | public void onSuccess(Integer value) { 134 | // Data saved to device 135 | Log.d("DeviceWrite","Written new Eddystone interval: " + value.toString()); 136 | } 137 | 138 | @Override 139 | public void onFailure(DeviceConnectionException exception) { 140 | // Handle exceptions here. 141 | Log.d("DeviceWrite","Write new Eddystone interval failed."); 142 | } 143 | }); 144 | ``` 145 | If entered value is invalid, the **DeviceConnectionException** object will contain information about possible values. 146 | Once you got the idea how to read/write device setting, let's learn how to make advanced operations. 147 | 148 | ## Advanced operations on connected device 149 | It might come in handy to update firmware or multiple settings at once - we've got you covered! 150 | ### Bulk setting write 151 | In order to make bulk settings write, you have to create **SettingsEditor** object. Take a look at example: 152 | 153 | ```Java 154 | // Take your connected DeviceConnection object and get it's editor 155 | SettingsEditor edit = connection.edit() 156 | edit.set(connection.settings.beacon.proximityUUID(), UUID.fromString("B9407F30-F5F8-466E-AFF9-25556B57FE6D")); 157 | edit.set(connection.settings.beacon.major(), 1000); 158 | edit.set(connection.settings.beacon.minor(), 100); 159 | edit.commit(new SettingCallback() { 160 | @Override 161 | public void onSuccess(Object value) { 162 | // Handle success here. It will be called only when all settings have been written. 163 | Log.d("DeviceBulkWrite","Bulk write successful"); 164 | } 165 | 166 | @Override 167 | public void onFailure(DeviceConnectionException exception) { 168 | // Handle exceptions 169 | Log.d("DeviceBulkWrite","Bulk write failed"); 170 | }); 171 | } 172 | ``` 173 | 174 | ### Updating firmware 175 | To check if a device i up to date - use `checkForFirmwareUpdate()` method on your **Connection** object. 176 | ```Java 177 | connection.checkForFirmwareUpdate(new DeviceConnection.CheckFirmwareCallback() { 178 | @Override 179 | public void onDeviceUpToDate(DeviceFirmware firmware) { 180 | // If device is up to date, handle that case here. Firmware object contains info about current version. 181 | Log.d("DeviceFirmwareUpdate","Device firmware is up to date."); 182 | } 183 | 184 | @Override 185 | public void onDeviceNeedsUpdate(DeviceFirmware firmware) { 186 | // Handle device update here. Firmware object contains info about latest version. 187 | Log.d("DeviceFirmwareUpdate","Device needs firmware update."); 188 | } 189 | 190 | @Override 191 | public void onError(DeviceConnectionException exception) { 192 | // Handle errors here 193 | Log.d("DeviceFirmwareUpdate","Error checking device firmware: " + exception.getMessage()); 194 | } 195 | }); 196 | ``` 197 | 198 | When your device needs an update, use `updateFirmware(FirmwareUpdateCallback callback)` on your **Connection** object. Remember to implement your callback methods! 199 | ```Java 200 | connection.updateDevice(new DeviceConnection.FirmwareUpdateCallback() { 201 | @Override 202 | public void onSuccess() { 203 | // Handle success 204 | Log.d("DeviceFirmwareUpdate","Device firmware updated."); 205 | } 206 | 207 | @Override 208 | public void onProgress(float progress, String message) { 209 | // Handle progress - range is 0.0 - 1.0 210 | Log.d("DeviceFirmwareUpdate","Device firmware update progress: " + progress + " Message: " + message); 211 | } 212 | 213 | @Override 214 | public void onFailure(DeviceConnectionException e) { 215 | // Handle failure. Don't worry about device state - upon failure, it resets back to its old version. 216 | Log.d("DeviceFirmwareUpdate","Device firmware update failure: " + e.getMessage()); 217 | } 218 | }); 219 | ``` 220 | 221 | Please keep in mind that firmware update is an **asynchronous long-term** process. Be sure to inform your user about it, and take care of UI reports - you can use `onProgress(float progress, String message)` to get current update progress. 222 | 223 | ### Accessing Nearable settings 224 | 225 | All nearables have their own advertisers assigned to setting tree. You can access each setting via calling `connection.settings.estimote.nearable`. You can change advertised packet by switching broadcasting scheme setting: 226 | ```Java 227 | connection.settings.estimote.nearable.broadcastingScheme().set(NearableMode.IBEACON, new SettingCallback() { 228 | @Override 229 | public void onSuccess(NearableMode value) { 230 | // Handle success 231 | Log.d("BroadcastingScheme","Changed nearable broadcastung scheme. "); 232 | } 233 | 234 | @Override 235 | public void onFailure(DeviceConnectionException exception) { 236 | // Handle errors here 237 | Log.d("Broadcasting Scheme","Error setting broadcasting scheme: " + exception.getMessage()); 238 | } 239 | }); 240 | ``` 241 | In addition, from Sticker firmware version 1.3 there is a possiblity to setup Eddystone URL using our SDK. You can simply achieve that by accessing proper setting: 242 | ```Java 243 | connection.settings.estimote.nearable.eddystoneUrl().set("http://estimote.com", new SettingCallback() { 244 | @Override 245 | public void onSuccess(String value) { 246 | // Handle success 247 | Log.d("Eddystone URL","Changed nearable eddystone url. "); 248 | } 249 | 250 | @Override 251 | public void onFailure(DeviceConnectionException exception) { 252 | // Handle errors here 253 | Log.d("Eddystone URL Scheme","Error changing eddystone url: " + exception.getMessage()); 254 | } 255 | }); 256 | ``` 257 | 258 | 259 | 260 | 261 | 262 | -------------------------------------------------------------------------------- /Docs/DOC_monitoring_after_restart.md: -------------------------------------------------------------------------------- 1 | # Monitoring after system restart # 2 | 3 | In order to have monitoring working after device is rebooted you must: 4 | * Create empty broadcast receiver (Android will invoke Application.onCreate before BroadcastReceiver.onReceive): 5 | ```java 6 | public class SystemBootReceiver extends BroadcastReceiver { 7 | @Override public void onReceive(Context context, Intent intent) { 8 | } 9 | } 10 | ``` 11 | * In AndroidManifest.xml register that receiver to boot event (and optionally power events): 12 | ```xml 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | ``` 21 | * Add a permission to start at boot. 22 | ```xml 23 | 24 | ``` 25 | * Create you own application class (if you don't have any) and start monitoring there (in onCreate method): 26 | ```java 27 | public class MyApp extends Application { 28 | 29 | private Region monitoringRegion = new Region("region", UUID.fromString("my-UUID"), 1, 1); 30 | private BeaconManager beaconManager; 31 | private NotificationManager notificationManager; 32 | 33 | @Override public void onCreate() { 34 | super.onCreate(); 35 | beaconManager = new BeaconManager(this.getApplicationContext()); 36 | beaconManager.connect(new BeaconManager.ServiceReadyCallback() { 37 | @Override public void onServiceReady() { 38 | startMonitoring(); 39 | } 40 | }); 41 | notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); 42 | } 43 | 44 | private void startMonitoring() { 45 | beaconManager.setMonitoringListener(new BeaconManager.MonitoringListener() { 46 | @Override public void onEnteredRegion(Region region, List list) { 47 | // invoke your action here 48 | } 49 | 50 | @Override public void onExitedRegion(Region region) { 51 | // invoke your action here 52 | } 53 | }); 54 | beaconManager.startMonitoring(monitoringRegion); 55 | } 56 | } 57 | ``` 58 | * Don't forget to add your Application class to AndroidManifest.xml in the `` tag. 59 | ```xml 60 | 67 | ``` 68 | * In one of your activities check permission for Bluetooth and Location. Access must be granted by the user before system is rebooted. If not, monitoring will not start. 69 | ```java 70 | SystemRequirementsChecker.checkWithDefaultDialogs(this); 71 | ``` 72 | -------------------------------------------------------------------------------- /Docs/DOC_monitoring_scanning.md: -------------------------------------------------------------------------------- 1 | # Ranging, Monitoring and Scanning 2 | 3 | 4 | 5 | - [Overview](#overview) 6 | - [Monitoring and ranging](#monitoring-and-ranging) 7 | - [1. Define beacon regions](#1-define-beacon-regions) 8 | - [2. Create a Beacon Manager object](#2-create-a-beacon-manager-object) 9 | - [3. Connect to the beacon scanning service](#3-connect-to-the-beacon-scanning-service) 10 | - [4. Set monitoring and ranging listeners](#4-set-monitoring-and-ranging-listeners) 11 | - [5. Set scan periods](#5-set-scan-periods) 12 | - [6. Start monitoring/ranging](#6-start-monitoringranging) 13 | - [Scanning](#scanning) 14 | - [Eddystone](#eddystone) 15 | - [Nearable](#nearable) 16 | - [Estimote Telemetry](#estimote-telemetry) 17 | - [Estimote Location](#estimote-location) 18 | 19 | 20 | 21 | ## Overview 22 | 23 | Estimote beacons and stickers are able to broadcast multiple packets: [iBeacon](http://developer.estimote.com/ibeacon/), [Eddystone](http://developer.estimote.com/eddystone/), [Nearable](http://developer.estimote.com/nearables/), Estimote Telemetry, and Estimote Location. Android SDK supports interacting with them in the following ways: 24 | 25 | - **monitoring** and **ranging** for [iBeacon](http://developer.estimote.com/ibeacon/) packets advertised by beacons. 26 | - **scanning** for [Eddystone](http://developer.estimote.com/eddystone/), Estimote Telemetry and Estimote Location packets advertised by beacons, and [Nearable](http://developer.estimote.com/nearables/) packets advertised by stickers. 27 | 28 | ## Monitoring and ranging 29 | 30 | [Monitoring](http://developer.estimote.com/ibeacon/tutorial/part-2-background-monitoring/) can be thought of as a geofence: a virtual barrier, here defined by the range of beacon or a group of beacons. Going in and out of this range triggers events that application can react to. 31 | 32 | [Ranging](http://developer.estimote.com/ibeacon/tutorial/part-3-ranging-beacons/) enables receiving more comprehensive beacon data: identifiers and proximity estimates of the beacons in range. 33 | 34 | To use monitoring and ranging, follow these steps: 35 | 36 | 1. Define beacon regions. 37 | 2. Create a Beacon Manager object. 38 | 3. Connect the Beacon Manager to the beacon scanning service maintained by the Estimote SDK. 39 | 4. Set monitoring and ranging listeners. 40 | 5. Set scan periods. 41 | 6. Start monitoring/ranging for the regions defined earlier. 42 | 43 | ### 1. Define beacon regions 44 | 45 | Beacon regions can be used to specify beacons or groups of beacons that should trigger a monitoring event or be included in the list of ranged devices. You can defined a region using beacon identifiers: 46 | 47 | - **UUID** - most commonly represented as a String, e.g.: `"B9407F30-F5F8-466E-AFF9-25556B57FE6D"` 48 | - **Major** - an unsigned short integer, (1–65535) 49 | - **Minor** - an unsigned short integer, (1–65535) 50 | 51 | You can find UUIDs, majors, and minors of your beacons in [Estimote Cloud](https://cloud.estimote.com). 52 | 53 | Define a Region object like this: 54 | 55 | ```java 56 | Region mintBeaconRegion = new Region("Mint beacon", 57 | UUID.fromString("B9407F30-F5F8-466E-AFF9-25556B57FE6D"), 24515, 28667); 58 | ``` 59 | 60 | You don't have to pass all three values—e.g., your region can be based on UUID only (skip other values by passing null): 61 | 62 | ```java 63 | Region allBeaconsRegion = new Region("Beacons with default Estimote UUID", 64 | UUID.fromString("B9407F30-F5F8-466E-AFF9-25556B57FE6D"), null, null); 65 | ``` 66 | 67 | The available combinations are: UUID + major + minor, UUID + major, UUID alone, or none of it. 68 | 69 | ### 2. Create a Beacon Manager object 70 | 71 | As you might need to reuse the Beacon Manager in many activities or fragments, it's a good practice to store an instance of it in your Application's subclass: 72 | 73 | ```java 74 | public class MyApplication extends Application { 75 | 76 | private BeaconManager beaconManager; 77 | 78 | @Override 79 | public void onCreate() { 80 | super.onCreate(); 81 | beaconManager = new BeaconManager(getApplicationContext()); 82 | } 83 | } 84 | ``` 85 | 86 | Make sure that you add your `Application` subclass to `AndroidManifest.xml`: 87 | 88 | ```xml 89 | 96 | ``` 97 | 98 | ### 3. Connect to the beacon scanning service 99 | 100 | Once you create the Beacon Manager object, you need to connect it to the **beacon service** that is responsible for performing BLE scanning operations. You can simply do it by invoking the `connect` method. Pass a `ServiceReadyCallback` to receive information when mentioned service is ready to use. 101 | 102 | ```java 103 | @Override 104 | public void onCreate() { 105 | super.onCreate(); 106 | beaconManager = new BeaconManager(getApplicationContext()); 107 | beaconManager.connect(new BeaconManager.ServiceReadyCallback() { 108 | @Override 109 | public void onServiceReady() { 110 | // Ready to start scanning! 111 | } 112 | }); 113 | } 114 | ``` 115 | 116 | Make sure that the `beaconManager`'s connection scope is strictly related to the lifecycle of its encompassing application (or activity, or fragment). 117 | 118 | ### 4. Set monitoring and ranging listeners 119 | 120 | Beacon Manager offers a variety of listeners that facilitate detecting beacons. 121 | 122 | #### Monitoring listener 123 | 124 | Monitoring listener enables you to subscribe to monitoring events, such as entering and exiting the range of beacons in a Region. 125 | 126 | ```java 127 | beaconManager.setMonitoringListener(new BeaconManager.MonitoringListener() { 128 | @Override 129 | public void onEnteredRegion(Region region, List list) { 130 | // ... 131 | } 132 | 133 | @Override 134 | public void onExitedRegion(Region region) { 135 | // ... 136 | } 137 | }); 138 | ``` 139 | 140 | #### Ranging listener 141 | 142 | Ranging listener enables you to subscribe to a continuous (by default: every second) stream of ranging events, which provides a detailed list of beacons detected in range, their full identifiers, and relative proximity to them. If a beacon goes out of range, it will disappear from the list. 143 | 144 | ```java 145 | beaconManager.setRangingListener(new BeaconManager.RangingListener() { 146 | @Override 147 | public void onBeaconsDiscovered(Region region, List beacons) { 148 | if (beacons.size() != 0) { 149 | Beacon beacon = beacons.get(0); 150 | // ... 151 | } 152 | } 153 | }); 154 | ``` 155 | 156 | ### 5. Set scan periods 157 | 158 | To conserve the host device's battery, Estimote SDK doesn't continuously scan for beacons. Instead, it cycles between periods of scanning and waiting. You can adjust the duration of these two periods with two methods listed below. Bear in mind that these values are only a hint—the internal Bluetooth stack of the device might shorten or extend the scan period. 159 | 160 | - **monitoring**: `setBackgroundScanPeriod(long scanPeriodMillis, long waitTimeMillis)` 161 | - **ranging**: `setForegroundScanPeriod(long scanPeriodMillis, long waitTimeMillis)` 162 | 163 | For example, to increase responsiveness of monitoring events, you may set the `scanPeriod` to 5 seconds and the `waitTime` to 10 seconds. 164 | 165 | ```java 166 | beaconManager.setBackgroundScanPeriod(5000, 10000); 167 | ``` 168 | 169 | Just keep in mind that shortening the cycle can increase the battery drain. 170 | 171 | If not sure what to do, leave these two methods out. The default values were picked carefully to provide a good balance between responsiveness and battery usage. 172 | 173 | ### 6. Start monitoring/ranging 174 | 175 | Once you set monitoring and ranging listeners you can start monitoring and ranging using the regions you defined earlier. 176 | 177 | ```java 178 | @Override 179 | public void onCreate() { 180 | super.onCreate(); 181 | beaconManager = new BeaconManager(getApplicationContext()); 182 | beaconManager.setMonitoringListener(/* ... */); 183 | beaconManager.setRangingListener(/* ... */); 184 | // beaconManager.setBackgroundScanPeriod(5000, 10000); 185 | beaconManager.connect(new BeaconManager.ServiceReadyCallback() { 186 | @Override 187 | public void onServiceReady() { 188 | // Ready to start scanning! 189 | beaconManager.startMonitoring(allBeaconsRegion); 190 | // beaconManager.startRanging(defaultUUIDRegion); 191 | } 192 | }); 193 | } 194 | ``` 195 | 196 | #### Hint: ranging only when in range of beacons 197 | 198 | Since ranging is much more energy-intensive than monitoring, it's a good practice to only do it when you know (thanks to monitoring) that you're in range of some beacons: 199 | 200 | ```java 201 | private void setMonitoringListener() { 202 | beaconManager.setMonitoringListener(new BeaconManager.MonitoringListener() { 203 | @Override 204 | public void onEnteredRegion(Region region, List list) { 205 | beaconManager.startRanging(region); 206 | } 207 | 208 | @Override 209 | public void onExitedRegion(Region region) { 210 | beaconManager.stopRanging(region); 211 | } 212 | }); 213 | } 214 | ``` 215 | 216 | #### Dealing with many onExit/onEnter events 217 | 218 | Accuracy of monitoring mostly depends on device's hardware and low level bluetooth stack implementation. Because of that, monitoring sometimes calls many onExit/onEnter events millis apart. There is no golden rule which applies to every Android device, so you need to tweak this by yourself - but don't worry, our SDK provides you with tools for doing that. 219 | First of all, you need to know, that beacon advertising interval is also affecting user experience. Setting your beacon to `200ms-300ms` interval is the best practice. Greater values might cause user phone to be less effective while scanning. 220 | On SDK side, you can tweak your background scan interval and wait period. The shorter they are, the more accurate scaning will be. Keep in mind, that short interval increases battery drain. 221 | Our internal engine tracks each beacon occurance, applies smoothing algorithms and does a lot of job to provide you with the best result possible. Unfortunately, we are not responsible for scan results returned by low-level bluetooth stack. We tested that on many devices, and some returns proper scan values, and some returns scans with large delay. To deal with that, we encourage you to play with public method `setRegionExitExpiration(long period)` in BeaconManager class. In that way, once visible beacon must not be seen for more then `long period` time. Bear in mind, that this will affect accuracy of onExit region event. For your information, our SDK default value for region expiration is set to `20s`. 222 | 223 | ## Scanning 224 | 225 | Android SDK supports scanning for devices that broadcast [Eddystone](http://developer.estimote.com/eddystone/), Estimote Telemetry, Estimote Location, and [Nearable](http://developer.estimote.com/nearables/) packets. 226 | 227 | Since scanning is similar in nature to ranging, it uses the `setForegroundScanPeriod` settings. 228 | 229 | ### Eddystone 230 | 231 | [Eddystone](http://developer.estimote.com/eddystone/) is an open Bluetooth 4.0 protocol from Google that is designed to support multiple data packet types such as **Eddystone-UID** or **Eddystone-URL**. Estimote Beacons are fully compatible with Eddystone. 232 | 233 | To start scanning for [Eddystone](http://developer.estimote.com/eddystone/) packets: 234 | 235 | - Set an `EddystoneListener`: 236 | 237 | ```java 238 | beaconManager.setEddystoneListener(new BeaconManager.EddystoneListener() { 239 | @Override 240 | public void onEddystonesFound(List eddystones) { 241 | // ... 242 | } 243 | }); 244 | ``` 245 | 246 | - Start scanning for Eddystone devices. Make sure that you store the `scanId` value—you will need it later to stop scanning: 247 | 248 | ```java 249 | public class MyActivity extends Activity { 250 | 251 | private BeaconManager beaconManager; 252 | private String scanId; 253 | 254 | @Override 255 | protected void onCreate() { 256 | super.onCreate(); 257 | beaconManager = new BeaconManager(this); 258 | beaconManager.setEddystoneListener(/* ... */); 259 | } 260 | 261 | @Override 262 | protected void onStart() { 263 | super.onStart(); 264 | beaconManager.connect(new BeaconManager.ServiceReadyCallback() { 265 | @Override 266 | public void onServiceReady() { 267 | scanId = beaconManager.startEddystoneScanning(); 268 | } 269 | }); 270 | } 271 | 272 | @Override 273 | protected void onStop() { 274 | super.onStop(); 275 | beaconManager.stopEddystoneScanning(scanId); 276 | } 277 | } 278 | ``` 279 | 280 | ### Nearable 281 | 282 | [Nearable](http://developer.estimote.com/nearables/) is the main advertising packet of Estimote Stickers. Apart from the sticker's 16-byte identifier, it includes sensor data (motion, temperature) and sticker's health data (battery voltage, firmware version). 283 | 284 | To start scanning for [Nearables](http://developer.estimote.com/nearables/): 285 | 286 | - Set a `NearableListener`: 287 | 288 | ```java 289 | beaconManager.setNearableListener(new BeaconManager.NearableListener() { 290 | @Override 291 | public void onNearablesDiscovered(List nearables) { 292 | // ... 293 | } 294 | }); 295 | ``` 296 | 297 | - Start scanning for Nearable devices. Make sure that you store the `scanId` value—you will need it later to stop scanning: 298 | 299 | ```java 300 | public class MyActivity extends Activity { 301 | 302 | private BeaconManager beaconManager; 303 | private String scanId; 304 | 305 | @Override 306 | protected void onCreate() { 307 | super.onCreate(); 308 | beaconManager = new BeaconManager(this); 309 | beaconManager.setNearableListener(/* ... */); 310 | } 311 | 312 | @Override 313 | protected void onStart() { 314 | super.onStart(); 315 | beaconManager.connect(new BeaconManager.ServiceReadyCallback() { 316 | @Override 317 | public void onServiceReady() { 318 | scanId = beaconManager.startNearableDiscovery(); 319 | } 320 | }); 321 | } 322 | 323 | @Override 324 | protected void onStop() { 325 | super.onStop(); 326 | beaconManager.stopNearableDiscovery(scanId); 327 | } 328 | } 329 | ``` 330 | 331 | ### Estimote Telemetry 332 | 333 | To start scanning for Estimote Telemetry packets: 334 | 335 | - Set a `TelemetryListener`: 336 | 337 | ```java 338 | beaconManager.setTelemetryListener(new BeaconManager.TelemetryListener() { 339 | @Override 340 | public void onTelemetriesFound(List telemetries) { 341 | // ... 342 | } 343 | }); 344 | ``` 345 | 346 | - Start scanning for Estimote Telemetry packets. Make sure that you store the `scanId` value—you will need it later to stop scanning: 347 | 348 | ```java 349 | public class MyActivity extends Activity { 350 | 351 | private BeaconManager beaconManager; 352 | private String scanId; 353 | 354 | @Override 355 | protected void onCreate() { 356 | super.onCreate(); 357 | beaconManager = new BeaconManager(this); 358 | beaconManager.setTelemetryListener(/* ... */); 359 | } 360 | 361 | @Override 362 | protected void onStart() { 363 | super.onStart(); 364 | beaconManager.connect(new BeaconManager.ServiceReadyCallback() { 365 | @Override 366 | public void onServiceReady() { 367 | scanId = beaconManager.startTelemetryDiscovery(); 368 | } 369 | }); 370 | } 371 | 372 | @Override 373 | protected void onStop() { 374 | super.onStop(); 375 | beaconManager.stopTelemetryDiscovery(scanId); 376 | } 377 | } 378 | ``` 379 | 380 | ### Estimote Location 381 | 382 | To start scanning for Estimote Location packets: 383 | 384 | - Set a `LocationListener`: 385 | 386 | ```java 387 | beaconManager.setLocationListener(new BeaconManager.LocationListener() { 388 | @Override 389 | public void onLocationsFound(List locations) { 390 | // ... 391 | } 392 | }); 393 | ``` 394 | 395 | - Start scanning for Estimote Location packets. Make sure that you store the `scanId` value—you will need it later to stop scanning: 396 | 397 | ```java 398 | public class MyActivity extends Activity { 399 | 400 | private BeaconManager beaconManager; 401 | private String scanId; 402 | 403 | @Override 404 | protected void onCreate() { 405 | super.onCreate(); 406 | beaconManager = new BeaconManager(this); 407 | beaconManager.setLocationListener(/* ... */); 408 | } 409 | 410 | @Override 411 | protected void onStart() { 412 | super.onStart(); 413 | beaconManager.connect(new BeaconManager.ServiceReadyCallback() { 414 | @Override 415 | public void onServiceReady() { 416 | scanId = beaconManager.startLocationDiscovery(); 417 | } 418 | }); 419 | } 420 | 421 | @Override 422 | protected void onStop() { 423 | super.onStop(); 424 | beaconManager.stopLocationDiscovery(scanId); 425 | } 426 | } 427 | ``` 428 | -------------------------------------------------------------------------------- /Docs/DOC_multiadvertisers.md: -------------------------------------------------------------------------------- 1 | # Multiple advertisers 2 | Estimote Location Beacons are able to advertise multiple data packets simultaneously. Here is a full list of featured advertisers: 3 | 1. Connectivity 4 | 2. Estimote Telemetry 5 | 3. Estimote Location 6 | 4. iBeacon 7 | 5. Eddystone UID 8 | 6. Eddystone URL 9 | 7. Eddystone Telemetry 10 | 11 | You can adjust each advertiser to have its own Tx power and advertising interval. You can set advertising interval in the range of `100 - 10000 ms` and Tx power as one of the allowed values: `-30, -20, -16, -12, -8, -4, 0, 4 dBm` 12 | ### Connectivity 13 | Estimote Connectivity packet lets you connect to a beacon. You can adjust its interval and power using `get()` and `set()` methods. This advertiser is always on and cannot be disabled. 14 | ```Java 15 | int txPower = -8; 16 | connection.settings.estimote.connectivity.transmitPower().set(txPower, new SettingCallback() {...}); 17 | ``` 18 | ```Java 19 | int advertisingInterval = 1000; 20 | connection.settings.estimote.connectivity.advertisingInterval().set(advertisingInterval, new SettingCallback(){...}); 21 | ``` 22 | ### Estimote Telemetry 23 | Estimote Telemetry advertiser provides information from beacon's sensors and GPIO. You can enable/disable it by using `set()` method: 24 | ```Java 25 | boolean enable = true; 26 | connection.settings.estimote.telemetry.enable().set(enable, new SettingCallback() { 27 | @Override 28 | public void onSuccess(Boolean value) { 29 | // Handle success here 30 | } 31 | 32 | @Override 33 | public void onFailure(DeviceConnectionException exception) { 34 | // Handle failure here 35 | } 36 | }); 37 | ``` 38 | You can also modify Tx power and advertising interval: 39 | ```Java 40 | int txPower = -8; 41 | connection.settings.estimote.telemetry.transmitPower().set(txPower, new SettingCallback() {...}); 42 | ``` 43 | ```Java 44 | int advertisingInterval = 1000; 45 | connection.settings.estimote.telemetry.advertisingInterval().set(txPower, new SettingCallback() {...}); 46 | ``` 47 | 48 | ### Estimote Location 49 | Beacon measured power advertiser. For getting distance to device. 50 | ```Java 51 | connection.settings.estimote.location.enable() 52 | ``` 53 | Modifying transmit power: 54 | ```Java 55 | int txPower = -8; 56 | connection.settings.estimote.location.transmitPower().set(txPower, new SettingCallback() {...}); 57 | ``` 58 | Modifying advertising interval: 59 | ```Java 60 | int advertisingInterval = 1000; 61 | connection.settings.estimote.location.advertisingInterval().set(txPower, new SettingCallback() {...}); 62 | ``` 63 | 64 | ### iBeacon 65 | Using and modifying iBeacon advertiser is also possible with our SDK. Here is how you can enable your iBeacon advertising: 66 | ```Java 67 | boolean enable = true; 68 | connection.settings.beacon.enable().set(enable, new SettingCallback() { 69 | @Override 70 | public void onSuccess(Boolean value) { 71 | // Handle success here 72 | } 73 | 74 | @Override 75 | public void onFailure(DeviceConnectionException exception) { 76 | // Handle failure here 77 | } 78 | }); 79 | ``` 80 | By default, Apple's iBeacon protocol has interval fixed at `100 ms`. We strongly recommend using this default value for optimal ranging/monitoring performance. 81 | If you want to change it, you need to turn your beacon into **non-strict mode**. Beacons in **non-strict mode** technically are not considered iBeacon-enabled by they are compatible with iBeacon apps: 82 | ```Java 83 | boolean enable = true; 84 | connection.settings.beacon.nonStrictMode().set(enable, new SettingCallback() { 85 | @Override 86 | public void onSuccess(Boolean value) { 87 | // Handle success here 88 | } 89 | 90 | @Override 91 | public void onFailure(DeviceConnectionException exception) { 92 | // Handle failure here 93 | } 94 | }); 95 | ``` 96 | Then you will be able to change advertising interval: 97 | ```Java 98 | int advertisingInterval = 1000; 99 | connection.settings.estimote.beacon.advertisingInterval().set(txPower, new SettingCallback() {...}); 100 | ``` 101 | Beside of that, you can always modify your transmit power: 102 | ```Java 103 | int txPower = -8; 104 | connection.settings.estimote.beacon.transmitPower().set(txPower, new SettingCallback() {...}); 105 | ``` 106 | Changing beacon proximity UUID: 107 | ```Java 108 | UUID newUUID = UUID.randomUUID(); 109 | connection.settings.beacon.proximityUUID().set(newUUID, new SettingCallback() { 110 | @Override 111 | public void onSuccess(UUID value) { 112 | // Handle success here 113 | } 114 | 115 | @Override 116 | public void onFailure(DeviceConnectionException exception) { 117 | // Handle failure here 118 | } 119 | }); 120 | ``` 121 | Changing **minor** and **major**: 122 | ```Java 123 | int minor = 1000; 124 | connection.settings.beacon.minor().set(minor, new SettingCallback() { 125 | @Override 126 | public void onSuccess(Integer value) { 127 | // Handle success here 128 | } 129 | 130 | @Override 131 | public void onFailure(DeviceConnectionException exception) { 132 | // Handle failure here 133 | } 134 | }); 135 | ``` 136 | ```Java 137 | int major = 2000; 138 | connection.settings.beacon.major().set(major, new SettingCallback() { 139 | @Override 140 | public void onSuccess(Integer value) { 141 | // Handle success here 142 | } 143 | 144 | @Override 145 | public void onFailure(DeviceConnectionException exception) { 146 | // Handle failure here 147 | } 148 | }); 149 | ``` 150 | Enabling **secure mode**: 151 | ```Java 152 | boolean enable = true; 153 | connection.settings.beacon.secure().set(enable, new SettingCallback() { 154 | @Override 155 | public void onSuccess(Boolean value) { 156 | // Handle success here 157 | } 158 | 159 | @Override 160 | public void onFailure(DeviceConnectionException exception) { 161 | // Handle failure here 162 | } 163 | }); 164 | ``` 165 | You can also enable **motion UUID** - it advertises different UUID when the beacon is in motion: 166 | ```Java 167 | boolean enable = true; 168 | connection.settings.beacon.enableMotionUUID().set(enable, new SettingCallback() { 169 | @Override 170 | public void onSuccess(Boolean value) { 171 | // Handle success here 172 | } 173 | 174 | @Override 175 | public void onFailure(DeviceConnectionException exception) { 176 | // Handle failure here 177 | } 178 | }); 179 | ``` 180 | 181 | ### Eddystone 182 | Eddystone packets can be modified using `set()` and `get()` methods as in examples above. For more info about each Eddystone packet please read [our article](http://developer.estimote.com/eddystone/). 183 | 184 | #### Eddystone UID 185 | ```Java 186 | boolean enable = true; 187 | connection.settings.eddystone.uid.enable().set(enable, new SettingCallback() {...}); 188 | ``` 189 | Modifying advertising interval: 190 | ```Java 191 | int advertisingInterval = 1000; 192 | connection.settings.eddystone.uid.advertisingInterval().set(advertisingInterval, new SettingCallback() {...}); 193 | ``` 194 | Modifying transmit power: 195 | ```Java 196 | int txPower = -8; 197 | connection.settings.eddystone.uid.transmitPower().set(txPower, new SettingCallback() {...}); 198 | ``` 199 | Modifying namespace: 200 | ```Java 201 | String namespace = "EDD1EBEAC04E5DEFA017"; 202 | connection.settings.eddystone.uid.namespace().set(namespace, new SettingCallback() { 203 | @Override 204 | public void onSuccess(String value) { 205 | // Handle success here 206 | } 207 | 208 | @Override 209 | public void onFailure(DeviceConnectionException exception) { 210 | // Handle failure here 211 | } 212 | }); 213 | ``` 214 | Modifying instance: 215 | ```Java 216 | String instance = "0BDB87539B67"; 217 | connection.settings.eddystone.uid.instance().set(instance, new SettingCallback() { 218 | @Override 219 | public void onSuccess(String value) { 220 | // Handle success here 221 | } 222 | 223 | @Override 224 | public void onFailure(DeviceConnectionException exception) { 225 | // Handle failure here 226 | } 227 | }); 228 | ``` 229 | #### Eddystone URL 230 | ```Java 231 | boolean enable = true; 232 | connection.settings.eddystone.url.enable().set(enable, new SettingCallback() { 233 | @Override 234 | public void onSuccess(Boolean value) { 235 | // Handle success here 236 | } 237 | 238 | @Override 239 | public void onFailure(DeviceConnectionException exception) { 240 | // Handle failure here 241 | } 242 | }); 243 | ``` 244 | Modifying transmit power: 245 | ```Java 246 | int txPower = -8; 247 | connection.settings.eddystone.url.transmitPower().set(txPower, new SettingCallback() {...}); 248 | ``` 249 | Modifying advertising interval: 250 | ```Java 251 | int advertisingInterval = 1000; 252 | connection.settings.eddystone.url.advertisingInterval(advertisingInterval, new SettingCallback() {...}); 253 | ``` 254 | Modifying url value: 255 | ```Java 256 | String url = "http://estimote.com"; 257 | connection.settings.eddystone.url.url().set(url, new SettingCallback() { 258 | @Override 259 | public void onSuccess(String value) { 260 | // Handle success here 261 | } 262 | 263 | @Override 264 | public void onFailure(DeviceConnectionException exception) { 265 | // Handle failure here 266 | } 267 | }); 268 | ``` 269 | #### Eddystone Telemetry 270 | ```Java 271 | boolean enable = true; 272 | connection.settings.eddystone.tlm.enable().set(enable, new SettingCallback() { 273 | @Override 274 | public void onSuccess(Boolean value) { 275 | // Handle success here 276 | } 277 | 278 | @Override 279 | public void onFailure(DeviceConnectionException exception) { 280 | // Handle failure here 281 | } 282 | }); 283 | ``` 284 | Modifying transmit power: 285 | ```Java 286 | int txPower = -8; 287 | connection.settings.eddystone.tlm.transmitPower().set(txPower, new SettingCallback() {...}); 288 | ``` 289 | Modifying advertising interval: 290 | ```Java 291 | int advertisingInterval = 1000; 292 | connection.settings.eddystone.tlm.advertisingInterval(advertisingInterval, new SettingCallback() {...}); 293 | ``` 294 | -------------------------------------------------------------------------------- /Docs/DOC_telemetry.md: -------------------------------------------------------------------------------- 1 | ## Using telemetry advertiser 2 | 3 | Estimote Location Beacons can broadcast Estimote Telemetry data packet, which gives you extra information from sensors and GPIO. This packet uses its own advertiser - you can easily enable/disable it and change its advertising interval and Tx power. 4 | 5 | ### Enabling telemetry 6 | If you want your beacon to advertise telemetry packets, you need a **DeviceConnection** object with an opened connection. You can get it from **DeviceConnectionProvider** in your activity. More about creating stable connection to your own devices can be found [here](/Docs/DOC_deviceConnection.md). 7 | ```Java 8 | DeviceConnection connection = connectionProvider.getConnection(device); 9 | connection.connect(new DeviceConnectionCallback(){...}); 10 | ``` 11 | Then you can change beacon settings to enable telemetry advertising. 12 | ```Java 13 | boolean enable = true; 14 | connection.settings.estimote.telemetry.enable().set(enable, new SettingCallback() { 15 | @Override 16 | public void onSuccess(Boolean value) { 17 | // Handle success here 18 | } 19 | 20 | @Override 21 | public void onFailure(DeviceConnectionException exception) { 22 | // Handle failure here 23 | } 24 | }); 25 | ``` 26 | 27 | ### Adjusting telemetry advertising interval 28 | ```Java 29 | int advertisingInterval = 1000; 30 | connection.settings.estimote.telemetry.advertisingInterval().set(advertisingInterval, new SettingCallback() { 31 | @Override 32 | public void onSuccess(Integer value) { 33 | // Handle setting success here 34 | } 35 | 36 | @Override 37 | public void onFailure(DeviceConnectionException exception) { 38 | // Handle failure here 39 | } 40 | }); 41 | ``` 42 | 43 | ### Adjusting telemetry transmit power 44 | ```Java 45 | int txPower = 4; 46 | connection.settings.estimote.telemetry.transmitPower().set(txPower, new SettingCallback() { 47 | @Override 48 | public void onSuccess(Integer value) { 49 | // Handle setting success here 50 | } 51 | 52 | @Override 53 | public void onFailure(DeviceConnectionException exception) { 54 | // Handle failure here 55 | } 56 | }); 57 | 58 | ``` 59 | -------------------------------------------------------------------------------- /Docs/DOC_thirdPartyLicenses.md: -------------------------------------------------------------------------------- 1 | ### Attribution 2 | Here is the list of licenses for third-party libraries used in Estimote SDK for Android: 3 | 1. Nordic DFU Library for Android - [license](https://github.com/NordicSemiconductor/Android-DFU-Library/blob/release/LICENSE) 4 | 2. Gson - [license](https://github.com/google/gson/blob/master/LICENSE) 5 | 3. Jtar - [license](https://github.com/kamranzafar/jtar/blob/master/LICENSE.txt) 6 | 4. Okhttp - [license](https://github.com/square/okhttp/blob/master/LICENSE.txt) 7 | 5. Okio - [license](https://github.com/square/okio/blob/master/LICENSE.txt) 8 | 6. Retrofit - [license](https://github.com/square/retrofit/blob/master/LICENSE.txt) 9 | -------------------------------------------------------------------------------- /Docs/manual_installation.md: -------------------------------------------------------------------------------- 1 | # Estimote SDK for android manual installation 2 | 3 | *Eclipse users:* Mark Murphy [on his blog explained](https://commonsware.com/blog/2014/07/03/consuming-aars-eclipse.html) how to use `aar` format in Eclipse. 4 | 5 | 1. Create `libs` directory inside your project and copy there [estimote-sdk.aar](https://github.com/Estimote/Android-SDK/blob/master/EstimoteSDK/estimote-sdk.aar). 6 | 2. In your `build.gradle` add `flatDir` entry to your repositories 7 | 8 | ```groovy 9 | repositories { 10 | mavenCentral() 11 | flatDir { 12 | dirs 'libs' 13 | } 14 | } 15 | ``` 16 | 3. Add dependency to Estimote SDK. All needed permissions (`BLUETOOTH`, `BLUETOOTH_ADMIN` and `INTERNET`) and services will be merged from SDK's `AndroidManifest.xml` to your application's `AndroidManifest.xml`. 17 | 18 | ```groovy 19 | dependencies { 20 | compile(name:'estimote-sdk', ext:'aar') 21 | } 22 | ``` 23 | 4. Initialize Estimote SDK in your Application class onCreate() method - if you are using [Estimote Cloud](http://cloud.estimote.com): 24 | 25 | ```java 26 | // App ID & App Token can be taken from App section of Estimote Cloud. 27 | EstimoteSDK.initialize(applicationContext, appId, appToken); 28 | // Optional, debug logging. 29 | EstimoteSDK.enableDebugLogging(true); 30 | ``` 31 | -------------------------------------------------------------------------------- /Docs/quick_snippets.md: -------------------------------------------------------------------------------- 1 | ## Nearables quick start 2 | 3 | ```java 4 | private BeaconManager beaconManager = new BeaconManager(context); 5 | 6 | // Should be invoked in #onCreate. 7 | beaconManager.setNearableListener(new BeaconManager.NearableListener() { 8 | @Override 9 | public void onNearablesDiscovered(List nearables) { 10 | Log.d(TAG, "Discovered nearables: " + nearables); 11 | } 12 | }); 13 | 14 | // Should be invoked in #onStart. 15 | beaconManager.connect(new BeaconManager.ServiceReadyCallback() { 16 | @Override 17 | public void onServiceReady() { 18 | beaconManager.startNearableDiscovery(); 19 | } 20 | }); 21 | 22 | // Should be invoked in #onStop. 23 | beaconManager.stopNearableDiscovery(); 24 | 25 | // When no longer needed. Should be invoked in #onDestroy. 26 | beaconManager.disconnect(); 27 | ``` 28 | 29 | ## Secure UUID quick start 30 | 31 | Ranging and region monitoring works transparently with [Secure UUID](https://community.estimote.com/hc/en-us/articles/201371053-What-security-features-does-Estimote-offer-How-does-Secure-UUID-work-) enabled beacons. All you need is: 32 | 33 | 1. Enable _Secure UUID_ via [Estimote app](https://play.google.com/store/apps/details?id=com.estimote.apps.main&hl=en) from Google Play or via SDK 34 | 35 | ```java 36 | DeviceConnection connection = connectionProvider.getConnection(device); 37 | boolean enable = true; 38 | connection.settings.beacon.secure().set(enable, new SettingCallback() { 39 | @Override 40 | public void onSuccess(Boolean value) { 41 | // Handle success here 42 | } 43 | 44 | @Override 45 | public void onFailure(DeviceConnectionException exception) { 46 | // Handle failure here 47 | } 48 | }); 49 | ``` 50 | 51 | 2. Make sure you have initialised SDK with your App ID & App Token. 52 | ```java 53 | // App ID & App Token can be taken from App section of Estimote Cloud. 54 | EstimoteSDK.initialize(applicationContext, appId, appToken); 55 | ``` 56 | 57 | 3. Use `SecureBeaconRegion` instead of `BeaconRegion` when starting ranging or monitoring. 58 | 59 | ```java 60 | // Initialise BeaconManager as before. 61 | // Find all *your* Secure UUID beacons in the vicinity. 62 | beaconManager.startRanging(new SecureBeaconRegion(“regionId”, null, null, null)); 63 | 64 | // Remember that you can also range for other regions as well. 65 | beaconManager.startRanging(new BeaconRegion(“otherRegion”, null, null, null); 66 | ``` 67 | 68 | ## Eddystone quick start 69 | 70 | [Eddystone](https://developers.google.com/beacons) is an open protocol BLE protocol from Google. Estimote Beacons can broadcast the Eddystone packet. 71 | 72 | With Estimote SDK you can: 73 | - find nearby Eddystone beacons (`beaconManager.startEddystoneScanning()`) 74 | - configure Eddystone ralated properties: 75 | - URL property of `Eddystone-URL` (see `BeaconConnection#eddystoneUrl`) 76 | - namespace & instance properties of `Eddystone-UID` (see `BeaconConnection#eddystoneNamepsace`, `BeaconConnection#eddystoneInstance`) 77 | - configure broadcasting scheme of beacon to `Estimote Default`, `Eddystone-UID` or `Eddystone-URL` (see `BeaconConnection#broadcastingScheme`) 78 | 79 | [SDK Examples](https://github.com/Estimote/Android-SDK/tree/master/Examples) contains Eddystone related samples. 80 | 81 | Note that you can play with Estimote Beacons broadcasting the Eddystone packet and change their configuration via [Estimote app on Google Play](https://play.google.com/store/apps/details?id=com.estimote.apps.main). 82 | 83 | In order to start playing with Eddystone you need to update firmware of your existing Estimote beacons to at least `3.1.1`. Easiest way is through [Estimote app on Google Play](https://play.google.com/store/apps/details?id=com.estimote.apps.main). 84 | Then you can change broadcasting scheme on your beacon to Eddystone-URL or Eddystone-UID. 85 | 86 | Following code snippet shows you how you can start discovering nearby Estimote beacons broadcasting Eddystone packet. 87 | 88 | ```java 89 | private BeaconManager beaconManager = new BeaconManager(context); 90 | 91 | // Should be invoked in #onCreate. 92 | beaconManager.setEddystoneListener(new BeaconManager.EddystoneListener() { 93 | @Override 94 | public void onEddystonesFound(List eddystones) { 95 | Log.d(TAG, "Nearby Eddystone beacons: " + eddystones); 96 | } 97 | }); 98 | 99 | // Should be invoked in #onStart. 100 | beaconManager.connect(new BeaconManager.ServiceReadyCallback() { 101 | @Override 102 | public void onServiceReady() { 103 | beaconManager.startEddystoneScanning(); 104 | } 105 | }); 106 | 107 | // Should be invoked in #onStop. 108 | beaconManager.stopEddystoneScanning(); 109 | 110 | // When no longer needed. Should be invoked in #onDestroy. 111 | beaconManager.disconnect(); 112 | ``` 113 | 114 | ## Connecting to your devices quick start 115 | 116 | At first, you will need to scan for configurable devices around you: 117 | 118 | ```Java 119 | BeaconManager beaconManager = new BeaconManager(this); 120 | // set foreground scan periods. This one will scan for 2s and wait 2s 121 | beaconManager.setForegroundScanPeriod(2000, 2000); 122 | // connects beacon manager to underlying service 123 | beaconManager.connect(new BeaconManager.ServiceReadyCallback() { 124 | @Override 125 | public void onServiceReady() { 126 | // add listener for ConfigurableDevice objects 127 | beaconManager.setConfigurableDevicesListener(new BeaconManager.ConfigurableDevicesListener() { 128 | @Override 129 | public void onConfigurableDevicesFound(List configurableDevices) { 130 | // handle the configurable device here. You can use it to acquire connection from DeviceConnectionProvider 131 | } 132 | }); 133 | beaconManager.startConfigurableDevicesDiscovery(); 134 | ``` 135 | 136 | Once you have your `ConfigurableDevice` object, you want to acquire `DeviceConnection` for it. To do that, you need to be connected to `DeviceConnectionProvider`. 137 | It creates simple service that lets you handle multiple connections at once. This provider is bound to your context, so you only need to connect once during your context lifetime. Here is how to do that in your activity `onCreate` method: 138 | 139 | ```Java 140 | @Override 141 | protected void onCreate(Bundle savedInstanceState) { 142 | DeviceConnectionProvider connectionProvider = new DeviceConnectionProvider(this); 143 | connectionProvider.connectToService(new DeviceConnectionProvider.ConnectionProviderCallback() { 144 | @Override 145 | public void onConnectedToService() { 146 | // Handle your actions here. You are now connected to connection service. 147 | // For example: you can create DeviceConnection object here from connectionProvider. 148 | }); 149 | } 150 | ``` 151 | Remember to call `connectionProvider.destroy()` method in your activity `onDestroy()`: 152 | 153 | ```Java 154 | @Override 155 | protected void onDestroy() { 156 | connectionProvider.destroy(); 157 | super.onDestroy(); 158 | } 159 | ``` 160 | 161 | When your Activity is connected to `ConnectionProvider`, and you got your `ConfigurableDevice` object, you can now try to establish device connection. Doing that is really easy from now on: 162 | ```Java 163 | // Pass your ConfigurableDevice to connection provider method 164 | DeviceConnection connection = connectionProvider.getConnection(device); 165 | connection.connect(new DeviceConnectionCallback() { 166 | @Override 167 | public void onConnected() { 168 | // Do something with your connection. 169 | // You can for example read device settings, or make an firmware update. 170 | Log.d("DeviceConnection", "onConnected"); 171 | } 172 | 173 | @Override 174 | public void onDisconnected() { 175 | // Every time your device gets disconnected, you can handle that here. 176 | // For example: in this state you can try reconnecting to your device. 177 | Log.d("DeviceConnection", "onDisconnected"); 178 | } 179 | 180 | @Override 181 | public void onConnectionFailed(DeviceConnectionException exception) { 182 | // Handle every connection error here. 183 | Log.d("DeviceConnection", "onConnectionFailed"); 184 | } 185 | }); 186 | ``` 187 | Now you can use `DeviceConnection` object to communicate with a configurable device. Remember that every time your connection fails, your `DeviceConnectionCallback` needs to handle that. 188 | 189 | Don't worry about connection state while switching application context - after first creation, your connection is always kept in the underlying service. Launching new activity and creating new `DeviceConnection` object for the same `ConfigurableDevice` only adds new observers to current connection. 190 | If you only want to detach your activity callbacks from connection, just use `connection.destroy()` method in your activity `onDestroy()` method: 191 | ```Java 192 | @Override 193 | protected void onDestroy() { 194 | super.onDestroy(); 195 | connection.destroy(); 196 | } 197 | ``` 198 | 199 | To completely close the underlying connection just call: 200 | ```Java 201 | connection.close() 202 | ``` 203 | From now on, if any application context holds active `DeviceConnectionCallback`, it will have it's `onDisconnected()` called. Of course, it will only happen when you haven't called `connection.destroy()` on that context. Be sure to handle that! 204 | 205 | 206 | ## Bulk updater quick start 207 | 208 | Bulk updater is a stand alone object that takes scans from your ``BeaconManager`` and updates devices that belongs to the user. In basic form it will simply connect to the device and synchronise it with Estimote cloud. This operation can be customised with firmware updates or include custom settings to write. The bulk updater runs constantly and checks if scanned devices have any new changes to apply. 209 | 210 | ### Building bulk updater 211 | 212 | ```Java 213 | BulkUpdater bulkUpdater = new BulkUpdaterBuilder(this) 214 | .withCloudFetchInterval(5, TimeUnit.SECONDS) 215 | .withFirmwareUpdate() 216 | .withRetryCount(3) 217 | .withTimeout(0) 218 | .build() 219 | ``` 220 | `withCloudFetchInterval(long)` - sets how often bulk updater should sync data from the cloud. The shorter this interval is, the quicker new pending settings from the cloud are applied to subsequent devices. The default value is 5 seconds. 221 | 222 | `withFirmwareUpdate()` - allows bulk updater to update firmware of selected devices. This feature is disabled by default. 223 | 224 | `withRetryCount(int)` - specifies how many retries BU should take to update each device. After N unsuccessful attempts, the device status will be reported as `Status.FAILED`. The default value is 3. 225 | 226 | ` withTimeout(long)` - Sets the time after which bulk updater should end its job. It will simply stop updating and fetching data. If the value is 0, the process will run constantly (forever and ever, as long as your battery will last). 227 | 228 | ### Listening to bulk update events 229 | `BulkUpdater` progress is reported via listener interface. You can react on each device status change with the proper UI change. You can pass a listener while starting the `BulkUpdater` - it is recommended to start it in you Activity's `onResume()` method. 230 | 231 | ```Java 232 | @Override 233 | protected void onResume() { 234 | super.onResume(); 235 | bulkUpdater.start(new BulkUpdater.BulkUpdaterCallback() { 236 | @Override 237 | public void onDeviceStatusChange(ConfigurableDevice device, BulkUpdater.Status newStatus, String message) { 238 | // do something here 239 | logTextView.append(device.deviceId + ": " + newStatus); 240 | } 241 | 242 | @Override 243 | public void onFinished(int updatedCount, int failedCount) { 244 | // do something here 245 | logTextView.append("Finished. Updated: " + updatedCount + " Failed: " + failedCount ); 246 | } 247 | 248 | @Override 249 | public void onError(DeviceConnectionException e) { 250 | // do somethign here 251 | logTextView.setText("Error: " + e.getMessage()); 252 | } 253 | }); 254 | } 255 | ``` 256 | You can also stop bulk updater whenever you want. Just use the `stop()` method: 257 | 258 | ```Java 259 | bulkUpdater.stop(); 260 | ``` 261 | DON'T FORGET: Because bulk updater uses an underlying service for handling connection to devices, it is necessary to call `destroy()` on your activity's `onDestroy` method. This will prevent any memory leaks. 262 | 263 | ```Java 264 | @Override 265 | protected void onDestroy() { 266 | super.onPause(); 267 | bulkUpdater.destroy(); 268 | } 269 | ``` 270 | 271 | ### Running scan and passing results to BulkUpdater 272 | You need to have a `BeaconManager` which will scan for `ConfigurableDevice` objects nearby. A list of such objects should be passed after each scan cycle to `BulkUpdater`, where all the magic happens: 273 | 274 | ```Java 275 | beaconManager.setConfigurableDevicesListener(new BeaconManager.ConfigurableDevicesListener() { 276 | @Override 277 | public void onConfigurableDevicesFound(List configurableDevices) { 278 | bulkUpdater.onDevicesFound(configurableDevices); 279 | } 280 | }); 281 | beaconManager.startConfigurableDevicesDiscovery(); 282 | ``` 283 | 284 | And that's all! You can consider temporarily stopping `BeaconManager` scanning while device update is in progress - just check whether any device has changed its state to `Status.UPDATING` and invoke `beaconManager.stopConfigurableDeviceDiscovery()`. 285 | You can also play with scan periods - sometimes scanning every 1 s is not that efficient and is just a waste of energy. You can play with this settings using`beaconManager.setForegroundScanPeriod(long, long)`. 286 | 287 | ### Mesh Gateway 288 | Mesh gateway is a tool build especially to make process of configuration beacons in mesh smooth and easy. 289 | Once you start Mesh Gateway it will automatically synchronize all changes you made on cloud straight to beacons in your mesh. 290 | When changes gets applied to particular beacon then Mesh Gateway will automatically confirm them up to cloud and thus pending settings will be confirmed - pure magic! 291 | 292 | #### Prerequisites 293 | - Android phone hosting Mesh Gateway needs to be in range of at least one beacon in your mesh network. 294 | 295 | #### Implementation 296 | Just like for all other Estimote SDK components, you have to initialize EstimoteSDK to make Mesh Gateway able to work properly: 297 | ```Java 298 | EstimoteSDK.initialize(, "", ""); 299 | ``` 300 | It is also highly recommended to ensure all necessary requirements are granted - In your Activity's onCreate call: 301 | ```Java 302 | SystemRequirementsChecker.checkWithDefaultDialogs(this) 303 | ``` 304 | 305 | Now, lets do the fun part and launch mesh gateway: 306 | ```Java 307 | MeshGatewayHandler gatewayHandler = MeshGateway(applicationContext).startWithSimpleScanner() 308 | ``` 309 | Above command will fire-up Mesh Gateway and give you handler object you can utilize later to stop running gateway: 310 | ```Java 311 | gatewayHandler.stop() 312 | ``` 313 | Gateway - to be able to operate - require BeaconManager and DeviceConnectionManager instances. When Gateway is configured and launched as shown in above snippet then necessary instances will be created internally. No additional steps are required from your side. 314 | However if You already have BeaconManager and/or DeviceConnectionManager instances and you'd like to reuse them, then you can launch Mesh gateway as follows: 315 | 316 | ```Java 317 | MeshGatewayHandler gatewayHandler = MeshGateway(applicationContext) 318 | .withBeaconManager() 319 | .withDeviceConnectionProvider() 327 | ``` 328 | 329 | When launched this way, Gateway will boot-up foreground service with notification you supplied and schedule it internal logic inside it. 330 | 331 | 332 | 333 | 334 | -------------------------------------------------------------------------------- /Docs/switching_to_1.0.0.md: -------------------------------------------------------------------------------- 1 | # Switching to SDK 1.0.0 2 | 3 | To help you migrate your old project to our new API, we prepared a short how-to-switch guide! 4 | We did a lot of work to improve the quality of our SDK. We introduced some changes to our documentation (and will add more over time). We appreciate your feedback, so feel free to post any issue/improvement ideas on our Github page. 5 | 6 | Be sure you add new line to your build.gradle file: 7 | 8 | ```gradle 9 | dependencies { 10 | compile 'com.estimote:sdk:{PUT HERE THE MOST RECENT VERSION}' 11 | } 12 | ``` 13 | 14 | 15 | ## New packages and fixing imports 16 | Some classes are now in different packages. You compiler will not see the old classes and will highlight them. 17 | A simple way to fix that is to delete the lines from the old (previous) import. After that, Android Studio will show pop-ups with newly found packages. 18 | Use this trick to fix the wrong imports. 19 | Why did we do that? 20 | Because we believe in constant improvement and our old packages were in need of some spring cleaning. 21 | 22 | ## BeaconManager api changes 23 | The old `Region` class is now replaced with `BeaconRegion` / `MirrorRegion`. 24 | This allows us to add new region implementations in the future. You can use `BeaconRegion` just as you used `Region` - in fact it's the same class with just the name changed. As for `MirrorRegion` — you can create a region from the list of Mirror devices id's. You can also make it `null` - it will scan for every Mirror packet around you. 25 | 26 | All `startDiscovery()` methods (Location, Eddystone, ConfigurableDevice, Telemetry) are now of the `void` type. You no longer need to use `scanId` for stopping discovery via `stopDiscovery()`. 27 | For example, starting Eddystone discovery should look like this: 28 | 29 | ```Java 30 | beaconManager.setEddystoneListener(new BeaconManager.EddystoneListener() { 31 | @Override public void onEddystonesFound(List eddystones) { 32 | // Handle your Eddystones here! 33 | } 34 | }); 35 | beaconManager.startEddystoneDiscovery(); 36 | ``` 37 | 38 | Don't forget to stop your scanning when not in use: 39 | 40 | ```Java 41 | beaconmanager.stopEddystoneDiscovery() 42 | ``` 43 | 44 | ## Scanning for ConfigurableDevice objects 45 | Scanning for `ConfigurableDevice` objects is now handled in BeaconManager instead of the old `ConfigurableDevicesScanner`. These objects are crucial for establishing connection to each device. 46 | The basic flow for connecting to device is as follows: 47 | 48 | ```Java 49 | BeaconManager beaconManager = new BeaconManager(this); 50 | // set foreground scan periods. This one will scan for 2s and wait 2s 51 | beaconManager.setForegroundScanPeriod(2000, 2000); 52 | // connects beacon manager to underlying service 53 | beaconManager.connect(new BeaconManager.ServiceReadyCallback() { 54 | @Override 55 | public void onServiceReady() { 56 | // add listener for ConfigurableDevice objects 57 | beaconManager.setConfigurableDevicesListener(new BeaconManager.ConfigurableDevicesListener() { 58 | @Override 59 | public void onConfigurableDevicesFound(List configurableDevices) { 60 | // handle the configurable device here. You can use it to acquire connection from DeviceConnectionProvider 61 | } 62 | }); 63 | beaconManager.startConfigurableDevicesDiscovery(); 64 | ``` 65 | 66 | # New BulkUpdater 67 | 68 | New bulk updater is a stand alone object that takes scans from your ``BeaconManager`` and updates devices that belongs to the user. In basic form it will simply connect to the device and synchronise it with Estimote cloud. This operation can be customised with firmware updates or include custom settings to write. The bulk updater runs constantly and checks if scanned devices have any new changes to apply. 69 | 70 | ## Building bulk updater 71 | 72 | ```Java 73 | BulkUpdater bulkUpdater = new BulkUpdaterBuilder(this) 74 | .withCloudFetchInterval(5, TimeUnit.SECONDS) 75 | .withFirmwareUpdate() 76 | .withRetryCount(3) 77 | .withTimeout(0) 78 | .build() 79 | ``` 80 | ``withCloudFetchInterval(long)`` - sets how often bulk updater should sync data from the cloud. The shorter this interval is, the quicker new pending settings from the cloud are applied to subsequent devices. The default value is 5 seconds. 81 | ``withFirmwareUpdate()`` - allows bulk updater to update firmware of selected devices. This feature is disabled by default. 82 | ``withRetryCount(int)`` - specifies how many retries BU should take to update each device. After N unsuccessful attempts, the device status will be reported as `Status.FAILED`. The default value is 3. 83 | `` withTimeout(long)`` - Sets the time after which bulk updater should end its job. It will simply stop updating and fetching data. If the value is 0, the process will run constantly (forever and ever, as long as your battery will last). 84 | 85 | ## Listening to bulk update events 86 | `BulkUpdater` progress is reported via listener interface. You can react on each device status change with the proper UI change. You can pass a listener while starting the `BulkUpdater` - it is recommended to start it in you Activity's `onResume()` method. 87 | 88 | ```Java 89 | @Override 90 | protected void onResume() { 91 | super.onResume(); 92 | bulkUpdater.start(new BulkUpdater.BulkUpdaterCallback() { 93 | @Override 94 | public void onDeviceStatusChange(ConfigurableDevice device, BulkUpdater.Status newStatus, String message) { 95 | // do something here 96 | logTextView.append(device.deviceId + ": " + newStatus); 97 | } 98 | 99 | @Override 100 | public void onFinished(int updatedCount, int failedCount) { 101 | // do something here 102 | logTextView.append("Finished. Updated: " + updatedCount + " Failed: " + failedCount ); 103 | } 104 | 105 | @Override 106 | public void onError(DeviceConnectionException e) { 107 | // do somethign here 108 | logTextView.setText("Error: " + e.getMessage()); 109 | } 110 | }); 111 | } 112 | ``` 113 | You can also stop bulk updater whenever you want. Just use the ``stop()`` method: 114 | 115 | ```Java 116 | bulkUpdater.stop(); 117 | ``` 118 | DON'T FORGET: Because bulk updater uses an underlying service for handling connection to devices, it is necessary to call ``destroy()`` on your activity's `onDestroy` method. This will prevent any memory leaks. 119 | 120 | ```Java 121 | @Override protected void onDestroy() { 122 | super.onPause(); 123 | bulkUpdater.destroy(); 124 | } 125 | ``` 126 | 127 | ## Running scan and passing results to BulkUpdater 128 | You need to have a `BeaconManager` which will scan for `ConfigurableDevice` objects nearby. A list of such objects should be passed after each scan cycle to `BulkUpdater`, where all the magic happens: 129 | 130 | ```Java 131 | beaconManager.setConfigurableDevicesListener(new BeaconManager.ConfigurableDevicesListener() { 132 | @Override 133 | public void onConfigurableDevicesFound(List configurableDevices) { 134 | bulkUpdater.onDevicesFound(configurableDevices); 135 | } 136 | }); 137 | beaconManager.startConfigurableDevicesDiscovery(); 138 | ``` 139 | 140 | And that's all! You can consider temporarily stopping `BeaconManager` scanning while device update is in progress - just check whether any device has changed its state to `Status.UPDATING` and invoke `beaconManager.stopConfigurableDeviceDiscovery()`. 141 | You can also play with scan periods - sometimes scanning every 1 s is not that efficient and is just a waste of energy. You can play with this settings using`beaconManager.setForegroundScanPeriod(long, long)`. 142 | 143 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013 Estimote, Inc. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Estimote Fleet Management SDK for Android 2 | 3 | * [Introduction](#introduction) 4 | + ["Can I use this SDK to detect beacons?"](#can-i-use-this-sdk-to-detect-beacons) 5 | + ["Do I need to build an app to configure my beacons?"](#do-i-need-to-build-an-app-to-configure-my-beacons) 6 | * [Requirements](#requirements) 7 | * [Installation](#installation) 8 | + [Connecting Fleet Management SDK to your Estimote Cloud account](#connecting-fleet-management-sdk-to-your-estimote-cloud-account) 9 | * [Bulk Updater](#bulk-updater) 10 | * [Configuring individual beacons](#configuring-individual-beacons) 11 | * [API documentation (AKA JavaDocs)](#api-documentation-aka-javadocs) 12 | * [Feedback, questions, issues](#feedback-questions-issues) 13 | * [Changelog](#changelog) 14 | 15 | ## Introduction 16 | 17 | Estimote Fleet Management SDK allows you to **configure and update your Estimote Beacons via your own Android app**, for example: 18 | 19 | - enable Estimote Monitoring and Estimote Telemetry 20 | - enable iBeacon, and change its UUID, major, minor, transmit power 21 | - update beacon's firmware 22 | - etc. 23 | 24 | You can [configure your beacons one by one](#configuring-individual-beacons), or use Estimote Cloud to queue "pending settings" on your beacons and apply these settings with the [Bulk Updater](#bulk-updater). 25 | 26 | Integrating this SDK into your app means the users of your app can automatically propagate any configuration changes to your beacons. Say, you deployed the beacons, but the initial usage suggests you need to bump the transmit power up a notch, or maybe make the Telemetry advertise more frequently. With Bulk Updater integrated into the app, any user of the app in range of a "pending settings" beacon will apply the new settings. 27 | 28 | (Settings that live entirely in Estimote Cloud, like the beacon's name, tags, and attachments, are always updated instantly, without the need to propagate settings to beacons.) 29 | 30 | ### "Can I use this SDK to detect beacons?" 31 | 32 | Short version: no, use the [Proximity SDK](https://github.com/Estimote/Android-Proximity-SDK) instead. 33 | 34 | Longer version: this SDK was previously known as "Estimote SDK", and it included APIs for detecting your beacons, which you could use to show notifications, etc. **These APIs are now deprecated and are no longer supported.** They have been replaced with the [Estimote Proximity SDK for Android](https://github.com/Estimote/Android-Proximity-SDK), powered by [Estimote Monitoring](https://community.estimote.com/hc/en-us/articles/360003252832-What-is-Estimote-Monitoring-). 35 | 36 | You can, and are encouraged to, use the Fleet Management SDK alongside the Proximity SDK: Proximity SDK for driving the proximity-based events in your app, and Fleet Management SDK for remotely managing your beacons. 37 | 38 | ### "Do I need to build an app to configure my beacons?" 39 | 40 | No, you can use our [Estimote Android app](https://play.google.com/store/apps/details?id=com.estimote.apps.main&hl=en) to change the most common settings, and to apply "pending settings" to individual beacons. Connecting to the beacon in the app automatically applies the latest settings from Estimote Cloud. 41 | 42 | If you have more Estimote devices, [Estimote Deployment app](https://itunes.apple.com/us/app/estimote-deployment/id1109375679?mt=8) can apply "pending settings" in bulk. At this time, it's available on iOS only. 43 | 44 | ## Requirements 45 | 46 | Android 4.3 or later, and an Android device with Bluetooth Low Energy. 47 | 48 | The minimum Android API level this SDK will run on is 9 (= Android 2.3), but the Bluetooth-detection features (which is most of them) won't work. You can handle this gracefully in your app by not using the fleet management features if you detect Android < 4.3, or no Bluetooth Low Energy available. 49 | 50 | Bluetooth Low Energy scanning on Android also requires the app to obtain the location permissions from the user, and "location" must also be enabled system-wide. Chances are, if your app is using beacons (e.g., via the Estimote Proximity SDK), [you already have this permission](https://developer.estimote.com/proximity/android-tutorial/#request-location-permissions). 51 | 52 | ## Installation 53 | 54 | This SDK is distributed via JCenter repository. Most of the time, you'll already have JCenter repo configured in your Android project, with these lines in the Project build.gradle: 55 | 56 | ```gradle 57 | allprojects { 58 | repositories { 59 | jcenter() 60 | // ... 61 | } 62 | } 63 | ``` 64 | 65 | If not, add `jcenter()` inside `repositories`, as shown above. Then, in the Module build.gradle, add: 66 | 67 | ```gradle 68 | dependencies { 69 | implementation 'com.estimote:mgmtsdk:1.4.6' 70 | implementation 'com.estimote:coresdk:1.3.4' 71 | // if using an older version of Gradle, try "compile" instead of "implementation" 72 | } 73 | ``` 74 | 75 | ### Connecting Fleet Management SDK to your Estimote Cloud account 76 | 77 | This SDK needs to be able to access your Estimote Cloud account in order to configure your beacons. 78 | 79 | To do that, register your mobile app in Estimote Cloud in the "Mobile Apps" section. You'll get an App ID and App Token, which you can use to initialize the SDK: 80 | 81 | ```java 82 | // do this before you use any of the fleet management features 83 | EstimoteSDK.initialize(applicationContext, "my-app-bf6", "7bcabedcb4f..."); 84 | ``` 85 | 86 | Your Estimote Cloud account needs to have a fleet management subscription. As of now, there's a free, indefinite trial available if you have less than 20 devices. 87 | 88 | ## Bulk Updater 89 | 90 | This is how to set up the Bulk Updater: (we recommend doing this in an Application subclass) 91 | 92 | ```java 93 | private BulkUpdater bulkUpdater; 94 | 95 | @Override 96 | protected void onCreate() { 97 | super.onCreate(); 98 | 99 | Context context = getApplicationContext(); 100 | bulkUpdater = new BulkUpdaterBuilder(context) 101 | .withFirmwareUpdate() 102 | .withCloudFetchInterval(1, TimeUnit.HOURS) 103 | .withTimeout(0) 104 | .withRetryCount(3) 105 | .build() 106 | } 107 | ``` 108 | 109 | And this is how to use it: 110 | 111 | ```java 112 | bulkUpdater.start(new BulkUpdater.BulkUpdaterCallback() { 113 | @Override 114 | public void onDeviceStatusChange(ConfigurableDevice device, 115 | BulkUpdater.Status newStatus, String message) { 116 | Log.d("BulkUpdater", device.deviceId + ": " + newStatus); 117 | } 118 | 119 | @Override 120 | public void onFinished(int updatedCount, int failedCount) { 121 | Log.d("BulkUpdater", "Finished. Updated: " + 122 | updatedCount + ", Failed: " + failedCount); 123 | } 124 | 125 | @Override 126 | public void onError(DeviceConnectionException e) { 127 | Log.d("BulkUpdater", "Error: " + e.getMessage()); 128 | } 129 | }); 130 | ``` 131 | 132 | One more thing: you need to feed the BulkUpdater with data from the beacons' Connectivity packets: 133 | 134 | ```java 135 | private BeaconManager beaconManager; 136 | 137 | // ... 138 | 139 | beaconManager = new BeaconManager(context); 140 | 141 | // this will make the beacon attempt to detect Connectivity packets for 10 seconds, 142 | // then wait 50 seconds before the next detection, then repeat the cycle 143 | beaconManager.setForegroundScanPeriod(10000, 50000); 144 | 145 | // this connects to an underlying service, not to the beacon (-; 146 | beaconManager.connect(new BeaconManager.ServiceReadyCallback() { 147 | @Override 148 | public void onServiceReady() { 149 | beaconManager.setConfigurableDevicesListener(new BeaconManager.ConfigurableDevicesListener() { 150 | @Override 151 | public void onConfigurableDevicesFound(List configurableDevices) { 152 | bulkUpdater.onDevicesFound(configurableDevices); 153 | } 154 | }); 155 | } 156 | }); 157 | beaconManager.startConfigurableDevicesDiscovery(); 158 | ``` 159 | 160 | To stop, and clean up after the BulkUpdater, do: 161 | 162 | ```java 163 | beaconManager.stopConfigurableDevicesDiscovery() 164 | bulkUpdater.stop(); 165 | bulkUpdater.destroy(); 166 | ``` 167 | 168 | ## Configuring individual beacons 169 | 170 | If you want to individually configure a beacon, you'll need to connect to it first: [Connecting to beacons](https://github.com/Estimote/Android-Fleet-Management-SDK/blob/master/Docs/DOC_deviceConnection.md). 171 | 172 | Once connected, you can read and write settings, as well as update the beacon's firmware: [Basic operations on connected device](https://github.com/Estimote/Android-Fleet-Management-SDK/blob/master/Docs/DOC_deviceConnection.md#basic-operations-on-connected-device) and [Advanced operations on connected device](https://github.com/Estimote/Android-Fleet-Management-SDK/blob/master/Docs/DOC_deviceConnection.md#advanced-operations-on-connected-device). 173 | 174 | ## API documentation (AKA JavaDocs) 175 | 176 | … is available here: 177 | 178 | 179 | 180 | ## Feedback, questions, issues 181 | 182 | Post your questions and feedback to [Estimote Forums](https://forums.estimote.com), we'd love to hear from you! 183 | 184 | Report issues on the [issues page](https://github.com/Estimote/Android-Fleet-Management-SDK/issues). 185 | 186 | ## Changelog 187 | 188 | See [CHANGELOG.md](CHANGELOG.md). 189 | --------------------------------------------------------------------------------