I need to make a notification where in the user will choose the date and time the notification will start. In order for that, I store the date, time and notes in the Database. Now I want to start the alarm using the data from the database and using the id of each alarm as a unique id for the PendingIntent.
This is the how I get the data from the database
db=new events_database(events_main.this);
c=db.queryData("select * from events_list ORDER BY event_ID ASC");
if(c != null && c.moveToNext())
{
int id=c.getInt(0);
String type=c.getString(1);
String date=c.getString(2);
String time=c.getString(3);
String note=c.getString(4);
String[] newDate=date.split("/");
int year=Integer.valueOf(newDate[0]);
int month=Integer.valueOf(newDate[1]);
int day=Integer.valueOf(newDate[2]);
String[] newTime=time.split(":");
int hour=Integer.valueOf(newTime[0]);
int min=Integer.valueOf(newTime[1]);
Alarms(id,year,month,day,hour,min,type,note);
}
After getting it I pass the data into the Alarms method
public void Alarms(int id, int year, int month, int day, int hour, int minute, String type, String note) {
Calendar calendar1 = Calendar.getInstance();
calendar1.set(Calendar.YEAR,year);
calendar1.set(Calendar.MONTH,month);
calendar1.set(Calendar.DAY_OF_MONTH,day);
calendar1.set(Calendar.HOUR_OF_DAY, hour);
calendar1.set(Calendar.MINUTE, minute);
calendar1.set(Calendar.MILLISECOND, 0);
if (calendar1.before(Calendar.getInstance())) {
calendar1.add(Calendar.DATE, 1);
}
Intent intent = new Intent(events_main.this, events_receiver.class);
intent.putExtra("type",type);
intent.putExtra("note",note);
intent.putExtra("id", id);
PendingIntent dog1 = PendingIntent.getBroadcast(this, id, intent, PendingIntent.FLAG_UPDATE_CURRENT);
final AlarmManager alarm1 = (AlarmManager) getSystemService(ALARM_SERVICE);
alarm1.setExact(AlarmManager.RTC_WAKEUP, calendar1.getTimeInMillis(), dog1);
Toast.makeText(events_main.this, "alarms",Toast.LENGTH_SHORT).show();
}
then in the Receiver
public class events_receiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
int id= Integer.valueOf(intent.getStringExtra("id"));
String note=intent.getStringExtra("note");
String type=intent.getStringExtra("type");
NotificationManager notificationManager2=(NotificationManager)context.getSystemService(context.NOTIFICATION_SERVICE);
Intent dog_intent2=new Intent(context,HomeActivity.class);
dog_intent2.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent dog_pending2=PendingIntent.getActivity(context, id,dog_intent2, PendingIntent.FLAG_ONE_SHOT);;
NotificationCompat.Builder builder2=new NotificationCompat.Builder(context)
.setContentIntent(dog_pending2)
.setSmallIcon(R.drawable.ic_action_prof_breed_icon)
.setSound(Uri.parse("android.resource://" +context.getPackageName()+ "/" + R.raw.dog))
.setContentTitle("Pet Guide 101")
.setContentText(type)
.setContentText(note)
.setVibrate(new long[] { 1000, 1000})
.setAutoCancel(true);
notificationManager2.notify(id,builder2.build());
}
}
But for some reason the alarm doesn't get triggered. When I test the code I do get the data from the database but the alarm still doesn't get executed. If you can look it up, please tell me if I'm doing it wrong especially the part of passing the unique id into the receiver.
Related
I am developing an alarm and I need to retrieve times from a database.
The code explains how I iterate through my database and retrieve the hour and minutes and then set it in calendar.
How can I set that function to always be working and looping in my database to compare with the current time and then ring?
what about requestcode? I have read that it's important and I should take the id of the row in my database and put it requestcode.
private void ringalarms(){
Cursor data = myDB.getListContents();
int hr,mt = 0;
alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
final Calendar calendar = Calendar.getInstance();
final Intent myIntent = new Intent(this.context, Alarm_Receiver.class);
data.moveToFirst();
while (!data.isAfterLast()) {
hr=Integer.parseInt(data.getString(0));
mt=Integer.parseInt(data.getString(1));
calendar.set(Calendar.HOUR_OF_DAY, hr);
calendar.set(Calendar.MINUTE, mt);
myIntent.putExtra("extra", "yes");
//myIntent.putExtra("id", i);
pending_intent = PendingIntent.getBroadcast(Add_Alarm.this, 0, myIntent, PendingIntent.FLAG_UPDATE_CURRENT);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),AlarmManager.INTERVAL_DAY, pending_intent);
data.moveToNext();
}
}
and
public Cursor getListContents(){
SQLiteDatabase db = this.getWritableDatabase();
Cursor data = db.rawQuery("SELECT Hour, Minutes FROM " + TABLE_NAME, null);
return data;
}
You can use a variety of options for scheduling a background task.
For more info look into Service, JobScheduler and AlarmManager
I am currently debugging an issue with notifications inside my application. For some context, what I'd like to do is schedule notifications that should popup whenever a rocket launch is occurring. What I was doing was, after getting a list of scheduled launches from an API, I would take the launch date (in milliseconds since Jan 1 1970) and subtract the System.currentTimeMillis() from it. I would then use the resulting time to schedule the notification in the future, represented as System.currentTimeMillis() + timeDifference. I noticed that for whatever reason, only 1 notification is ever displayed.
I've tried debugging by scheduling notifications at 2, 4, and 6 minutes in the future, however a notification is only displayed at the 6 minute mark.
Some relevant code is below:
public void scheduleNotifications(List<Launch> launches) {
for(int i = 0; i < launches.size(); i++) {
SimpleDateFormat format = new SimpleDateFormat("MMMM dd, yyyy HH:mm:ss z");
Date date = null;
try {
date = format.parse(launches.get(i).getWindowstart());
} catch (ParseException e) {
e.printStackTrace();
}
long timeBetween = date.getTime() - System.currentTimeMillis();
Integer id = Long.valueOf(date.getTime()).intValue();
Intent notificationIntent = new Intent(this, NotificationPublisher.class);
notificationIntent.putExtra(NotificationPublisher.NOTIFICATION_ID, id);
notificationIntent.putExtra(NotificationPublisher.NOTIFICATION, getNotification(launches.get(i).getRocket().getName(), launches.get(i).getLocation().getPads().get(0).getName()));
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, notificationIntent, 0);
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
//Debug. Schedule at 2, 4, 6 minutes.
if (i == 0) {
alarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + 120000, pendingIntent);
}
if (i == 1) {
alarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + 240000, pendingIntent);
}
if (i == 2) {
alarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + 360000, pendingIntent);
}
}
}
private Notification getNotification(String rocketName, String padName) {
Notification.Builder builder = new Notification.Builder(this);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, new Intent(this, MainActivity.class), 0);
builder.setContentIntent(pendingIntent);
builder.setContentTitle("Upcoming Launch");
builder.setContentText("A launch of a " + rocketName + " is about to occur at " + padName + ". Click for more info.");
builder.setSmallIcon(R.drawable.rocket_icon);
return builder.build();
}
Broadcast Receiver:
public class NotificationPublisher extends BroadcastReceiver {
public static String NOTIFICATION_ID = "notification_id";
public static String NOTIFICATION = "notification";
public void onReceive(Context context, Intent intent) {
NotificationManager notificationManager = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);
Notification notification = intent.getParcelableExtra(NOTIFICATION);
int id = intent.getIntExtra(NOTIFICATION_ID, 0);
notificationManager.notify(id, notification);
}
}
I'd like to know why only a single notification is ever presented, as well as what I need to add to achieve the previously stated goal.
When you set an alarm using AlarmManager, it automatically cancels any existing alarm that has a matching PendingIntent. Since all your PendingIntents contain the same components, every time you set an alarm, the previously set ones are automatically cancelled.
If you want to set multiple alarms, you must make sure that each of the PendingIntents is unique. You can do this in one of the following ways:
Use a different requestCode (second parameter to PendingIntent.getBroadcast()) for each PendingIntent
Use a different ACTION in the Intent you pass to PendingIntent.getBroadcast() for each PendingIntent
I'm making an app that stores medicines data in an SQLite database in order to send to the user notifications when it's time to take them.
I already created the BroadcastReceiver class and managed the notification Intent.
The Calendar.set() function is called when I add the time (hh:mm:ss) in the database but the problem is that every time I set the time in the TimePicker dialog, the notification is sent instantly, at regardless from time.
Here is the setAlarm function from the activity where I store the time and the other stuff:
public void setAlarm()
{
String mName = NameFld.getText().toString();
String mFormat = FormatSpn.getSelectedItem().toString();
Calendar calendar = Calendar.getInstance();
char[] sTime = TimeBtn.getText().toString().toCharArray();
if(sTime[0] == '0')
{
calendar.set(Calendar.HOUR_OF_DAY, sTime[1]);
}
else
{
String tmp = "";
tmp += sTime[0];
tmp += sTime[1];
int hour = Integer.parseInt(tmp);
calendar.set(Calendar.HOUR_OF_DAY, hour);
}
if(sTime[3] == '0')
{
calendar.set(Calendar.MINUTE, sTime[4]);
}
else
{
String tmp = "";
tmp += sTime[3];
tmp += sTime[4];
int minute = Integer.parseInt(tmp);
calendar.set(Calendar.MINUTE, minute);
}
calendar.set(Calendar.SECOND, 0);
Intent intent = new Intent(this, AlarmReceiver.class);
intent.putExtra("mName", mName);
intent.putExtra("mFormat", mFormat);
sendBroadcast(intent);
PendingIntent pIntent = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager aManager = (AlarmManager) getSystemService(ALARM_SERVICE);
aManager.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pIntent);
The two lines of code below:
String mName = NameFld.getText().toString();
String mFormat = FormatSpn.getSelectedItem().toString();
Just takes data from the EditText fields then put in an Intent to manage them in the notification building.
In order to set the time to the Calendar variable, I take the text from the TimeBtn button that consists in the time string itself. I just set it when I pick the time from the TimePicker dialog.
Then I cast it in a char array in order to split hour and minute values and I put them in the calendar.set() function, distinguishing if the value starts with 0 to avoid an octal conversion when I cast them to int.
Once the time has been set, the AlarmReceiver class (extends BroadcastReceiver) does the following:
#Override
public void onReceive(Context context, Intent intent) {
String mName = intent.getStringExtra("mName");
String mFormat = intent.getStringExtra("mFormat");
NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
builder.setAutoCancel(true);
builder.setTicker("It's pill time!");
builder.setContentTitle(mName);
builder.setContentText(mFormat);
builder.setSmallIcon(R.drawable.ic_launcher);
Notification notification = builder.build();
NotificationManager nManager = (NotificationManager) context.getSystemService(context.NOTIFICATION_SERVICE);
nManager.notify(0, notification);
}
There aren't compilation errors, I just can't spot the issue.
Thanks in advance for any help!
Try replacing
aManager.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pIntent);
with
aManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis()+calendar.getTimeInMillis(), pIntent);
I'm getting this error in my Android broadcast receiver code below (the last line). I don't understand why this constant isn't available in this context?
public class OnBootReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// Code to be executed after a phone reboot
PendingIntent pi;
AlarmManager am;
// Read the pending_alarms table and re-create the pending intents
List<pending_alarm> pending_alarm = new TableControllerPendingAlarm(
context).read();
if (pending_alarm.size() > 0) {
int idx = 0;
for (pending_alarm obj : pending_alarm) {
long id = obj.id;
String mealItemDesc = obj.alarm_desc;
int alarmMinutes = obj.alarm_minutes;
int alarmHours = obj.alarm_hours;
long mealPlanId = obj.id;
Calendar cal = new GregorianCalendar();
cal.set(Calendar.DAY_OF_MONTH, obj.alarm_day);
cal.set(Calendar.MONTH, obj.alarm_month - 1);
cal.set(Calendar.YEAR, obj.alarm_year);
cal.set(Calendar.MINUTE, obj.alarm_minutes);
cal.set(Calendar.HOUR, obj.alarm_hours);
Intent alarmIntent1 = new Intent(context, AlarmReceiver.class);
alarmIntent1.putExtra("meal_item_desc", obj.alarm_desc);
alarmIntent1.putExtra("meal_id", obj.fk_meal_id);
alarmIntent1.putExtra("pending_alarm_id", obj.fk_meal_plan_id);
alarmIntent1.setAction(Long.toString(id));
idx++;
pi = PendingIntent.getBroadcast(context, idx, alarmIntent1, FLAG_UPDATE_CURRENT);
That flag is a constant which is not part the current class. It's part of the PendingIntent class.
So address it as such:
PendingIntent.FLAG_UPDATE_CURRENT
FLAG_UPDATE_CURRENT belongs to Intent.
Change
pi = PendingIntent.getBroadcast(context, idx, alarmIntent1, FLAG_UPDATE_CURRENT);
to
pi = PendingIntent.getBroadcast(context, idx, alarmIntent1, Intent.FLAG_UPDATE_CURRENT);
I have an app that sends notifications to the status bar as a reminder to take a pill. If two pills need to be taken at the same time. then two separate notifications shall be sent. I know you need to use an unique id for this to happen in the .notify(int id, notification notification) function. However it doesn't seem to be working. I know for sure my ids are different as I've tested them by displaying a toast. I would appreciate any suggestions. Heres my code:
Alarm class:
DatabaseHelper notiDb = new DatabaseHelper(this);
notiDb.open();
final String dataName = notiDb.getDataName(pushed_name);
String dataDaily = notiDb.getDataDaily(pushed_name);
String dataWeekly = notiDb.getDataWeekly(pushed_name);
String dataTwice = notiDb.getDataTwice(pushed_name);
String dataDosage = notiDb.getDataDosage(pushed_name);
String dataStart = notiDb.getDataStart(pushed_name);
String dataID = notiDb.getDataID(pushed_name);
notiDb.close();
ID = Integer.parseInt(dataID);
Calendar uncalendar = Calendar.getInstance();
String unID = dataID +uncalendar;
Toast toast=Toast.makeText(this, "Alarm class, Notification for " +dataName +" has been set id: " +ID, Toast.LENGTH_LONG);
toast.show();
Intent intent_unique = new Intent(this, NotiScenario.class);
intent_unique.putExtra("ID", ID);
intent_unique.setData(Uri.parse(intent_unique.toUri(Intent.URI_INTENT_SCHEME)));
PendingIntent pIntent = PendingIntent.getActivity(this, ID, intent_unique, 2);
// Build notification
Notification noti = new Notification.Builder(this)
.setContentTitle("MedScan")
.setContentText("3. You should take "+dataDosage +" pills of " +dataName)
.setSmallIcon(R.drawable.original)
.setContentIntent(pIntent)
.build();
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
noti.defaults |= Notification.DEFAULT_ALL;
//Hide the notification after its selected
noti.flags |= Notification.FLAG_AUTO_CANCEL;
notificationManager.notify(ID, noti);
Info class:
DatabaseHelper notiDb = new DatabaseHelper(this);
notiDb.open();
final String dataName = notiDb.getDataName(pushed_name);
String dataDaily = notiDb.getDataDaily(pushed_name);
final String dataWeekly = notiDb.getDataWeekly(pushed_name);
String dataTwice = notiDb.getDataTwice(pushed_name);
final String dataDosage = notiDb.getDataDosage(pushed_name);
String dataStart = notiDb.getDataStart(pushed_name);
String dataID = notiDb.getDataID(pushed_name);
notiDb.close();
ID = Integer.parseInt(dataID);
int value_Weekly = Integer.parseInt(dataWeekly);
int value_Daily = Integer.parseInt(dataDaily);
int value_Twice = Integer.parseInt(dataTwice);
int value_Start = Integer.parseInt(dataStart);
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, value_Start);
calendar.set(Calendar.MINUTE, 46);
calendar.set(Calendar.SECOND, 00);
int setTime = (value_Daily*value_Twice)/value_Weekly;
Intent intent_noti = new Intent(this,Alarm.class);
intent_noti.putExtra("ID", ID);
intent_noti.setData(Uri.parse(intent_noti.toUri(Intent.URI_INTENT_SCHEME)));
PendingIntent pendingIntent = PendingIntent.getActivity(this, ID, intent_noti, PendingIntent.FLAG_ONE_SHOT);
AlarmManager am = (AlarmManager)getSystemService(Activity.ALARM_SERVICE);
am.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), setTime, pendingIntent);
The problem isn't in your Alarm class which creates the notification but in your Info class which creates an alarm to call the Info class on a regular basis.
The two lines creating the pending intent for your alarm are:
Intent intent_noti = new Intent(this,Alarm.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, ID, intent_noti, PendingIntent.FLAG_CANCEL_CURRENT);
Because the Intent is the same regardless of your ID, a newly created PendingIntent will just cancel the previously created one.
In order for your code to work the Intent has to be different according to the Intent.filterEquals() method: http://developer.android.com/reference/android/content/Intent.html#filterEquals(android.content.Intent)
To get a unique Intent you could do:
intent_noti.setAction(""+System.currentTimeMillis());
or:
intent_noti.putExtra("ID", ID);
intent_noti.setData(Uri.parse(intent_noti.toUri(Intent.URI_INTENT_SCHEME)));