I am developing an application where I am streaming live sensor data via bluetooth, then have several Activities that can work on this live stream of data to display it in different ways (e.g. statistics, histogram, trend charts etc.)
I need to maintain the bluetooth link across Activities, and I also need to maintain receiving the data into a buffer across Activities (e.g. you can be viewing the data in the trend chart activity, then hop across into a statistics Activity without it clearing the data.)
How I've done it is to extend application and have it hold a custom class which holds all the relevant Bluetooth objects (bluetooth device, IOstreams.) Then when the user initiates the connection through the front page Activity, the bluetooth connection is opened and a service is started that reads the data from the input stream, converts it and stores it into a arraylist. Then any of the display Activities work on this ArrayList.
That works great. But I can't work out how to close the bluetooth connection and service when the application is either killed, or placed into the background. As it's important to ensure the bluetooth connection is closed properly, or else it can be difficult to re-establish a connection.
About the best I've come up with so far is to implement a task transition timer as described in this post https://stackoverflow.com/a/15573121/3015368, and have it close the connection and service if the timer completes.
I was hoping there might be a better way of doing this?
you can stop services by making an intent which points to ur service class and call this function if your service is running it kills it if its not running then it wont do anything
stopService(/* intent name*/)
u can do that in onPause() method which is automatically called when ur app goes to the background
then if you need to restart the service u can call onResume() which is also automatically called when ur app gains focus
hence: u need to override onPause() and onResume() methods.
Related
In my app, a Service is started in the background to handle BLE communication with a BLE device. I have an Activity (StartActivity) on start of the app which searches the BLE device and when it found it, it starts the Service (BleService), hands the found Device to it and then binds to it to receive Broadcasts from BleService.
BleService establishes the BLE connection, sets notifiers on different characteristics and reads them. As it got all the information it initially needs, a Broadcast is sent.
This Broadcast causes StartActivity to switch to another Activity (MainActivity), which then binds again to BleService and reacts to BleService's Broadcasts.
So far, so good.
When I press the back button while in MainActivity, the app 'closes'. Now, when I restart the app (either by clicking on its icon or in the recent app list), the app gets back into StartActivity and can't connect to the BLE device. As the LED on my BLE device is constantly signalling me, it's connected, I think the first BleService is still running and connected to the BLE device.
I checked this by adding a Log output to BleService's onDestroy() method and yes, onDestroy() isn't called. It is called, when I close my app through the recent app list.
What should I do when closing my app through the use of the back button?
EDIT: So I want to destillate my problem out of my question:
When I close my app on pressing the back button in MainActivity and then start it through the recent app list or via its icon again, I get stuck in StartActivity. This is, because StartActivity can't find the BLE device, as it is still connected to the still running BleService.
How can I avoid this?
I am not sure what you want to have happen when "back" is pressed, but you can take a look at this answer to help you determine if the service is running or not and take appropriate action.
If your client and server code is part of the same .apk and you are binding to the service with a concrete Intent (one that specifies the exact service class), then you can simply have your service set a global variable when it is running that your client can check.
We deliberately don't have an API to check whether a service is running because, nearly without fail, when you want to do something like that you end up with race conditions in your code.
An Android Service is meant to remain running even when its parent application terminates. This is an important function to be able to execute any critical operations even when the application crashes/closes/gets killed...
For you, this simply means that you have to close your service upon quitting your app, at least if this is what you intend to do. Doing this is very simple:
stopService(new Intent(ActivityName.this, ServiceClassName.class));
If you are starting your Service via Context.startService() then it must be stopped via Context.stopService() or the service itself calling stopSelf(). Binding/unbinding to the service will only stop it if the binding was how the Service was started in the first place (e.g. not using startService()).
I know this look like tons of question around SO. But it's not (although I can also be wrong).
I have a long running Service (running in a separate thread using blutooth socket pooling for data in a OBD2 adapter every 5 seconds).
This Service is running in the same process and is a Foreground Service.
The user start this Service through an Activity. It then connect to the Bluetooth device and start pooling and saving data to a SQLiteDataBase.
The user can then minimize the activity and do other stuff.
When he returns (if ever, he can stop the service through a notification area button) to the application it checks if the Service is running and if so, it starts another Activity which show the data that is being pulled from the OBD2.
My question is, between this visualization Activity and the Service should I use and by this I mean the recommended or the right one:
LocalBroadcast? This is actually what I am using. Every time the service pull some data, it sends a broadcast with the data everytime it was pulled. Then in the onReceive method call runOnUiThread to update the respective View.
Messenger? As far as I know (never used it) I should send a Messenger from the Activity to the Service (much like a Handler) and in the Service it should send the Messages with the data pulled. But from this I would get a RemoteObjectException if the Activity was destroyed (like I said, the user could just minimized the activity and then it got GCed). So, I would probably need a way of sending the Messenger to the Service every time the Activity gets created and check if it's ok to use the messenger form the Service every time (if that's even possible, I've never used this).
BindService? Should I bind to the service when I open the Activity and then get the data directly from methods in the Service? But this would probably mean I would have another thread in the Activity gets this data from the Service every time, right?
Handler? (for a moment now I realize don't know the difference between Messenger and Handler, should it be that "use Messenger when Service runs in another process and Handler otherwise)
I've seen/read a lot of answers here in SO and through the web in general.
But in the end I don't see a ultimate answer for my case. But I'm sorry if this is just because I couldn't figure it out.
Thanks in advance!
EDIT: forgot to mention, I would rather make use only support libraries and android framework stuff, I'm still learning Android and I want to understand what's happening within its own classes.
First sorry for my english.
I have a problem, and i can't find a solution, it sounds like:
i'm developping an app that's getting my location from gps and send it to a tcp server on pc , and store the data into a listview (for example). I have set a timer that send the location every 2 seconds. Everything works fine even if i connect two clients to server, until the phones gets locked .. then my server receive ugly string ..it seems like the sent-strings it straddles (the string contains parts of data from bought clients, parts are concatenated) .. but when i unlock the phones the server receive normal strings again..
I want to know how to make my app run in the same parameters when lock screen occurs .. Any ideas?
If you are doing this inside an activity or a fragment you are probably having an issue with the lifecycle of your app. If you want to understand the lifecycle, read this documentation article: http://developer.android.com/training/basics/activity-lifecycle/index.html
Doing nothing on your onPause method won't prevent your activity from sleeping, Android can kill your activity anytime.
The proper way to do this would be inside a Service, a service is a special component on Android that is executed independently of what the user is doing or not doing, and in this case, you could create a service that holds a wake lock in order to prevent it from sleeping for the couple of seconds you need to send your data.
An easier solution would be to use something like this Location polling library and suit it to your needs.
When the screen locks your activity is either paused on stopped and it is important you handle these methods so that any interuptions are handled elegantly and without error. Or so the app will continue to run in the background.
If you read up about the activity lifecycle.
During normal app use, the foreground activity is sometimes obstructed by other visual components that cause the activity to pause. For example, when a semi-transparent activity opens (such as one in the style of a dialog), the previous activity pauses. As long as the activity is still partially visible but currently not the activity in focus, it remains paused.
However, once the activity is fully-obstructed and not visible, it stops (which is discussed in the next lesson).
Activity Lifecycle from android.com
To put things simply, I'm writing a video chat application that's supposed to connect say, two Android phones. So far, I've managed to negotiate interactions between clients, until the point I've reached the part where I'm supposed to do the streaming of video (and later audio) data between the clients.
The problem is as follows:
I am trying to implement a service that will, once a person has decided to contact someone, be started from a ChatActivity, and that will negotiate streaming between the two clients, making the sockets and the data going between them completely independent of the events going on within the ChatActivity, except for the moment the conversation is over, where the activity is terminated for good, and with it the service.
However, my concern comes from the point that if the service terminates the sockets mid-conversation, I have the problem of having to renegotiate streaming between client and client.
As is probably obvious, my knowledge of android services is limited, at best, and any advice on the subject is welcome
My questions are:
Is it doable to create a service that will, bar unexpected crashes due to outside influences, keep such a connection active and running regardless of how many times the activity that displays the video from the streaming (ChatActivity) is destroyed and created?
Should I be going with a bound service or a started service for this, or some hybrid of the two?
If I were to somehow create a pair usable stream of video data from the service, one via internet connection other via camera, would I be able to send them back to the activity, and keep reconnecting them to the components, regardless of how many times they get destroyed and created during the lifecycle?
Despite my efforts, I haven't managed to find any examples of anything similar, if anyone has come across code that does some similar socket/service juggling, I'd be most grateful for directions.
Is it doable to create a service that will, bar unexpected crashes due to outside influences, keep such a connection active and running regardless of how many times the activity that displays the video from the streaming (ChatActivity) is destroyed and created?
The Service lifecycle, if started via startService(), is independent of the lifecycle of any of the activities. Activities can come and go, but a service can stick around for a while.
Should I be going with a bound service or a started service for this, or some hybrid of the two?
You will need to use startService() if you intend for your Service to run without any activities around.
If I were to somehow create a pair usable stream of video data from the service, one via internet connection other via camera, would I be able to send them back to the activity, and keep reconnecting them to the components, regardless of how many times they get destroyed and created during the lifecycle?
That's impossible for me to answer, without a complete description of what "a pair usable stream of video data" means.
That being said, you will probably want to consider an event bus like Square's Otto or greenrobot's EventBus, as they both have support for the UI layer receiving events on the fly (e.g., service just establishes communications) and retrieving on demand the last-sent event (e.g., activity needs to reconnect to the last stream).
I am trying to develop an application which will require a service to
run in the background. I am relatively new to android programming,
and after reading many posts, blogs, how-to's and books on creating
and managing services, I am still pretty confused about which model I
should try to use.
First, let me present (in general) the application requirements: I
need an application which will spawn a background process (service?)
which will connect to a bluetooth device. The bluetooth device is
designed to deliver data to the android device. The issue is that the
data could come in at any moment, so the bluetooth connection has to
stay active. Note that the application is a VERY SPECIFIC app and is
NOT intended for public use. I do understand the arguments for not
having background apps running all the time, but please understand
that this is a very specific application for a very specific client.
Now, in general, I think the program flow would be to start the
application (and launch a UI activity). Then I need to configure and
connect to the bluetooth device. At this point, the user should be
able to do other things - make phone calls, check their email, etc.,
while the bluetooth connection is still active and potentially
receiving data. If data comes in, a notification is fired, etc.
So here are my questions and concerns:
If I start an app (which spawns a UI activity and ultimately my
bluetooth connection service) but the app is killed, apparently, the
service handling the bluetooth connection is killed as well. How can
I keep that alive? I read that Service.setForeground() was
depricated, but even if I were to set it to the foreground, if the app
is killed, the service is killed as well. I need to have it run in
the background with as high of a priority as possible (again, I do
understand that this is considered "bad form", but this is a specific
app and this functionality has been requested by the client).
If I started the app (and the service, etc.), but the user, say,
answers a phone call, the app is put into the background. However,
let's say the user goes back to the home screen and starts a DIFFERENT
instance of the app, i.e., he doesn't hold down the home key to select
the already running app from the task manager but starts a completely
new one. If the service handling the bluetooth connection is still
running, how will this new instance behave? i.e., how can I get it to
connect to the bluetooth service which is ALREADY running in the FIRST
instance of the app instead of this new instance? Do I have to use
some form of a Remote service instead of a local service? This is
where I'm a little confused by things as it seems remote services and
defining an AIDL seems to create a lot of extra overhead, and since
I'm already creating a lot of overhead with the service running in the
background all the time, I want to keep that as small as possible.
How can I insure I am connecting to the same service already running?
1)
The service does not depend on an Activity. You can have it running on the background until you call stopSelf().
You can have a BroadcastReceiver that listens to the android.intent.action.BOOT_COMPLETED so your service is started when the phone is turned on.
2)
Your Activity should bind to the service. And get the info from it.
Check this question.