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.
Related
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.
What is maximum acceptable frequency from your point of view or experience of sending broadcasts in Android to be received by BroadcastReceivers without performance impact?
Let's say we send only basic data in a Bundle without need for long deserialization.
I am going to send broadcasts only inside my app with LocalBroadcastManager.
In other words this question is about when you should stop using broadcasters and write you own implementation for faster usage and when you should not do it.
First of all, if you send data inside one app, I would advise you, instead of BroadcastReceiver use LocalBroadcastManager or even not use any type of broadcast receivers at all - just Observer Pattern (here good article on this topic).
I am writing an application that shows "Japanese Traditional Time" (JTT for short). There are several components (notification, widgets, application itself, alarms) which all use the same data - current JTT.
My current version uses a single service that does all the calculation and uses a Handler to notify everyone about "ticking", mimicking ACTION_TIME_TICK.
However with alarms I need to also have a way to translate "usual time" to JTT and vice versa. The calculations are quite CPU-heavy (it's all based on sunrises and sunsets) and thus I prefer having it all done in a single place and then cached (calculating stuff knowing sunrise and sunset times is not as heavy).
So I have several ways to do that now:
Keep it all in Service
And use binding to request the data I need. It's actually already done in one case and seems a bit cumbersome since I have to handle asynchronous responses
Move to content provider
And use content observers instead of broadcasting
Or send broadcasts from provider
Combine both ways
Use content provider to calculate the data for service which in turn will broadcast it when needed
Which would be better? Maybe something else?
Content providers are for structured data, so it doesn't really fit your use case. Not sure what you mean by 'asynchronous responses'? Calling a remote service is usually just like a local function call, it will block and return a value when done. If you have to notify multiple components a broadcast is the way to go. Explore using a LocalBroadcast if all components are in the same process (check Android support library source), or set a permission on it to make sure other apps cannot get it if you need to send a system-wide (regular) one.
I'm sticking with "just service" - I have discovered Sticky Broadcasts which actually cover the problem I had with common Broadcasts (having to request latest data from service after registering but before getting the first "tick") and that leaves me with much less cases where I need actual service connection.
I am developing an application which has around 8 Activities, and a class which is used to connect/receive data to/from an embedded Bluetooth chip. When I started, a Bluetooth object was initialized in my initial Activity, where there was a Handler which received messages from the Bluetooth object.
After poking around on the internet for a while, it seems like the best idea for me is to turn my class into an Application subclass. However, doing this removes the need for me to initialize an object in the MainMenu, which removes my ability to pass it the Handler used.
Does anyone know of a way to eliminate the need for a Handler, so that every time the Bluetooth Application changes it state or receives data, the current Activity can access it?
My main problem with this approach is that the Activity doesn't know when the Bluetooth Application will be sending it messages, the Application waits and listens, and then notifies the Activity when it happens.
OR
Is it bad practice for me to write the Handler into the MainMenu, have it handle messages for ALL the different activities, and then pass the Handler from Activity to Activity?
I'm going to assume that you're trying to achieve the following as it's a little unclear from your question your ultimate aim (sorry!):
Your application has several activities but only one Activity receives the data from the bluetooth device.
The other activities in in your application require the data from the bluetooth device but are not receiving it directly from the bluetooth device. Currently you're providing the data via the one activity mentioned above.
You want to NOT use a Handler to achieve this.
If my above assumptions are correct then you are going along the correct lines but you probably do not want to use a Handler.
You are quite correct in having one Activity handle all the interactions with the Bluetooth device. It simplifies things and provides a much better, cleaner way of handling the Bluetooth device. However you need to get the data from this one Activity to all the others and to achieve this you would probably want to use Broadcasts, BroadcastReceivers and Intents. See here for an overview.
However if you can you might want to take a look at using LocalBroadcastManager as this keeps any broadcasts within your own app's space. Broadcasts are global and should be avoided if you do not need to pass the data outside of your own app due to security implications.
Finally, have you considered using Fragments for your other Activities? Another disadvantage with Broadcasts is there is extra overhead associated with them. If you're keeping data within your app then you can create an interface to be implemented by each of your Fragments and your main activity just calls that interface on the Fragment that is currently selected.
You can use BroadcastReceiver class to send broadcast messages to your activities. see here http://developer.android.com/reference/android/content/BroadcastReceiver.html
When you get the data you need into the application class, you can send it to the activity you want.. just make sure that the activity has registered to receive that broadcast message..
I have to develop an application where i have to continuously collect the GPS, accelerometer data [esp. when user is in motion i.e traveling, else it can be relaxed). Also I have to communicate with web server and handle the response from the sever. So for this(handling response ) part application should continuously poll.
Based on response from server I have show UI to the user.
I am not very clear about the design.
Do I have to create activity from where I start service. Should service be ran as a separate thread(this always runs in background).
I am planning to create two services. One service to continuously collect GPS data.
Other service for communicating with the web server[start timer/alarm manager] for polling.
ALso can these two services communicate with each other.
Also after processing the response frm server the service should be able to start user interface to show some form. I am not clear how to handle this.
Also is acquiring wakelock required if I have to collect GPS data continuously.
Please clarify.
Thanks
You can use an AlarmManager for polling. You just need to set the interval. You will notice that most components Application, Service, Activity all are Contexts. So they all can get Application Context. The way to think about communication is that the android message/event is essentially the Intent. So you define your custom Intents. You just need to give them a custom name for the action. Then you use Intent filters. You can do point to point messaging by doing startService, startActivity or you can broadcast the intent. I would recommend that you communicate via broadcasted intents. Message routing is handled using Intent filters. Starting form etc would just be a startActivity(Intent) and the Intent itself could contain using intent.getExtras(). Just so long as you can put it in the Bundle you can pass it and display. So to answer your question, just use Intents for everything. Use broadcasting and filtering for communication and Intents again to start your activity for display.
The May 10th Google I/O had an afternoon session called Android Pro Tips. The first section covered several different approaches to making your app more continuously location aware.