AlarmManager is discarded when application is cleared from background - android

This is how I am creating an alarm.
When the app is still running in background the alarm is fired.
but when it is cleared from the recent apps, the alarm is getting discarded. I am registering a new receiver and providing a unique action for differentiation between two alarms. Is there any mistake in my code.
String filter_action = "myPackageName" + request_code_value +"_time";
IntentFilter filter = new IntentFilter(filter_action);
registerReceiver(new AlarmReciever(), filter);
Intent intent = new Intent(filter_action);
intent.putExtra(getString(R.string.get_current_intent_value), request_code_value);
intent.putExtra(getString(R.string.alarmtext), alarm_title);
intent.putExtra(getString(R.string.alarm_time), newAlarm_Choose_Alarm_Value.getText().toString());
Calendar calNow = Calendar.getInstance();
Calendar calSet = (Calendar) calNow.clone();
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, request_code_value, intent, 0);
calSet.setTimeInMillis(timeInMillis);
if (calSet.compareTo(calNow) <= 0) {
// Today Set time passed, count to tomorrow
calSet.add(Calendar.DATE, 1);
}
alarmManager.set(AlarmManager.RTC_WAKEUP, calSet.getTimeInMillis(), pendingIntent);
Manifest file.
<receiver android:name="com.bigbangpartners.YoWakeUp.activities.AlarmReciever" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="AlarmManager_Start" />
</intent-filter>
</receiver>
Please help me.
Thanks in advance.

If you are registering and de-registering the BroadcastReceiver programmatically in your Activitys, then a BroadcastReceiver created in this way will remain in existence only as long as the app process is alive. So when you remove your app from the list of recent apps, this BroadcastReceiver is also, in effect, destroyed.
On the other hand, a BroadcastReceiver registered in the manifest is a global, permanent component of an Android app that remains in existence forever, whether the app process is alive or not.
If you want your alarms to be activated even when the app is not in the foreground, then you need to register the BroadcastReceiver in the app manifest and specify the alarm action as well. You are not doing that, and this, I believe, is the root of your problem.
What you should do:
1. Define your BroadcastReceiver in manifest like this:
<receiver android:name="com.bigbangpartners.YoWakeUp.activities.AlarmReciever" >
</receiver>
2. Remove all calls to registerReceiver() and unRegisterReceiver() in your app code as that is not needed.
3. Define your alarm Intent like this:
Intent intent = new Intent(this, AlarmReceiver.class);
Rest of code remains same. First try this and see if it works.

Related

Broadcast not getting called with AlarmManager

I'm having trouble with the broadcast message the alarm manager should send.
This is my code:
case Intent.ACTION_BOOT_COMPLETED:
long repeatInterval = 10*1000;
long triggerTime = SystemClock.elapsedRealtime() + repeatInterval;
AlarmManager manager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
if(manager != null){
Intent in = new Intent(context, AppReceiver.class);
in.setAction("haz");
PendingIntent inte = PendingIntent.getBroadcast(context, 500, in, PendingIntent.FLAG_UPDATE_CURRENT);
manager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, triggerTime, repeatInterval, inte);
}
break;
That's being triggered correctly with the action boot completed broadcast message, but that piece of code if I'm right should call the app receiver with the "haz" action, but that's not being called, ever.
I've tried to create a service but that's also not being called.
Anyone has any clue for what I have to do?
<receiver android:name=".YourReceiver">
<intent-filter android:priority="1000">
<action android:name="android.intent.action.BOOT_COMPLETED" />
<!-- check properly boot intent syntax for manifest file -->
</intent-filter>
</receiver>
I've found a solution thanks to CommonsWare reply to my question. The answer was to have another receiver separately probably because android can't handle fast repetitions. Mine wasn't going to be that short in the end, it was for testing purposes only, but having two receivers and to call the second one with the repetitions was the answer. Thank you both #CommonsWare and #Arwy Shelke for your time and responses!!

Oreo: Alarm is not fired when Application is not running

