Search code examples
androidservicebluetooth-lowenergysensors

Android: Using an IntentService for rapid data


I have an Android app that will be receiving rapid data over bluetooth (BLE). The data will be arriving at 50-100 Hz from a remote sensor device into a dedicated service (the Nordic nRF BLE manager) on an Android smartphone. I want to hand the data, at full rate, to a separate service to compute analytics on it. If I use an IntentService for the analytics, that means intents will come in every 10 milliseconds. I'm sure there is significant overhead for each Intent and I doubt it was designed for this much data. But everything I read suggests that this is the simplest solution. Is this the right approach? Thanks.


Solution

  • First of all you need to decide whether you need real-time behavior. The data is being received over BLE in real-time, but do you really need to process it in real time? If the analytics that you're computing are not required in real-time, then it is ok to receive the data, store it, and process later.

    If you really need real-time data processing then IntentService is not an adequate design choice.

    If you don't need real-time data processing then IntentService can work, but will be non-optimal from performance point of view.

    There will be two overheads.

    The first one you found by yourself - sending intent bears some additional overhead because the OS needs to "route" the intent to the service.

    The second one will be associated with starting and stopping the IntentService. If the period of time between intent arrivals will be lower than the time it takes onHandleIntent() to return, then the system will be starting and stopping the IntentService for each intent. This overhead is much higher that the first one.

    Therefore, even though IntentService can work in this situation, IMHO you shouldn't use this approach.

    The best solution to this problem will be to use bound Service. Bind to it from the BLE receiver and send the data using regular method calls. The downside is that you'll need to implement two features by yourself:

    1. Blocking queue for data that needs to be processed
    2. The logic that offloads the processing to background thread

    Writing this logic is not trivial, but if your application is a serious project, then it is the only right thing to do IMHO. You can copy-paste threading logic from the source code of IntentService.

    One word of caution: you must be aware of excessive memory consumption. For example: if you use a single background thread for processing, and the rate of incoming data is higher than the rate of processing, then your queue will be constantly growing. In such a situation, if given enough time, your application will crash with OutOfMemory exception (can happen with IntentService too).

    If this happens, you'll need to do either of:

    1. Use multiple threads for background processing
    2. Store data into SQLite (but then SQLite can grow excessively)
    3. Drop some data