The documentation for GcmNetworkManager::cancelTask
https://developers.google.com/android/reference/com/google/android/gms/gcm/GcmNetworkManager"
says
Cancel a task, specified by tag. Note that a cancel will have no
effect on an in-flight task.
What's an "in-flight" task ?
According to the documentation, the GcmNetworkManager collects various requests and executes them batch-wise (in the intention to minimize the times, the network system is used, in order to save battery).
To my understanding, "in-flight" then means tasks, that are really already started, i.e. where the syncing is already in progress. So basically, you can only cancel tasks that have not yet started.
Related
My question is can I close the activity after starting work manager?. currently in my app, I want to use WorkManager to print a receipt from the printer. So I want to start WorkManager from the activity, then I need to close the activity. Will the code from the WorkManager continue the print task from the worker or will it stop after closing the activity ?
Short Answer :- Yes
that's the whole point of the using the workmanager so you can schedule your task based on System events, so it does not not matter what activity is running.
as according to the documentation
For work that is deferrable and expected to run even if your device or
application restarts, use WorkManager.
https://developer.android.com/guide/background/#workmanager
About how to implement workmanager, below documentation will help you.
https://developer.android.com/topic/libraries/architecture/workmanager/basics
here at the end you will find section "Hand off your task to the system".
the system will place your task in a system queue to execute it based on system event that you will define
It's mentioned in WorkManager documentation that cancelling a Worker is best-effort
WorkManager makes its best effort to cancel the task, but this is
inherently uncertain--the task may already be running or finished when
you attempt to cancel it
What if i have a use case that it's mandatory that the Worker gets cancelled upon calling one of the cancelling methods?
As you wrote WorkManager can only try with a best-effort to cancel a work. In particular, if a task is scheduled to run, and you cancel it, WorkManager will remove it from the schedule.
However, if the tasks it's already running, WorkManager cannot safely interrupt it. The best option is that you write your Worker class taking care of an external cancellation. This has been covered in the Working with WorkManager talk (around minute 15) recorded at the Android Developer Summit 2018.
To be a good citizen you can pool WorkManager using the method: ListenableWorker.isStopped(). You can combine this with the onStopped callback to cleanup your code when you or the OS request to stop the task.
In our app, we have periodic sync tasks. So we have implemented Job scheduler to fire every sync interval. When the job gets fired, we are starting an intent service and this job gets killed. Intent service starts the 3rd party sync from internet/Server
Questions:
Is this design ok for Oreo and Nougat?
If the intent service takes few mins to complete, will the system allow?
Ref: Medium link
If your job inent service depend on network restriciton you need to set setRequiredNetworkType as there are some new changes done in oreo developement for job scheduler you shold opt for that part as per your flow please take in to account that
Calling setRequiredNetworkType defines network as a strict requirement for your job. If the network requested is not available your job will never run. See setOverrideDeadline(long) to change this behavior. Calling this method will override any requirements previously defined by setRequiredNetwork(NetworkRequest); you typically only want to call one of these methods.
When your job executes in onStartJob(JobParameters), be sure to use the specific network returned by getNetwork(), otherwise you'll use the default network which may not meet this constraint.
for more details go to this source of the above answer https://developer.android.com/reference/android/app/job/JobInfo.Builder.html#setRequiredNetwork(android.net.NetworkRequest)
I'm trying to implement a PeriodicTask with the GcmNetworkManager API (existing since Google Play Services 7.5).
My task is scheduled as soon as my app starts and will check the content of a Queue of objects in order to send them as batches to my server.
If the queue is empty, the method onRunTask() will do pretty much nothing (it will check the queue and return GcmNetworkManager.RESULT_SUCCESS).
I have put some logs in the implementation and noticed that the PeriodicTask keeps running forever, even after my app is in background or removed from memory.
This made me worry about my users' battery. Even though I won't perform any heavy task or HTTP request, the process is started periodically without real need.
At first, I thought GcmNetworkManager would be smart to exponentially back-off my Task until it stopped (or maybe I'm doing something wrong that prevents that), but, as my logs showed, that did not happen.
Afterwards, I have tried using cancelTask() and cancelAll() but those do not work if called from within the Task's onRunTask() method itself. Even calling stopSelf() is not a good idea since GcmNetworkManager is the one responsible for the Service lifecycle so I do not want to get in the way.
The difficulty of actually finishing the task made me think if that is the right approach (maybe I should just let the Task live forever?).
How can I use PeriodicTask properly while not draining the user's battery?
First of all, do you really need periodic task execution? It sounds like you can register OneoffTask with updateCurrent whenever you update your Queue. In case of upload failure, you can use RESULT_RESCHEDULE to retry later (and Google Play service will employ exponential back off strategy to decide when to retry).
I don't know your requirement, so you may really need PeriodicTask. If so, you don't have to worry too much about battery. The idea of GcmNetworkManager is that, you let Google Play service handle task execution, so it can execute multiple tasks together.
Phone will consume battery when it changes its state from inactive to active (see e.g., https://www.youtube.com/watch?v=-3ry8PxcJJA) so as long as your job is executed in batch with other tasks and finishes your job immediately, you don't waste much power. You can configure executionWindow to encourage batching.
I have used background service in for updating tasks like playing with web server frequent times(sending Geo-Location data or send/get web data time-wise) in my android apps and also I have faced many problems(slow process, application hang) for this.
But In my current application I have used the AlarmManager followed by PendingIntents for some tasks which worked well.
So I think its good if I replace each updating tasks which use service with AlarmManager followed by PendingIntents.
Is it the right way or I am going doing a big mistake ?
All kind of suggestions are appreciable.
Thanks in advance.
Services and alarms scheduled with AlarmManager serve different but complementary purposes at times. When you schedule an alarm with one of the set methods, the alarm will be triggered at the specified time and you should handle it on a BroadcastReceiver. This means that your handling has to be responsive and cannot have asynchronous operations. According to the docs:
A BroadcastReceiver object is only valid for the duration of the call to onReceive(Context, Intent). Once your code returns from this
function, the system considers the object to be finished and no longer
active. (...) Anything that requires asynchronous operation is not
available, because you will need to return from the function to handle
the asynchronous operation, but at that point the BroadcastReceiver is
no longer active and thus the system is free to kill its process
before the asynchronous operation completes.
In case you want to handle more complex operations, it is advised to start a service for doing so. Even if you use the more recently available goAsync() call on the receiver, you are still expected to be responsive:
This does not change the expectation of being relatively responsive to the broadcast (finishing it within 10s)
So it ultimately depends on what you are trying to achieve, when to use each of these or combine their use.
I don't tell that using Alaram Manager is a big mistake..
Right now to run the background services there are only few options upon which the easy and partially reliable one would be AlarmManager.
Though sometimes the Alarm Manager is not 100% reliable on looking into other categories for doing these operations (like Asynchronous Thread and delay looping techniques) are much more complex and not that much reliable to do the background services.
When we compare the pros and cons of the techniques needed for background services AlarmManager wins the race.
I prefer AlarmManager would be the good option for these kind of background services upon thinking the options open right now to complete the tasks in background.
Hope that Google will comeup with a better solution to handle the background services.