I have relatively simple setup that should trigger an alarm at certain time of the day and show a notification to user. here is relative code,
Setting the alarm
long inTime = /*expirationTime*/ Calendar.getInstance().getTimeInMillis() + 10000;
Intent startIntent = new Intent("parking.event");
startIntent.setClass(getBaseContext(), ParkingExpirationWarmingBroadcast.class);
PendingIntent startPendingIntent = PendingIntent.getBroadcast(this, 99, startIntent, 0);
alarmMgr.setExact(AlarmManager.RTC_WAKEUP,
inTime,
startPendingIntent);
BroadcastReceiver registered
<receiver
android:name=".modules.parking.ParkingExpirationWarmingBroadcast"
android:enabled="true">
<intent-filter>
<action android:name="parking.event" />
</intent-filter>
</receiver>
Broadcast Receiver
class ParkingExpirationWarmingBroadcast : BroadcastReceiver() {
#SuppressLint("NewApi")
override fun onReceive(context: Context, intent: Intent) {
}
}
The receiver is only getting triggered if app is in background. as soon as i swipe the app from multitasking, the notification is cleared and no new Alarms are triggered. I checked this setup on Android 7.0 and BroadcastReceiver is triggered regardless of app running or not.
I am aware regarding restrictions over implicit broadcasts in Android Oreo but i don't believe the intent that i have mentioned above is considered implicit.
Can anyone point out what i am doing wrong?
This is a general behavior of any Android's version. If you force-quit an application, then its Alarms and PendingIntents are deleted as well.
You can find the same answer here and here.
Force closing an app destroys its components . This is what force stop does. It's not a bug, it is very much a feature. Follow the following thread , it has been discussed by android framework engineers .
https://groups.google.com/forum/?fromgroups=#!topic/android-developers/anUoem0qrxU

App crashes when BroadcastReceiver gets called

I have two small questions;
My app's BroadcastReceiver works fine when the app is running, I get the "Tuesday at 2" toast message perfectly and it updates the app, but when I close my app, that means the app stops running, it doesn't get called but instead it crashes "Your app stopped working", so it knows it's supposed to call it, but doesn't, right?
It seems that the BroadcastReceiver gets called everyday at around 2pm, not only on Tuesdays at 2pm, I want the app to update once a week. Is it maybe because I call my setAlarm() method on my UpcomingFragment's onCreate?
In the UpcomingFragment class (where I set the alarm for it to go off each Tuesday at 2)
private void setAlarm(){
AlarmManager alarmMgr = (AlarmManager) getActivity().getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(getActivity(), UpdateReceiver.class);
intent.putExtra("greeting", "Hello");
PendingIntent alarmIntent = PendingIntent.getBroadcast(getActivity(), 0, intent, 0);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.DAY_OF_WEEK, Calendar.TUESDAY);
calendar.set(Calendar.HOUR_OF_DAY, 14);
// With setInexactRepeating(), you have to use one of the AlarmManager interval
// constants--in this case, AlarmManager.INTERVAL_DAY.
alarmMgr.setInexactRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
AlarmManager.INTERVAL_DAY, alarmIntent);
}
In the BroadcastReceiver's onReceive()
public class UpdateReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
UpcomingFragment.getInstance().update();
//if tuesday
Toast.makeText(context, "Tuesday at 2" , Toast.LENGTH_LONG).show();
}
}
Manifest:
<uses-permission android:name="com.android.alarm.permission.SET_ALARM"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<receiver android:name=".UpdateReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"></action>
</intent-filter>
</receiver>
i can't provide you with the logcat, cause it doesn't print it when it cashes, i don't know if my android studio is at fault here or my app. Thanks!
You can't manipulate Fragments inside a BroadCastReceiver's context. Essentially broadcast receivers are run inside application context and in which you can't access UI stuff.
If you would like to start an Activity once that broadcast is fired, you would need the following code:
Intent intent = new Intent(context, MyActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
Note: Accessing to UI (including Fragments) must be done in an activity context.
Update #1
It seems that the BroadcastReceiver gets called everyday at around 2pm, not only on Tuesdays at 2pm, I want the app to update once a week. Is it maybe because I call my setAlarm() method on my UpcomingFragment's onCreate?
I think I have a better approach than yours.
Getting current time and setting its day of week to Tuesday may result in weird behaviors.
Using a boot completed broadcast receiver to set the alarm may be better.
For the former, your scheduling codes should set the alarm to the nearest coming Tuesday on 2 PM. For this, this answer may be helpful.
For the latter, first, add the following permission to your manifest file.
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
Then, define another broadcast receiver and declare it to the manifest file.
<receiver android:name="your.package.name.BootCompletedReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
In your newly created broadcast receiver add this code.
#Override
public void onReceive(Context context, Intent intent) {
// Set the alarm to coming Tuesday on 2 PM
}
This ensures your app to get updated on every Tuesday on 2 PM in all circumstances.

Service or IntentService or AlarmManager approach

I am building a game-like application and I've been reading about all the different approaches of running things with Services in background, foreground, Alarms and so on, and I am a bit confused.
My app would go like this (example):
user presses a button in Main, then he can close the app
after 30 minutes Activity1 opens up
user finishes whatever he needs to do in that activity, which
triggers the next activity to start after 2 hours
after 2 hours Activity2 opens up
user finishes whatever he needs to do there as well, triggering the
next one
after a day Activity3 opens up, and so on
What would be the best approach? Have a service running continuously to open those activities, or get a new alarm set up to start every time the user finishes one of the activities?
Please do not create a service just to it can stay idle for several hours. It makes no sense.
What you need to do is to create an alarm. something like:
alarmMgr = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, 14);
alarmMgr.setInexactRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
AlarmManager.INTERVAL_DAY, alarmIntent);
This is just a general example for the Alarm API. You will need to adjust it for your needs.
Finally - please be aware: alarms is not boot resilient! That is: if for any reason
the user's device goes down, all of your alarms will be lost.
if you do want your app to be boot resilient you will need to register to an
event called RECEIVE_BOOT_COMPLETED (think post-boot) where you will restart your pending
alarms:
//manifest:
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<receiver android:name=".MyBootReceiver"
android:enabled="false">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"></action>
</intent-filter>
</receiver>
//java class
public class MyBootReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals("android.intent.action.BOOT_COMPLETED")) {
// restart alarms
}
}
}
Hope it helps

