I create several notifications like this:
public class NotificationCreator {
Context context;
int c = 0;
public NotificationCreator(final Context context) {
this.context = context;
}
void create() {
String text = "" + c + " " + new Date().toGMTString();
// Intent
Intent intent = new Intent(context, SecondActivity.class);
intent.putExtra(SecondActivity.KEY, text);
Intent[] intents = new Intent[1];
intents[0] = intent;
PendingIntent pendingIntent = PendingIntent.getActivities(
context,
c,
intents,
PendingIntent.FLAG_CANCEL_CURRENT);
// Build notification
NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
builder.setSmallIcon(R.drawable.notification);
builder.setContentTitle("Test");
builder.setContentText(text);
// builder.setGroup("");
builder.setContentIntent(pendingIntent);
Notification notification = builder.build();
// Send notification
NotificationManager notificationManager = (NotificationManager)
context.getSystemService(NOTIFICATION_SERVICE);
notificationManager.notify(c, notification);
c++;
}
}
The outcome on Android 7 is:
The system has grouped all notifications.
When I set explicitly on the builder:
builder.setGroup("myGroup");
the outcome is:
The notifications are not grouped, but all shown individually, despite all having the same group key.
Is this the expected behaviour?
In the first case (grouped), can I determine what happens when the user clicks on the grouped notification? The individual intents seem to be ignored and just the app opened.
Had the same problem and figured it out by using a "Summary notification". Basically, you create one regular notification with the desired group and the "Summary notification" with the same group and setGroupSummary(true).
More here https://blog.stylingandroid.com/nougat-bundled-notifications/
Related
I have a notification in my app with the following code:
public class NewMessageNotification {
private static final String NOTIFICATION_TAG = "NewMessage";
public static void notify(final Context context,
final String exampleString,final String boday ,final int number) {
final Resources res = context.getResources();
// This image is used as the notification's large icon (thumbnail).
// TODO: Remove this if your notification has no relevant thumbnail.
final Bitmap picture = BitmapFactory.decodeResource(res, R.drawable.billsms);
final String ticker = exampleString;
final String title = res.getString(
R.string.new_message_notification_title_template, exampleString);
final String text = boday;
final NotificationCompat.Builder builder = new NotificationCompat.Builder(context)
// Set appropriate defaults for the notification light, sound,
// and vibration.
// Set required fields, including the small icon, the
// notification title, and text.
.setSmallIcon(R.drawable.billsms)
.setContentTitle(title)
.setContentText(text)
// All fields below this line are optional.
// Use a default priority (recognized on devices running Android
// 4.1 or later)
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
// Provide a large icon, shown with the notification in the
// notification drawer on devices running Android 3.0 or later.
.setLargeIcon(picture)
// Set ticker text (preview) information for this notification.
.setTicker(ticker)
// Show a number. This is useful when stacking notifications of
// a single type.
.setNumber(number)
// If this notification relates to a past or upcoming event, you
// should set the relevant time information using the setWhen
// method below. If this call is omitted, the notification's
// timestamp will by set to the time at which it was shown.
// TODO: Call setWhen if this notification relates to a past or
// upcoming event. The sole argument to this method should be
// the notification timestamp in milliseconds.
//.setWhen(...)
// Set the pending intent to be initiated when the user touches
// the notification.
.setContentIntent(
PendingIntent.getActivity(
context,
0,
new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.google.com")),
PendingIntent.FLAG_UPDATE_CURRENT))
// Show expanded text content on devices running Android 4.1 or
// later.
.setStyle(new NotificationCompat.BigTextStyle()
.bigText(text)
.setBigContentTitle(title)
.setSummaryText("Dummy summary text"))
// Example additional actions for this notification. These will
// only show on devices running Android 4.1 or later, so you
// should ensure that the activity in this notification's
// content intent provides access to the same actions in
// another way.
.addAction(
R.drawable.ic_action_stat_share,
res.getString(R.string.action_share),
PendingIntent.getActivity(
context,
0,
Intent.createChooser(new Intent(Intent.ACTION_SEND)
.setType("text/plain")
.putExtra(Intent.EXTRA_TEXT, "Dummy text"), "Dummy title"),
PendingIntent.FLAG_UPDATE_CURRENT))
.addAction(
R.drawable.ic_action_stat_reply,
res.getString(R.string.action_reply),
null)
// Automatically dismiss the notification when it is touched.
.setAutoCancel(true);
notify(context, builder.build());
}
#TargetApi(Build.VERSION_CODES.ECLAIR)
private static void notify(final Context context, final Notification notification) {
final NotificationManager nm = (NotificationManager) context
.getSystemService(Context.NOTIFICATION_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ECLAIR) {
nm.notify(NOTIFICATION_TAG, 0, notification);
} else {
nm.notify(NOTIFICATION_TAG.hashCode(), notification);
}
}
/**
* Cancels any notifications of this type previously shown using
* .
*/
#TargetApi(Build.VERSION_CODES.ECLAIR)
public static void cancel(final Context context) {
final NotificationManager nm = (NotificationManager) context
.getSystemService(Context.NOTIFICATION_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ECLAIR) {
nm.cancel(NOTIFICATION_TAG, 0);
} else {
nm.cancel(NOTIFICATION_TAG.hashCode());
}
}
}
My notifications fires very well, but my problem is that, when I click on notification in Notification Center, it does not start my app.
Basically, after clicking on my notification nothing happens!Thanks.
Basically your Pending Intent should have your application's one of the activity components.
Intent appIntent = new Intent(context, YourActivityName.class);
PendingIntent.getActivity(context, 0, appIntent, PendingIntent.FLAG_UPDATE_CURRENT));
Similarly you can add other components like Activity, Service and Receiver.
PendingIntent.getActivity ...
PendingIntent.getBroadcast ...
PendingIntent.getService ...
Hope this helps.
I found the answer to my question.
The only change this code :
.setContentIntent(
PendingIntent.getActivity(
context,
0,
new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.google.com")),
PendingIntent.FLAG_UPDATE_CURRENT))
To this code :
.setContentIntent(
PendingIntent.getActivity(
context,
0,
new Intent(context.getApplicationContext(),MainActivity.class),
PendingIntent.FLAG_UPDATE_CURRENT))
I was wondering how to implement the onClickListener for an android notification. I am trying to implement sendText() in the notification instead of sending the user to the main activity:
public class AlertReceiver extends BroadcastReceiver {
Context mContext;
String number;
String messageList;
String name;
#Override
public void onReceive(Context context, Intent intent) {
mContext = context;
name = intent.getStringExtra("name");
messageList = intent.getStringExtra("messageList");
number = intent.getStringExtra("number");
createNotification(context, "times up " + name, "5 seconds passed!", "alert");
}
public void createNotification(Context context, String message, String messageText, String messageAlert){
PendingIntent notificIntent = PendingIntent.getActivity(context, 0, new Intent(context, MainActivity.class), 0);
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(context).setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle(message)
.setTicker(messageText)
.setContentText(messageAlert);
mBuilder.setContentIntent(notificIntent);
mBuilder.setDefaults(NotificationCompat.DEFAULT_SOUND);
mBuilder.setAutoCancel(true);
NotificationManager mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(1, mBuilder.build());
}
public void sendText(){
//Turn string of all messages into an ArrayList in order to get one specific message at random
ArrayList<String> messagesArrayList = null;
try {
messagesArrayList = Utility.getArrayListFromJSONString(messageList);
} catch (JSONException e) {
e.printStackTrace();
}
Random rand = new Random();
//todo the following may cause a bug if there are no messages in list
int n = rand.nextInt(messagesArrayList.size());
String message = messagesArrayList.get(n);
try {
//send text message
SmsManager smsManager = SmsManager.getDefault();
smsManager.sendTextMessage(number, null, message, null, null);
Toast.makeText(mContext, "Message Sent",
Toast.LENGTH_SHORT).show();
} catch (Exception ex) {
//If text message wasn't sent attempt to send text another way (through the user's text messaging app)
// Most likely due to text message permissions not being accepted by user
Intent intent = new Intent(Intent.ACTION_SENDTO);
intent.setData(Uri.parse("smsto:" + number)); // This ensures only SMS apps respond
intent.putExtra("sms_body", message);
if (intent.resolveActivity(mContext.getPackageManager()) != null) {
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mContext.startActivity(intent);
}
}
}
}
Note the following information is not really necessary. It is mainly because stackoverflow thinks my code to text ratio is too low but also may help clarify a little bit:
The sendText() is basically a method that tries to send a pre-made text message without opening up a new activity. However, if permissions aren't there then it will open up the new activity using an intent. So in an effort to minimize amount of screens coming up and make it easiest on the user I tried to do it using the sendtext method.
Instead of creating a pendingIntent to start an Activity, you can create a pendingIntent to fire a Broadcast receiver as shown below
PendingIntent intent = PendingIntent.getBroadcast(context, 0, new Intent(context, SendTextReceiver.class), 0);
so when you click notification, it will invoke your BroadCast receiver SendTextReceiver and do your sendText logic inside it, so by this way you dont have to always start an activity and your logic will be done without an activity
If you don't want to send the user to an Activity, then you can fire a service: PendingIntent.getService(...) when user clicks on the notification and do the job to send the text there.
Try this:
public class AlarmReceiver extends BroadcastReceiver {
private static final int MY_NOTIFICATION_ID=1;
NotificationManager notificationManager;
Notification myNotification;
#Override
public void onReceive(Context context, Intent intent) {
// here DoSomething is your service name that you want to start
Intent myIntent = new Intent(context, DoSomething.class);
PendingIntent pendingIntent = PendingIntent.getService(
context,
0,
myIntent,
0);
myNotification = new NotificationCompat.Builder(context)
.setContentTitle("Exercise of Notification!")
.setContentText("Do Something...")
.setTicker("Notification!")
.setWhen(System.currentTimeMillis())
.setContentIntent(pendingIntent)
.setDefaults(Notification.DEFAULT_SOUND)
.setAutoCancel(true)
.setSmallIcon(R.drawable.ic_launcher)
.build();
notificationManager =
(NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(MY_NOTIFICATION_ID, myNotification);
}
}
I am new to android and currently learning about notifications, there's a small app I am making which is supposed to show notification later in time and should open an activity when user taps on them. I have been looking for content all over internet but can't really understand how to do both task. I am using a broadcast receiver and here's my code
Notification.Builder builder = new Notification.Builder(getActivity());
builder.setContentTitle("Remember to return");
builder.setContentText(title);
builder.setSmallIcon(R.drawable.ic_notification);
builder.setAutoCancel(true);
//NotificationCompat.Builder builder = new NotificationCompat.Builder(getActivity());
Notification notification = builder.build();
Intent notificationIntent = new Intent(getActivity(),NotificationPublisher.class);
notificationIntent.putExtra(NotificationPublisher.NOTIFICATION_ID,1);
notificationIntent.putExtra(NotificationPublisher.NOTIFICATION,notification);
PendingIntent pendingIntent = PendingIntent.getBroadcast(activity,0,notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
//long _notificationTimeInMillis = SystemClock.elapsedRealtime()+date.getTime()+getMillisFromHours(6);
long notificationTimeInMillis = SystemClock.elapsedRealtime() + 5000;
AlarmManager alarmManager = (AlarmManager)activity.getSystemService(Context.ALARM_SERVICE);
alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,notificationTimeInMillis,pendingIntent);
Toast.makeText(activity,"Notification Set",Toast.LENGTH_SHORT);
and for reciever
public class NotificationPublisher extends BroadcastReceiver {
public static String NOTIFICATION_ID = "notification-id";
public static String NOTIFICATION = "notification";
#Override
public void onReceive(Context context, Intent intent) {
NotificationManager notificationManager = (NotificationManager)
context.getSystemService(Context.NOTIFICATION_SERVICE);
Notification notification = intent.getParcelableExtra(NOTIFICATION);
int id = intent.getIntExtra(NOTIFICATION_ID, 0);
notificationManager.notify(id, notification);
}
}
Currently I am able to show notifications, what changes to I have to make so that an activity (say HomeActivity.class) opens when user clicks on notification.
You need to set a pending intent on the notification itself that will open the activity:
Notification.Builder builder = new Notification.Builder(getActivity());
builder.setContentTitle("Remember to return");
builder.setContentText(title);
builder.setSmallIcon(R.drawable.ic_notification);
builder.setAutoCancel(true);
// add these lines
PendingIntent pi = PendingIntent.getActivity(
getActivity(),
REQUEST_CODE_FOR_THIS_ONE,
new Intent(getActivity(), HomeActivity.class),
0
);
builder.setContentIntent(pi);
Notification notification = builder.build();
I am implementing one sdk where when user click on notification then certain activity will be open.I am just wondering how can i pass different -different activity on intent.Here is my sample code:-
void fireNotification(Context _context, String appname,
String appdescription) {
Intent resultIntent = new Intent(_context, ResultActivity.class);
try {
PendingIntent contentIntent = PendingIntent.getActivity(_context,0, resultIntent,PendingIntent.FLAG_UPDATE_CURRENT);
mBuilder = new NotificationCompat.Builder(_context);
}
Please suggest me how can pass different activity in intent.
I assume that you wanted to load another Activity instead of ResultActivity, you could just change the ResultActivity.class to the class name of the other activity.
If you are looking to have the ability to determine which activity to load after user taps on the notification, you can create a new Activity that will determine which Activity to load after it launches, kinda like an Activity to "redirect" the screen.
Try this..
void fireNotification(Context _context, String appname,
String appdescription) {
Intent resultIntent = null;
if(something)
resultIntent = new Intent(_context, SomeActivity1.class);
else
resultIntent = new Intent(_context, SomeActivity2.class);
try {
PendingIntent contentIntent = PendingIntent.getActivity(
_context,
0,
resultIntent,
PendingIntent.FLAG_UPDATE_CURRENT);
mBuilder = new NotificationCompat.Builder(
_context);
}
Here is some code I use to create notifications. It uses the v4 Compatibility library.
As you can see you have to recreate the PentingIntent if you want to change the Activity to be launched. There is nothing wrong with cancelling and reissuing the intent as I have done. If you dont have allowing ticket text user likely not even notice it. Also, note that I know the compatibility builder lets you assign custom views but this crashes for me every time, directly assigning it seems more stable.
public static void setupNotification(Context context) {
if (mNotificationManager == null) {
mNotificationManager = (NotificationManager) context.getSystemService(Service.NOTIFICATION_SERVICE);
}
mNotificationManager.cancel(R.layout.main);
int icon = R.drawable.ic_stat_notify_connected;
String tickerText = context.getString(R.string.TickerText);
createNotification(context, tickerText, icon);
mNotificationManager.notify(R.layout.main, mNotification);
}
private static void createNotification(Context context, String tickerText, int icon) {
Intent notificationIntent = new Intent();
notificationIntent = new Intent(context, NotificationOptionsActivity.class);
String contentTitle = context.getString(R.string.MessageTitle);
PendingIntent contentIntent = PendingIntent.getActivity(context, 0, notificationIntent, Intent.FLAG_ACTIVITY_NEW_TASK);
if (mNotification == null) {
mNotification = new NotificationCompat.Builder(context.getApplicationContext()).setContentTitle(contentTitle).setSmallIcon(icon).setContentIntent(contentIntent).build();
mNotification.flags |= Notification.FLAG_ONGOING_EVENT;
RemoteViews contentView = new RemoteViews(context.getApplicationContext().getPackageName(), R.layout.notification_custom_layout);
mNotification.contentView = contentView;
} else {
mNotification.contentIntent = contentIntent;
}
}
Note: You have to use Intent.FLAG_ACTIVITY_NEW_TASK nothing else will work.
You can remove the code for the custom view if you don't have a custom view.
If you do have a custom view, you can set values in it as follows:
mNotification.contentView.setTextViewText(R.id.noti_user, user);
//default image
mNotification.contentView.setImageViewResource(R.id.noti_image, R.drawable.ic_user_icon);
I'm building an app that shows a notification with two options "Dim" and "Full" when a BroadcastReceiver is called. Each of this buttons broadcasts an action.
So far everything is possible to do, right?
The problem is that the buttons shown on the notification do not respond to the tap but the whole notification does (if I click on the icon or text instead of the button).
I have this function to build the notification:
private Notification buildReleaseNotification(NotificationManager nManager, Context context) {
Notification.Builder builder = new Builder(context);
builder.addAction(R.drawable.rate_star_big_half_holo_dark, "Dim", buildPendingIntent(context, DIM));
builder.addAction(R.drawable.rate_star_big_on_holo_dark, "Full", buildPendingIntent(context, FULL));
builder.setContentTitle("Car notification");
builder.setContentText("Freed");
builder.setSmallIcon(R.drawable.ic_launcher);
builder.setOngoing(true);
Notification notification = builder.build();
return notification;
}
and it is called when receiving a broadcast:
public void onReceive(Context context, Intent intent) {
NotificationManager nManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
Notification noty = null;
noty = buildReleaseNotification(context);
startService(context, RELEASE);
if (noty != null) {
nManager.notify(ChangeLockService.GLOBAL_TAG, ID, noty);
}
}
------ edit
Just noticed that the following function returns null... So, how can I build a pending intent to perform a broadcast?
private PendingIntent buildPendingIntent(Context context, String action) {
Intent i = new Intent(action);
PendingIntent pi = PendingIntent.getBroadcast(context, ID, i, Intent.FLAG_RECEIVER_REPLACE_PENDING);
return pi;
}
When creating the intent through
PendingIntent pi = PendingIntent.getBroadcast(context, ID, i, Intent.FLAG_RECEIVER_REPLACE_PENDING);
caused it to return null.
According to the documentation, I understood that the flag Intent.FLAG_RECEIVER_REPLACE_PENDING would replace any pending intent that already existed for that button. If I send no flags then everything works fine:
PendingIntent pi = PendingIntent.getBroadcast(context, ID, i, 0);