So far and thanks to this website, I've been able to set up an alarm that will be set up and active, even if I turn of my phone.
Now, I set up a alarm to show a reminder for event A and I need the application to setup another alarm to show another reminder for event B.
I must be doing something wrong, because it only fires the reminder for event A. It seems that once set up, any other alarm is understood as the same one. :-(
Here is the detail of what I am doing in two steps:
1) From an activity I set an alarm that at certain time and date will call a receiver
Intent intent = new Intent(Activity_Reminder.this,
AlarmReceiver_SetOnService.class);
intent.putExtra("item_name", prescription
.getItemName());
intent
.putExtra(
"message",
Activity_Reminder.this
.getString(R.string.notif_text));
intent.putExtra("item_id", itemId);
intent.putExtra("activityToTrigg",
"com.companyName.appName.main.Activity_Reminder");
PendingIntent mAlarmSender;
mAlarmSender = PendingIntent.getBroadcast(
Activity_Reminder.this, 0, intent, 0);
long alarmTime = dateMgmt.getTimeForAlarm(pickedDate);
Calendar c = Calendar.getInstance();
c.setTimeInMillis(alarmTime);
// Schedule the alarm!
AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
am.set(AlarmManager.RTC_WAKEUP, alarmTime + 15000,
mAlarmSender);
2) From the receiver I call a service
Bundle bundle = intent.getExtras();
String itemName = bundle.getString("item_name");
String reminderOrAlarmMessage = bundle.getString("message");
String activityToTrigg = bundle.getString("activityToTrigg");
int itemId = Integer.parseInt(bundle.getString("item_id"));
NotificationManager nm = (NotificationManager) context.getSystemService("notification");
CharSequence text = itemName + " "+reminderOrAlarmMessage;
Notification notification = new Notification(R.drawable.icon, text,
System.currentTimeMillis());
Intent newIntent = new Intent();
newIntent.setAction(activityToTrigg);
newIntent.putExtra("item_id", itemId);
CharSequence text1= itemName + " "+reminderOrAlarmMessage;
CharSequence text2= context.getString(R.string.notif_Go_To_Details);
PendingIntent pIntent = PendingIntent.getActivity(context,0, newIntent, 0);
notification.setLatestEventInfo(context, text1, text2, pIntent);
notification.flags = Notification.FLAG_AUTO_CANCEL;
notification.defaults = Notification.DEFAULT_ALL;
nm.notify(itemId, notification);
Thanks in Advance,
monn3t
Ok, when you set an PendingIntent, you're supposed to assign it a unique ID to it, incase you want to identify it later (for modifying/canceling it)
static PendingIntent getActivity(Context context, int requestCode, Intent intent, int flags)
//Retrieve a PendingIntent that will start a new activity, like calling Context.startActivity(Intent).
static PendingIntent getBroadcast(Context context, int requestCode, Intent intent, int flags)
//Retrieve a PendingIntent that will perform a broadcast, like calling Context.sendBroadcast().
The Request code is that ID.
In your code, you keep resetting the SAME PendingIntent, instead use a different RequestCode each time.
PendingIntent pIntent = PendingIntent.getActivity(context,uniqueRQCODE, newIntent, 0);
It has to be an integer, i suppose you have a primaryid (itemId) that can identify Alarm A from Alarm B.
You can set up multiple alarms by supplying different request code in pendingIntent.getBroadcast(......)
The approach which I used to setup multiple alarm is that I created a single alarm. I initialized a static integer in alarm setting class which will be incremented each time from my main activity whenever I click on "add alarm" button in my main activity.
E.g.
MainActivity.java
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void addAlarmClick(View v) {
AlarmActivity.broadcastCode++;
startActivity(new Intent(this, AlarmActivity.class));
}
}
AlarmActivity.java
public class AlarmActivity extends AppCompatActivity {`
//........
public static int broadcastCode=0;
//........
Intent myIntent = new Intent(AlarmActivity.this, AlarmReceiver.class);
pendingIntent = PendingIntent.getBroadcast(AlarmActivity.this,
broadcastCode, myIntent, 0);
For an easier way, if you are listing your Alarms by RecyclerView,
PendingIntent pendingIntent = PendingIntent.getBroadcast(getBaseContext(), recyclerAdapterAlarm.getItemCount()+1, intent, PendingIntent.FLAG_UPDATE_CURRENT);
It works for me.
Related
I have the below class to check if my alarms are being triggered at the exact time which I scheduled or is it differing.
I will call SetAlarm method inside the BroadCast Reciever from MainActivity. The consecutive alarms will be set by the Receiver itself by setting current time as its new string extra.
Alarms are working fine except the issue Intent string extras are not getting updated. ScheduledTime will always hold the initial value regardless of what I have set it in the setAlarm method.
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Date currentTime = new Date();
String ScheduledTime = "";
if (null != intent) { //Null Checking
ScheduledTime = intent.getStringExtra("ScheduledTime");
//intent.removeExtra("ScheduledTime");
}
String message = "Current Time" + currentTime + ", Scheduled Time was: " + ScheduledTime ;
//Show Notification
long alarmMillis =(10*60*1000) ; //Set Alarm after 10 minutes
Long newTimeInMillis = System.currentTimeMillis() + alarmMillis;
currentTime.setTime(newTimeInMillis );
setAlarm(context, newTimeInMillis , currentTime.toString());
}
public void setAlarm(Context context, Long timeMillis, String ScheduledTime)
{
AlarmManager am =( AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent(context, AlarmReceiver.class);
i.putExtra("ScheduledTime", ScheduledTime);
PendingIntent pi = PendingIntent.getBroadcast(context, 0, i, 0);
am.setExact(AlarmManager.RTC_WAKEUP, timeMillis, pi);
}
}
From Android official site
public static final int FLAG_UPDATE_CURRENT
Flag indicating that if the described PendingIntent already exists,
then keep it but replace its extra data with what is in this new
Intent. For use with getActivity(Context, int, Intent, int),
getBroadcast(Context, int, Intent, int), and getService(Context, int,
Intent, int).
This can be used if you are creating intents where only the extras
change, and don't care that any entities that received your previous
PendingIntent will be able to launch it with your new extras even if
they are not explicitly given to it.
So change your code from
PendingIntent pi = PendingIntent.getBroadcast(context, 0, i, 0);
to
PendingIntent pi = PendingIntent.getBroadcast(context, 0, i, PendingIntent.FLAG_UPDATE_CURRENT);
In my android app I'm willing to show multiple notifications on a particular day,for this I'm using Alarm Manager and Broadcast Receiver problem is when I used alarm it worked fine but when I add notification builder to show the notification its not working
Here is my mainActivity
public static final String ACTION_ONE = "Hello, Test Message 1";
public static final String ACTION_TWO = "Hello, Test Message 2";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
AlarmManager alarmManager1 = (AlarmManager) getSystemService(ALARM_SERVICE);
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(System.currentTimeMillis());
Intent myIntent1 = new Intent(this, AlarmBroadCustReciver.class);
myIntent1.setAction(ACTION_ONE);
PendingIntent pendingIntent1 = PendingIntent.getBroadcast(this, 1253, myIntent1,
PendingIntent.FLAG_UPDATE_CURRENT);
// Set the time for first alarm here
cal.set(2015, 10, 20, 15, 55);
alarmManager1.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), pendingIntent1);
Intent myIntent2 = new Intent(this, AlarmBroadCustReciver.class);
myIntent2.setAction(ACTION_TWO);
PendingIntent pendingIntent2 = PendingIntent.getBroadcast(this, 1263, myIntent2,
PendingIntent.FLAG_UPDATE_CURRENT);
// Set the time for second alarm here
cal.set(2015, 10, 20, 15, 56);
alarmManager1.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), pendingIntent2);
// In this way set time for all the rest of the alarms
Here is BroadCastReceiver
public class AlarmBroadCustReciver extends BroadcastReceiver {
public static final String ACTION_ONE = "Hello, welcome to the Server1";
public static final String ACTION_TWO = "Hello, welcome to the Server2";
#Override
public void onReceive(Context context, Intent intent) {
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
builder.setLargeIcon(BitmapFactory.decodeResource(context.getResources(), R.mipmap.ic_launcher));
builder.setContentTitle(context.getString(R.string.app_name));
if (intent.getAction().equalsIgnoreCase(ACTION_ONE)) {
builder.setContentText("Alarm one");
} else {
builder.setContentText("Alarm two");
}
Notification notification = builder.build();
int notificationID = 0;
notificationManager.notify(notificationID, notification);
You need to pass different notification id for each Notification . If you pass same id (i.e., 0 in your case), the existed notification will be updated with the new data.
change the notification id: eg have a variable and increment it. notificationid++
I had a similar issue, I was creating multiple notifications with different IDs, however, when I clicked on one, only the first one opened the specific scree, all the sequential notifications were ignore (clicking on them didn't do anything, they were just dismissed). Then I tried to do this:
intent.setAction(context.getPackageName() + "." + notificationId);
Which means that each unique notification also carries its own unique Intent and in this case the Intents weren't ignored and each of them opened the needed screen. I must note that my Intents were the same (e.g. NoteDetails.class), so I guess I had to separate them somehow...i'm glad it worked anyways.
Box's answer was a nudge in the right direction for me.
I just had to change the requestCode in the PendingIntent I was passing to the AlarmManager, so it wasn't the same value.
Old code:
PendingIntent pI = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
New code:
PendingIntent pI = PendingIntent.getBroadcast(context, notificationId, intent, PendingIntent.FLAG_UPDATE_CURRENT);
What the application should do, is get a String from the editReminder EditText and send it to the AlarmManager using an intent. That works, the first time.
But when you close the app and try it again, the notification does not use the string you just typed into the EditText but it uses the text you typed in the first time you ran the app.
How do we make the newly inserted text appear in the notification instead of the old text?
MainActivity: the method executed on buttonclick
public void setAlarm(View v) {
//get user input
EditText editText = (EditText) findViewById(R.id.editReminder);
String reminder = editText.getText().toString();
String snoozeString = getString(R.string.snooze_result);
//the AlarmManager
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
//get date and time
Calendar c = Calendar.getInstance();
//sets time for alarm
c.set(Calendar.YEAR, year);
c.set(Calendar.MONTH, month);
c.set(Calendar.DAY_OF_MONTH, day);
c.set(Calendar.HOUR_OF_DAY, hour);
c.set(Calendar.MINUTE, minute);
c.set(Calendar.SECOND, 0);
//pIntent to launch activity when alarm triggers
Intent intent = new Intent("com.garden.DisplayNotification"); //(1)From here to DisplayNotification ...
//DisplayNotification is the activity that is intended to be evoked
//sometimes you have to use (this,DisplayNotification.class)?
//when the alarm is triggered
//assign an ID of 1, and add the text
intent.putExtra("NotifID", 1);
intent.putExtra("notification", reminder); //("STRING_I_NEED",strname)
intent.putExtra("notifyAction", snoozeString); //string for the action button
//set the flags so the mainactivity isn't started when the notification is triggered
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
PendingIntent displayIntent = PendingIntent.getActivity(
getBaseContext(), 0,
intent, 0); //this intent instead of new Intent("com.garden.Reminder")
//sets alarm
alarmManager.set(AlarmManager.RTC_WAKEUP,
c.getTimeInMillis(), displayIntent);
showConfirmDialog(v);
}
DisplayNotification: executed when the alarm for the notification triggers
package com.garden.gardenapp;
import android.app.Activity;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Intent;
import android.os.Bundle;
public class DisplayNotification extends Activity {
/**
* This activity is to display a notification only. It is called when
* the system alarm goes off.
*/
//called when activity is first created
//don't forget to update the manifest!!
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//get notification ID passed by MainActivity
int notifID = getIntent().getExtras().getInt("NotifID");
//----Oh of course, have to pass on the strings again.....-----
//initialize strings (reminder is also used for notification text
String reminderText = getIntent().getStringExtra("notification");
String snoozeString = getIntent().getStringExtra("notifyAction");
//pIntent to launch activity if user selects notification
/** making a new Intent has to be done with (this, Reminder.class) instead
* of ("com.garden.Reminder")... why? (otherwise the reminder text is not shown)
*/
Intent reminderIntent = new Intent(this, Reminder.class); //(2)... and from here to Reminder ...
reminderIntent.putExtra("NotifID", notifID);
//pass on strings again in the intent
reminderIntent.putExtra("notification", reminderText);
//intent.putExtra("notifyAction",snoozeString); //---> in different intent
PendingIntent reminderPIntent = PendingIntent
.getActivity(this, 0, reminderIntent, 0);
Intent actionIntent = new Intent(this, Reminder.class);
actionIntent.putExtra("notifyAction", snoozeString); //("STRING_I_NEED", strName)
//don't forget to pass the notifID also to the second intent
actionIntent.putExtra("NotifID",notifID);
PendingIntent actionPIntent = PendingIntent.getActivity(this,
(int) System.currentTimeMillis(), actionIntent, 0);
//create notification
Notification notif = new Notification.Builder(this) //build the notification
.setContentTitle(getString(R.string.app_name)) //required
.setContentText(reminderText) //required
.setSmallIcon(R.drawable.garden) //required
.setContentIntent(reminderPIntent)
//associate pendingIntent with a gesture of NotificationCompat.Builder: click
.addAction(R.drawable.pixel, "Snooze me", actionPIntent)
//should be addAction(NotificationCompat.Action action)
.setAutoCancel(true) //to be dismissed in the Reminder activity
.setPriority(Notification.PRIORITY_MAX) //to show the action buttons by default
// .setVibrate(new long[] {200, 600, 200, 600})
.build();
NotificationManager nm = (NotificationManager)
getSystemService(NOTIFICATION_SERVICE);
nm.notify(notifID, notif); //(int id, Notification notification);
finish(); //because this doesn't have a GUI we don't need it anymore
}
}
(In the DisplayNotification class we split the strings into two intents, so when you click the snooze (notification action) button it fires a different intent than when you click on the notification)
We think it has to do with the AlarmManager not updating the String that comes with the intent or something. Because when we make a notification without the AlarmManager the app works perfectly fine.
Please let me know if you need additional code.
We found it! You don't need to cancel the alarm manager, but you need to give the intent a flag FLAG_UPDATE_CURRENT to let the alarm manager update the intent with the new string you put in the intent.
So in this case, the PendingIntent displayIntent becomes
PendingIntent displayIntent = PendingIntent.getActivity(
getBaseContext(), 0,
intent, PendingIntent.FLAG_UPDATE_CURRENT);
And that solved the problem of updating the string.
The user sets the date he wants to be notified in (receives a push notification that the movie is out) about a movie, for example. To do this I take the movie's id to set up the BroadcastReceiver and I also take the name of the movie; to use it as a text message for the broadcast receiver, for example, "movieName is out", with the method SetAlarm(). Note: my app doesn't have to do anything with movies, I'm speaking in general.
public void setAlarm(View view){
Calendar cal = Calendar.getInstance();
cal.set(Calendar.YEAR, year);
cal.set(Calendar.MONTH, month);
cal.set(Calendar.DAY_OF_MONTH, day);
Intent alertIntent = new Intent(this, AlertReceiver.class);
alertIntent.putExtra("id", mainId);
alertIntent.putExtra("name", name);
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(),
PendingIntent.getBroadcast(this, 1, alertIntent,
PendingIntent.FLAG_UPDATE_CURRENT));
}
As you can see I'm passing with an intent the id and the name of the movie to the AlertReceiver class
public class AlertReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
int id = intent.getIntExtra("id", 0);
String name = intent.getStringExtra("name");
createNotification(context, "Movie", name + " Now Out" , name, id);
}
public void createNotification(Context context, String msg, String msgText, String msgAlert, int id){
//intent for MainActivity
PendingIntent notificIntent = PendingIntent.getActivity(context, 0, new Intent(context, MainActivity.class), 0);
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(context)
.setContentTitle(msg)
.setContentText(msgText)
.setTicker(msgAlert)
.setSmallIcon(R.mipmap.ic_launcher);
//the intent when the notification is clicked on
mBuilder.setContentIntent(notificIntent); //goes to MainActivity
//how the user will be notified
mBuilder.setDefaults(NotificationCompat.DEFAULT_LIGHTS);
//stop notification when it's clicked on
mBuilder.setAutoCancel(true);
//now to notify the user with NotificationManager
NotificationManager mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(id, mBuilder.build());
}
}
It works perfectly, the user gets notified only when the app is still running in the background, but after closing it or reboot, the broadcast receiver still gets called; the user gets notified, that means no problem with the id, but the name is null, I get as a text message "null is out". So how can I save the name?
Use SharedPreference to save the user name.
SharedPreference,disk,database...
recommend SharedPreference
I have been searching for this since morning and referred to most of the android alarm problems on stackoverflow.
I am trying to set multiple alarms with different intents. On receiving the the alarm, I want the alarm to be cancelled and the activity to come in front, in case its already running, or start again if it was killed, but this time the alarm shouldnt be set again. I dont want the other alarms to be effected.
Currently, the problem is that clicking on the notification starts the activity again and resets the alarm. If I try to cancel it using alarmmanager.cancel, it doesnt notify the user at all.
Here is my code, please help
My MainActivity thats sets multiple alarms
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Calendar cal = Calendar.getInstance(); //for using this you need to import java.util.Calendar;
// add minutes to the calendar object
cal.set(Calendar.DAY_OF_WEEK,Calendar.MONDAY);
cal.set(Calendar.HOUR_OF_DAY, 22);
cal.set(Calendar.MINUTE, 8);
// cal.add(Calendar.MINUTE, 1);
AlarmManager mgrAlarm = (AlarmManager) this.getSystemService(ALARM_SERVICE);
ArrayList<PendingIntent> intentArray = new ArrayList<PendingIntent>();
for(int i = 0; i < 10; ++i)
{
Intent intent = new Intent(this, AlarmReceiver.class);
intent.putExtra("title", "notification no."+String.valueOf(i));
intent.putExtra("NOTIFICATION_ID", String.valueOf(i));
// Loop counter `i` is used as a `requestCode`
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, i, intent, 0);
// Single alarms in 1, 2, ..., 10 minutes (in `i` minutes)
mgrAlarm.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime() + 60000 * i,
pendingIntent);
intentArray.add(pendingIntent);
}
}
My AlarmReceiver Class
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
NotificationManager manger = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);
Notification notification = new Notification(R.drawable.ic_launcher, "Alarm App", System.currentTimeMillis());
Bundle extras=intent.getExtras();
String title=extras.getString("title");
int notif_id=Integer.parseInt(extras.getString("NOTIFICATION_ID"));
//here we get the title and description of our Notification
Class myclass = MainActivity.class;
PendingIntent contentIntent = PendingIntent.getActivity(context, notif_id,
new Intent(context, MainActivity.class), 0);
String note=extras.getString("note");
notification.setLatestEventInfo(context, note, title, contentIntent);
notification.flags = Notification.FLAG_INSISTENT;
notification.defaults |= Notification.DEFAULT_SOUND;
//here we set the default sound for our
//notification
// The PendingIntent to launch our activity if the user selects this notification
manger.notify(notif_id, notification);
}
};
In your MainActivity, you can differentiate a launch from the Notification with an additional parameter in the intent. You would anyway need the notification id to cancel the particular notification. So, you can try the following in your MainActivity
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent appIntent = this.getIntent();
int notif_id = appIntent.getIntExtra( "my_notification_id", -1 ) ;
if( notif_id != -1 )
{
Log.d ( "LOG_TAG", "Launched from Notification ");
NotificationManager nm = (NotificationManager) getSystemService( NOTIFICATION_SERVICE );
nm.cancel( notif_id );
/* Do the separate processing here */
.....
}
else
{
/* Your previous onCreate code goes here */
In the file AlarmReceiver.java, you need to make the following changes
//PendingIntent contentIntent = PendingIntent.getActivity(context, notif_id, new Intent(context, MainActivity.class), 0);
Intent appIntent = new Intent( context, MainActivity.class );
appIntent.putExtra( "my_notification_id", notif_id );
PendingIntent contentIntent = PendingIntent.getActivity(context, notif_id, appIntent, 0);
Hope this helps.