How do I make every call to my alarmManager unique? - android

I'm having problem in scheduling my alarm. I want to make every call of my alarm unique so that it will not overlap the previous alarm that I've already set.
This is my code:
public void compareDates()
{
String callName;
String dateStart;
String dateDue;
SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd HH:mm");
long callTime = System.currentTimeMillis();
Date callsDateStart = new Date();
Date dateNow = new Date();
GlucoseDatabaseAdapter gda = new GlucoseDatabaseAdapter(this);
gda.open();
Cursor c = gda.getEntries(GlucoseDatabaseAdapter.TABLE_CALLS, null,null,null,null,null,null);
AlarmManager callsAlarm = (AlarmManager)getSystemService(ALARM_SERVICE);
Intent alarmIntent = new Intent(this,callsNotify.class);
callAlarm = PendingIntent.getService(this, 0, alarmIntent, 0);
if(c.moveToFirst())
{
do
{
//GET DATA
callName = c.getString(GlucoseDatabaseAdapter.CALLS_NAME_KEY);
dateStart = c.getString(GlucoseDatabaseAdapter.CALLS_DATE_START_KEY);
dateDue = c.getString(GlucoseDatabaseAdapter.CALLS_DATE_DUE_KEY);
//COMPARE DATES
try
{
callsDateStart = sdf1.parse(dateStart); }
catch (ParseException e)
{ // TODO Auto-generated catch block
e.printStackTrace(); }
if(callsDateStart.after(dateNow))
{
long callsDs = callsDateStart.getTime();
long ff = callsDs - callTime;
callsAlarm.set(AlarmManager.RTC, System.currentTimeMillis() + ff, callAlarm);
}
}while(c.moveToNext()); }
// I'm calling callsAlarm multiple times in this code. When I set callsAlarm here it only sets the latest one. How do I make every set here unique?

You have to make sure the Intent you are passing in is unique or can only be called once. It looks like you are using the same one over and over so it is getting over written. You may want to change your pending intent to look like something as follows and read the android documentation for other possible flags to set
PendingIntent sender = PendingIntent.getBroadcast(con, 0, intent, PendingIntent.FLAG_ONE_SHOT);

Related

SQLite, Alarm Manager using broadcast class and service class

I am new to android development. I want set an alarm from sqlite db and fetch the alarms on time and date. I have try my best to see it works using extends BroadcastReceiver class and extends Service but i couldnt. here is the code for the BroadcastReceiver
public class MyReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equalsIgnoreCase(Intent.ACTION_BOOT_COMPLETED)) {
Intent serviceIntent = new Intent(context, MyService.class);
context.startService(serviceIntent);
}
}
}
and for the other class, that is Service class. Here is the code
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
Calendar calender = Calendar.getInstance();
calender.clear();
SimpleDateFormat format = new SimpleDateFormat("dd/MM/yyyy");
SimpleDateFormat formatt = new SimpleDateFormat("hh:mm");
CharSequence text = format.format(new Date());
;
CharSequence time = formatt.format(new Date());
;
String sql = String.format("SELECT * FROM comments_table WHERE time = '" + String.valueOf(time) + "'" +
"and date = '%s'", String.valueOf(text) + "");
Cursor c = db.rawQuery(sql, null);
int count = c.getCount();
String[] data_me = new String[count];
for (int i = 0; i < count; i++) {
c.moveToNext();
data_me[i] = c.getString(0);
}
c.close();
db.close();
AlarmManager[] alarmManager = new AlarmManager[24];
for (int ii = 0; ii < data_me.length; ii++) {
alarmManager[ii] = (AlarmManager) getSystemService(ALARM_SERVICE);
Intent i = new Intent(getBaseContext(), MyReceiver.class);
PendingIntent displayIntent = PendingIntent.getBroadcast(getBaseContext(), ii, i, 0);
alarmManager[ii].set(AlarmManager.RTC_WAKEUP, calender.getTimeInMillis(), displayIntent);
}
}
}
Pls, Can someone assist me?
This is a good start. Based on what you posted, your service will only after the broadcast receiver kicks in. In this case, after the device boots up. Before Android 6 (Marshmallow), this was enough to handle actions after reboot. This intent doesn't usually suffice as is to handle reboot.
Are you using a device running Android 6? If yes, you can create a simulated device in you development environment that runs Android 5 or lower just to see that your code works for devices running this Android 5 or lower. Assuming that you want to support devices running Android 6 or higher, you'll have to choose a different intent to be handled by your receiver.
To handle the AlarmManager:
Sorry. Alarmmanager's set method is using the calendar object you created before retrieving the date and time from your database. So when you use it to set the AlarmManager it'll go off then, instead of your saved dates and time FRM the data tabs. You could make a Calendar Array or Array list to store the retrieved dates and then loop through that to set the AlarmManager(s).
As an aside, it's more secure to use the query method for instead of rawQuery in order to prevent a sqlite injection.
EDIT Let's walk through your code:
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
Calendar calender = Calendar.getInstance();
calender.clear(); //WHY CLEAR CALENDAR? LATER YOU USE IT TO SET THE ALARMMANAGER.
SimpleDateFormat format = new SimpleDateFormat("dd/MM/yyyy");
SimpleDateFormat formatt = new SimpleDateFormat("hh:mm");
CharSequence text = format.format(new Date());
; //REMOVE SEMI-COLON
CharSequence time = formatt.format(new Date());
; //REMOVE SEMI-COLON
String sql = String.format("SELECT * FROM comments_table WHERE time = '" + String.valueOf(time) + "'" + "and date = '%s'", String.valueOf(text) + "");
/*WHAT ARE YOU SELECTING FROM THE DB?
*YOU ARE ALREADY USING THE CURRENT TIME AS A PARAMETER; ASSUMEDLY,
*YOU'RE NOT RETRIEVING THE DATE AND TIME*/
Cursor c = db.rawQuery(sql, null); //WHERE IS YOUR db INITIALIZED & OPENED? ADD APPROPRIATE CODE **BEFORE** MAKING THIS QUERY
int count = c.getCount();
String[] data_me = new String[count];
for (int i = 0; i < count; i++) {
c.moveToNext();
data_me[i] = c.getString(0);
}
c.close();
db.close();
AlarmManager[] alarmManager = new AlarmManager[24];
for (int ii = 0; ii < data_me.length; ii++) {
alarmManager[ii] = (AlarmManager) getSystemService(ALARM_SERVICE);
Intent i = new Intent(getBaseContext(), MyReceiver.class);
PendingIntent displayIntent = PendingIntent.getBroadcast(getBaseContext(), ii, i, 0);
alarmManager[ii].set(AlarmManager.RTC_WAKEUP, calender.getTimeInMillis(), displayIntent);
}
}
}
Is there a different way you want to initiate the service, specifically, do you want to have the user set a time and/or date (using a TimePicker, for example) for the service to run? In that case you would have a BroadcastReceiver receive the intent and then call the Service, just like you're doing now after a reboot. In fact you can add an intent to your current Receiver class to handle such an intent; just remember to check that any applicable intent-filters are in your manifest file.
If you retrieve dates/time from your query and want to use them to set the AlarmManager, you might want to store the day/time in a Calendar object and place it in a Calendar ArrayList, which you'll loop through when setting up the AlarmManager.

