I have a notifications system working that a service is scheculing then and the notifications are working fine.
I have some notifications that require user input/action.
Here is the code where I build my notification:
public int onStartCommand(Intent intent, int flag, int startId)
{
super.onStartCommand(intent , flag, startId);
Uri uri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
Context context = this.getApplicationContext();
notificationManager = (NotificationManager)context.getSystemService(context.NOTIFICATION_SERVICE);
Intent mIntent = new Intent(this, MainActivity.class);
pendingIntent = PendingIntent.getActivity(context, 0, mIntent, PendingIntent.FLAG_UPDATE_CURRENT);
Notification builder = null;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN ) {
builder = new Notification.Builder(this)
.setContentTitle(Utils.Title)
.setContentText(Utils.Body)
.setSmallIcon(R.drawable.ic_launcher)
.addAction(0, Utils.button1Value, pendingIntent)
.addAction(0, Utils.button2Value, pendingIntent)
.setSound(uri)
.setContentIntent(pendingIntent)
.build();
}
notificationManager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
notificationManager.notify(Utils.NotificationID, builder);
return START_STICKY;
My question is: How do I get what button in the notification user clicked? In other words, how can I create some sort of button listener for those 2 actions in the notification?
Also, how can I stack my notifications so they don`t appear all separated? I have read on Google API that I need to use .setGroup, but that is not working. Can anyone share some example of notification stacking ?
********** Added *************
final static String GROUP_KEY = "myGroup"; // added String to identify the group
public int onStartCommand(Intent intent, int flag, int startId)
{
super.onStartCommand(intent , flag, startId);
Uri uri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
Context context = this.getApplicationContext();
notificationManager = (NotificationManager)context.getSystemService(context.NOTIFICATION_SERVICE);
Intent mIntent = new Intent(this, MainActivity.class);
pendingIntent = PendingIntent.getActivity(context, 0, mIntent, PendingIntent.FLAG_UPDATE_CURRENT);
Notification builder = null;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN ) {
builder = new Notification.Builder(this)
.setContentTitle(Utils.Title)
.setContentText(Utils.Body)
.setSmallIcon(R.drawable.ic_launcher)
.setGroup(GROUP_KEY) // added group for Stacking
.addAction(0, Utils.button1Value, pendingIntent)
.addAction(0, Utils.button2Value, pendingIntent)
.setSound(uri)
.setContentIntent(pendingIntent)
.build();
}
notificationManager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
notificationManager.notify(0, builder); // ID is always the same because the notifications are all stacking into one, tried with unique ID not working either
return START_STICKY;
For button listener problem:
Notification action will trigger that pendingIntent, so just put your custom intent into it. Each text should have a different pendingIntent so that you can distinguish it.
public int onStartCommand(Intent intent, int flag, int startId) {
//......
Intent mIntent1 = new Intent(this, MainActivity.class);
mIntent1.setAction("clickAc1");
PendingIntent pendingIntent1 = PendingIntent.getActivity(context, 0, mIntent1, PendingIntent.FLAG_UPDATE_CURRENT);
Intent mIntent2 = new Intent(this, MainActivity.class);
mIntent2.setAction("clickAc2");
PendingIntent pendingIntent2 = PendingIntent.getActivity(context, 0, mIntent2, PendingIntent.FLAG_UPDATE_CURRENT);
Intent it = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, it, PendingIntent.FLAG_UPDATE_CURRENT);
Notification builder = null;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN) {
builder = new Notification.Builder(this)
.setContentTitle("Title")
.setContentText("Text")
.setSmallIcon(R.drawable.your_logo)
.addAction(0, "ac1", pendingIntent1)
.addAction(0, "ac2", pendingIntent2)
.setSound(uri)
.setContentIntent(pendingIntent)
.build();
}
and when user click the text ac1, then you can handle it in MainActivity(or other context you want.
//MainActivity
#Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
Log.d("probe","onNewIntent:"+intent.getAction());
//response your click event by case intent.getAction(),
//it will be `clickAc1` or `clickAc2`, the string you write down in intent.setAction
}
If you use custom RemoteViews, you can follow this:
Intent intent = new Intent("Your Custom intent string, like com.yourpackage.ClickButtonXXX");
pendingIntent = PendingIntent.getService(getApplicationContext(),
yourRequestCode, intent, PendingIntent.FLAG_UPDATE_CURRENT);
mRemoteViews.setOnClickPendingIntent(R.id.yourViewId, pendingIntent);
then your can response it with override Service.onStartCommand(Intent intent, int flags, int startId), case intent.getAction(); to distinguish different button.
Stacking messages:
I found this in this notification history article:
.setGroup(GROUP_KEY_MESSAGES) // added group for Stacking
.setGroupSummary(true)
.setContentTitle(count+" new notes")
.setStyle(new NotificationCompat.BigTextStyle().setSummaryText(count+" more"))
.build();
count++;
If you use Notification, change NotificationCompat.BigTextStyle() to Notification.BigTextStyle().
I think this may be what you want.
The roll-up notification cheats a little bit.
Related
How would I stop the foreground service using the notification it creates in the class?
Intent stopnotificationIntent = new Intent(this, HelloIntentService.class);
//Not sure which is the current action to set
stopnotificationIntent.setAction("ACTION.STOPFOREGROUND_ACTION");
PendingIntent pIntent = PendingIntent.getService(this, 0, stopnotificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, channelId)
.addAction(0, "Cancel", pIntent);
startForeground(1111, notificationBuilder.build());
the button is created from .addAction and I want to stop that current foreground service
String ACTION_STOP_SERVICE= "STOP";
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (ACTION_STOP_SERVICE.equals(intent.getAction())) {
Log.d(Statics.LOG_TAG,"called to cancel service");
stopSelf();
}
Intent stopSelf = new Intent(this, HelloIntentService.class);
stopSelf.setAction(ACTION_STOP_SERVICE);
PendingIntent pStopSelf = PendingIntent
.getService(this, 0, stopSelf
,PendingIntent.FLAG_CANCEL_CURRENT); // That you should change this part in your code
notification = new NotificationCompat.Builder(this, CHANNEL_ID)
.setContentText("Bla Bla Bla")
.setSmallIcon(R.drawable.ic_notification)
.setContentIntent(pendingNotificationIntent)
.addAction(R.drawable.xxxx,"Close", pStopSelf)
.setSound(null)
.build();
startForeground(REQUEST_CODE, notification);
}
I have implemented push notifications for my android app .I am able to show multiple notification in notification bar but only one notification work at a time.If I click on any notification it will start the intended activity and that particular notification will disappear from notification bar but other notification for same app will become dead.Nothing happens when I click on rest of the notification.My code for handling notification is following:
private void sendNotification(String msg, String msgId, int notificationId,
int type) {
// SharedPreferences prefs = getSharedPreferences(
// Utility.PREFS_NAME, MODE_PRIVATE);
mNotificationManager = (NotificationManager) this
.getSystemService(Context.NOTIFICATION_SERVICE);
Intent intent = null;
Bundle bundle = new Bundle();
if (type == 1) {
intent = new Intent(this, Activity_Received.class);
// bundle.putString("greeting", msg);
bundle.putString(Utility.KEY_MESSAGE_DELIVERY_ID, msgId);
} else if (type == 2) {
intent = new Intent(this, Activity_Birth.class);
} else {
return;
}
bundle.putBoolean(Utility.KEY_IS_NOTIFICATION, true);
intent.putExtras(bundle);
PendingIntent contentIntent;
// The stack builder object will contain an artificial back stack
// for
// the
// started Activity.
// This ensures that navigating backward from the Activity leads out
// of
// your application to the Home screen.
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
// Adds the back stack for the Intent (but not the Intent itself)
if (type == 1) {
stackBuilder.addParentStack(Activity_Received.class);
} else {
stackBuilder.addParentStack(Activity_Birth.class);
}
// Adds the Intent that starts the Activity to the top of the stack
stackBuilder.addNextIntent(intent);
contentIntent = stackBuilder
.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT
| PendingIntent.FLAG_ONE_SHOT);
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(
this)
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle("WishnGreet")
.setStyle(new NotificationCompat.BigTextStyle().bigText(msg))
.setContentText(msg)
.setAutoCancel(true)
.setSound(
RingtoneManager
.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION));
mBuilder.setContentIntent(contentIntent);
mNotificationManager.notify(notificationId, mBuilder.build());
}
Please advise what do I need to change in above code so that I can click on every notification that I receive for my application and start the intended activity.
Pass a different notificationId for each different notification you want to have in the method: sendNotification(String msg, String msgId, int notificationId, int type)
I have wrote the following method which is working in case of multiple notifications.
private void pushNotification(String msg, String msgId, int notificationId,
int type) {
mNotificationManager = (NotificationManager) this
.getSystemService(Context.NOTIFICATION_SERVICE);
Bundle bundle = new Bundle();
bundle.putString(Utility.KEY_MESSAGE_DELIVERY_ID, msgId);
bundle.putBoolean(Utility.KEY_IS_NOTIFICATION, true);
Intent intent = new Intent(this, Activity_ReceivedGreeting.class);
intent.putExtras(bundle);
PendingIntent contentIntent = PendingIntent.getActivity(
getApplicationContext(), notificationId, intent,
PendingIntent.FLAG_ONE_SHOT);
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(
this)
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle("WishnGreet")
.setStyle(new NotificationCompat.BigTextStyle().bigText(msg))
.setContentText(msg)
.setAutoCancel(true)
.setSound(
RingtoneManager
.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION));
mBuilder.setContentIntent(contentIntent);
mNotificationManager.notify(notificationId, mBuilder.build());
}
The key was to remove the FLAGS on pending intent.
I have prepared a simple test app which posts a notification on a button click:
The source code from MainActivity.java creating the notification is displayed below:
Button showButton = (Button) findViewById(R.id.show);
showButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
Intent appIntent = new Intent(mContext, MainActivity.class);
appIntent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
appIntent.putExtra("my_data", 12345);
String question = getString(R.string.the_question);
PendingIntent contentIntent = PendingIntent.getActivity(mContext, 0, appIntent, PendingIntent.FLAG_UPDATE_CURRENT);
Notification notification = new NotificationCompat.Builder(mContext)
.setContentTitle(question)
.setContentText(question)
.setTicker(question)
.setWhen(System.currentTimeMillis())
.setContentIntent(contentIntent)
.setDefaults(Notification.DEFAULT_ALL)
.setAutoCancel(true)
.setSmallIcon(R.drawable.ic_launcher)
.build();
mManager.notify(NOTIFY_ID, notification);
}
});
My question is: how to modify the notification, so that the user is asked a Yes/No question (in this case: "Do you want to open the car?") and - after she selects Yes or No to launch the same app and run a corresponding method in it (in this case: openCar() or closeCar() method).
I probably should use NotificationCompat.Action.Builder - but how exactly?
Also I am not really sure if this code is the correct code for launching an app from notification and what flags should I use:
Intent appIntent = new Intent(mContext, MainActivity.class);
appIntent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
And finally I wonder if hardcodidng some random number in NOTIFY_ID is the correct way when posting notifications?
Here is a source code I used for notification with Login/Register action.
private void sendNotification(String message, String title) {
try {
Intent intent = new Intent(this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent,
PendingIntent.FLAG_ONE_SHOT);
Intent secondActivityIntent = new Intent(this, SecondActivity.class);
PendingIntent secondActivityPendingIntent = PendingIntent.getActivity(this, 0 , secondActivityIntent, PendingIntent.FLAG_ONE_SHOT);
Intent thirdActivityIntent = new Intent(this, ThridActivity.class);
PendingIntent thirdActivityPendingIntent = PendingIntent.getActivity(this, 0 , thirdActivityIntent, PendingIntent.FLAG_ONE_SHOT);
Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_3d_rotation_white_36dp)
.setContentTitle(title)
.setContentText(message)
.addAction(R.drawable.ic_lock_open_cyan_600_24dp,"Login",secondActivityPendingIntent)
.addAction(R.drawable.ic_lock_pink_700_24dp,"Register",thirdActivityPendingIntent)
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setContentIntent(pendingIntent);
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0 /* ID of notification */, notificationBuilder.build());
} catch (Exception e) {
e.printStackTrace();
}
}
To use it: simply call this method sendNotification(String yourMessage, String yourTitle)
e.g. sendNotification("Hello Message", "Hello Title")
Here is a snapshot of the output
Notify user on pending Intent.. an example is here..
public void notifyUser() {
NotificationManager notificationManager = (NotificationManager) this
.getSystemService(Context.NOTIFICATION_SERVICE);
Intent intent = new Intent(HappyActivity.this, NotificationDialog.class);
intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
// use the flag FLAG_UPDATE_CURRENT to override any notification already
// there
pendingIntent = PendingIntent.getActivity(this, 0, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
Notification notification = new Notification(R.drawable.ic_launcher,
"Question.....?????", System.currentTimeMillis());
notification.flags = Notification.FLAG_AUTO_CANCEL
| Notification.DEFAULT_LIGHTS | Notification.DEFAULT_SOUND;
notification.setLatestEventInfo(this, "title",
"Explanation of question..", pendingIntent);
// 10 is a random number I chose to act as the id for this notification
notificationManager.notify(10, notification);
}
I successfully created an activity which starts a service which by turn shows a notification like this
public int onStartCommand(Intent intent, int flags, int startId){
String notificationText = "working"
myNotification = new NotificationCompat.Builder(getApplicationContext())
.setContentTitle("test")
.setContentText(notificationText)
.setTicker("Notification!")
.setWhen(System.currentTimeMillis())
.setDefaults(Notification.DEFAULT_SOUND)
.setAutoCancel(true)
.setSmallIcon(R.drawable.ic_launcher)
.build();
//FOLLOWING TECHNIQUE IS DEPRECATED
/* PendingIntent contentIntent = PendingIntent.getActivity(this, 0, intent, 0);
myNotification.setLatestEventInfo(context, contentTitle, contentText, contentIntent); */
myNotification.flags |= Notification.FLAG_NO_CLEAR;
myNotification.flags = Notification.FLAG_ONGOING_EVENT;
notificationManager.notify(1, myNotification);
return START_STICKY;
}
I know there are other questions related to this one BUT they all use setLatestEventInfo which is deprecated
And this is what I call from another activity:
protected void beginBackgroundSer(){
intentService = new Intent(this, Service.class);
intentService.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
this.startService(intentService);
}
So what I'd like is to resume the activity whenever I click the notification by non-deprecated methods. Thank you very much for your help.
You can create a notification by using the following steps.
Create a notification id for the future reference to update the notification by notification manager.
// Notification ID to allow for future updates
private static final int MY_NOTIFICATION_ID = 1;
Create the text elements for the notification.
// Notification Text Elements
private final CharSequence tickerText = "This is a Really, Really, Super Long Notification Message!";
private final CharSequence contentTitle = "Notification";
private final CharSequence contentText = "You've Been Notified!";
Define the notification Action elements i.e. when the user clicks on the view in the notification drawer what action happens? We use intents for handling this.
// Notification Action Elements
private Intent mNotificationIntent;
private PendingIntent mContentIntent;
You can also define sound and vibration for this notification.
// Notification Sound and Vibration on Arrival
private Uri soundURI = Uri
.parse("android.resource://com.examples.Notification.StatusBarWithCustomView/"
+ R.raw.alarm_rooster);
private long[] mVibratePattern = { 0, 200, 200, 300 };
Create the notification using the Notification.Builder class. Do this in your onCreate()
mNotificationIntent = new Intent(getApplicationContext(),
YourActivity.class);
mContentIntent = PendingIntent.getActivity(getApplicationContext(), 0,
mNotificationIntent, Intent.FLAG_ACTIVITY_NEW_TASK);
// Build the Notification
Notification.Builder notificationBuilder = new Notification.Builder(
getApplicationContext())
.setTicker(tickerText)
.setSmallIcon(android.R.drawable.stat_sys_warning)
.setAutoCancel(true)
.setContentIntent(mContentIntent)
.setSound(soundURI)
.setVibrate(mVibratePattern)
.setContent(mContentView);
// Pass the Notification to the NotificationManager:
NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(MY_NOTIFICATION_ID,
notificationBuilder.build());
From the documentations
public NotificationCompat.Builder setContentIntent (PendingIntent intent) - Supply a PendingIntent to send when the notification is clicked. If you do not supply an intent, you can now add PendingIntents to individual views to be launched when clicked by calling RemoteViews.setOnClickPendingIntent(int,PendingIntent). Be sure to read Notification.contentIntent for how to correctly use this.
So you can use setContentIntent(PendingIntent intent) method something like
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, intent, 0);
myNotification = new NotificationCompat.Builder(getApplicationContext())
.setContentTitle("test")
.setContentText(notificationText)
.setTicker("Notification!")
.setWhen(System.currentTimeMillis())
.setDefaults(Notification.DEFAULT_SOUND)
.setAutoCancel(true)
.setSmallIcon(R.drawable.ic_launcher)
.setContentIntent(contentIntent) //added this new line
.build();
notificationManager.notify(1, myNotification);
I am trying to get my on going notification to have a button, when clicked it should call my service which is controlling audio playback.
Here is my notification with the intent
Intent intent = new Intent(context, AudioStreamService.class);
Random generator = new Random();
PendingIntent i = PendingIntent.getActivity(context, 579, intent,PendingIntent.FLAG_UPDATE_CURRENT);
final NotificationCompat.Builder builder = new NotificationCompat.Builder(context)
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle(title)
.setContentText(text)
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setLargeIcon(picture)
.setTicker(ticker)
.setNumber(number)
.setOngoing(true)
.addAction(
R.drawable.ic_action_stat_reply,
res.getString(R.string.action_reply),
i);
notify(context, builder.build());
Here is the on start for my service
public int onStartCommand(Intent intent, int flags, int startId) {
Log.e("APP ID", "APP ID - service called ");
if(isPlaying){
stop();
}
else {
play();
}
return Service.START_STICKY;
}
The log is never triggered when called from the action in the notification. But the service is used by a button in the app and works fine. Log gets called as do commands below.
Use :
PendingIntent pendingIntent = PendingIntent.getService(context, 579, intent,PendingIntent.FLAG_UPDATE_CURRENT);
instead of :
PendingIntent pendingIntent = PendingIntent.getActivity(context, 579, intent,PendingIntent.FLAG_UPDATE_CURRENT);
^^ This is used to start an activity from the notification.