I am having trouble to stop the alarm from ringing even after I have pressed the stopAlarm button. thank you for any help.
This is my start alarm switch in MainActivity java class.
public void switchClicked (View view) {
if (((Switch) view).isChecked()) {
Log.d("MainActivity", "Alarm On");
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, alarmTimePicker.getHour());
calendar.set(Calendar.MINUTE, alarmTimePicker.getMinute());
Intent myIntent = new Intent(MainActivity.this, AlarmReceiver.class);
pendingIntent = PendingIntent.getBroadcast(MainActivity.this, 0, myIntent, 0);
alarmManager.set(AlarmManager.RTC, calendar.getTimeInMillis(), pendingIntent);
setAlarmText("ON");
} else {
alarmManager.cancel(pendingIntent);
setAlarmText("OFF");
Log.d("MainActivity", "Alarm Off");
}
}
public void setAlarmText(String alarmText) {
alarmTextView.setText(alarmText);
}
Here is my StopAlarm button in MainActivity java class.
public void stopAlarm(View view) {
setAlarmText("Alarm stopped");
Intent myIntent = new Intent(MainActivity.this, AlarmReceiver.class);
pendingIntent = PendingIntent.getService(MainActivity.this, 0, myIntent, PendingIntent.FLAG_UPDATE_CURRENT);
alarmManager.cancel(pendingIntent);
}
This is the AlarmReciver java class.
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(final Context context, Intent intent) {
MainActivity inst = MainActivity.instance();
inst.setAlarmText("Alarm! Wake up! Wake up!");
Uri alarmUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM);
if (alarmUri == null) {
alarmUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
}
Ringtone ringtone = RingtoneManager.getRingtone(context, alarmUri);
ringtone.play();
}
}
The problem is in this line
pendingIntent = PendingIntent.getService(MainActivity.this, 0, myIntent, PendingIntent.FLAG_UPDATE_CURRENT);
You are using getService() but you should use getBroadcast() instead.
Why?
getService() retrieves a PendingIntent that will start a service, but since you are using a BroadcastReceiver you should use getBroadcast() that retrieves a PendingIntent that will perform a broadcast.
Related
I have RecyclerView that contains notes, when I add new note I want to add reminder for that particular note but when the notification appears and I click on it I want to navigate to that activity and open that note. Notification works properly but what I want is, when I clicked on the notification open that note I set reminder on it.
AlarmReceiver class:
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Intent i = new Intent(context, ChecklistChildActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, i, 0);
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, "alarmChannel")
.setContentTitle("title")
.setContentText("text")
.setAutoCancel(true)
.setDefaults(NotificationCompat.DEFAULT_ALL)
.setSmallIcon(R.drawable.alarm)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setContentIntent(pendingIntent);
NotificationManagerCompat managerCompat = NotificationManagerCompat.from(context);
managerCompat.notify(123, builder.build());
}
}
setAlarm method:
private void setAlarm() {
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR, hour);
calendar.set(Calendar.MINUTE, minute);
alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(this, AlarmReceiver.class);
pendingIntent = PendingIntent.getBroadcast(this, 0, intent, 0);
alarmManager.setExact(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);
Toast.makeText(this, "Alarm is set", Toast.LENGTH_SHORT).show();
}
I have an o'clock interface in RecyclerAdapter that I implemented in MainActivity:
#Override
public void onNoteClicked(int position, View itemView) {
Intent intent = new Intent(this, NoteDetail.class).setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.putExtra("id", noteAdapter.itemList.get(position).getId());
intent.putExtra("title", noteAdapter.itemList.get(position).getTitle());
intent.putExtra("content", noteAdapter.itemList.get(position).getContent());
intent.putExtra("date", noteAdapter.itemList.get(position).getDate());
intent.putExtra("backgroundColor", noteAdapter.itemList.get(position).getBackgroundColor());
startActivity(intent);
}
When I clicked on the notification this method somehow should be called. When I add the note I don't know which position it goes in order to pass that position with the intent, though if I know the position, the position may change when I add or remove another note.
Great, I have an idea, I assume your activity gets id and other data from intent. so we have to put data to alarm intent and read them from AlarmReceiver and put them again into the Activity Intent.
private void setAlarm() {
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR, hour);
calendar.set(Calendar.MINUTE, minute);
alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(this, AlarmReceiver.class);
intent.putExtra("id", "myId");
intent.putExtra("title", "my title");
pendingIntent = PendingIntent.getBroadcast(this, 0, intent, 0);
alarmManager.setExact(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);
Toast.makeText(this, "Alarm is set", Toast.LENGTH_SHORT).show();
}
and get that from the Receiver class:
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Intent i = new Intent(context, ChecklistChildActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
i.putExtra("id", intent.getStringExtra("id"));
i.putExtra("title", intent.getStringExtra("title"));
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, i, 0);
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, "alarmChannel")
.setContentTitle("title")
.setContentText("text")
.setAutoCancel(true)
.setDefaults(NotificationCompat.DEFAULT_ALL)
.setSmallIcon(R.drawable.alarm)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setContentIntent(pendingIntent);
NotificationManagerCompat managerCompat = NotificationManagerCompat.from(context);
managerCompat.notify(123, builder.build());
}
that is a simple way but I suggest using the database in your activity and getting the note details in the onCreate method with id, so you need just add id in your intents and add get query in NoteDetail.java class.
This application allows me to start a service to remind me drinking. If i click the notification i want to see if the service is running or not, but i don't get any output with the Intent.putExtra method.
My MainActivity class:
Boolean isServiceRunning = false;
AlarmManager alarmManager;
PendingIntent pendingIntent;
TextView mainText;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mainText = findViewById(R.id.mainTextView);
Bundle extras = getIntent().getExtras();
if (extras == null) {
mainText.setText("Service is paused");
} else {
mainText.setText("Service is running");
}
}
public void sendNotification(View view) {
if (!isServiceRunning) {
isServiceRunning = true;
Toast.makeText(this, "Reminder service started.", Toast.LENGTH_SHORT).show();
alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
mainText.setText("Service is running.");
Intent i = new Intent(this, reciever.class);
i.putExtra("isServiceRunning", isServiceRunning.booleanValue());
pendingIntent = PendingIntent.getBroadcast(this, 100, i, PendingIntent.FLAG_UPDATE_CURRENT);
Calendar calendar = Calendar.getInstance();
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), 1000 * 60 * 10, pendingIntent);
} else {
isServiceRunning = false;
Toast.makeText(this, "Reminder service ended.", Toast.LENGTH_SHORT).show();
mainText.setText("Service paused.");
alarmManager.cancel(pendingIntent);
}
}
I think its possible to solve this problem with sharedpreferences, but this shouldn't be a good resolution.
EDIT:
My broadcast reciever class:
public class reciever BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Intent notificationIntent = new Intent(context, drinkReminder.class);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);
stackBuilder.addParentStack(drinkReminder.class);
stackBuilder.addNextIntent(notificationIntent);
PendingIntent pendingIntent = stackBuilder.getPendingIntent(100, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
Notification notification = new NotificationCompat.Builder(context, CHANNEL_1_ID)
.setContentTitle("Title")
.setContentText("description")
.setSmallIcon(R.drawable.icon_waterdrop)
.setTimeoutAfter(30000)
.setContentIntent(pendingIntent)
.setAutoCancel(true)
.build();
notificationManager.notify(0, notification);
}
}
You are adding the "extra" to the Intent that you pass to AlarmManager. This "extra" will be in the Intent that gets delivered to your BroadcastReceiver in onReceive(), but you don't do anything with it there.
When you click on the Notification, it will launch drinkReminder, which I hope is an Activity.
You also said in a comment:
Could you tell me please one more thing. Sometimes if i press the
button to start the service, a notification appers after about 10
seconds, after this it shows all 10 minutes like it should. How can i
fix this?
Here is your code for setting the alarm:
Calendar calendar = Calendar.getInstance();
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP,
calendar.getTimeInMillis(), 1000 * 60 * 10, pendingIntent);
When you call setRepeating(), the 2nd parameter specifies the first time the alarm should go off, and the 3rd parameter specifies the repeat interval. You've told alarm manager that you want the first alarm to trigger immediately and then every 10 minutes after that.
If you want the first alarm to trigger 10 minutes after you press the button, you need to adjust the second parameter so it represents a time that is 10 minutes in the future, like this:
Calendar calendar = Calendar.getInstance();
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP,
calendar.getTimeInMillis() + (1000 * 60 * 10), 1000 * 60 * 10, pendingIntent);
Instead of the code in onCreate() and putExtra() ,you can create two pending intents in each case and each intent uses a different broadcast receiver. In that broadcast receiver you can print the separate toast messages.
MyBroadcastRecieverStart.java
public class MyBroadcastReceiverStart extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(this, "Reminder service started.", Toast.LENGTH_SHORT).show();
}
}
MyBroadcastReceiverStop.java
public class MyBroadcastReceiverStop extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(this, "Reminder service ended.", Toast.LENGTH_SHORT).show();
}
}
SendNotification method -
public void sendNotification(View view) {
if (!isServiceRunning) {
isServiceRunning = true;
alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
mainText.setText("Service is running.");
Intent i = new Intent(this, MyBroadcastReceiverStart.class);
pendingIntent = PendingIntent.getBroadcast(this, 100, i, PendingIntent.FLAG_UPDATE_CURRENT);
Calendar calendar = Calendar.getInstance();
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), 1000 * 60 * 10, pendingIntent);
} else {
isServiceRunning = false;
mainText.setText("Service paused.");
Intent i = new Intent(this, MyBroadcastReceiverStop.class);
pendingIntent = PendingIntent.getBroadcast(this, 100, i, PendingIntent.FLAG_UPDATE_CURRENT);
Calendar calendar = Calendar.getInstance();
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), 1000 * 60 * 10, pendingIntent);
alarmManager.cancel(pendingIntent);
}
}
If you write alarmManager.cancel(pendingIntent) in else block , it is cancelling an intent which does not exist as you have created the intent in if block and it does not get created if else gets executed , so I have created the intent in else block also.
I'm using alarmmanager class to schedule notification for the user to lunch every day in a certain time but when th time comes it force stop the application
this is the setAlarm() method that i call onCreate of the main activity
public void setAlarm() {
// TODO Auto-generated method stub
AlarmManager alarmMgr;
PendingIntent alarmIntent;
alarmMgr = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(this, AlarmReceiver.class);
alarmIntent = PendingIntent.getBroadcast(this, 0, intent, 0);
// Set the alarm to start at approximately 8:00 p.m.
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, 10);
calendar.set(Calendar.MINUTE, 17);
// With setInexactRepeating(), you have to use one of the AlarmManager
// interval
// constants--in this case, AlarmManager.INTERVAL_DAY.
alarmMgr.setInexactRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY,
alarmIntent);
}
and that's the the BroadcastReceiver Class
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent arg1) {
creatNotification(context, "Times Up", "5 Seconds Passed", "Alert");
}
private void creatNotification(Context context, String MSG, String MSgText, String MSGAlert) {
PendingIntent NotifIntent = PendingIntent.getActivity(context, 0, new Intent(context, MainActivity.class), 0);
NotificationCompat.Builder notifBuilder = new NotificationCompat.Builder(context);
notifBuilder.setContentTitle("title").setContentText("Content")
.setTicker("Ticker").setSmallIcon(R.drawable.ic_launcher);
notifBuilder.setContentIntent(NotifIntent);
notifBuilder.setDefaults(NotificationCompat.DEFAULT_SOUND);
notifBuilder.setAutoCancel(true);
NotificationManager notificationManager = (NotificationManager) context
.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(1, notifBuilder.build());
}
any Ideas ??
Did you define your Broadcast receiver on Manifest file?
the notifications of my app open without a logical sense than the code that I wrote. I should receive a notification every day at the same time but if I open the app I get the same notification. This is the code in MainActivity:
public void setRepeatingAlarm() {
Intent intent = new Intent(this, MyAlarmService.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0,
intent, PendingIntent.FLAG_CANCEL_CURRENT);
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, 13);
calendar.set(Calendar.MINUTE, 00);
calendar.set(Calendar.SECOND, 00);
am.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),24*60*60*1000,pendingIntent);
}
And this is MyAlarmService:
public class MyAlarmService extends BroadcastReceiver {
NotificationManager nm;
#Override
public void onReceive(Context context, Intent intent) {
nm = (NotificationManager) context
.getSystemService(Context.NOTIFICATION_SERVICE);
CharSequence from = "Locali Torino";
CharSequence message = "Visita le serate!";
Intent action = new Intent(context, MainActivity.class);
PendingIntent contentIntent = PendingIntent.getActivity(context, 0,
action, 0);
Notification notif = new Notification(R.drawable.disco,
"Visita le serate!", System.currentTimeMillis());
notif.setLatestEventInfo(context, from, message, contentIntent);
notif.flags |= Notification.FLAG_AUTO_CANCEL;
nm.notify(0, notif);
}
}
Why I get notifications when I open the app or at least not only at the set time?
EDIT
MyAlarmService:
public class MyAlarmService extends BroadcastReceiver {
NotificationManager nm;
#Override
public void onReceive(Context context, Intent intent) {
nm = (NotificationManager) context
.getSystemService(Context.NOTIFICATION_SERVICE);
CharSequence from = "Locali Torino";
CharSequence message = "Visita le serate!";
Intent action = new Intent(context, MainActivity.class);
PendingIntent contentIntent = PendingIntent.getActivity(context, 0,
action, 0);
Notification notif = new Notification(R.drawable.disco,
"Visita le serate!", System.currentTimeMillis());
notif.setLatestEventInfo(context, from, message, contentIntent);
notif.flags |= Notification.FLAG_AUTO_CANCEL;
nm.notify(0, notif);
SharedPreferences mPref = context.getSharedPreferences("pref_name", Context.MODE_PRIVATE);
SharedPreferences.Editor mEditor = mPref.edit();
long time = System.currentTimeMillis();
mEditor.putLong("UPDATE_TIME", time);
mEditor.commit();
}And this is MainActivity:
public void setRepeatingAlarm() {
Intent intent = new Intent(this, MyAlarmService.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0,
intent, PendingIntent.FLAG_CANCEL_CURRENT);
long startAt;
long period;
SharedPreferences mPref = context.getSharedPreferences("pref_name", Context.MODE_PRIVATE);
long dif = System.currentTimeMillis() - mPref.getLong("UPDATE_TIME", 0);
if (dif >= UPDATE_PERIOD) {
startAt = 0;
period = UPDATE_PERIOD;
} else {
startAt = dif;
period = dif;
}
am.setRepeating(AlarmManager.RTC_WAKEUP, startAt, period,pendingIntent);
}
The service runs when you register it, so what you need to do is pass a boolean value with the intent when registering the service to prevent it from running when the application runs, but to run periodically thereafter.
In your activity add:
intent.putExtra("run", false);
Then in MyAlarmService:
private boolean run = true;
// ...
action.getBooleanExtra("run", run);
if(run) {
// notifications code
} else {
run = true;
}
Actually it works exactly as code is written. The cause of that behavior is your startAt parameter in setRepeating method.
am.setRepeating(AlarmManager.RTC_WAKEUP,
calendar.getTimeInMillis(),
24*60*60*1000,
pendingIntent);
calendar.getTimeInMillis() time in milliseconds that the alarm should first go off, using the appropriate clock (depending on the alarm type).
For example :
//send first alarm after 1 second and repeat it every 24 hours
am.setRepeating(AlarmManager.RTC_WAKEUP,
1000,
24*60*60*1000,
pendingIntent);
//send first alarm after 10 second and repeat it every 24 hours
am.setRepeating(AlarmManager.RTC_WAKEUP,
10000,
24*60*60*1000,
pendingIntent);
UPDATE :
You need to save your last update time :
public class MyAlarmService extends BroadcastReceiver {
NotificationManager nm;
#Override
public void onReceive(Context context, Intent intent) {
//send alarm here
//...
SharedPreferences mPref = context.getSharedPreferences("pref_name", Context.MODE_PRIVATE);
SharedPreferences.Editor mEditor = mPref.edit();
mEditor.putLong("UPDATE_TIME", time);
mEditor.commit();
}
}
Then you can make your setRepeatingAlarm method like this :
public void setRepeatingAlarm() {
Intent intent = new Intent(this, MyAlarmService.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0,
intent, PendingIntent.FLAG_CANCEL_CURRENT);
long startAt;
long period;
SharedPreferences mPref = context.getSharedPreferences("pref_name", Context.MODE_PRIVATE);
long dif = System.currentTimeMillis() - mPref.getLong("UPDATE_TIME", 0);
if (dif >= UPDATE_PERIOD) {
startAt = 0;
period = UPDATE_PERIOD;
} else {
startAt = dif;
period = dif;
}
am.setRepeating(
AlarmManager.RTC_WAKEUP,
startAt,
period,
pendingIntent);
}
I have this code:
set alarm:
public void setAlarm()
{
Calendar Calendar_Object = Calendar.getInstance();
Calendar_Object.add (Calendar.DAY_OF_YEAR, 1);
Calendar_Object.set(Calendar.HOUR_OF_DAY, 0);
Calendar_Object.set(Calendar.MINUTE, 0);
Calendar_Object.set(Calendar.SECOND, 1);
Intent myIntent = new Intent(Main.this, AlarmReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(Main.this,
0, myIntent, PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.RTC, Calendar_Object.getTimeInMillis(),1000*60*60*24, pendingIntent);
}
Broadcast receiver:
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Intent myIntent = new Intent(context, NotificationService.class);
context.startService(myIntent);
}
}
the service:
public class NotificationService extends Service {
private NotificationManager mManager;
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
#Override
public void onCreate() {
super.onCreate();
}
#SuppressWarnings("deprecation")
#Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
mManager = (NotificationManager) this.getApplicationContext()
.getSystemService( this.getApplicationContext().NOTIFICATION_SERVICE);
Intent intent1 = new Intent(this.getApplicationContext(), ABC.class);
Notification notification = new Notification(R.drawable.ic_launcher,
"xxx", System.currentTimeMillis());
intent1.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP
| Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingNotificationIntent = PendingIntent.getActivity(
this.getApplicationContext(), 0, intent1,
PendingIntent.FLAG_UPDATE_CURRENT);
notification.flags |= Notification.FLAG_AUTO_CANCEL;
notification.setLatestEventInfo(this.getApplicationContext(),
"abc", "xyz",
pendingNotificationIntent);
mManager.notify(0, notification);
}
}
after setting the alarm at 00:00:01 everything is perfect but the next time the problem is happening. the PendingIntent triggers like 6 to 8 times between the 24 hours interval. I don't remember if the time is the same for each trigger but I want it one time each day. What is wrong with the code?
This will create an alarm that will go off every day at 00:05, the important part is the AlarmManager.INTERVAL_DAY
Date date = new Date();
Calendar cal = Calendar.getInstance();
cal.setTime(date);
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 5);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
cal.add(Calendar.HOUR, 24);
PendingIntent pi = PendingIntent.getBroadcast(context, 0, alarmIntent, 0);
mgr.cancel(pi);
mgr.setRepeating(AlarmManager.RTC, cal.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pi);
Also, don't forget to always cancel previous similar alarms, when re-setting a new one, or else they'll all go off, old set alarms, and the new one, see above mgr.cancel(pi);