I am making an alarm app in which the alarm can be set with a toggle button. The code works in ADV, but if I test it on a real device, the the App closes imediatly after settting the alarm once and then turning it off. Also the alarm does not turn off.
(button press alarmOn -> alarm is on,
button press alarmOff-> app closes + alarm is still on)
mStartBtn1.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
long time;
if (((ToggleButton) view).isChecked()){ //if button is on
Intent intent = new Intent(MainActivity.this, AlarmReceiverActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(MainActivity.this, 2, intent, PendingIntent.FLAG_CANCEL_CURRENT);
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, timePicker1.getCurrentHour());
calendar.set(Calendar.MINUTE, timePicker1.getCurrentMinute());
time = (calendar.getTimeInMillis() - (calendar.getTimeInMillis() % 60000));
if (System.currentTimeMillis() > time) {
if (calendar.AM_PM == 0)
time = time + (1000 * 60 * 60 * 12);
else
time = time + (1000 * 60 * 60 * 24);
}
am.set(AlarmManager.RTC_WAKEUP, time, pendingIntent); //sets the alarm
}else{ //if button is off
am.cancel(pendingIntent);
}
}
});
Thank you for helping,
Florian
Your app is basically crashing. Maybe because you are passing null to am.cancel(pendingIntent)//pendingIntent might be null here.
Try moving PendingIntent pendingIntent = PendingIntent.getActivity(MainActivity.this, 2, intent, PendingIntent.FLAG_CANCEL_CURRENT); outside the if condition. If that is not the case then check AlarmReceiverActivity for crashes.
Related
I have this app release in Android that notifies the user everyday at specific time (for example 10:00 pm). I didn't use setRepeating as it was not recommended on higher APIs from 21 up. The following was the pseudo code I used to keep resetting the alarm.
AlarmController (set alarm)
Once time was met send to alarm receiver
Alarm receiver would call the Alarm Controller and Increase the day by 1 and set it again
At the same time Alarm receiver will fire up the Intentservice for notification and set notified **true** in DataBase
In theory it was supposed to work. I am using Joda Time here to easily increase the day by 1. But the problem was, the notification kept firing up at a random time, sometimes it will fire up 6, after it was last fire up, or most often every 1 hour or 30 mins. I don't get it. Now the pseudo code I provided was the basic one. On my real code I have two alarms, one for firing up the notification and set Notified to true and the other was to reset the notified to false once the day change.
My app has been released. I never expected this scenario to happen because the way I debug this was on genymotion, I move the time manually and everything seems to be working alright. I had to fire a log on fabric IO but it seems that the log would only show once you get an error. Anyone thanks
Here is my bare minimum code that I was using exactly:
Alarm Controller
public static void setAdaptiveReminder(Context context, long ALARM_ID, DateTime dateTime, boolean shouldsetAlarm) {
Intent myIntent = new Intent(context, AdaptiveReminderReceiver.class);
myIntent.putExtra("reminder", shouldsetAlarm);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, (int) ALARM_ID, myIntent, PendingIntent.FLAG_UPDATE_CURRENT);
ALARMMANAGER = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Log.d(TAG, "setAdaptiveReminder: " + dateTime.toLocalTime().toString() + " " + dateTime.toLocalDate().toString());
CrashUtility.LogErrorReportToFabric(TAG + " setAdaptiveReminder", dateTime.toLocalTime().toString() + " " + dateTime.toLocalDate().toString());
if (Utility.GetBuildVersion() >= 19 && Utility.GetBuildVersion() < 23) { // if lollipop
//ALARMMANAGER.setRepeating(AlarmManager.RTC_WAKEUP,System.currentTimeMillis() + 5000,1000,pendingIntent);
ALARMMANAGER.setExact(AlarmManager.RTC_WAKEUP, dateTime.toDate().getTime(), pendingIntent);
//ALARMMANAGER.setRepeating(AlarmManager.RTC_WAKEUP,dateTime.toDate().getTime(), AlarmManager.INTERVAL_DAY,pendingIntent);
} else if (Utility.GetBuildVersion() >= 23 || Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
//Log.d(TAG, "setTimeSinceLastUseReminder: android M and UP");
ALARMMANAGER.setAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, dateTime.toDate().getTime(), pendingIntent);
//ALARMMANAGER.setrep(AlarmManager.RTC_WAKEUP,dateTime.toDate().getTime(), AlarmManager.INTERVAL_DAY,pendingIntent);
}
}
AlarmPresenter
public void setAdaptiveReminder() {
//AlarmController.setAdaptiveReminder(context,778,d);
DateTime dateTime = TimeUtility.SetCorrectTimeInCorrectDate(settingsRepository.getAdaptiveReminderTime());
boolean isNotified = settingsRepository.isNotifiedReminder();
//Toast.makeText(context, "" + dateTime.toLocalTime().toString(), Toast.LENGTH_SHORT).show();
Log.d(TAG, "setAdaptiveReminder: gggfss " + TimeUtility.DateIsToday(dateTime) + " " + dateTime.toLocalTime().toString());
Log.d(TAG, "setAdaptiveReminder: " + isNotified);
if (TimeUtility.DateIsToday(dateTime) && !isNotified) {
dateTime = dateTime.plusDays(1);
CrashUtility.LogErrorReportToFabric(TAG + " setAdaptiveReminder", dateTime.toLocalTime().toString() + " " + dateTime.toLocalDate().toString());
AlarmController.setAdaptiveReminder(context, 778, dateTime, true);
Log.d(TAG, "setAdaptiveReminder: " + dateTime.toLocalDate() + " " + dateTime.toLocalTime().toString());
}
}
Receiver
public void onReceive(Context context, Intent intent) {
// TODO: This method is called when the BroadcastReceiver is receiving
// an Intent broadcast.
this.context = context;
alarmControllerPresenter = new AlarmControllerPresenter(context,settingsRepository,habitRepository);
alarmControllerPresenter.setAdaptiveReminder();
}
So the code I have provided was the exact same code I am using to set the alarm every day. I just did some cleaning up and that was about it.
I'm trying to set several alarms with my app, and cancel them upon request.
I've read a lot of topics about the same, and went through the documentation, but it seems like it doesn't work.
Documentation says that cancel will try to find an intent that matches the one I provide with 'filterEquals'('Determine if two intents are the same for the purposes of intent resolution (filtering). That is, if their action, data, type, class, and categories are the same. This does not compare any extra data included in the intents.')
I'm providing same action, data, type, class, and category, so why does it not work?
Create alarm:
AlarmManager manager = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
int interval = 30000;
Intent intent = new Intent(getApplicationContext(), Broadcast.class);
intent.putExtra("alarmTime",alarmTime);
intent.putExtra("reminder1",reminder1);
intent.putExtra("reminder2",reminder2);
intent.putExtra("title",title);
intent.putExtra("message",message);
intent.putExtra("vibrate",vibrate);
intent.putExtra("sound",sound);
intent.putExtra("name",name);
//Create _id from data input. is unique
int _id = 0;
for (char i: name.toCharArray()){
_id += Character.getNumericValue(i);
}
for (char i:title.toCharArray()){
_id += Character.getNumericValue(i);
}
for (char i:message.toCharArray()){
_id += Character.getNumericValue(i);
}
_id += (int) alarmTime.getTime();
_id += (int) reminder1.getTime();
_id += (int) reminder2.getTime();
Log.e("ALARMS", "Creating alarm with id: "+_id);
intent.setData(Uri.parse("custom://" + _id));
intent.setAction(String.valueOf(_id));
PendingIntent pendingUpdateIntent = PendingIntent.getBroadcast(getApplicationContext(), _id, intent, 0);
manager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + interval, pendingUpdateIntent);
Cancel alarm
AlarmManager manager = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(getApplicationContext(), Broadcast.class);
intent.putExtra("alarmTime",alarmTime);
intent.putExtra("reminder1",reminder1);
intent.putExtra("reminder2",reminder2);
intent.putExtra("title",title);
intent.putExtra("message",message);
intent.putExtra("vibrate",vibrate);
intent.putExtra("sound",sound);
intent.putExtra("name",name);
int _id = 0;
for (char i:name.toCharArray()){
_id += Character.getNumericValue(i);
}
for (char i:title.toCharArray()){
_id += Character.getNumericValue(i);
}
for (char i:message.toCharArray()){
_id += Character.getNumericValue(i);
}
_id += (int) alarmTime.getTime();
_id += (int) reminder1.getTime();
_id += (int) reminder2.getTime();
intent.setData(Uri.parse("custom://" + _id));
intent.setAction(String.valueOf(_id));
PendingIntent pendingUpdateIntent = PendingIntent.getBroadcast(getApplicationContext(), _id, intent, 0);
Log.e("ALARMS", "Cancelling alarm with id: "+_id);
// Cancel alarms
try {
manager.cancel(pendingUpdateIntent);
} catch (Exception e) {
Log.e("ALARMS", "AlarmManager update was not canceled. " + e.toString());
}
So I call 3 times the create alarm with different parameters, so my _id is different each time.
Then I call 3 times the cancel alarm and the ids generated match for each alarm upon create and cancel.
So the cancel runs but my alarms still get fired.
My alarms trigger a broadcast receiver that will output a notification per alarm.
I forgot to mention that I tried with different flags for the PendingIntent but none work (FLAG_CANCEL_CURRENT, FLAG_UPDATE_CURRENT)
Seems like I was feeding different dates to the alarms, and the _id's were different by a couple of numbers (start and finish were the same), this resulted on calling a cancel on _id values that were different and not working.
Changed the way I generate the _id to exclude the dates (which I generated with new Date()) and not it works
By bad, I didn't see it.
In my app, I would like to delete all pendingIntent in my alarmManager.
Is possible to do a for() to delete all?
Try this.
Android: Get all PendingIntents set with AlarmManager
To cancel all alarm, first you have to find all the pending intent for that and cancel alarm using that.
If it is helpful to you than don't miss to accept this as your answer.
// set up alarm
List<PendingIntent> mPendingIntentList = new ArrayList<PendingIntent>();
Intent alarmIntent = new Intent(getApplicationContext(),Receiver.class);
alarmIntent.setData(Uri.parse("custom://" + alarm.ID));
alarmIntent.setAction(String.valueOf(alarm.ID));
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
PendingIntent displayIntent = PendingIntent.getBroadcast(getContext(), 0, alarmIntent, 0);
// add pending intent in list
mPendingIntentList.add(displayIntent );
alarmManager.set(AlarmManager.RTC_WAKEUP, alarmDateTime, displayIntent);
//cancel all alarms
for(int idx = 0 ; idx < mPendingIntentList.size() ; idx++){
alarmManager .cancel(mPendingIntentList.get(idx));
}
See AlarmManager.cancel(PendingIntent)
Create a PendingIntent matching the intent(s) you wish to cancel. Calling the above function once, will cancel all matching alarms
.
I want to trigger alarm with my song at specified time, below is what I've done :
This is in the java file :
public class MainActivity extends Activity implements View.OnClickListener
/** Called when the user clicks the Send button */
public void startMusic(View view) {
Integer hr = timepickerStart.getCurrentHour();
Integer min = timepickerStart.getCurrentMinute();
// Start service using AlarmManager
if(selectedFile != null && selectedFile.length() > 0)
{
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
final Intent intent = new Intent(this,MusicPlayActivity.class);
intent.putExtra(EXTRA_MESSAGE, selectedFile.getPath());
PendingIntent pendingIndent = PendingIntent.getBroadcast(this, 0, intent,PendingIntent.FLAG_UPDATE_CURRENT);
Calendar firingCal = Calendar.getInstance();
System.out.println("Before Present time in mili" + firingCal.getTimeInMillis());
firingCal.add(Calendar.HOUR, hr);
firingCal.add(Calendar.MINUTE, min);
firingCal.add(Calendar.SECOND, 0);
long intendedTime = firingCal.getTimeInMillis();
System.out.println("After setting Present time in mili" + firingCal.getTimeInMillis());
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, intendedTime, AlarmManager.INTERVAL_DAY, pendingIndent);
Toast.makeText(this, "Alarm set from today", Toast.LENGTH_LONG).show();
} else
{
Toast.makeText(this, "Please select music File", Toast.LENGTH_LONG).show();
}
}
Now in manifest file
<activity android:name="com.example.test.MainActivity"
android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
The issue is it starts on its own will.
Exmaple :
If the mobile time is 9:30 AM 2/12/2013 (DD/MM/YYYY), and I select the Trigger time at 10:00 AM on the same day. This will not trigger at 10:00 AM at all, it will trigger the next day that is 3/12/2013 some different time that too not at 10:00 AM
I am not able to judge the timing properly.
First of all why are using wrapper class(Integer) to store hour and min simply use int variable
Set value to calender not add to calender
firingCal.set(Calendar.HOUR, hr);//better use Calander.HOUR_OF_DAY bcoz hour range is 0 to 11 HOUR_OF_DAY 0 23 bcoz of this also your alarm is triggering next day
firingCal.set(Calendar.MINUTE, min);
firingCal.set(Calendar.SECOND, 0);
I have made some simple alarm manager demo,which is working fine in my case,try and if it works fine for you than implement same in your code
Here is my MainActivity
Here is MyReceiver Class
Here is AlarmActivity class
And here are layout xml files
activity_main.xml
alarmview.xml
In AlarmActivity at line number 76 this line mMediaPlayer.setVolume(0,0); is responsible for muting alarm sound,if you don't want to mute it than simply comment that line.
I have been developing an Android application and I need to execute 1 task every hour. I uses the following code for it:
private static final long ALARM_PERIOD = 1000L;
public static void initAlarmManager(Context context) {
Editor editor=PreferenceManager.getDefaultSharedPreferences(context).edit();
editor.putBoolean(context.getString(R.string.terminate_key), true).commit();
AlarmManager manager = (AlarmManager) context.getSystemService(context.ALARM_SERVICE);
Intent i = new Intent(context, AlarmEventReceiver.class);
PendingIntent receiver = PendingIntent.getBroadcast(context, 0, i, 0);
manager.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime(), ALARM_PERIOD, receiver);
}
It works for me, but my client tells me that the task works only 1 time and won't work 1 hour. Where have I made a mistake? Please, tell me. Thank you.
According to your code, ALARM_PERIOD is 1000L, as repeating interval. So I doubt the alarm will set of in every 1000 milliseconds.
if you are setting repeating interval for every hour, it should be 3600000L.
And take note that if the phone is restarted, your alarm manager will no longer work unless you start again.
Here is the my Code:
private void setAlarmManager() {
Intent intent = new Intent(this, AlarmReceiver.class);
PendingIntent sender = PendingIntent.getBroadcast(this, 2, intent, 0);
AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
long l = new Date().getTime();
if (l < new Date().getTime()) {
l += 86400000; // start at next 24 hour
}
am.setRepeating(AlarmManager.RTC_WAKEUP, l, 86400000, sender); // 86400000
}
Have you added receiver tag in application tag in manifest.xml
<receiver android:name=".AlarmReceiver" android:process=":remote"/>
Instead of Alram-Manager I recommended you to use Android-TimerTask
The TimerTask class represents a task to run at a specified time. The task may be run once or repeatedly. Its perfect suits for your requirements.
Try by modifying your code by changing your setRepeating() method like this
manager.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,SystemClock.elapsedRealtime(), SystemClock.elapsedRealtime()+(60*60*1000), receiver);
OR
Test this it is repeating for every minute
manager.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,Calendar.getInstance().getTimeInMillis(), Calendar.getInstance().getTimeInMillis()+(1*60*1000), receiver);