Android Notifications empty when app is closed - android

I have working notifications(with service) on my app and it works ok when the app is in onPause, but when I close the app, the notification text/title is null and the notification appear, but with no title/body.
Here is the Notification builder code:
public int onStartCommand(Intent intent, int flag, int startId)
{
super.onStartCommand(intent , flag, startId);
String titleS = Utils.Title;
String bodyS = Utils.Body;
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_CANCEL_CURRENT);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
builder.setContentTitle(titleS);
builder.setContentText(bodyS);
builder.setSmallIcon(R.drawable.ic_launcher);
builder.setContentIntent(pendingIntent);
builder.setAutoCancel(true);
notificationManager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
notificationManager.notify(NOTIFICATION_ID, builder.build());
return START_NOT_STICKY;
}
It is obvious that the titleS and bodyS is null when the app is closed and that is why the notification appear without any information.
My question is what is the correct way to save/display this data into notification when my app is closed ?

I set my alarmintent putExtra (forgot completly about this)
alarmIntent.putExtra("title" , Title);
alarmIntent.putExtra("body" , Body);
And then in my Broadcast reciever, onReceive I get those String with:
String titleS = intent.getStringExtra("title");
String bodyS = intent.getStringExtra("body");
It`s working fine now.

Related

Scheduling Notifications with broadcast reciever and actions on click

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();

Android notifications via service

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.

workaround FLAG_UPDATE_CURRENT behaviour

I have defined a service that issues notifications when an event occurs. I add the notification id as an extra in the intent so that, when the user opens the app through the notification, i can retrieve the id in the activity and cancel the specific notification.
The problem is that, if there are multiple notifications visible in the drawer at any time, all of them end up with the same Extra value. This is because of the FLAG_UPDATE_CURRENT behaviour. It will update the extras of any existing matching Intents with the new Extra. So now i cannot retrieve the correct notification id to cancel it.
Is there a way to work around this so that the previous Intents retain their Extra value.
According to the doc :
public static final int FLAG_UPDATE_CURRENT
Added in API level 3
Flag indicating that if the described PendingIntent already exists, then keep it but replace its extra data with what is in this new Intent.
Service onStartCommand() :
int notificationId = getId();
Intent contentIntent = new Intent(this,MainActivity.class);
contentIntent.putExtra(MainActivity.KEY_NOTIFICATION_ID, notificationId);
PendingIntent contentPendingIntent = PendingIntent.getActivity(this, REQUEST_CODE_OPEN_APP, contentIntent, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(MyApplication.getContext())
.setContentTitle("title")
.setContentText("text")
.setSmallIcon(R.drawable.icon)
.setContentIntent(contentPendingIntent);
notificationManager.notify(notificationId,notificationBuilder.build());
In the Activity's onCreate() :
Bundle bundle = getIntent().getExtras();
if(bundle != null){
int notificationId = bundle.getInt(KEY_NOTIFICATION_ID);
if(notificationId != 0){
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.cancel(notificationId);
}
}
One workaround is to have a unique request code for every PendingIntent. You can reuse the notification id itself. We can set an action for the intent as well, so that the activity can recognize the intent. So change the code to :
Service onStartCommand() :
public static final String ACTION_NOTIFIED = "ACTION_NOTIFIED"; //added
int notificationId = getId();
Intent contentIntent = new Intent(this,MainActivity.class);
contentIntent.putExtra(MainActivity.KEY_NOTIFICATION_ID, notificationId);
contentIntent.setAction(ACTION_NOTIFIED);//added
PendingIntent contentPendingIntent = PendingIntent.getActivity(this, notificationId, contentIntent, PendingIntent.FLAG_UPDATE_CURRENT);//changed
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(MyApplication.getContext())
.setContentTitle("title")
.setContentText("text")
.setSmallIcon(R.drawable.icon)
.setContentIntent(contentPendingIntent);
notificationManager.notify(notificationId,notificationBuilder.build());
In the Activity's onCreate() :
if(getIntent().getAction().equals(AppService.ACTION_NOTIFIED)){//added
Bundle bundle = getIntent().getExtras();
if(bundle != null){
int notificationId = bundle.getInt(KEY_NOTIFICATION_ID);
if(notificationId != 0){
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.cancel(notificationId);
}
}
}//added

Bundle data is not updating in the activity passed from a notification in service, always populating the first bundle

I am handling push notification in my application using GCMIntentService. I am creating a status bar notification and navigating to an activity using pending Intent.
my Code for creating a notification is :
private static void generateNotification(Context context, String message, String title1, String desc, String soln, String date, String time) {
int icon = R.drawable.notification_icon;
long when = System.currentTimeMillis();
Log.i("","###### notificatin"+title1+desc+soln+message);
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
Notification notification = new Notification(icon, message, when);
String title = context.getString(R.string.app_name);
Intent notificationIntent = new Intent(context,AppLog.class);
notificationIntent.putExtra(Description.REQUEST_FROM, "notification");
notificationIntent.putExtra(Description.INFO_TITLE, title1);
notificationIntent.putExtra(Description.INFO_DESC, desc);
notificationIntent.putExtra(Description.INFO_SOLUTION, soln);
notificationIntent.putExtra(Description.INFO_DATE, date);
notificationIntent.putExtra(Description.INFO_TIME, time);
PendingIntent pIntent = PendingIntent.getActivity(context, 0,notificationIntent, 0);
notification.setLatestEventInfo(context, title, message, pIntent);
Uri uri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
notification.sound=uri;
notification.flags |= Notification.FLAG_AUTO_CANCEL;
notificationManager.notify(0, notification);
}
And inside my AppLog.class I am handling it like :
if(bundle!=null && bundle.containsKey(Description.REQUEST_FROM)){
Log.i("","###### applog"+bundle);
}
When the first notification is sent to the device data will be populated correctly in my AppLog Activity class. But onwards for all notifications it always show me the old bundle.
I tried everything but still the issue persist. Is there any issue with pending intents or notification created from services ?
This works
PendingIntent pIntent = PendingIntent.getActivity(context, 0,notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
Instead of always passing a 0 value as the second parameter try and pass a random number.
Random r = new Random();
int no = r.nextInt(999999);
PendingIntent pIntent = PendingIntent.getActivity(context, no,notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);

Android show notification from BroadcastReceiver

I have a class which extends BroadcastReceiver that gets called whenever new Wifi scan results are available (the receiver is registered in the manifest with the Scan_Results broadcast as the intent-filter).
From this class, I want to be able to show a notification to the user. Currently, I pass the context that is received as a parameter in the onReceive method of my broadcast intent class to a "show notification" method of another class.
When it gets to the line:
myNotificationManager.notify(notificationId, notification);
it fails with the following exception:
java.lang.IllegalArgumentException: contentView required: pkg=com.mumfordmedia.trackify id=2131034122 notification=Notification(vibrate=null,sound=null,defaults=0x0,flags=0x0)
Any idea why this is happening? All I can think of is because the context that I am getting from the onReceive parameter is not ... for lack of a better phrase, "right for the job"...
Any ideas?
Thanks,
Max.
ContentView is the view which is required when the notification is clicked. The code below works fine and setLatestEventInfo() is required method.
NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
Notification notification = new Notification(R.drawable.ic_launcher,
"Hello from service", System.currentTimeMillis());
Intent intent = new Intent(this, MainActivity.class);
notification.setLatestEventInfo(this, "contentTitle", "contentText",
PendingIntent.getActivity(this, 1, intent, 0));
manager.notify(111, notification);
Not sure exactly why it wasnt working before but here is the code I got it working with:
Declare the following outside of any method:
int YOURAPP_NOTIFICATION_ID = 1234567890;
NotificationManager mNotificationManager;
Then in the onReceive method call the following:
mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
showNotification(context, R.drawable.icon, "short", false);
Then declare the following method:
private void showNotification(Context context, int statusBarIconID, String string, boolean showIconOnly) {
// This is who should be launched if the user selects our notification.
Intent contentIntent = new Intent();
// choose the ticker text
String tickerText = "ticket text";
Notification n = new Notification(R.drawable.icon, "ticker text", System.currentTimeMillis());
PendingIntent appIntent = PendingIntent.getActivity(context, 0, contentIntent, 0);
n.setLatestEventInfo(context, "1", "2", appIntent);
mNotificationManager.notify(YOURAPP_NOTIFICATION_ID, n);
}
You have to call Notification.setLatestEventInfo().
Use this code along with your notification
Intent intent = new Intent(this, MusicDroid.class);
PendingIntent activity = PendingIntent.getActivity(this, 0, intent, 0);
notification.setLatestEventInfo(this, "This is the title",
"This is the text", activity);
notification.number += 1;
nm.notify(NOTIFY_ID, notification);
From what I can tell, when you're creating you notification to pass to the Notification manager, you're not giving it a content view to display. Review the line where you actually create the notification to see if you're actually giving the notification a view to display.
For those who are using NotificationCompat, the following code will work:
NotificationCompat.Builder n = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.icon).setContentText("Notify Title").setContentText("Sample Text");
NotificationManager nm = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
Intent i = new Intent(this,MainActivity.class);
PendingIntent ac = PendingIntent.getActivity(this, 0, i, 0);
n.setContentIntent(ac);
nm.notify(12222, n.build());

Categories

Resources