Alarm manager not pushing data in server periodically for nougat

i am using AlarmManager to call the PendingIntent. which triggers the WakefulBroadcastReceiver to push the data in server periodically. but for nougat, its not pushing in the periodic time. and also draining battery too much.
my code is here->
public static void startSyncAlarm(String enteredTime) {
// Construct an intent that will execute the AlarmReceiver
Intent intent = new Intent(context, SyncDbToServerAlarmReceiver.class);
intent.putExtra(Constants.ENTERED_TIME, enteredTime);
// Create a PendingIntent to be triggered when the alarm goes off
final PendingIntent pIntent = PendingIntent.getBroadcast(context, SyncDbToServerAlarmReceiver.REQUEST_CODE,
intent, PendingIntent.FLAG_UPDATE_CURRENT);
// alarm needs to be set after 5 minutes of entered time
// convert entered time to milliseconds
// create Date object using string time format with using Simple date format
SimpleDateFormat format = new SimpleDateFormat("MM/dd/yyyy hh:mm:ss aa");
try {
Date enteredDate = format.parse(enteredTime);
long enteredTimeInMillis = enteredDate.getTime();
long intervalMillis = 30 * 60 * 1000; // 30 minutes gap
long triggerAtMillis = enteredTimeInMillis + intervalMillis;
Log.d(TAG, "start alarm, enteredTimeMillis = " + enteredTimeInMillis + "\ntriggerAtMillis = " + triggerAtMillis);
//long firstMillis = System.currentTimeMillis(); // alarm is set right away
syncDbAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
// Setup periodic alarm every 5 minutes
syncDbAlarmManager.setRepeating(AlarmManager.RTC_WAKEUP, triggerAtMillis/*firstMillis*/,
intervalMillis, pIntent);
} catch (ParseException e) {
e.printStackTrace();
}
}

Notification Message Instantly Fired - Android

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);

Repeating Alarm not getting triggered

