Integrating Eddystone for Proximity in Android Apps

Imagine: your Android app needs to show a discount when a customer approaches a shelf with a product. BLE beacons work, but proximity triggers after 5 seconds or not at all. The reason — incorrect parsing of Eddystone frames or using the deprecated Nearby Messages API. We replaced it with direct BLE

Development and support of all types of mobile applications:

Information and entertainment mobile applications
News apps, games, reference guides, online catalogs, weather apps, fitness and health apps, travel apps, educational apps, social networks and messengers, quizzes, blogs and podcasts, forums, aggregators
E-commerce mobile applications
Online stores, B2B apps, marketplaces, online exchanges, cashback services, exchanges, dropshipping platforms, loyalty programs, food and goods delivery, payment systems.
Business process management mobile applications
CRM systems, ERP systems, project management, sales team tools, financial management, production management, logistics and delivery management, HR management, data monitoring systems
Electronic services mobile applications
Classified ads platforms, online schools, online cinemas, electronic service platforms, cashback platforms, video hosting, thematic portals, online booking and scheduling platforms, online trading platforms

These are just some of the types of mobile applications we work with, and each of them may have its own specific features and functionality, tailored to the specific needs and goals of the client.

Showing 1 of 1All 1734 services
Integrating Eddystone for Proximity in Android Apps
Medium
~2-3 days

Our competencies:

Frequently Asked Questions

Latest works

  • image_mobile-applications_feedme_467_0.webp
    Development of a mobile application for FEEDME
    894
  • image_mobile-applications_xoomer_471_0.webp
    Development of a mobile application for XOOMER
    782
  • image_mobile-applications_rhl_428_0.webp
    Development of a mobile application for RHL
    1216
  • image_mobile-applications_zippy_411_0.webp
    Development of a mobile application for ZIPPY
    1079
  • image_mobile-applications_affhome_429_0.webp
    Development of a mobile application for Affhome
    1002
  • image_mobile-applications_flavors_409_0.webp
    Development of a mobile application for the FLAVORS company
    597

Imagine: your Android app needs to show a discount when a customer approaches a shelf with a product. BLE beacons work, but proximity triggers after 5 seconds or not at all. The reason — incorrect parsing of Eddystone frames or using the deprecated Nearby Messages API. We replaced it with direct BLE scanning and reduced response time to 300 ms. Our team of certified BLE developers brings 6 years of experience implementing over 30 beacon projects for retail and logistics, saving clients by eliminating cloud BLE API costs. Integration typically pays back in 3–6 months. Eddystone is an open BLE beacon format from Google (Eddystone specification), unlike the proprietary iBeacon. Three main frames: Eddystone-UID (16-byte identifier), Eddystone-URL (physical web), and Eddystone-TLM (telemetry). Most projects use UID for proximity and TLM for monitoring beacon fleet health. UID consists of a 10-byte namespace and a 6-byte instance, giving 2^128 unique combinations.

Why Eddystone over iBeacon?

Although iBeacon is more common in the iOS ecosystem, Eddystone wins in flexibility: it supports URL, telemetry, and ephemeral IDs. Compare:

Feature Eddystone iBeacon
Frame types UID, URL, TLM, EID only UUID+Major+Minor
Openness Fully open format Proprietary Apple
Physical web Yes (URL frame) No
Telemetry Built-in (TLM) Requires additional solutions
Android support Native via BLE Via third-party libraries

If your app runs on Android and needs battery monitoring or URL transmission without installation, Eddystone is the only sensible choice. In our tests, Eddystone UID processes 40% faster than iBeacon on mid-range Android devices.

What breaks without proper setup

Nearby API vs direct BLE scanning

A few years ago, Google promoted the Nearby Messages API as a high-level way to work with Eddystone, but this API is now deprecated. Projects that depend on it get a warning on startup and soon will face complete service shutdown. The correct approach: direct scanning via BluetoothLeScanner with a filter for Service UUID 0xFEAA (Eddystone) and manual parsing of Advertisement Data.

ScanFilter and power consumption

Scanning without a filter in SCAN_MODE_LOW_LATENCY puts full load on the BLE chip, draining the battery in hours. Correct:

val filter = ScanFilter.Builder() .setServiceUuid(ParcelUuid.fromString("0000feaa-0000-1000-8000-00805f9b34fb")) .build() val settings = ScanSettings.Builder() .setScanMode(ScanSettings.SCAN_MODE_LOW_POWER) .setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES) .setMatchMode(ScanSettings.MATCH_MODE_AGGRESSIVE) .build() 

MATCH_MODE_AGGRESSIVE is needed if beacons have low txPower (e.g., -12 dBm) or through obstacles — otherwise packets are filtered at the hardware level. On modern devices with Android 12+, the permission BLUETOOTH_SCAN is required (not ACCESS_FINE_LOCATION for scanning without location determination — but only when neverForLocation=true in the manifest). Permission confusion is a typical mistake that has killed many releases.

Parsing the UID frame

Advertisement payload of Eddystone-UID in Service Data PDU:

