reminder as part of app in android - java

I am working on a project on android studio, it about medication reminder and I have some difficulties that how can I import a reminder in it.
for example I want the user to set the time as when he want to take his pill and then alert him at that time.
So, I search a lot but I did not find a suitable thing.
the reminder is part of my app so I want it as simple as possible.
I hope you understand me.
I tried this code but it didn't work !
final Calendar calender = Calendar.getInstance();
final int hours = calender.get(Calendar.HOUR_OF_DAY);
final int minutes = calender.get(Calendar.MINUTE);
alarm.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
TimePickerDialog pickTime = new TimePickerDialog(AddMedication.this, new TimePickerDialog.OnTimeSetListener() {
#Override
public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
alarm.setText(hourOfDay + ":" + minute);
}
}, hours, minutes, true);
}
});

the method you show in your post is suitable when the app is running in the foreground all the time which is usually not the case.
The solution you need is using AlarmManager and BroadcastReceiver to accomplish this:
AlarmManager alarmMgr;
PendingIntent alarmIntent;
alarmMgr = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, AlarmReceiver.class);
alarmIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
alarmMgr.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime() +
60 * 1000, alarmIntent); //this alarm for example is set for the next minute
in your AlarmReceiver class you will have onReceive method:
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
//Either start an activity or send a notification here
}
}

Related

Encapsulating alarm creation code in a different class than the Activity

I'm creating my first Android Notifications app, so I'm very much a beginner. I have a class, Notification.java, that asks the user for the time and date. Using these data, it creates an alarm that is triggered at the specified date and time.
Here is my code for Notification.java
public class Notification extends Activity {
private PendingIntent pendingIntent;
private SetAlarm alarm;
private Date date;
private Time time;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_alarm);
findViewById(R.id.setTime).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
setAlarmTime();
}
});
findViewById(R.id.setDate).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
setAlarmDate();
}
});
findViewById(R.id.checkBox).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
createAlarm();
}
});
}
private void setAlarmTime() {
}
private void setAlarmDate() {
}
private void createAlarm() {
alarm = new SetAlarm();
}
}
The createAlarm() method is supposed to actually create the alarm using the information that the user has provided (i.e. time and date). However, I understand that I need the following code block to create the alarm?
private void setTheAlarm() {
Intent alarmIntent = new Intent(SetAlarm.this, AlarmReceiver.class);
pendingIntent = PendingIntent.getBroadcast(SetAlarm.this, 0, alarmIntent, 0);
AlarmManager manager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
int interval;
/* Set the alarm to the date specified by user */
/* Repeating on every x minutes interval */
}
However, the Notification.java is where I am extending 'Activity'. It is also where I have the 'pendingIntent; code.
So essentially, how can I move the alarm creation code into a separate class when the code dealing with the Activity is in an entirely different class?
Thanks for the help. I hope my question is clear enough.
Not exactly clear if that is what you want, but if I understand you correct, you need the alarmManager inside an extra class to reach it from everywhere? You could make a static one like this:
public class MyAlarmManager{
private static AlarmManager mAlarmManager;
private static PendingIntent mPendingIntent;
//start alarm
public static void setAlarm(Context context, int alarmId, long alarmTime) {
if (mAlarmManager== null) {
mAlarmManager= (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
}
Intent startAlarmIntent = new Intent(context, YouReceiver.class);
if(mPendingIntent==null){
mPendingIntent = PendingIntent.getBroadcast(context, alarmId,
startAlarmIntent, PendingIntent.FLAG_UPDATE_CURRENT);
}
//check the version because of doze mode since MM
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
mAlarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP,
alarmTime, mPendingIntent);
} else {
mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, alarmTime, mPendingIntent);
}
}
//stop alarm
public static void stopAlarm(Context context, int id) {
if (mAlarmManager == null) {
mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
}
Intent stopAlarmIntent = new Intent(context, YourReceiver.class);
if(mPendingIntent==null){
mPendingIntent= PendingIntent.getBroadcast(context, id, stopAlarmIntent, 0);
}
mAlarmManager.cancel(mPendingIntent);
mPendingIntent.cancel();
}
}
Then you can call it like:
MyAlarmManager.setAlarm(this, id, interval);
and stop it:
MyAlarmManager.stopAlarm(this, id);
You can do this from every class by passing the context and the identical id . The alarm id must be the same as you passed by starting the alarm, otherwise it will not work. Notice that above MarshMallow, there are some changes for AlarmManager and it´s possible that it does not work in every case. If your app get´s killed or goes into idle mode, the alarm won´t be triggered in every circumstance. To handle doze mode, see this:https://developer.android.com/training/monitoring-device-state/doze-standby.html
And be aware of any third party app and battery managers, that could kill your app. Also, Huawei devices have their own battery management besides the doze mode.
If this is not what you wanted, come back. Can´t guarantee that there is no error because I have overseen something, it´s from scratch.

Notification shows when it's not supposed to