I want to trigger repeating alarm at specific time & I'm using below code but it does not trigger the alarm at the time I wanted.
boolean weeklyAlarmUp = (PendingIntent.getBroadcast(ctxt, 0, new Intent(ctxt, ScheduledWeeklyService.class), PendingIntent.FLAG_NO_CREATE) != null);
if (!weeklyAlarmUp) {
AlarmManager mgr = (AlarmManager)ctxt.getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent(ctxt, ScheduledWeeklyService.class);
PendingIntent pi = PendingIntent.getBroadcast(ctxt, 0, i, 0);
Date date = null;
try {
date = (Date) formatter.parse("17-Mar-2014 13:10:00"); // This date & time will be an user input from some activity
} catch (ParseException e) {
e.printStackTrace();
}
long triggerWeeklyTaskAt = date.getTime();
long currentTime = System.currentTimeMillis();
// Don't trigger the alarm is input date time is in the past, set it to next day but at the same time
if (currentTime > triggerWeeklyTaskAt) {
Calendar c = Calendar.getInstance();
c.set(Calendar.HOUR_OF_DAY, 13);
c.set(Calendar.MINUTE,10);
c.set(Calendar.SECOND,0);
c.set(Calendar.MILLISECOND, 0);
c.add(Calendar.DATE, 1);
date = c.getTime();
triggerWeeklyTaskAt = date.getTime();
}
Locale locale = Locale.getDefault();
msgFormatter.setLocale(locale);
Object[] objs = { "Dummy" };
SchedulerLog.logInfo(ctxt, ctxt.getString(R.string.module_scheduler), msgFormatter.format(objs));
mgr.setInexactRepeating(AlarmManager.RTC_WAKEUP, triggerWeeklyTaskAt, PERIOD_WEEKLY, pi);
}
Can anyone tell me what is wrong in below code? How can I check what time it'll trigger alarm at?
Thanks
Your outer if statement looks a bit weird. Are you sure execution is making it inside of it? Throw in a Log statement and/or step through the code to make sure.
If I understand your logic, you're attempting to not create a duplicate PendingIntent. So if the PI already exists, you bypass the whole body of the if. The problem with that is that your alarm setup is inside the if statement too.
The reference page says "...even if its owning application's process is killed, the PendingIntent itself will remain usable from other processes that have been given it." So perhaps a matching PI still exists from a previous run? It might be better to always (re)create the PI, but use FLAG_CANCEL_CURRENT or FLAG_UPDATE_CURRENT depending on whether you want to update the particulars.

Repetitive alarm using alarm manager

I am trying to make an alarm application that takes multiple "n" time inputs from the user and rings at those particular times. For that I have created an array of EditTexts for both the hour and minute entries. In the onclick listener for the start button, I wish to have alarm managers for all the entered time inputs initialized.
After creating an array of calendar, should i create an array of intents and pending intents and alarm manager objects also--one each for each calendar object?
This is the code for my start button:
public void setAlert(View view) {
int length = editHour.length;
int h[] = new int[length];
int m[] = new int[length];
Calendar[] cal = new Calendar[length];
for (int i = 0; i < length; i++) {
cal[i] = Calendar.getInstance();
}
for (int i = 0; i < length; i++) {
try {
m[i] = Integer.parseInt(editHour[i].getText().toString());
h[i] = Integer.parseInt(editMinute[i].getText().toString());
cal[i].set(Calendar.HOUR, h[i]);
cal[i].set(Calendar.MINUTE, m[i]);
Intent intent = new Intent(this, AlarmService.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this,
12345, intent, PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC_WAKEUP,
cal[i].getTimeInMillis(), pendingIntent);
Toast.makeText(this, "Alarm set", Toast.LENGTH_LONG).show();
} catch (Exception ex) {
ex.printStackTrace();
System.out.print("OOPS!");
}
}
}
your request code is unique and this is your problem. you must use unique code for your different alarms. your code with one request code override alarm time. (sorry for my bad english, it is not my language!)
use this code:
for (int i = 0; i < length; i++) {
.
.
.
int requestCode = (int) (System.currentTimeMillis());
PendingIntent pendingIntent = PendingIntent.getActivity(this,
requestCode, intent, PendingIntent.FLAG_CANCEL_CURRENT);
Thread.sleep(10);
.
.
.
}
If you want 5 different alarms then your PendingIntent should be different. You can make a PendingIntent unique by putting an extra in it. but anyway, your code should at least generate one alarm. Verify that the time you are setting in the calendar is correct.
Anyway, you don't need 5 separate calendars, intents or anything. just update them and set the alarm. you definitively don't need to save them in an array.

Categories

Resources