Doubts Regarding AlarmManager - Android - java

I have some doubts that I would like to clear regarding the AlarmManager class in Android.
I have an app that needs to:
Allow the user to set a time.
Start an alarm.
Then, even if the app is closed, it should start up on the preset time and do a certain function (like button.performClick()) in the main activity.
So, I have successfully created an activity called alarm.java, created the layout in res\layout and added it to AndroidManifest.xml. Also, I have successfully set the alarm as follows in my alarm.java class:
onCreate(){
alarm = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
intent = new Intent(context, MyActivity.class);
pi = PendingIntent.getBroadcast(this.getApplicationContext(), ALARM_ID, intent, 0);
}
onClick(){
cal.setTimeInMillis(System.currentTimeMillis());
cal.set(Calendar.HOUR_OF_DAY, hour);
cal.set(Calendar.MINUTE, minute);
alarm.setInexactRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pi);
Toast.makeText(getApplicationContext(), "Alarm Set For " + hour + ":" + minute + " " + ampm, Toast.LENGTH_LONG).show();
}
Now, in my MyActivity.java class, which is the main activity, I have added the BroadcastReceiver
public BroadcastReceiver AlarmReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
/*This is the part I got from SO for starting an activity from `BroadcastReceiver`
Intent i = new Intent();
i.setClassName("com.kanishka.nightstalker.homeautomation", "com.kanishka.nightstalker.homeautomation.MainActivity");
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);*/
Toast.makeText(getApplicationContext(), "APP STARTED", Toast.LENGTH_LONG).show();
button.performClick();
}
};
Obviously, this method isn't working as I see no Toast popping up after elapsed time. I kinda understand what the issue is, and I should be using a Service for this. But from what I know, AlarmManager itself runs in the background and SHOULD trigger the BroadcastReceiver of MyActivity.java on elapsed time. Where am I going wrong?

Where am I going wrong?
You are using setInexactRepeating(). Here, "inexact" means "not exact", and so the alarm will occur sometime within INTERVAL_DAY of your requested time.
You are taking the current time, then setting the hour and minute, which could result in a time in the past.
You are creating an Intent for MyActivity, which is probably not a BroadcastReceiver (or, if it is, MyActivity is a very odd name to choose).
If you want the alarm to go off "even if the app is closed", then you need to use a BroadcastReceiver that is registered in the manifest.
It is not possible to "do a certain function (like button.performClick()) in the main activity", as there will not be an activity "if the app is closed".

Related

Problems with android alarm manager, when the app is closed

During development of a small android app, I am having problem in running an alarm manager, after the app is terminated by the user. While the app is running in the foreground or background, everything works fine.
I did the following steps:
AndroidManifest.xml
<receiver android:name="MyBroadcastReceiver" ></receiver>
MainActivity.java
Within the OnClick method of a button, I call
startAlert( x*60*1000);
x is a class-wide visible variable
public void startAlert(long timeInMillis){
Intent intent = new Intent(this, MyBroadcastReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this.getApplicationContext(), 234324243, intent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP,System.currentTimeMillis()+(timeInMillis),pendingIntent);
}
Toast.makeText(this, "Alarm in " + x + " Minuten",Toast.LENGTH_LONG).show();
}
MyBroacastReciever.java
public void onReceive(Context context, Intent intent) {
MediaPlayer player = MediaPlayer.create(context,MainActivity.link);
player.start();
Toast.makeText(context, "Alarm....", Toast.LENGTH_LONG).show();}
What should I do to get the alarmManager successfully running, after the app is closed?
You could put the alarm manager in the service. The foreground service is used to keep our application alive even though the main application has been quit by the user. And then the alarm manager could trigger the code in the broadcast receiver class

Android Java - Alarm Manager Mostly Works Perfect But Sometimes Delayed

