SQLite, Alarm Manager using broadcast class and service class - android

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.

Related

convert string to long triggerAtMilli

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

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

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.

how can i get the repeat alarm for week days using alarm manager in android?

Hi i am new to android i am developing alarm application for that i need to invoke alarm repeatedly for the same time in different days selected by the user. what i meen if i set alarm time as 10AM and repeat option as sunday, monday, saturday the alarm will be invoked on every sunday,monday,saturday.
Here i am using the code to invoke the alarm
AlarmManager am = (AlarmManager)getSystemService(ALARM_SERVICE);
Intent intent = new Intent(Alarm.this, OneShotAlarm.class); //here i am calling broad \cast receiver to invoke alarm
PendingIntent sender = PendingIntent.getBroadcast(Alarm.this, requestCode, intent, 0);
Calendar calendar = Calendar.getInstance();
calendar.set(Calender.HOUR_OF_DAY,10);
am.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), sender);
By using this code i am invoking present day at 10AM.But my gole is need to invoke the alarm for selected days at 10AM.
Here i have another question please help for this also. When i am trying to put the passed time the alarm will be invoked for the current time. How can i give the past time. i mean when i am at 11AP i am need to give 9AM.
Please suggest me if there is any way.
Thanks in advance.
Please Write below Code in your Broadcast Receiver Class, it will solve your problem.
public class MyBroadcastReceiver extends BroadcastReceiver {
DBAdapter mDba;
SQLiteDatabase mDb;
Ringtone rt;
MediaPlayer mp;
AlertDialog.Builder alertbox;
Context ctx;
#Override
public void onReceive(Context context, Intent intent) {
DBHelper mDbh = new DBHelper(context, null, null, 1);
mDb = mDbh.getWritableDatabase();
mDb.setLockingEnabled(true);
mDba = new DBAdapter(context);
mDba.open();
Cursor cr = mDb.query("mReminderEntry", null, null, null, null,
null, null);
if (cr.equals(null)) {
System.out.println("No Data Found");
} else {
Date d = new Date();
System.out.println("Current Hour is:- " + d.getHours());
System.out.println("Current Minute is:- " + d.getMinutes());
Calendar calendar = Calendar.getInstance();
int day = calendar.get(Calendar.DAY_OF_WEEK);
String today = null;
if (day == 2) {
today = "Monday";
} else if (day == 3) {
today = "Tuesday";
} else if (day == 4) {
today = "Wednesday";
} else if (day == 5) {
today = "Thursday";
} else if (day == 6) {
today = "Friday";
} else if (day == 7) {
today = "Saturday";
} else if (day == 1) {
today = "Sunday";
}
System.out.println("Today is:- " + today);
int system_hour = d.getHours();
int system_minute = d.getMinutes();
cr.moveToFirst();
for (int i = 0; i < cr.getCount(); i++) {
if (cr.getString(3).equals(system_hour + ":" + system_minute)
&& cr.getString(1).equals("Daily")) {
System.out.println("Matched");
Intent scheduledIntent = new Intent(context, MyScheduledActivity.class);
scheduledIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(scheduledIntent);
break;
} else if (cr.getString(3).equals(
system_hour + ":" + system_minute)
&& cr.getString(1).equals(today)) {
Intent scheduledIntent = new Intent(context, MyScheduledActivity.class);
scheduledIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(scheduledIntent);
System.out.println("Matched");
break;
} else {
System.out.println("No Matching");
}
cr.moveToNext();
}
}
cr.close();
mDba.close();
}
}
If U have any issue regarding that then tell me.
Dipak Keshariya is right and you need to have some logic.. one logic could be:
Use a database to store the alarms.
Make a service which gets the latest time from Database.
Register an Alarm on that
Upon Triggering, Check if the alarm was repeating
if yes, then update the alarm time in db. i.e now alarm will be edited for next repeat day.
Restart the service
Now if your logic is ok, then you dont need to have an answer of your second question as you wouldn't be needing it.
You can Implement your Repeating alarm in follwing way:
1:First create a database and store your alarms .
2:Rather then using service you can use Time tick reciever(Broad cast Reciever) and in the on recieve method of time tick reciever you can check the current time and current day and match it with the alarm date and time in the database.
3:If the date and time both matches you can trigger the alarm.

How do I make every call to my alarmManager unique?

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

Categories

Resources