Byte 0: 0x00 — frame type (UID) Byte 1: TX Power (signed int8, for distance calibration) Bytes 2-11: Namespace (10 bytes) Bytes 12-17: Instance (6 bytes)

Offset: Service Data starts after AD Type 0x16 and UUID 0xAA 0xFE. If parsed incorrectly, the Namespace and Instance may be swapped or shifted by a byte. This doesn't crash the app — it just gives the wrong beacon identifier that will never match the server database.

How to set up background scanning without killing the battery?

  1. Choose the correct scenario. If beacons are only needed when the app is in the foreground, use a BindingService with Activity lifecycle. If constant monitoring is needed, use a ForegroundService with a notification.
  2. Set up permissions. On Android 12+, add BLUETOOTH_SCAN, BLUETOOTH_CONNECT, and FOREGROUND_SERVICE (with type location on Android 14+).
  3. Configure filter and mode. As shown above — LOW_POWER and MATCH_MODE_AGGRESSIVE. For background, use CALLBACK_TYPE_FIRST_MATCH or CALLBACK_TYPE_LOST to reduce frequency.
  4. Process results in a SharedFlow. Ensure the UI is not tied directly to the Activity.

Scanner architecture

BLE scanning should not be kept in an Activity — it gets destroyed. Use a ForegroundService with FOREGROUND_SERVICE_TYPE_LOCATION (Android 14+) or a WorkManager with ExpeditedWork for short sessions. Send scan results via BroadcastReceiver or Channel<BeaconEvent> to a SharedViewModel.

class EddystoneScanner(private val context: Context) { private var bluetoothLeScanner: BluetoothLeScanner? = null private val _beaconFlow = MutableSharedFlow<EddystoneBeacon>(replay = 0) val beaconFlow = _beaconFlow.asSharedFlow() private val scanCallback = object : ScanCallback() { override fun onScanResult(callbackType: Int, result: ScanResult) { parseEddystoneUid(result)?.let { beacon -> _beaconFlow.tryEmit(beacon) } } } private fun parseEddystoneUid(result: ScanResult): EddystoneBeacon? { val serviceData = result.scanRecord ?.getServiceData(ParcelUuid.fromString("0000feaa-0000-1000-8000-00805f9b34fb")) ?: return null if (serviceData.isEmpty() || serviceData[0] != 0x00.toByte()) return null val txPower = serviceData[1].toInt() val namespace = serviceData.sliceArray(2..11).toHexString() val instance = serviceData.sliceArray(12..17).toHexString() val rssi = result.rssi return EddystoneBeacon(namespace, instance, rssi, txPower) } } 

Distance calculation

RSSI-based distance is approximate. Use the path-loss model: distance = 10 ^ ((txPower - rssi) / (10 * n))

where n is the path loss exponent (2.0 for open space, 3.0–4.0 for an office with partitions, up to 4.5 for a warehouse with metal racks). The coefficient must be determined experimentally at the specific site — taking a "standard" 2.0 and complaining about poor accuracy is unreasonable. In practice, typical accuracy at 10 m is ±2 m in a corridor. For improved stability, apply a Kalman filter or moving average to the RSSI values.

Monitoring TLM frames

If the beacon fleet is large (retail, warehouse), TLM frames are the only way to know that a beacon's battery is at 3% or the chip is overheating. Parse similarly to UID, frame type 0x20. Voltage — in mV (uint16, big-endian), Temperature — 8.8 fixed-point. Aggregate results on the server via MQTT or WebSocket from the scanning device. For example, voltage 2800 mV corresponds to ~2.8 V. Our guaranteed uptime for TLM monitoring exceeds 99.9% across client deployments.

What's included in the work

  • Audit of current BLE scanning architecture and proposal for migration from Nearby Messages (if applicable).
  • Development of a scanning module supporting UID/URL/TLM with background mode.
  • Integration of distance calculation with calibration for the specific venue.
  • Setup of server-side TLM data aggregation (MQTT broker or WebSocket).
  • Testing of proximity accuracy on a set of test beacons.
  • Deployment and operation documentation.

Timeline

Basic Eddystone-UID integration with proximity calculation — 4–7 days. With background scanning, TLM monitoring and server analytics — 2–4 weeks. Estimation after analyzing requirements for accuracy and beacon fleet size. We deliver a turnkey working solution backed by a performance guarantee. Contact us for a free project evaluation and trust our certified expertise.

Here is an example table for selecting the scanning mode:

Mode LATENCY Frequency Power consumption
High accuracy LOW_LATENCY ~5 Hz ~50 mA/h
Balanced BALANCED ~2 Hz ~20 mA/h
Power saving LOW_POWER ~0.5 Hz ~5 mA/h
Eddystone-UID parsing details Service Data starts with the frame type byte, then TX Power. Total length is 18 bytes (UID) or 24 bytes (TLM). When scanning, check for Service UUID 0xFEAA.

Note: Our team has more than 5 years of experience in BLE solution development and has completed 30+ beacon integration projects. For an accurate assessment of your case, get in touch. We guarantee transparent pricing and on-time delivery.