Alarm doesn't trigger after reboot

I have an alarm to reset a data connection say every 15 minutes. The problem is, once the phone is rebooted, the application gets killed and the alarm (service) doesn't trigger anymore.
(This is not a duplicate, the other similar questions on SO do not solve my problem.)
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<receiver
android:name="com.sang.mobiledata.ResetBroadcastReceiver"
android:exported="false" >
<intent-filter>
<action android:name="com.sang.mobiledata.IntentAction.RECEIVE_RESETCONN_UPDATE" />
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
Broadcast Receiver:
public void onReceive(Context context, Intent intent) {
// if(CONN_ACTION.equals(intent.getAction())) {
if (intent.getAction().equalsIgnoreCase(
"com.sang.mobiledata.IntentAction.RECEIVE_RESETCONN_UPDATE")) {
MainActivity objMain = new MainActivity();
objNetwork.setMobileDataEnabled(context, false);
objNetwork.setMobileDataEnabled(context, true);
}
if (intent.getAction().equalsIgnoreCase(
"android.intent.action.BOOT_COMPLETED")) {
// code to restart/resume/retain alarm
Code to fire alarm (on the onClick):
Intent myIntent = new Intent(
"com.sang.mobiledata.IntentAction.RECEIVE_RESETCONN_UPDATE");
myIntent.putExtra("FLAG_KEY", false);
PendingIntent pi = PendingIntent.getBroadcast(this, 0, myIntent,
PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager) this
.getSystemService(Context.ALARM_SERVICE);
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.add(Calendar.SECOND, 10);
long interval = intHrs * 3600000 + intMins * 60000;
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP,
calendar.getTimeInMillis(), interval, pi);
long mins = interval / 60000;
Toast.makeText(
MainActivity.this,
"Data Connection will be reset every " + mins
+ " minute(s).", Toast.LENGTH_SHORT).show();
}
Any suggestions please?
Read the AlarmManager document, there it is written, that AlarmManager will not hold alarms after reboot.
As per the Android Developers,
.... 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.
And regarding BOOT_COMPLETED, they write:
... This is broadcast once, after the system has finished booting. It can be used to perform application-specific initialization, such as installing alarms. You must hold the RECEIVE_BOOT_COMPLETED permission in order to receive this broadcast.
As for permission is concerned, you have already registered that. Well what probably happening is, the service BOOT_COMPLETED is being used locally, with the application. The reboot of the mobile is system activity, which is not overridden to accomplish re-registry of the alarms being saved. But I am not sure. So, you need to do something when execution comes in hand of BOOT_COMPLETED.
Read Automatically starting Services in Android after booting, this might help you with it.
What I did was, I registered all the alarms and formed a database, using SQLite; On restart, I use to reset all the alarms. Well that worked for me. If you want to go with my process then,
Make a database for your alarms, and save them there. Write your application in such a way that, when the phone restarts, the AlarmManager resets all the alarms. This is how it works.
In Automatically starting Services in Android After booting again. It is written:
Also note that as of Android 3.0 the user needs to have started the application at least once before your application can receive android.intent.action.BOOT_COMPLETED events.

Categories

Resources