Android: Using an IntentService for rapid data - android

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.

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:
Blocking queue for data that needs to be processed
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:
Use multiple threads for background processing
Store data into SQLite (but then SQLite can grow excessively)
Drop some data

IntentService has embedded queue of incoming Intents, so, if you process intents slower than they arrive, it is possible to do.
But, I'd use HandlerThread for posting incoming data within Message onto it. It has embedded message queue too, but there is no overhead, as with creating IntentService.
Another approach - use ordinary Service and handle backpressure with RxJava library.

Related

Android app advice, multiple intent services?

My app has a UI and a connection is made to a bluetooth device which is periodically sending barcode scan data to my app. I then want to cache this data in a sqlite db and have another process push this data up to a web server.
I have managed to get the UI and bluetooth scan process separated by using an Intent Service for the scanner component... The thread in the intent service connects to the bluetooth device and loops endlessly pulling in new scan data as it comes... communicating with the UI via broadcast messages as it needs to.
So now I need to handle storing the data in a sqlite db and pushing it up to the Internet.
I'm thinking I can insert a db row directly in the intent service loop I already have working for the bluetooth data... would I do that by firing of an async task or something like that?
Then, would I have a completely different intent service running and looping endlessly checking for new records to be processed and pushed up to my web server via an http post?
I guess the main reason I'm thinking of using intent services is that they seem to keep running even if I lock my phone and put it in my pocket... has worked so far for the bluetooth barcode scanner... can scan away happily with my phone locked and in my pocket.
I also need to handle the reality that internet won't always be available... hence the sqlite db... kind of like a safe buffer to store data until it can eventually be pushed up to the Web server.
Am I going down the right path? I'm really new to Android development and even after much research I'm still unsure about my approach.
You can store data or communicate from IntentService onHandleIntent() directly. You don't need to run it in separate thread, unless you want reading bluetooth to continue ASAP.
Handling everything in an infinite loop smells. Also keeping service alive depends on few factors. If IntentService dies, it won't be restored because by default IntentService.onStartCommand implicitly returns START_NOT_STICKY, or START_REDELIVER_INTENT if you call setIntentRedelivery(true) on this service. Check Service javadoc for more info.
If you can scan bluetooth periodically then I would consider kind of scheduler. For that you would probably need to implement Service, not IntentService and handle background thread yourself. Alternatively, you could use a Timer. These are more hints, not ready solution. Since you asked about direction, I assume you will investigate solutions yourself.
Depending on handled data you could separate DB operations and network to separate services. Think about them as modules which are decoupled. You will benefit maintaing this code in the future and in case one service goes down due to any reason, the rest will keep working. It depends on data size because it's not a good practise to push heavy data between service/activities(data is serialised and deserialised every time it is sent).
If DB is just a buffer/queue then maybe use it directly after reading bluetooth data. In other words queue data for sending. Create second service for HTTP communications. Don't push entire data to second service, just inform it about(knock the door :)) and let HTTP service access DB by itself. I would wrap DB in ContentProvider and access it from services.
There are probably different techniques out there too, but that's what I thought about it in the first place.

When to use and when not to use a Service in Android

I have been developing for Android for little less then 2 years, and I am still puzzled by this seemingly simple question.
When should one implement a service?
From my experience there are some rare cases but I am questioning this because on every phone there are quite a lot of them running and I doubt it's just a poor application design.
This is essentially core of my question but following are some of my experiences and thoughts about the subject which can explain my question in more detail.
In all apps that I have developed only one really required a service. It was a background sound recorder and I was using it as Foreground service with notification since I wanted buttons to be able to control it (like music players do for example).
Except this I never really saw a requirement for the constantly running service because:
A) Intent listeners (Manifest registered BroadcastReceivers) are quite a useful feature and using them as you know is usually enough for many use-cases (for example showing notifications).
B) If scheduled execution is a must one can subscribe to alarm events.
C) I know that service in Android is quite different then for example in Windows since in Android services are just a "package" to organize your code in and have a the system manage the lifetime of the object. Services use the Main Thread but it's customary to spawn new threads in them.
D) In the development documentation services are suggested for network communication and background calculations but I don't get why you should not just use AsyncTasks for that. I am a big fan of these and use them extensively for lot of things from downloading data from the internet to doing FFT calculations under time critical conditions.
E) I get the usefulness of Foreground services but why are people using background services so much (excluding the system apps).
Those are my thoughts about the SERVICE and I hope someone with more experience will be able to explain these PROS and CONS (along with others that I probably missed).
When should one implement a service?
When you have work -- delivering value to the user -- that:
Needs some time to complete, perhaps longer than you have time for in the component wishing the work to be done, or
Is delivering that value under user control (e.g., music player, controlled by play/pause buttons in a UI), or
In rare cases, needs to be running continuously, as it delivers value continuously
there are quite a lot of them running and I doubt it's just a poor application design
Some are likely to be poor implementations, either due to technical misunderstandings, or other concerns (e.g., making marketing happy) trumping making users happy.
It was a background sound recorder and I was using it as Foreground service with notification since I wanted buttons to be able to control it (like music players do for example)
That is a reasonable use for a service, IMHO.
Intent listeners are quite a useful feature and using them as you know is usually enough for many use-cases (for example showing notifications)
I assume that by "Intent listeners" you mean manifest-registered BroadcastReceivers. In that case, if the work to be done by the BroadcastReceiver will take more than a millisecond, that work should be delegated to an IntentService for completion. onReceive() is called on the main application thread, and it is not safe for a manifest-registered BroadcastReceiver to fork a bare thread, as the process could go away shortly after onReceive() returns. However, in these cases, the service is usually short-lived (e.g., do some network I/O and disk I/O, then go away).
In the development documentation services are suggested for network communication and background calculations but I don't get why you should not just use AsyncTasks for that
An AsyncTask is a fine solution for background work that is:
Requested by the UI (activity or fragment), and
Will take less than a second or so, and
Is non-critical
For example, if you are downloading avatars to show in a ListView, AsyncTask is probably a fine choice, whether you use them directly or use some image-fetching library that uses them internally.
Conversely, if the user buys an MP3 through your app, and you need to download that MP3 file, an AsyncTask is not a good solution. That could easily take over a second. While the download is going on, the user could switch away from the app (e.g., press HOME). At that point, your process is eligible to be terminated... perhaps before your download is complete. Using an IntentService to manage the download is a signal to the OS that you are really doing work here, adding value to the user, and so the process will be left alone for a little while.
Note that if the background work might take 15+ seconds, WakefulBroadcastReceiver or my WakefulIntentService is probably a good idea, so the device does not fall asleep while you are trying to wrap up this bit of work.
I can name some of the Service uses from my experience:
to implement
location listener,
sound module, generating various voices
in app content updates,
API, provide services to other apps
in app billing
Communication with webservices (if requests frequency is high)
actually (excluding 5.) they all are working for the whole app duration, they are using some of the other android services, also they manage their state. I suppose one of the important thing here is state management during application life cycle changes.
I prefer to look at AsyncTasks in a same way as Executors (ExecutorService), they should be executed sequentially and for small tasks.
In the android website, you can find a table when to use Service, Thread, or WorkManager (the new API for scheduling jobs, currently in alpha as of this comment posted). https://developer.android.com/guide/background/#table-choose
The website also state that you need to use started service only as last resort. The Android platform may not support started services in the future. Refer to this link https://developer.android.com/topic/performance/scheduling#services
You should avoid using started services that run perpetually or perform periodic work, since they continue to use device resources even when they aren't performing useful tasks. Instead, you should use other solutions that this page describes, and that provide native lifecycle management. Use started services only as a last resort. The Android platform may not support started services in the future.
If you consider UI and bound services, u would think that both can exist and not be doing anything for certian periods. In such scenarios, your UI can be recreated a lot of times however service does not. And this is where service is important. Lets say you are processing images and then rotate device you want processing to continue while UI is being recreated. You recording a voice and then rotate device. These are one of the places where I find service very important. (Having lot of heavy data processing, interaction with web, that could be few seconds)

