Update data in Background Periodically (Android) - android

The main objective of my app is, when a button is pressed:
Collect data from the sensors
Store data in the database
Repeat periodically (every X seconds)
I want to have it done in background, and if the Main Activity is destroyed, the background progress to be still running. So if you delete the activity, I want it still running.
What I am doing right now, is having an AlarmManager with an Intent Service, to set the periodic recording of the Data, but whenever I destroy the Activity, as they are related, my app crashes.
I know there are different to run a background process, but none fits in mine:
Service: Depends on MainThread, so if the MainActivity is destroyed,
crashes
Intent Service: The one using right now, but as far as it is
related to AlarmManager, that is related to MainActivity, when it is
destroyed, crashes.
AsyncTask: The problem of this one, is that it is
supposed to do one task in background and it finishes, but what I
really want is to do it periodically until the user says to stop. So
it's not a matter of one time thing.
Is there any other way to have a background service?
Can any of the stated before be used for my purpose?
How do you recommend me to do it?
Thanks for your answers.

Try to start service in separate process using android:process=":servicename" in AndroidManifest.xml. If service is running in another process, it wouldn't be killed with activity.

Related

How is a running IntentService managed after the app process is killed

Just trying to clarify my understanding of how an IntentService is managed by the OS once terminating states have been reached. By terminating, I mean when the current activity is destroyed or the app process is killed, as per the following documentation:
https://developer.android.com/guide/components/activities/activity-lifecycle
Given the comment
Also, an IntentService isn't affected by most user interface lifecycle events, so it continues to run in circumstances that would shut down an AsyncTask
at https://developer.android.com/training/run-background-service/create-service;
I feel as if:
1) A started IntentService is unaffected by the activity lifecycle. Is this correct?
2) If (1) is true, will it continue to run indefinitely even after a terminating state is reached, up to some point that it either stops itself or the OS decides to stop it?
In my particular situation, I'm using an IntentService during app startup to query APIs, grab content, and then add a new (landing) Page to the Xamarin.Forms navigation stack (this would be equivalent to starting a new activity).
This leads me to my next question...
3) What happens if the app is already in a terminated state when it comes time to the IntentService creating a new Activity? Surely the Activity can't be added to the navigation stack as it no longer exists once the app is terminated?
Yes, a started IntentService is unaffected by the Activity Lifecycle. Actually, all Services outside of bound Services are unaffected by the Activity Lifecycle.
An IntentService will continue until it reaches completion of it's work, the application is destroyed, or if the System decides to kill the Service due to the changes in the Android 8.0 background Service rules.
Your use of terminated state is too broad... If the Application is already terminated, then nothing will happen because the IntentService would have been terminated already too. If it's the Activity that launched the IntentService that was terminated, then nothing happens, since by default, an IntentService has nothing to do with Activities, even if it's the one that started it.
For the last question, it really depends on how you choose to communicate the result of IntentService to an Activity.
If you're using a BroadcastReceiver, then nothing will happen because an IntentService will fire the broadcast without any problems, but the Activity won't be able to receive the results since it's terminated.
But if you're simply creating a new Activity, then you can simply use startActivity() with the result data added to the Intent. Though, I doubt the user will be happy to see an Activity suddenly open on the screen when they're no longer in your app. Starting a new Activity has nothing to do with a previous Activity, since any instance of a Context can start an Activity.
Honestly, based on your question, it sounds like you're very concerned with an IntentService and it's connection with the Activity that started it. If that's the case, you really shouldn't be using an IntentService, since that's not really it's purpose. It's not meant to have a connection with an Activity. It's simply meant to do work and finish.
Instead, a bound Service would be a better option since it has a direct connection with the Activity that started it.

want to make the service independently run

So basically what i am trying to do is i want a service that runs in background and updates the LatLong to the server. This operation needs to happen all the time even if the application is running or not.
Now when the application is launched i want the service to calculate the distance between the latlong and update the UI in addition to the work that it was already doing i.e. updating the latlong to the server. i want the service to do the additional work for multiple activities. lets say i launch the application and i am on Activity A, onclick of a button on Activity A the service starts updating the UI and when we click gain it stops updating. Now i am on Activity B and on click i want the service to do some work in addition to the updation of LatLong and update the UI.
What would be the best approach to achieve this.??
EDIT
The problem i am facing is not getting the service update the UI but making the activity communicate with the service when it has already started.
i can pass on some data when i am starting the service but how to communicate with the service when it has already started. How to tell the service that see you are already running and doing some operations now you have to perform some more operation on top of the previous operation.
I can make some static method in the service and call them when i need to perform the extra operation but i dont wanna do that.. i want to better approach.
Here is the basically services runs on the same main thread process as ui. When you want make it run continuously you have run it in your tread. In this way you avoid service being get stopped as application go in background or killed. (Please take look at Service.START_STICKY flag, this is what you need as i guess).
And more coming your second problem of activity getting updated with service information or data that is being collected for this you need look at " How Bind the service". (In activity check for service connection and Binding to a activity, Unbindibg is also there have look at it also). Activity has all the call backs for it you need to implement binder.
EDIT
Service to update ui has to have send and receive intent mechanism. You can broadcast and intent from the services check your activity is running or not. If running broadcast intent and have receiver in activity to listen it.
You can do it by interface mechanism too

When and how to exit file uploader service

