How to replace the deprecated WakefulBroadcastReceiver with JobScheduler when triggering Geofences - android

I am using the WakefulBroadcastReceiver to receive events of triggering Geofences. It starts an IntentService as wakefulService. I want in some cases to wake up the device and show an Activity and in other cases to just do some really minor work without waking it up.
With Android O the WakefulBroadcastReceiver is deprecated and should be replaced with the JobScheduler. The problem is, after reading the docs and some examples I still have no idea how to do this. If the examples don't just schedule the job in a running Activity they use a BroadcastReceiver but thats exactly what im not supposed to do.
Where should i schedule the job and how can i wake up the device without using a WakefulBroadcastReceiver?

Related

WakefulBroadcastReceiver does not works when app is closed

Please help me out, a wakeful broadcast receiver is not called, I have set an Alarm with the help of Alarm Manager using setExactAndAllowIdle() with RTC_WAKEUP but still, my broadcast receiver not getting called when App is closed (means App is swiped from Recent Apps).
I am working on android 8.
Actually, I want to create an Alarm App that fires at the exact time which set, even if the App is closed or the device is locked.
Here is what you need to check out:
Alarm manager is not working with long term tasks
How to use Android AlarmManager in Fragment in Kotlin?
All the information you need can be found in those topics.
It may be because the WakefulBroadcastReceiver has been deprecated as of Android O and should generally not be used anymore. From the documentation:
Deprecated: As of Android O, background check restrictions make this class no longer generally useful. (It is generally not safe to start a service from the receipt of a broadcast, because you don't have any guarantees that your app is in the foreground at this point and thus allowed to do so.) Instead, developers should use android.app.job.JobScheduler to schedule a job, and this does not require that the app hold a wake lock while doing so (the system will take care of holding a wake lock for the job).
https://developer.android.com/reference/kotlin/androidx/legacy/content/WakefulBroadcastReceiver

Time-based notification in Oreo

I am working on a task scheduling app that reminds me of a task at a certain time. I used to implement this with getSystemService(AlarmManager.class).set(RTC_WAKEUP, millis, pendingIntent);. Then a IntentService gets started later and shows a notification.
But in Android Oreo my IntentService simply doesn't get called at all. I noticed the massive discussion about the Background Execution Limits and how you should migrate from AlarmManager to JobScheduler, but nobody mentions how JobScheduler can start a job based on RTC.
What my IntentService does besides showing a notification is nothing more than setting the task as "notified" or "done", which I think is incomparable to the heavy tasks like synchronizing big amount of data over network that the JobScheduler was introduced for.
What is the best practice in Android Oreo to implement time-based notifications?
I am taking #balu-sangem 's solution:
Replace PendingIntent.getService() with
PendingIntent.getBroadcast()
Replace IntentService with BroadcastReceiver

Do I need to acquire wake lock when invoking a BroadcastReceiver

In the book Pro Android 4 By Satya Komatineni , Dave MacLean I've found:
Android acquires a partial wake lock when invoking a broadcast service and releases it when it returns from the service in the main thread
Does it mean that the Android OS ensures that the device will wake up for the time of going through onReceive of BroadcastReceiver? In my case the BroadcastReceiver should get an intent from Google Play Services (GoogleLocationServices and to be precise Geofences api).
Where is it documented?
EDIT: I've also found it here:
because it is guaranteed that the BroadcastReceiver.onReceive() will be always fully executed before the CPU goes to sleep
There is no such thing as a "broadcast service".
Also, you need to read the entire post containing your second quote, as that is only for a broadcast triggered by AlarmManager. It is AlarmManager, not the broadcast Intent mechanism, that holds the WakeLock. Also, as noted in that blog post, Dianne Hackborn had confirmed this behavior, and she's a core Android engineer.
Does it mean that Adnroid OS ensures that the device will wake up for the time of going thru onReceive of BroadcastReceiver?
Not generally.
In my case the BroadcastReceiver should get intent from Google Play Services (GoogleLocationServices and to be precise Geofences api).
If the Google Play Services documentation does not make any claims regarding the behavior of your receiver with respect to wakefulness, you should assume that you are not inside of a WakeLock. If the work is something that will take 1-2ms, and therefore is probably safe to do in onReceive() anyway, you're welcome to take the risk and skip a WakeLock and hope for the best.
But usually a broadcast like this triggers more work, involving disk I/O and/or network I/O, and you need to get that work off of the main application thread. Frequently, you do that by delegating to an IntentService, as it gives you a background thread with a marker service to let the OS know that you're still doing some work here. And, to ensure that the device will stay awake for that work to complete, use WakefulBroadcastReceiver or my WakefulIntentService, to hold a WakeLock from early in onReceive() until the completion of the work in onHandleIntent().
Where is it documented?
AFAIK, it isn't. Get used to it, as for complex systems, usually only a tiny fraction of the system's behavior winds up being documented.

Do BroadcastReceivers need to be their own process to be independent from the UI (activities)?

So I'm working on an app that uses the AlarmManager to broadcast an intent for my receiver to do a simple task and finish quickly. I want my receiver to run every few minutes so I use setRepeating to ensure this. I don't want to have to worry about the main activity of my app running or being visible when the alarm triggers. In order for my receiver to run separately from the main activity like that, do I need to add android:process=":remote" to the receiver in the manifest? or are they already inherently separate things? The two do not need to communicate. I'm trying my best to kill the activity without canceling any alarms and the receiver seems to be running properly for now, but I'm wondering if it'll continue to work for a few hours or days.
Yes, they're separate. No need to use that attribute.
By the way, how much work do you do in that BroadcastReceiver? Normally, you can't do very much inside the BroadcastReceiver itself, you use it to trigger other things.
Also, I'm wondering how you're doing the following:
"I'm trying my best to kill the activity..."
I'm wondering what problem you were trying to solve here by trying to kill the activity?
To your immediate question - certainly not - it will be a performance killer and is unneeded anyway.
To your design - flawed. You should :
Register an alarm (also take care to re-register it on boot) - see wakeLock does not wait for network connectivity for the code registering the alarm
When the AlarmaManager wakes your receiver up delegate to a WakefulIntentService. The intent service is NOT guaranteed to run when the device is asleep (see Android deep sleep and wake locks).
See also:
PowerManager.PARTIAL_WAKE_LOCK android
PowerManager wakelock not waking device up from service for the WIS skeleton
WakefulIntentService implementation clarifications

service implementation pattern

ok I have this application which needs to send periodic updates to a web-service, I have done a fair amount of research and I've come up with two service implementation patterns.
Implement a service with a thread, the periodic update time may vary therefore, I will put the thread to sleep with the required time-interval, then call the web-service again. I also need to update an activity, therefore will be using a broadcast receiver or a messenger.
Use a Service with a schedule timer/alarm manager, wake the system and use intent services coupled with a broadcast receiver.
Which would be the best approach?
I think I would go with the #2 option :
Create an IntentService to do the update.
Register a BroadcastReceiver with IntentFilter(s) and start the IntentService from it.
Use AlarmManager to Broadcast the registered action at the required time intervals.
I prefer this method because :
It is a very flexible pattern : You can start the service anytime by registering the same receiver for different actions like network connection changes, system boot changes etc.,
It keeps the logic loosely coupled from other parts of the app.
There is no hassle of managing threads. You get it for free by using IntentService
It is more android-ish way of solving this problem.
The main difference would be that a background service can be shut down by the user and then you won't get any more updates. If you register events with the AlarmManager, then you control when/if these events take place. If the user shuts down your app and goes into a task manager and shuts down any running services related to your app, the AlarmManager is still going to wake up and send a message that your BroadcastReceiver will receive.

Categories

Resources