How to structure an application properly on background processes

I have an application that uses a webservice to get information and save the changes made ​​by the user.
currently I have one service that runs while the application is open, and it has public methods for each operation. the trouble is that service is growing considerably and I'm thinking refactor, but the question is what is the best way?
I can think of the following options:
Deferred services the current service and that all are initialized at boot time application
Create small services and that these are initialized by local broadcast
although I have doubts about performance. Can give me some clue or example about which method is better, do not really care that changes are instantly synchronized, these are stored locally and can be synchronized when possible. Data sent are not many, so the synchronization is relatively fast
Synchronization processes are something like
Check if there is new data (I have several types of data, these are the ones that are growing)
Synchronize user preferences
Most likely there's no point of having Service running all the time. Instead, I'd go for IntentService. If possible, I'd also condifer using push notification (like GCM) so the server could let my app know that there's new data to fetch (or maybe even send it to me if you'd fit in the GCM payload limit).

Android deal with lot of intents

My app is design to get messages from an embedded Bluetooth device. While I was working with sensors which sends data each second or more, it was not such a big deal to broadcast intents to activities. The only visible slow down was when the Bluetooth device flushed its buffer.
Now I need to deal with high refresh rate sensors (such as ECG, every 2ms) so I have to be little more cleaver because the number of intents makes visualization not in real time (there is more measures incoming than displayed).
I try to work with putIntegerArrayListExtra() to send data each 2 seconds but now I get a A.N.R.
Is someone can advise me to deal with lot of intents? (It seems my service memory also grow up to much).
To bypass intents, I have to send an object from a service to an activity. As far I now this is impossible and the reason of Intent.
EDIT:
I had underestimate binding. In fact it enables activities to get from the service an instance of a "DeviceDriver" which register listeners to perform callback. As I can retrieve the instance of the driver in the activity, I can register it as a listener and cut down all intents between service and activities (At least for data exchange).
You can also use binding to pass data from service to intent:
http://developer.android.com/guide/components/bound-services.html
In your case I advice you to not use intents. Try to use thread inside activity or shared memory and synchronization.

Handler or Listeners. What is better?

Handler or Listeners. What is better use for notification of event? What is faster, more efficient etc.?
That's a good question!
scenario for using a handler
I've got an Android background service running in my app that uses handlers exclusively for web communications - I decided to go this route because the handler will queue requests and execute them one by one so then I know that a sequence is remained intact.
For example, in an instant messenger app you might find it desirable to maintain a sequence for your chatting.
scenario for using a callback
My background service also uses a class that reads from hardware (in a separate thread); some data might come in at any time and needs to be processed immediately. For that class I implemented a listener/callback interface.
My only question is whether there's any etiquette for the size of the handler.
I have about 50 unique messages:
outgoing web requests consists of about 25 messages (each message is a different API on the web server)
Each API returns a response, therefore there's another 25 incoming web
responses
The handler requires about 60% of the service's code - as you can imagine this results in a very big switch(case{}) structure (almost 1000 lines of code). Too big? How to break it apart?
There's no such thing as a Listener type, it's just a naming convention for callback interfaces. So you just use them if you want to process your events synchronously on the same thread.
A Handler is however an Android class... you use it for passing messages and runnables from the thread raising the event (e.g. "download complete") to the thread that needs to handle it (e.g. the UI thread).

Categories

Resources