I'm in the middle of building an Android version of my iOS app and could use some guidance as to how to implement certain features.
The app has several responsibilities; monitoring location changes and adding them to a DB, advertising and discovering available peers via Bonjour, maintaining connections to discovered peers and to a server, and advertising and listening for nearby peers via Bluetooth LE.
To organize them, I created 'Manager' singleton classes for each responsibility (e.g. LocationManager, BonjourManager, etc..) I start them when the app starts and stop them when the app terminates.
Obviously, I don't want them running in the background when the user is not interacting with the app. In iOS this was simple enough; each manager registers itself for lifecycle notifications, pausing on appDidEnterBackground and resuming on appDidEnterForeground.
My question is: How can I 'manage' these managers in Android so that they stop running when the app in not visible to the user and resume when the app is opened again? As far as I know, there is no global onPause and onResume which get called when the app switches between background and foreground.
I looked into using BoundServices but then I would need a binding between every activity and every manager so that the managers aren't destroyed until all activities unbound?
Help! I have a feeling that managers maybe aren't the right way to keep these activities alive...
Maybe this can help http://www.stackoverflow.com/questions/20912229/…
Something with keeping track of the onStart etc. count.
Init your services in Application class.
Termination is handled "by the system"...
public void onTerminate ()
This method is for use in emulated process environments. It will never be called on a production Android device, where processes are removed by simply killing them; no user code (including this callback) is executed when doing so.
Related
I am developing an application in Android that connects to a Bluetooth device. On occasion, an alarm created by the alarm manager goes off and is supposed to send information to the connected Bluetooth device. My question is, what is the best way to make this connection so that I can communicate with the device when the activity has been stopped (app is closed). I have read about intent services, foreground services, remote messenger services, and have not found any source that says the best way to make a service that won't end when the application is closed to host Bluetooth.
create your service class extend service and bluetoothadapter init in yourservice oncreate()
Foreground Service
First of all I suggest using a foreground service.
The service runs indefinitely and the app will be recreated each time it is killed (by user or by system).
In addition foreground services are also excluded from Oreos background execution limits.
Check out this post for a detailed description and test of Android service's lifecycle. Please also be aware that testing the lifecycle of services can be quite a struggle. Debugging tools usually loose connection to a service once the app is swiped off of recent used apps list or killed otherwise.
Service lifecycle
Once you set up the foreground service you should make use of service's lifecycle hooks as pointed out by Yongho to keep a reference to peripherals.
For example you could create and assign BluetoothScannerCallback to an instance variable in OnCreate() like so:
OnCreate() {
_scannerCallback = CreateScannerCallback();
}
This way you'll be notified about connection losses. Also use Androids Bluetooth Default Adapter inside the service in order to keep connections to Bluetooth devices alive when the host application is moved to background or killed (and recreated).
You should also deinitialize all references in OnDestroy().
In my application I check to the server some user state in the onCreate() method of the main activity.
I recently notice that doing so is an issue when I run the app from Eclipse while the phone is asleep (screen off, locked). In this situation, the application waits that the screen get unlocked to call the onStart() method and pursue its way. That makes fail the data update.
Maybe I should put it inside onStart?
Can the user do the same process = start an app with locked screen? I though of Tasker but are there other way?
Edit: All the server updates communication are done off main thread, handled by managing classes and I use volley. So it's not a service and though I will put one later, I have not enough time to do it now. Except if you say it's 2 days work to learn and implement. Can a user start an application like a dev can do it ?
This things that you are doing in an Activity must surely be performed in a Service. Android Service provides you with doing background data processing/syncing.
If I make a call to an external web service and the user rotates the device, the Activity will restart (I know you can handle it yourself but this is not recommended). I know I can preserve the state using onRetainNonConfigurationInstance().
The question I have is what happens to the inflight network IO after the Activity restarts? Does it continue, is it suspended or killed?
I am rather new to Android (iOS person) so the restarting Activity is rather odd.
Some network calls we make could be restarted, but checking out for a purchase is not one of them. How do I handle this so that purchases still work correctly? Assume I would use Asynctask (though I realize there are other choices such as Executors).
For network calls that need to maintain across activity restarts (e.g. purchase), consider using a service instead of doing it inside the activity.
If your connection is defined as instance variable inside the activity it will be destroyed/killed when the activity restarts.
Another alternative, but I would not recommend, is to implement an application class and maintain your connection there so it will be persistent as long as your app process is alive.
You should not be handling requests inside activities unless they are simple enough to fire off (i.e., do not require responses). The common use case is that you are interacting with a REST interface that you want to handle across multiple activities. The basic idea is to issue requests to the service and let it mediate the connection for you. Google IO 2010 had a good lecture that you can listen to.
Implementing the functionality inside an Application class is not recommended, as you will get strange behavior when your app is killed by Android when memory is tight.
I am making an android app which will have two services that will keep sending data about the usage of the phone by the user every 24 hours.
The user should execute the app, toggle the buttons to enable the logging of the usage of the phone and then the user should be able to do a normal life with his phone, until he starts again the app and disables the toggle button to stop the logging of the info.
What considerations should I take about the life cycle of the services?
What about the interaction of the user with the phone while the services should be sending the data?
All info is very much appreciated, as I my mind is getting a little bit overwhelmed with all this!
Thanks a lot in advance everybody!
The service can be cut at any time through the settings menu. It can also be killed at any time by Android if it decides it needs the resources for the currently running activity. onDestroy() will be called regardless so use that to store anything needed.
The service runs in the background but through the main UI thread. Thus, it is possible to block operation of the phone through a service. It looks like the phone locked up when it's really a service trying to do something. Any blocking procedure should be used in a thread such as Java timer, Java thread, or AsyncTask.
There can only be one running version of the service at any given time. However, calling startService(myService) if "myService" is already running will essentially override the current running service and onStartCommand() will be called again. However, one call to stopService(myService) is needed to stop it no matter how many times startService(myService) was called.
stopService(myService) will not stop a service if the service is bound to anything. It will wait until all bindings are removed before the service stops.
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.