I'm currently working on a notification that has to show at a specific time chosen by the user.
BUT when I run it, notifications show but not at the selected time, only when I ask the time in a timepickerdialog appear, before even choosing a time.
Does anyone know how to change the code so that notifications only appear at the time selected?
showDialog(DIALOG_ID); //this is the dialog that asks for an hour and minute.
alarmMethod1();
private void alarmMethod1(){
Calendar calendari1 = Calendar.getInstance();
calendari1.set(Calendar.HOUR_OF_DAY, hour_x);
calendari1.set(Calendar.MINUTE, minute_x);
calendari1.set(Calendar.SECOND, 00);
Intent myIntent1 = new Intent(Main2Activity.this, NotifyService1.class);
AlarmManager alarmManager1 = (AlarmManager) getSystemService(ALARM_SERVICE);
pendingIntent1 = PendingIntent.getService(Main2Activity.this, 0, myIntent1, 0);
alarmManager1.setRepeating(AlarmManager.RTC_WAKEUP, calendari1.getTimeInMillis(), 24 * 60 * 60 * 1000, pendingIntent1);
}
Then here is the class where the intent goes:
public class NotifyService1 extends Service {
#Override
public IBinder onBind(Intent intent) {
return null;
}
#TargetApi(Build.VERSION_CODES.JELLY_BEAN)
#Override
public void onCreate(){
Uri sound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationManager nNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
Intent intent1 = new Intent(this.getApplicationContext(),Main3Activity.class);
PendingIntent pIntent = PendingIntent.getActivity(this, 0, intent1, 0);
Notification mNotify = new Notification.Builder(this)
.setContentTitle("Hora d'entrenar!")
.setContentText("Clica per començar entrenament de pit i braços")
.setSmallIcon(R.drawable.logofinal)
.setContentIntent(pIntent)
.setSound(sound)
.build();
nNM.notify(1,mNotify);
}
}
Since Android API 19, all alarms are inexact in order to reduce battery consumption, that means that your alarms will not be triggered exactly when you want, but if you really need to do it, you need to use setExact and then write the repeat alarm handler by yourself, there's no longer a "set exact and repeat". Please, see:
http://developer.android.com/reference/android/app/AlarmManager.html#setRepeating(int, long, long, android.app.PendingIntent)
http://developer.android.com/reference/android/app/AlarmManager.html#setExact(int, long, android.app.PendingIntent)

AlarmManager not triggering onReceived

I have created a class called "VIAlarmManager" and in there I create an AlarmManager and set some properties. But no matter what, the Alarm is not fired, am I doing something wrong ? I try to call an task that is repeated in an given interval (eg 1 Minuten / 2 Minutes / 15 Minutes) and it should also be executed while in sleep.
Here is my code:
public final class VIAlarmManager{
public static AlarmManager alarmManager;
public int freq = 60;
public VIAlarmManager(int freq_in_sec){
this.freq = freq_in_sec;
}
public void setFrequency(int freq_in_sec){
this.freq = freq_in_sec;
}
public void setAlarm(){
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.add(Calendar.MINUTE, 1);
alarmManager = (AlarmManager) MainActivity.Context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(MainActivity.Context, VIAlarmManager.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(MainActivity.Context, 0, intent, 0);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),1000 * 60 * 1, pendingIntent);
}
public void cancleAlarm(){
Intent intent = new Intent(MainActivity.Context, VIAlarm_Heartbeat.class);
PendingIntent sender = PendingIntent.getBroadcast(MainActivity.Context, 0, intent, 0);
AlarmManager alarmManager = (AlarmManager) MainActivity.Context.getSystemService(Context.ALARM_SERVICE);
alarmManager.cancel(sender);
}
public static class VIAlarm_Heartbeat extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
Log.w("AlarmManager", "Calling Heartbeat now");
MainActivity.beat.beat();
}
}}
My AndroidManifest contains this line:
<receiver android:name="com.videro.util.VIAlarmManager$VIAlarm_Heartbeat" android:enabled="true" ></receiver>
And in my main activity I call:
AlarmManager = new VIAlarmManager(60);
AlarmManager.setAlarm();
If its a simple Alarm you require, the classical way is to use an Activity with TimePicker to select the time and a BroadcastReceiver to kick the Alarm along with a Service to send Notification to the user.
Here is a working way on how you can do it! Hope it helps:)

android alarm app using timepicker to select time and intents