I have a class that implements fileuploader service. Activites bind to it and supply it a list of files to be uploaded, and then unbind immediately. The files are then uploaded one-by-one by the service in a background thread(asynctask).
I start this service in my dashboard actvity using startService(), so that it keeps running until specifically stopService() is called.
Now, my question is when do I stop this service?
Basically I need to check two conditions: 1: all files are uploaded; 2: app has exited.
Also, to exit the App, user has to press back button on dashboard activity.
I could have overrided back button press and queriesd the service whether any files are left, but I dont want to use that method.
Any suggestions?
Activites bind to it and supply it a list of files to be uploaded, and then unbind immediately.
I would recommend then using startService() rather than bindService().
The files are then uploaded one-by-one by the service in a background thread(asynctask).
This seems like a much better fit for startService() and an IntentService (or a WakefulIntentService perhaps, if you are concerned about the device falling asleep during uploads).
I start this service in my dashboard actvity using startService()
This would not be needed if you used startService() for sending over the work.
so that it keeps running until specifically stopService() is called.
Ideally, the service would shut itself down, like IntentService does. After all, only the service knows when the service is done.
my question is when do I stop this service?
When you have no more work to do. IntentService does this automatically. If you really want to maintain your own thread pool for doing the work, then when your work queue is empty and all threads are done, call stopSelf() from within the service.
Basically I need to check two conditions: 1: all files are uploaded
Yes.
2: app has exited
No. Your UI should not care whether the service is running or not running. The service should take care of itself.
Also, to exit the App, user has to press back button on dashboard activity.
Users are welcome to leave your app however they please: BACK, HOME, RECENTS, a Notification, an incoming phone call, etc.
Any suggestions?
Use an IntentService. Send over the jobs to be uploaded via calls to startService(), packaging all needed data into the Intent used with startService() (e.g., extras). Do your upload work in onHandleIntent(). If desired, use LocalBroadcastManager to let activities in your app know about the upload status, so they can reflect that in their UI if they so choose. IntentService will handle stopping itself when its work queue empties.

Using Services for this task

I have tried to search many discussion threads but I am not clear on this thing. Being new I am unable to understand half of the things hence I am going to ask the direct question.
For my application when the final button (start analysis button) is clicked, I want a service to start, the analysis to be done inside the service is long almost 2-3 minutes, once the analysis has been done I want the service to automatically start a result activity page present in my main activity.
How can this task be achieved ? and I would also like to know that if the application will run in background and will not be closed by android automatically when on pause ?
Thanks
The definition of Android service is that it can run in the background, devoid of UI. So yes, it is possible. However, a Service by itself does not automatically run in the background (it runs on the main thread). Instead, what you want to do is probably something like this:
Have a service which listens for intents that say to start the operation.
When your user clicks the button, send the intent to that Service.
The service will start a new background thread, do some work for a while.
After finishing its work, the Service will start a new Activity. (Like this..)
Please take note, that it is considered extremely bad practice to start a new Activity if the user is not using your app. It's horrible if you're using a chat application and a random app starts taking over... Instead, a better idea is to stick a flag somewhere and then in the onResume() handler of your other Activity, check if the task is finished, and if so send the user to the other Activity.

Best strategy to implement this behavior in Android app?

In my Android app, I have some data that needs to be synced daily but also needs to be updated every hour when a user is inside the app.
I have already implemented a service that gets called from an alarm for the daily update. Im having a problem with developing a strategy to do the hourly sync. I could use an hourly alarm too and fire the same intent, but since your app can be killed at any time, there would be no way to cancel it (and since they use the same Intent, doing a cancel would cancel ALL alarms including my daily sync, so that's probably not good).
The other option is to use a Timer that's set when inside the app, and have that fire my Intent when inside the app. Im assuming all Timers get cancelled when an app is killed right? But my app consists of several activities and I want the timer to work across all activities, how do I do that? I dont want to duplicate code - we're already using a subclass for Activity and ListActivity.
I have some data that needs to be
synced daily but also needs to be
updated every hour when a user is
inside the app.
The solution seems easy: drop the second requirement. Few apps are used continuously for hours on end, since people tend to use their Android phones for other things (e.g., phones), so your update-hourly-if-used-all-the-time code will probably never run.
I could use an hourly alarm too and
fire the same intent, but since your
app can be killed at any time, there
would be no way to cancel it
FWIW, your app will not be killed while it is on-screen. And, while it is not on-screen, you don't want the updates going hourly.
Im assuming all Timers get cancelled
when an app is killed right?
Apps generally are not "killed". We expect you to clean up after yourself when your activities are called with onDestroy(). If you set up the Timer with a daemon thread, you will need to terminate that thread.
But my app consists of several
activities and I want the timer to
work across all activities, how do I
do that?
Bind to your service from each of your activities. If it is started by your alarm Intent, have it do normal update processing. If it is started due to a binding request, just have it make sure its hourly Timer is running. When it is called with onDestroy() (e.g., after all activities have unbound), have it stop the Timer.
You might be able to have a Timer run in a background service (which get killed less than activities) but there is still no guarantee that Android won't kill your service either. And running something like this is the background might use a lot of battery.
What about doing the hourly sync in a background thread that get's created in onResume? And just save the last time the user did the sync, and if it has been > an hour just do the sync. Because I don't think there is any reason to eagerly sync data that the user is never going to see.

Categories

Resources