I am working on an alarm application. Users can set alarms in the application and some actions have to do when one of the alarms triggered. I used the first alarm manager set method. But only the first alarm worked right time. Others triggered after almost 5 minutes of delayed.
Intent intent = new Intent(applicationContext, OneShotAlarm.class);
PendingIntent sender = PendingIntent.getBroadcast(applicationContext, 0,
intent, FLAG_ONE_SHOT);
AlarmManager alarmManager = (AlarmManager) applicationContext.getSystemService(ALARM_SERVICE);
alarmManager.cancel(sender);
alarmManager.set(AlarmManager.RTC_WAKEUP, alarmCalendar.getTimeInMillis(), sender);
Later, I found this. I changed set method to setexact method and all alarms looked like working perfectly.
alarmManager.setExact(AlarmManager.RTC_WAKEUP, alarmCalendar.getTimeInMillis(), sender);
But I saw sometimes still triggered with delay. Something like 5-8 minutes.
Where is my wrong?
UPDATE:
I kept log files when I first detect the error. I saw delay times in log files. Some of pre setexact method logs like below:
16:30:59 Next alarm set to 24/05/2020 16:35:00
16:35:00 Alarm triggered
16:35:00 Notification Sent
16:35:00 Next alarm set to 24/05/2020 16:40:00
16:44:47 Alarm triggered
16:44:47 Notification Sent
16:44:47 Next alarm set to 24/05/2020 16:50:00
16:54:48 Alarm triggered
16:54:48 Notification Sent
16:54:48 Next alarm set to 24/05/2020 18:00:00
And some of post setexact method logs like below:
03:00:00 Alarm triggered
03:00:00 Notification Sent
03:00:00 Next alarm set to 25/05/2020 07:00:00
07:08:14 Alarm triggered
07:08:15 Notification Sent
07:08:15 Next alarm set to 25/05/2020 08:30:00
08:34:47 Alarm triggered
08:34:47 Next alarm set to 25/05/2020 09:00:00
09:00:00 Alarm triggered
09:00:00 Next alarm set to 25/05/2020 18:00:00
UPDATE:
My alarm set code is inside of a method. I call it after every data update or triggered alarm. This way, I make sure always the next alarm can be set.
For current Android version, you should recall alarm manager again in onReceive. This is the example of Alarm Manager called every 5 second :
public class TestApplication extends Application {
private static Context context;
#Override
public void onCreate() {
super.onCreate();
context = getApplicationContext();
}
static void createAlarm() {
Intent intent = new Intent(context, AlarmReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, REQUEST_CODE, intent, 0);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + 5000, pendingIntent);
}
}
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "Alarm Manager Test", Toast.LENGTH_SHORT).show();
TestApplication.createAlarm();
}
}

Alarm Manager does not execute broadcaster class

I'm trying out alarms and have hit a wall. I don't think my alarm is setting up properly because I never get a confirmation after the alarm is supposed to go off. Here's how I call on the alarm manager:
long alarmtime=new GregorianCalendar().getTimeInMillis()+10*1000;//run after 10 seconds
Intent i = new Intent(this, AlarmReceiver.class);
PendingIntent pi = PendingIntent.getService(this, 0, i, 0);
AlarmManager alarmman = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmman.cancel(pi); // cancel any existing alarms
alarmman.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
alarmtime, 10 * 1000, pi);//run every 10 seconds
And here's my AlarmReceiver.java:
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "TEST", Toast.LENGTH_LONG).show();
}
}
However, the TEST text does not appear, and I can't figure out why.
Since you are using the AlarmManager.ELAPSED_REALTIME_WAKEUP argument, your initial alarm-time should be base on the elapsed real time of the device:
long alarmtime = SystemClock.elapsedRealtime() + 10 * 1000;
alarmman.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, alarmtime, 10 * 1000, pi);
(see this link).
For a BroadcastReceiver it's probably PendingIntent.getBroadcast() instead of PendingIntent.getService(). You are also cancelling the alarm, just update your PendingIntent like this and try not cancelling before:
PendingIntent pi = PendingIntent.getBroadcast(this, 0, i, PendingIntent.FLAG_UPDATE_CURRENT);
Read the documentation thoroughly for further information.
Make sure that the BroadcastReceiver is being called by doing a System.out.println("TEST"); instead of Toast. If you are able to see that in your logcat, then the problem probably is that you need to run the Toast in UI thread.

How to create Notification which avoid TaskManager's killing?