can anyone help me with a normal alarm clock app that uses TimePicker to set the time ..and also uses intents,etc instead of normal comparisons.This is the code that i've done till now.But this is not working. The 'TimePicker' sets the time and on pressing the 'ToggleButton' a 'TextVew' shows that alarm is on .But when the alarmtime is reached,Alarm Ringing message is not shown.Please someone help me out.
this is the code of main activity
public class FullscreenActivity extends Activity implements OnClickListener {
TimePicker TimePickerForGettingTime;
TextView AlarmSet;
TextView AlarmOnOff;
ToggleButton ConfirmButton;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_fullscreen);
TimePickerForGettingTime= (TimePicker)findViewById(R.id.TimePickerForGettingTime);
ConfirmButton = (ToggleButton) findViewById(R.id.ConfirmButton);
ConfirmButton.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View v)
{ boolean on=((ToggleButton) v).isChecked() ;
AlarmOnOff=(TextView)findViewById(R.id.AlarmOnOff);
if(on)
{
AlarmOnOff.setText("Alarm on");
Calendar cal = Calendar.getInstance();
cal.set(TimePickerForGettingTime.getCurrentHour(),TimePickerForGettingTime.getCurrentMinute(),00);
setAlarm(cal);
}
else
{
AlarmOnOff.setText("Alarm off");
}
}
});
}
private void setAlarm(Calendar targetCal)
{
Intent alarmintent = new Intent(FullscreenActivity.this, AlarmReceiver.class);
PendingIntent sender = PendingIntent.getBroadcast(FullscreenActivity.this, 0, alarmintent, 0);
AlarmManager alarmManager = (AlarmManager)getSystemService(ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC_WAKEUP, targetCal.getTimeInMillis(), sender);
}
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
}
}
this is the onbootreceiver class
public class OnBootReceiver extends BroadcastReceiver {
private static final int PERIOD=10000; // 10sec
#Override
public void onReceive(Context context, Intent intent) {
AlarmManager mgr=(AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Intent i=new Intent(context, AlarmReceiver.class);
PendingIntent pi=PendingIntent.getBroadcast(context, 0, i, 0);
mgr.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime(), PERIOD, pi);
}
}
this is the alarmreceiver class
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
PendingIntent sender = PendingIntent.getBroadcast(context, 0, intent, 0);
NotificationManager manager = (NotificationManager)context.getSystemService(android.content.Context.NOTIFICATION_SERVICE);
Notification noti = new Notification(android.R.drawable.stat_notify_more, "Wake up alarm", System.currentTimeMillis());
noti.setLatestEventInfo(context, "My Alarm", "WAKE UP...!!!", sender);
noti.flags = Notification.FLAG_AUTO_CANCEL;
manager.notify(R.string.app_name, noti);
//intent to call the activity which shows on ringing
Intent myIntent = new Intent(context, FullscreenActivity.class);
myIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(myIntent);
//display that alarm is ringing
Toast.makeText(context, "Alarm Ringing...!!!", Toast.LENGTH_LONG).show();
}
}
Have you registered the alarm receiver in you manifest ?
You should have this in your manifest.
<application>
.
.
.
<receiver android:name=".AlarmReceiver" android:process=":remote" />
</application>
Also, I am not sure that is the right way to calendar set, but I could be wrong . I do it like this and it works fine for me
Calendar cal = Calendar.getInstance();
cal.set (Calendar.HOUR_OF_DAY, time_picker.getCurrentHour());
cal.set (Calendar.MINUTE, time_picker.getCurrentMinute());

How can I run my application when device is in locked state and screen is in turned off state?

I am using Alarm services to keep my application running when mobile is locked and screen turned off but it does not work.
My Alarm service class is:
public class AlarmService extends BroadcastReceiver {
// Restart service every 60 seconds
private static final long REPEAT_TIME = 1000 * 60;
#Override
public void onReceive(Context context, Intent intent) {
AlarmManager service = (AlarmManager) context
.getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent(context, StartUp_broadcast.class);
PendingIntent pending = PendingIntent.getBroadcast(context, 0, i,
PendingIntent.FLAG_CANCEL_CURRENT);
Calendar cal = Calendar.getInstance();
// Start 60 seconds after boot completed
cal.add(Calendar.SECOND, 60);
//
// Fetch every 60 seconds
// InexactRepeating allows Android to optimize the energy consumption
service.setRepeating (AlarmManager.RTC_WAKEUP,
cal.getTimeInMillis(), REPEAT_TIME, pending);
// service.setRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(),
// REPEAT_TIME, pending);
}
}
and my brodcast service class is:
public class StartUp_broadcast extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Intent myIntent = new Intent(context, AlarmService.class);
PendingIntent pendingIntent = PendingIntent.
getService(context, 0, myIntent, 0);
AlarmManager alarmManager = (AlarmManager) context
.getSystemService(Context.ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP,
System.currentTimeMillis() + 1000, 1000, pendingIntent);
Intent Startup_Intent = new Intent(context, LocationService.class);
Startup_Intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startService(Startup_Intent);
}
}
My main Activity class has PowerManager Service for WakeLock
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "MyWakeUp");
wl.acquire(1000); //wake up the screen
setContentView(R.layout.main);
this.getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
this.getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
Kindly help me. How to keep my application running when mobile is locked and scrren is off ?
If you want to run application when screen lock and also run alaram then you need to start service at boot. may be this link is helpfull to you.
http://www.androidcompetencycenter.com/2009/06/start-service-at-boot/
first read and do your self step by step. i hope it is helpfull to you.
Your code is fine, only you need to change your Alarm variables to the class level with static modifier like below,
public class AlarmService extends BroadcastReceiver
{
private static Intent myIntent;
private static AlarmManager service;
private static PendingIntent pendingIntent;
.
.
.
}
I can suggest you one thing..when your app will start and or the service will start, may be you can try to unlock the keyguard.
getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
So when your app is running, it will unlock the key guard and keep the screen on. And when the service is stop, again lock the key guard.
Note: Don't use the PowerManager class. Because it will drain the battery very fast. I faced this problem.
Thanks.

Categories