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.
Related
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);
I have an app that sends a notification with AlarmManager every day at an exact time.
But it has a bug. The notification is sent whenever the app is open.
How can I get to the notification is send once a day? Thank you
MAINACTIVITY
public class MainActivity extends Activity {
private PendingIntent pendingIntent;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Calendar calendar = Calendar.getInstance();
int d = Integer.valueOf(1440);
calendar.setTimeInMillis(System.currentTimeMillis());
Intent i = new Intent(MainActivity.this, Receiver.class);
pendingIntent = PendingIntent.getBroadcast(MainActivity.this, 0, i, 0);
AlarmManager alarmManager = (AlarmManager)getSystemService(ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), 1000 * 60 * d, pendingIntent);
}
}
RECEIVER
public class Receiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
NotificationManager notificationManager = (NotificationManager) context.getSystemService(context.NOTIFICATION_SERVICE);
Intent i = new Intent(context, MainActivity.class);
Notification notification = new Notification(R.drawable.ic_launcher,"This is a test message!", System.currentTimeMillis());
long[] vibrate = {100, 100, 200, 300};
notification.vibrate = vibrate;
notification.defaults = Notification.DEFAULT_ALL;
i.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP| Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingNotificationIntent = PendingIntent.getActivity(context, 0, i,PendingIntent.FLAG_UPDATE_CURRENT);
notification.flags |= Notification.FLAG_AUTO_CANCEL;
notification.setLatestEventInfo(context, "AlarmManagerDemo", "This is a test message!", pendingNotificationIntent);
notificationManager.notify(0, notification);
}
}
Code to call CallThisClass.class every int d mins
Intent myIntent = new Intent(getActivity(), CallThisClass.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(getActivity(), 0, myIntent, 0);
AlarmManager alarmManager = (AlarmManager) getActivity().getSystemService(Context.ALARM_SERVICE);
Calendar calendar = Calendar.getInstance();
int d = Integer.valueOf(duration);
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.add(Calendar.SECOND, 2);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), 1000 * 60 * d, pendingIntent);
Code to stop calling CallThisClass.class
Intent myIntent = new Intent(getActivity(), CallThisClass.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(getActivity(), 0, myIntent, 0);
alarmManager = (AlarmManager) getActivity().getSystemService(Context.ALARM_SERVICE);
alarmManager.cancel(pendingIntent);
CallThisClass.class
public class CallThisClass extends BroadcastReceiver {
#Override
public void onReceive(final Context context, Intent intent) {
Log.i("Received", "Broadcast Received !");
// Do your stuff
}
}
Dont forget Receiver inyour AndroidManifest.xml
<receiver android:name=".CallThisClass" />
And Permission
<uses-permission android:name="com.android.alarm.permission.SET_ALARM" />
You can start calling CallThisClass.class whenever you want. Eg. on a click of a button, or when your main activity start. Just make sure to Stop Calling the class when you dont want it working. Eg You want when the user first installs your application you want every 24 hours there should be something updated (notification or something), rit? in your prefrences store a variable that changes itself only if it is loaded for the first time. Check for that variable every time user enters application. if it is first time Start the Calling code. (now we dont want to call the stop code yet because we cant to keep on calling that class even if the application is closed!) close the application and it will work. And you can have a button in you setting or something for testing that when clicked will run code for not calling the class. It will stop the calling calling class every d mins i.e 24 hours in your case (also you can change the prefrnce to default value on clik of this button so that next time you start activity or click activate or something again that code to start calling that class starts). I hope it helps.
Also, i would suggest a read here for Best practices
hi ia m new to android..
i have developed a programme to set notification onspecific time
but the problem is it shows notification only of date before october 2011
if i enter any date of november its not showing any notification..
seems strange but really stuck here....
main activity..
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Calendar cal = Calendar.getInstance(); // for using this you need to
cal.set(Calendar.MONTH, 11);
cal.set(Calendar.YEAR, 2011);
cal.set(Calendar.DAY_OF_MONTH, 25);
cal.set(Calendar.HOUR_OF_DAY, 18);
cal.set(Calendar.MINUTE, 28);
Intent alarmintent = new Intent(getApplicationContext(),
AlarmReceiver.class);
alarmintent.putExtra("title", "Title of our Notification");
alarmintent.putExtra("note", "Description of our Notification");
int HELLO_ID = 1;
PendingIntent sender = PendingIntent.getBroadcast(
getApplicationContext(), HELLO_ID, alarmintent,
PendingIntent.FLAG_UPDATE_CURRENT |
Intent.FILL_IN_DATA);
AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
am.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), sender);
}
and the alarm reciever activity...
public class AlarmReceiver extends BroadcastReceiver {
private static final String NotificationManager = null;
private static int NOTIFICATION_ID = 0;
#Override
public void onReceive(Context context, Intent intent) {
(NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
NotificationManager manger = (NotificationManager) context
.getSystemService(Context.NOTIFICATION_SERVICE);
Notification notification = new Notification(R.drawable.ic_launcher,
"Combi Note", System.currentTimeMillis());
PendingIntent contentIntent = PendingIntent.getActivity(context,
NOTIFICATION_ID, new Intent(context,
AlarmReceiver.class), 0);
Bundle extras = intent.getExtras();
String title = extras.getString("title");
String note = extras.getString("note");
notification.setLatestEventInfo(context, note, title, contentIntent);
notification.flags = Notification.FLAG_INSISTENT;
notification.defaults |= Notification.DEFAULT_SOUND;
manger.notify(NOTIFICATION_ID, notification);
}
};
Calendar.set(Calendar.MONTH, month)
Expects a 0-based value. 11 is december.
You are setting an alarm for 5/5/2011, this date has passed so it is executed immediately.
When you receive a instance of Calendar, I think that the system automatically fills in the current date & time. So change only what you need to change (I.E if you want to send a notification in 5 days, change the day only in the calendar instance)
By the way, when clicking the notification it will, again, call your BroadcastReceiver and this time the intent won't have the extras you have put in it while in the activity. When clicking the notification, you should launch an activity - not a broadcast receiver.
I currently have an app which, when a button is pressed, and after a certain period of time, a statusbar notification is set.
Everything works fine apart from the fact if the user does not have the application open, when the notification appears, the app also reopens. This is not what i would like to happen. I would like the notification to appear on it's own (wherever the user is).
On my button press i use:
// get a Calendar object with current time
Calendar cal = Calendar.getInstance();
// add minutes to the calendar object
cal.add(Calendar.SECOND, time);
Intent alarmintent = new Intent(getApplicationContext(), AlarmReceiver.class);
alarmintent.putExtras(bundle);
// In reality, you would want to have a static variable for the request code instead of 192837
PendingIntent sender = PendingIntent.getBroadcast(getApplicationContext(), HELLO_ID, alarmintent, 0);
// Get the AlarmManager service
AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
am.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), sender);
This calls my AlarmReceiver.class, which uses this code to call my notification class:
Intent myIntent = new Intent(context, Note.class);
myIntent.putExtras(bundle2);
myIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TOP);
context.startActivity(myIntent);
notification.class:
public class Note extends Activity {
/** Called when the activity is first created. */
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
String ns = Context.NOTIFICATION_SERVICE;
final NotificationManager mNotificationManager = (NotificationManager) getSystemService(ns);
int icon = R.drawable.launcher;
CharSequence tickerText = "Remind Me!";
long when = System.currentTimeMillis();
final Notification notification = new Notification(icon, tickerText, when);
notification.flags |= Notification.FLAG_AUTO_CANCEL | Notification.FLAG_NO_CLEAR;
final Context context = getApplicationContext();
CharSequence contentTitle = "Remind Me!";
CharSequence contentText = param1;
Intent notificationIntent = new Intent(context, Completed.class);
PendingIntent contentIntent = PendingIntent.getActivity(context, 0, notificationIntent, 0);
notification.setLatestEventInfo(context, contentTitle, contentText, contentIntent);
mNotificationManager.notify(HELLO_ID, notification);
HELLO_ID++;
}
}
This is the expected result, as the Intent you create in your AlarmReceiver class explicitly launches your Note Activity.
Why not simply create the Notification in your AlarmReceiver? (rather than launching your activity)
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.