I want to create Notification in Android.
But, If I kill the application via TaskManager, it terminate the Notification too..
It is the code-snipet.
it is the caller.
Intent intent = new Intent(myActivity, NotificationReciever.class);
String appName = myActivity.getTitle().toString();
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.add(Calendar.SECOND, time);
AlarmManager alarmManager = (AlarmManager)
myActivity.getSystemService(Context.ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), sender);
it is the Reciever.
public class NotificationReciever extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
I added the code, but it can't
intent.setFlags( Intent.FLAG_ACTIVITY_NEW_TASK );
I' like to make alive the Notification.
Would you tell me how to avoid the TaskManager's killing?
Would you tell me how to avoid the TaskManager's killing?
That is not possible, except perhaps via a custom build of the Android OS, put into your own ROM mod to deploy on your own devices.

AlarmManager not adding new Alarms, or not triggering receiver

I'm currently developing an application which makes use of Android's AlarmManager. I'm trying to add a new alarm to the AlarmManager, but after several hours of trying various things and checking various threads on SO, I'm still at a brick wall. Are there any problems with my code?
Main Activity - saveAlarm() function
/**
* Saves the current alarm. Adds to the database if it doesn't already exist, or updates if it does.
* Also sets alert with AlarmManager.
*/
public void saveAlarm() {
// Create Database instance
DbHandler db = new DbHandler(getApplicationContext());
if(alarm.getId() == -1) {
// Saving a new alarm
db.open();
alarm.setId(db.addAlarm(alarm));
db.close();
}
else {
db.open();
db.updateAlarm(alarm);
db.close();
}
// Create the wakeup intent
Intent intent = new Intent(this, AlarmReceiver.class);
intent.putExtra("alarm_id", alarm.getId());
// Create the Pending Intent
PendingIntent sender = PendingIntent.getBroadcast(this, AlarmPlayer.REQUEST_ALARM + alarm.getId(), intent, PendingIntent.FLAG_UPDATE_CURRENT);
// Debug
Calendar now = Calendar.getInstance();
long dTime = alarm.getNextAlarmTime().getTimeInMillis() - now.getTimeInMillis();
Log.d(TAG, "Setting alarm for " + (dTime / 1000) + " seconds time");
// Add to Android Alarm Manager
AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
am.set(AlarmManager.RTC_WAKEUP, alarm.getNextAlarmTime().getTimeInMillis(), sender);
}
I've verified that the correct time is being passed into am.set (see the debug section above it).
AlarmReceiver.class
/**
* This class listens out for broadcasts from AlarmManager
* and launches the AlarmPlayer activity accordingly.
* #author Michael
*
*/
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context c, Intent intent) {
Log.d("RSS Alarm", "Waking up alarm");
// Launch the AlarmPlayer activity
Intent i = new Intent(c, AlarmPlayer.class);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
c.startActivity(i);
}
}
I also have <receiver android:process=":remote" android:name="AlarmReceiver" /> set up in AndroidManifest.xml. I have no idea what's causing this problem, but it's happening nonetheless. Any help would be greatly appreciated, many thanks in advance.
Edit 1
Changing the timezone to UTC doesn't seem to solve anything, my calendar seems to default to UTC regardless. Current code:
// Debug
Calendar now = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
long dTime = alarm.getNextAlarmTime().getTimeInMillis() - now.getTimeInMillis();
Log.d(TAG, "Setting alarm for " + (dTime / 1000) + " seconds time");
// Add to Android Alarm Manager
AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
Log.d(TAG, "Timezone offset is " + TimeZone.getDefault().getRawOffset());
Log.d(TAG, "UTC time is currently " + Calendar.getInstance(TimeZone.getTimeZone("UTC")).getTimeInMillis() / 1000);
am.set(AlarmManager.RTC_WAKEUP, (alarm.getNextAlarmTime().getTimeInMillis() - TimeZone.getDefault().getRawOffset()), sender);
Is this possibly a case that AlarmManager.set(AlarmManager.RTC_WAKEUP, ...) needs the time in UTC? This causes problems if you're setting a 'local time' and don't adjust to UTC. In short, the alarm may be being properly added but it doesn't trigger when you expect it unless your time-zone is UTC.
From the docs...
public static final int RTC_WAKEUP Since: API Level 1
Alarm time in System.currentTimeMillis() (wall clock time in UTC), which will wake up the device when it goes off.
In your manifest, I believe you need android:name".AlarmReceiver" note the dot.
If that doesn't do it, post your manifest file. Also, does your logcat mention adding alarm and alarm triggering?
Edit: You might try this
AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Other than that, I don't see anything jumping out at me. Good Luck

Categories