I have a simple application (custom calendar). Every time a user creates event a new AlarmManager with custom broadcast receiver is created to call a notification 5 minuts before the event start. When that time come and user click on the notification a simple activity just shows the events info.
What is the problem: When i run app and create the event for the first time, everything works fine. When user click notification the correct one is displayed. But, when I create the second event, the problem occurs. When the notification for second notification is displayed, it looks fine (the correct information is shown in notification bar), but when i click it the first created event is shown. The same with third, fourth ...
how alarm manager is created, this is located in the activity that create event...
if (hasAlarm) {
Bundle bundle = new Bundle();
bundle.putString("name", eventName);
bundle.putLong("time", dateStart);
bundle.putString("desc", eventDescription);
bundle.putString("location", eventLocation);
bundle.putLong("end", dateEnd);
bundle.putString("username", username);
bundle.putString("password", password);
bundle.putString("mailServer", mailServer);
Intent alarmIntent = new Intent(this, AlarmReceiver.class);
alarmIntent.putExtras(bundle);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this,
0, alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC_WAKEUP, dateStart
- (1000 * 60 * 5), pendingIntent);
}
and custom broadcast receiver ...
public class AlarmReceiver extends BroadcastReceiver {
private static int id = 0;
#Override
public void onReceive(Context context, Intent intent) {
Bundle bundle = intent.getExtras();
String desc = bundle.getString("desc");
long time = bundle.getLong("time");
String name = bundle.getString("name");
for (String key : bundle.keySet()) {
Log.d("Bundle ALARM REVEIVER", key + " = \"" + bundle.get(key)
+ "\"");
}
long[] vibrate = { 0, 100, 200, 300 };
Uri alarmSound = RingtoneManager
.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder builder = new NotificationCompat.Builder(
context).setSmallIcon(R.drawable.stat_notify_chat)
.setContentTitle("Upcoming event: " + name)
.setContentText(desc).setWhen(time).setVibrate(vibrate)
.setSound(alarmSound);
Intent viewEvent = new Intent(context, ViewEvent.class);
viewEvent.putExtras(intent.getExtras());
PendingIntent contentIntent = PendingIntent.getActivity(context, 0,
viewEvent, 0);
builder.setContentIntent(contentIntent);
NotificationManager mNotificationManager = (NotificationManager) context
.getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(id++, builder.build());
}
}
I found where the problem was ...as we can see in the documentation, we need to add PendingIntent.FLAG_UPDATE_CURRENT for broadcast receiver as well, so the full implementation looks like
Intent viewEvent = new Intent(context, ViewEvent.class);
viewEvent.putExtras(intent.getExtras());
PendingIntent contentIntent = PendingIntent.getActivity(context, 0,
viewEvent, PendingIntent.FLAG_UPDATE_CURRENT);
builder.setContentIntent(contentIntent);
Related
Not sending notification at selected time, when I ran my code, directly showed notification
and showed error as well
Here is the error message: E/NotificationManager: notifyAsUser: tag=null, id=12345, user=UserHandle{0}
I thought the error message was due to Build.VERSION.SDK_INT, but after adding that, the error message is still there.
Place all of these under onCreate:
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, 13);
calendar.set(Calendar.MINUTE,9)
;
Intent intent = new Intent ();
intent.setAction("com.example.Broadcast");
PendingIntent contentIntent = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
// PendingIntent alarmIntent = PendingIntent.getBroadcast(this,0, intent,0);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY, contentIntent);
and here is the extend.
public class wakeReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
setNotification(context);
}
protected void setNotification(Context context){
PendingIntent contentIntent = PendingIntent.getActivity(context, 0,
new Intent(context, MainActivity.class), 0);
String ChannelId = "12345";
int uniID = 12345;
NotificationCompat.Builder builder = new NotificationCompat.Builder(context,ChannelId )
.setSmallIcon(R.mipmap.ic_launcher_round)
.setContentTitle("Hi")
.setAutoCancel(true)
.setWhen(System.currentTimeMillis())
.setContentText("Please Rate.");
builder.setContentIntent(contentIntent);
//
// Send notification to your device
NotificationManager manager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
builder.setChannelId("com.myApp");
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(
"com.myApp",
"My App",
NotificationManager.IMPORTANCE_DEFAULT
);
if (manager != null) {
manager.createNotificationChannel(channel);
}
}
manager.notify(uniID, builder.build());
}
}
Can someone please help me with this?
You are very confused.
In your code you call NotificationManager.notify(). This will show the Notification immediately.
You do:
Intent intent = new Intent(this, MainActivity.class);
PendingIntent alarmIntent = PendingIntent.getBroadcast(this,0, intent,0);
This won't work. You have created a PendingIntent which will be sent via broadcast using an Intent that is for an Activity! What do you want to happen? Do you want an Activity to be launched or do you want a BroadcastReceiver to be triggered?
I think what you want to do is as follows:
Create an Intent for a BroadcastReceiver, wrap that in a PendingIntent using getBroadcast() and pass that to the AlarmManager so that the broadcast Intent will be set at some future time.
Create a class that extends BroadcastReceiver. In onReceive() create the Notification and call NotificationManager.notify() to post the Notification. In the Notification you can set a PendingIntent that opens your Activity so that if the user clicks on the Notification your Activity will be launched. To do this, call PendingIntent.getActivity() and pass an Intent that contains MainActivity.class.
When users click the icon of my app on the Notification bar, users will be redirected to my app.
Can anyone provide sample code? How to subscribe to the click event, and the redirection.
Update
My application might be using some services that cause the display of icon on Notification bar.
My application is calling SetForeground, not getBroadcast().
Update 2
how can I redirect users to the last Activity rather than the hard-code activity? For example, the last Activity might be different when users navigate to different activity.
Notification click event in xamarin forms
It's a sample from my app, it works. I think you can do somthing similar.
public class AlarmReceiver extends BroadcastReceiver {
public final static String NOTIF_TEXT = AlarmSetActivity.class.getPackage() + ".NOTIF_TEXT";
private String notifText;
#Override
public void onReceive(Context context, Intent intent) {
notifText = intent.getExtras().getString(NOTIF_TEXT);
//().getExtras().getString(NOTE_BODY);
Toast.makeText(context, "Notification from " + R.string.app_name,
Toast.LENGTH_LONG).show();
buildNotification(context);
}
private void buildNotification(Context context) {
NotificationManager notificationManager = (NotificationManager) context
.getSystemService(Context.NOTIFICATION_SERVICE);
String channelId = "default_channel_id";
String channelDescription = "Default Channel";
Notification.Builder builder = new Notification.Builder(context);
Intent intent = new Intent(context, **EditorActivity.class**);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0,
intent, 0);
builder.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle(context.getString(R.string.notificTitle)).setContentText(notifText)
.setContentInfo(context.getString(R.string.notificInfo)).setTicker(context.getString(R.string.notifTicker))
.setLights(0xFFFF0000, 500, 500)
//.setChannelId(id)
.setContentIntent(pendingIntent).setAutoCancel(true);
Notification notification = builder.build();
//notification.so
notificationManager.notify(2, notification);
}
}
And:
private void setAlarm(Calendar targetCal) {
mTimeTextView.setText(R.string.alarm_on);
mTimeTextView.append(String.valueOf(targetCal.getTime()));
Intent intent = new Intent(getApplicationContext(), AlarmReceiver.class);
intent.putExtra(AlarmReceiver.NOTIF_TEXT,notificationText);
PendingIntent pendingIntent = PendingIntent.getBroadcast(
getApplicationContext(), RQS_TIME, intent, 0);
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC_WAKEUP, targetCal.getTimeInMillis(),
pendingIntent);
}
I am using the code of PingService.java https://github.com/android/platform_development/blob/master/samples/training/notify-user/src/com/example/android/pingme/PingService.java
PingService.Java
/**
* PingService creates a notification that includes 2 buttons: one to snooze the
* notification, and one to dismiss it.
*/
public class PingService extends IntentService {
private NotificationManager mNotificationManager;
private String mMessage;
private int mMillis;
NotificationCompat.Builder builder;
public PingService() {
// The super call is required. The background thread that IntentService
// starts is labeled with the string argument you pass.
super("com.example.android.pingme");
}
#Override
protected void onHandleIntent(Intent intent) {
// The reminder message the user set.
mMessage = intent.getStringExtra(CommonConstants.EXTRA_MESSAGE);
// The timer duration the user set. The default is 10 seconds.
mMillis = intent.getIntExtra(CommonConstants.EXTRA_TIMER,
CommonConstants.DEFAULT_TIMER_DURATION);
NotificationManager nm = (NotificationManager)
getSystemService(NOTIFICATION_SERVICE);
String action = intent.getAction();
// This section handles the 3 possible actions:
// ping, snooze, and dismiss.
if(action.equals(CommonConstants.ACTION_PING)) {
issueNotification(intent, mMessage);
} else if (action.equals(CommonConstants.ACTION_SNOOZE)) {
nm.cancel(CommonConstants.NOTIFICATION_ID);
Log.d(CommonConstants.DEBUG_TAG, getString(R.string.snoozing));
// Sets a snooze-specific "done snoozing" message.
issueNotification(intent, getString(R.string.done_snoozing));
} else if (action.equals(CommonConstants.ACTION_DISMISS)) {
nm.cancel(CommonConstants.NOTIFICATION_ID);
}
}
private void issueNotification(Intent intent, String msg) {
mNotificationManager = (NotificationManager)
getSystemService(NOTIFICATION_SERVICE);
// Sets up the Snooze and Dismiss action buttons that will appear in the
// expanded view of the notification.
Intent dismissIntent = new Intent(this, PingService.class);
dismissIntent.setAction(CommonConstants.ACTION_DISMISS);
PendingIntent piDismiss = PendingIntent.getService(this, 0, dismissIntent, 0);
Intent snoozeIntent = new Intent(this, PingService.class);
snoozeIntent.setAction(CommonConstants.ACTION_SNOOZE);
PendingIntent piSnooze = PendingIntent.getService(this, 0, snoozeIntent, 0);
// Constructs the Builder object.
builder =
new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_stat_notification)
.setContentTitle(getString(R.string.notification))
.setContentText(getString(R.string.ping))
.setDefaults(Notification.DEFAULT_ALL) // requires VIBRATE permission
/*
* Sets the big view "big text" style and supplies the
* text (the user's reminder message) that will be displayed
* in the detail area of the expanded notification.
* These calls are ignored by the support library for
* pre-4.1 devices.
*/
.setStyle(new NotificationCompat.BigTextStyle()
.bigText(msg))
.addAction (R.drawable.ic_stat_dismiss,
getString(R.string.dismiss), piDismiss)
.addAction (R.drawable.ic_stat_snooze,
getString(R.string.snooze), piSnooze);
/*
* Clicking the notification itself displays ResultActivity, which provides
* UI for snoozing or dismissing the notification.
* This is available through either the normal view or big view.
*/
Intent resultIntent = new Intent(this, ResultActivity.class);
resultIntent.putExtra(CommonConstants.EXTRA_MESSAGE, msg);
resultIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
// Because clicking the notification opens a new ("special") activity, there's
// no need to create an artificial back stack.
PendingIntent resultPendingIntent =
PendingIntent.getActivity(
this,
0,
resultIntent,
PendingIntent.FLAG_UPDATE_CURRENT
);
builder.setContentIntent(resultPendingIntent);
startTimer(mMillis);
}
private void issueNotification(NotificationCompat.Builder builder) {
mNotificationManager = (NotificationManager)
getSystemService(NOTIFICATION_SERVICE);
// Including the notification ID allows you to update the notification later on.
mNotificationManager.notify(CommonConstants.NOTIFICATION_ID, builder.build());
}
private void startTimer(int millis) {
Log.d(CommonConstants.DEBUG_TAG, getString(R.string.timer_start));
try {
Thread.sleep(millis);
} catch (InterruptedException e) {
Log.d(CommonConstants.DEBUG_TAG, getString(R.string.sleep_error));
}
Log.d(CommonConstants.DEBUG_TAG, getString(R.string.timer_finished));
issueNotification(builder);
}
}
Intent mServiceIntent = new Intent(context.getApplicationContext(), PingService.class);
mServiceIntent.putExtra(Const.EXTRA_MESSAGE, "" + msg);
mServiceIntent.putExtra(Const.ID, reminder_id);
startService(mServiceIntent);
And passing the data to issueNotification method for Action Button intent like
Intent dismissIntent = new Intent(this, PingService.class);
dismissIntent.setAction(CommonConstants.ACTION_DISMISS);
dismissIntent.putExtra(CommonConstants.ID, reminder_id);
PendingIntent piDismiss = PendingIntent.getService(this, 0, dismissIntent, 0);
Intent snoozeIntent = new Intent(this, PingService.class);
snoozeIntent.setAction(CommonConstants.ACTION_SNOOZE);
snoozeIntent.putExtra(CommonConstants.ID, reminder_id);
PendingIntent piSnooze = PendingIntent.getService(this, 0, snoozeIntent, 0);
But i am not getting the ID at the time of Click event of the Action button from issueNotification and passing the intent in onHandleIntent method
It is automatically set to 1 after Notification generation and i am not able to cancel that notification due to wrong notification id set into putExtra of PendingIntent
I am trying with passing different flag like
PendingIntent piDismiss = PendingIntent.getService(this, 0, taken_intent, PendingIntent.FLAG_UPDATE_CURRENT);
Please help me out i am trying it since long time but not getting the correct id.
My putExtra is override with 1 somehow....
Thank you in advnace
After so much reasearching finally got a solution that i need to pass different code in pending intent like
PendingIntent piDismiss = PendingIntent.getBroadcast(this, CommonConstants.NOTIFICATION_ID, dismissIntent, 0);
which is dynamic one and unique one in each Action Button case.
Use Broadcast receiver to achieve this instead of Service ( getBroadcast ).
Thank you.
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 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.