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
Related
Documentation for AlarmManager startes that
Note: The Alarm Manager is intended for cases where you want to have your application code run at a specific time, even if your application is not currently running. For normal timing operations (ticks, timeouts, etc) it is easier and much more efficient to use Handler.
However, once my application is closed (force close from task manager) my alarm does not work and the OnReceive method is never called inside the broadcast receiver.
I am targeting 4.x.
What's happening?
What #Shrikant says is pretty much the answer.
The longer verison is that it is assumed by Android that something is amiss with the app if the user had to force close it manually. Therefore all activities (BroadcastReceiver's, alarms, etc) related to the app will not be initiated until the app is run manually by the user at least once. For example, app's boot BroadcastReceiver will not be called when device is turned off and on in this state until the user runs the app, then the next device boot event will be delivered to the app's BroadcastReceiver.
This behavior is confirmed as by design by Android framework devs: https://groups.google.com/forum/?fromgroups=#!topic/android-developers/anUoem0qrxU
*edited for grammar & added an example behavior
I am making an app that needs to execute a function each hour even the app is closed.
First of all, I thought to create a service, but during my tests, I realise that android sometimes kills my service. So I was looking for another solution and I found AlarmManager. I have implemented it and it seems to work but I have the doubt if it will happen the same the service or it will run forever? (Until reboot of the mobile...)
Another question, it is necessary to create a new thread to execute the process in alarm manager or it runs directly in other thread?
I have implemented it and it seems to work but I have the doubt if it will happen the same the service or it will run forever? (Until reboot of the mobile...)
It will run until:
the device is rebooted, as you noted, or
the user uninstalls your app, or
you cancel the events yourself, or
the user goes into Settings, finds your app in the list of installed apps, taps on that entry, and clicks the Force Stop button
It's possible that alarms will need to be scheduled again after your app is upgraded (I forget...).
it is necessary to create a new thread to execute the process in alarm manager or it runs directly in other thread??
Unless the work you are going to do will take only a couple of milliseconds, you will want a background thread for it. That leads to two possible patterns:
If you are not using a _WAKEUP-style alarm, use a getService() PendingIntent to send control to an IntentService every hour
If you are using a _WAKEUP-style alarm, you will need to use a getBroadcast() PendingIntent, and have it either invoke your subclass of my WakefulIntentService, or you will need to manage a WakeLock yourself to keep the device awake while you do your bit of work
No, Android won't kill scheduled alarms and they got executed as planned unless app is replaced or device is rebooted. Use broadcast receivers for these events to reschedule Alarms. There's no way to prevent Force Stop as it kills all of your app components and threads totally.
That depends on what Alarm Manager do. If it sends a broadcast, the receiver limit is 10 second.
If it starts an Activity, Service or Intent Service, there is no limit. For Activity and Services you must finish or stop it and for Intent Services until the process is finished. Be aware that you can't have another thread inside Intent Service and you'r limited to code inside the OnHandleIntent.
Also you must consider device state. If it's sleep and you are using Wake Up flag receivers won't need a wake lock, but others do. It won't take long for device to go back to sleep.
Don't waste system resources with a service because Alarm Manager do what you want.
In my app, I have to make it vibrate in time intervals defined by the user.
Basically it has a chronometer that makes the device vibrate when it has reached the defined time. Currently I do that by reading the chronometer value and comparing it with the desired value, in the onChronometerTick() method
I need this app to work in the background too. I've googled and found some examples about the android Service class.
My doubt is how my Service class will get the chronometer value? I've seen that the Service class can't handle layout components.
How can I do this? Is service the best way to handle this issue?
Thank you!
It sounds like what you want is an alarmmanager. Here's what it says regarding alarm managers:
These allow you to schedule your application to be run at some point
in the future. When an alarm goes off, the Intent that had been
registered for it is broadcast by the system, automatically starting
the target application if it is not already running. Registered alarms
are retained while the device is asleep (and can optionally wake the
device up if they go off during that time), but will be cleared if it
is turned off and rebooted.
So if you're going to want the counter to continue after turning it off, you'll have to find an on-boot option or something. But yes, this is what you need to schedule events if you want them to keep happening after the screen locks.
I'm developing an app designed to transform an android phone into a remote device running without user action. At the time the app is made by an Activity that sets AlarmManager to execute a service (class inside project) every X minutes.
All this works OK, but occasionally after 5-6 DAYS continuosly running the application crashes (currently I don't know why, because i can't get the phone now). It isn't a connection problem (I know) and the phone is still running (plugged into AC). The only thing that i can suppose is that the application is down.
I don't think that this is due to a bug, because the prew debugging doesn't give me any errors.
So I must suppose that android has killed the activity (system needs more memory?) and as the image explain there is no way to back it up.
But I have a doubt: in my application the activity doesn't matter, because all the work is done by the service. The service itself is called by an Alarm Manager and in the time between two calls the service is terminated by StopSelf().
In my case the system may kill my alarm manager service schedule?
What can I do to have the service start up by Alarm Manager forever?
(ATTENTION: currently there is yet a WAKE LOCK but this consider only the execution of the service! I hope that you have understand that the service is called each x minutes by alarm manager and than terminated...i want to perform this operations for an indefinite time)
[I haven't posted the source code because is too long]
Lork,
After wrestling with a similar issues myself, I may have some pointers for you. I assume that you are using your Android device as a sort of remote ‘embedded controller’, which performs its functions with minimum user interaction. I believe that you are 95% there and just need to make some slight architectural changes. As you have not provided code, I’ll just explain in abstract terms rather than give code examples.
CommonsWare is correct that you need to use AlarmManager, but I suspect you already knew that.
A couple of background comments first, just to make sure that everything is understandable.
Alarms created by AlarmManager exist at the system level, that is they can exist beyond the lifecycle of the activity and application that created them. If you set an alarm but don’t want it to go off if your app changes state (for example after it has been destroyed), then you can cancel it using alarmManager.cancel(pendingIntent) – just create the intents and alarm manager with the same parameters and Android will match the alarm).
Similarly, BroadcastReceivers are registered at the system level (at least if they are declared in manifest.xml) and can exist beyond the lifecycle of the activity and application that created them. Again if you want to ensure that a BroadcastReceiver does not fire in response to an event occurring after your app has changed state (for example after it has been destroyed), you need to explicitly unregister in it code. If it was registered programmatically then use context.unregisterReceiver(broadcastReceiver); if it was registered statically in the Manifest its not so easy – you will have to retrieve the receiver using PackageManager and ComponentName (see: Android - how to unregister a receiver created in the manifest? ) - and remember that you will need to re-enable the receiver if you need it again.
You say you have already set up your alarm. Make sure you specify ELAPSED_REALTIME_WAKEUP or RTC_WAKUP for the alarm Type to ensure that it runs even when the phone is in ‘sleep’ mode.
You also say you have already created the associated BroadcastReceiver to handle to alarm event. The BroadcastReceiver should do a minimum of work, so you should handle any processing in a separate thread or by launching a Service. You opted to launch a Service and terminate it using stopSelf() when it has finished, so that it doesn’t use up system resources. So far so good.
This is fine when the app is running, however as you require something that runs reliably for an indefinite period, you need to ensure that you manage the 'exception' situations where it has paused, the device is ‘sleeping’, the app has crashed/terminated, or the device has rebooted (and any other exception scenarios you may think of). Here are the issues I have identified that you need to address:
First: WakeLock is only guaranteed for the duration of the onReceive() method of the BroadcastReceiver. After it has terminated, the device could go back to ‘sleep’ even if your Service has not started or even completed, so you need to create a WakeLock, pass it to the Service and release it before you stop the Service. (Note: for your application, you require a PARTIAL_WAKE_LOCK). Be very careful using WakeLocks – make sure you only hold a WakeLock for the minimum required time and ensure you release it, as it’s use can lead to excessive battery drain). See http://www.netmite.com/android/mydroid/development/pdk/docs/power_management.html for an example of using WakeLocks.
Second: If you reset your alarm in code (rather than defining an automatically repeating one), do this in the OnReceive() method of the BroadcastReceiver or as the first thing in the Service you have launched – this will ensure that the alarm repeats, irrespective of the state of the application or device.
Third: Make sure that any Contexts you use are going to be non-null values. You can dynamically fetch the context in the Service using getApplicationContext(). Otherwise this can be achieved by EXPLICITLY passing the Context from your application to the alarm and make sure it is passed all the way through the BroadcastReceiver, and associated threads and Services. If you have statically stored Context in your application so you can retrieve it anywhere, then this will return a null value if the application has terminated. If you use the Context (for example to retrieve a resource, access a database etc), and it is null, it will cause a null pointer exception and the Service or BroadcastReceiver will crash. I believe this is the most likely reason for your Broadcast receivers not to be working when your app has terminated.
Fourth: You may wish to make references to ResourceIDs (e.g. R.drawable.icon) in your Service or BroadcastReceiver fully qualified (. R.drawable.icon) or generated from the passed Context. I haven’t yet found this to be necessary, but I suspect it may be prudent.
Fifth: Implement a separate BroadcastReceiver to handle a device reboot scenario (ON_BOOT_COMPLETE event). You could get this receiver to re-launch the app if appropriate or it could launch a service to check that your app is supposed to be active, set up any required parameters and set up the relevant alarms, then terminate it using stopSelf(), or just set the alarm again and let that receiver handle it all. Remember to ensure the service has a WakeLock for its duration and to release the WakeLock when it is complete. If you don’t just relaunch the app, or a Service (declared as part of your application) then you should also statically store the correct Context as a class attribute in your BroadcastReceiver, if you need it, so that it is available to access resources.
A couple of other things you may wish to consider:
As your set up is remote, I would seriously consider storing any persistent data in SQLite database tables. This will ensure that data is recoverable between application terminations and device reboots, without having to regenerate it.
If your application communicates with a server service, consider using push notifications for server initiated communication, rather than have the app periodically poll. Push Notifications can also be used to ‘wake up and launch services and apps’, so could be used as part of a remote mechanism to query the status of the device and your application. This approach is also more power efficient and timely.
Post information to LogCat at key points in your code for debugging. If the application terminates, then adb stops tracking the source code running for the receiver and service, but LogCat continues to function, so can be used to check the path through the code and variable values.
Other people may have better ways to address these issues or some other pointers (I would certainly be very happy to see other input), but I hope these ideas are helpful and good luck!
The point behind using AlarmManager with a service is to start up a service that will run briefly, then the service goes away (e.g., an IntentService). If you are going to try to have an everlasting service, you do not need AlarmManager, and your service will be shut down by Android after some period of time.
If you rewrite your app to not need an everlasting service, but rather use AlarmManager as it was intended, you should have better survivability.
I believe that what Lork wants to achieve is similar to something I am also wrestling with.
He wants the alarm manager to trigger a broadcast receiver that will handle the alarm, even when the application it is part of, has been terminated (for example by the Android OS).
For example: The application sets an alarm, with a type of ELAPSED_REALTIME_WAKEUP or RTC_WAKUP and has a Broadcast Receiver to handle it when it fires, via an Intent which references the application context and the Broadcast receiver class. The receiver is declared as a in the application manifest.
Under normal circumstances, when the application is running or paused, when the alarm goes off, the Broadcast Receiver is triggered, waking up the device and resuming the application as necessary, and the alarm in handled.
However, if the application has been killed (for example by the OS), then the alarm will still go off (as it is still registered) but the Broadcast Receiver will not be triggered and LogCat shows a null pointer exception, (I assume because the reference to the application is no longer in memory). This will occur, even if the Context has been passed.
Am I (and I assume Lork) missing an easy strategy here? Or is it not possible? Can a broadcast receiver exist on its own and trigger the app if necessary?
One, imperfect strategy I have been toying with, is to move all the app data access into a Content Provider, and have a separate low profile app which just implements the broadcast receiver – triggering a service to do the work and accessing the application data it requires via the Content Provider. This would still be subject to being terminated by the OS, but would be less likely.
I have a service that will monitor location changes daily. What I know so far that to start a service at boot, I have to follow the linked tutorial. This way I can get the service started at boot, but to save battery I need it only between 9am-9pm.
Question is pretty simple, so I will repeat:
How can I ensure a service is started at 9am and stopped 9pm every day?
Use AlarmManager to set two alarms, each with a PendingIntent that will call startService() on your service, but with distinct action strings ('start', 'stop'). When onStart() of your service detects the 'stop' action Intent, it arranges for an orderly shutdown (e.g., stopSelf()).
This will fail if the user applies a task manager to you in Android 2.1 or earlier, since the technique they tend to use will wipe out your alarms (in addition to killing the service). In that case, the user is presumably voting for your service to not run, so you should try to accommodate the user's wishes.
CommonsWare is right. This is the best way.
You are writing an application and you had better not to change anything out of the application. If you want to add a system service(on boot started service), you need to modify the BSP and add your service to systemserver.java. It's not recommended.CommonsWare's suggestion can do this work.
As you said about the activity, you can start the activicy when you receive the boot broadcast. Then do what your want.....