I'm trying to create an notification to launch an Activity with extra information. However, currently it is not working.
Here is the code for creating the notification
private void showNotification(RemoteMessage remoteMessage){
try{
// Create an explicit intent for an Activity in your app
Intent i = new Intent(getBaseContext(), MainActivity.class);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
i.putExtra(EXTRA_MESSAGE,remoteMessage);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, i, 0);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID)
.setSmallIcon(R.drawable.ic_action_name)
.setContentTitle("Title")
.setContentText("Content")
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setCategory(NotificationCompat.CATEGORY_CALL)
.setAutoCancel(true)
// Set the intent that will fire when the user taps the notification
.setFullScreenIntent(pendingIntent, true);
// notificationId is a unique int for each notification that you must define
notificationId++;
//https://developer.android.com/training/notify-user/time-sensitive
// Provide a unique integer for the "notificationId" of each notification.
startForeground(notificationId, builder.build());
}catch (Exception e){
Log.d(TAG, e.getMessage());
}
}
The Activity is launching after clicking the notification. However, inside the onCreate of the Activity when checking for the extra in the bundle it doesn't find it:
EDIT: Actually what I want is for the activity to show without the user having to click anything hence why I am using setFullScreenIntent.
if(bundle!=null && bundle.containsKey(CustomFirebaseMessagingService.EXTRA_MESSAGE)){
Log.d(TAG, "MainActivity has extra message");
}else{
Log.d(TAG, "MainActivity doesn't have extra message");
}
My logs say
MainActivity doesn't have extra message
Try
setContentIntent(pendingIntent)
Since you want an intent that will fire on the notification click, the docs for this method says:
Supply a PendingIntent to send when the notification is clicked.
You need to set the flag FLAG_UPDATE_CURRENT when creating the PendingIntent:
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, i,
PendingIntent.FLAG_UPDATE_CURRENT);
This will ensure that your "extras" are actually added to the PendingIntent.
Related
Here is i am creating notification with the message "wake up wake up !!!"
What i want to do when notification comes on particular time and user clicks on it i need to get that message "wake up wake up !!!" and send to SnoozeActivity where i am creating custom alert dialog and i want to show that message into that dialog
alarmNotificationManager = (NotificationManager) this
.getSystemService(Context.NOTIFICATION_SERVICE);
PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
new Intent(this, SnoozeActivity.class), 0);
NotificationCompat.Builder alamNotificationBuilder = new NotificationCompat.Builder(
this).setContentTitle("Alarm").setSmallIcon(R.drawable.ic_launcher)
.setStyle(new NotificationCompat.BigTextStyle().bigText("wake up wake up !!!"))
.setContentText(msg).setAutoCancel(true);
alamNotificationBuilder.setContentIntent(contentIntent);
alarmNotificationManager.cancelAll();
alarmNotificationManager.notify(1, alamNotificationBuilder.build());
But i am not able to figure out how to get the message/data of clicked notification and send to next activity?
An Intent can carry data which you attach via Intent.putExtra()like this:
Intent intent = new Intent(this, SnoozeActivity.class);
intent.putExtra("com.example.mycoolapp.MYDATA", "wake up wake up !!!");
Then you continue with
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
In the onCreate() method of your SnoozeActivity, you can query the Intent for extras:
Intent intent = getIntent();
if (intent.hasExtra("com.example.mycoolapp.MYDATA"))
{
String myText = intent.getStringExtra("com.example.mycoolapp.MYDATA");
}
It's recommended that the keys you use for Intent extras start with your package name.
NOTE not every kind of data is possible with putExtra(), please see the documentation
TL;DR
How can I make a notification that does some work from the lock-screen without unlocking? After clicking an action, a button on the notification or just the complete notification, I want to do an API call (without typing my unlock code)
Details
Goal
Based on the answer on this question I tried to make a notification with an action that works on the lockscreen without unlocking the device. The action is something that doesn't need any further interface or interaction (think 'send an API request').
Status
The notification and click do work with an unlocked device. However, when locked I still need to enter the unlock code first, so either there is something new going on, or I just misunderstood the way it is supposed to work.
If I understand correctly I can set my visibility to 'public' to show the content (this works), and instead of defining an action (which does't seem to be public) I can handle clicks on the (now visible) layout. I tried this with the below code, but obviously it doesn't work.
I have tried both sending the intent to my app and to a service, as florian suggested below.
Code
This is code where I start the notification (this lives in an Activity, code was shortened for your convenience )
private void startNotification() {
NotificationCompat.Builder builder =
new NotificationCompat.Builder(this)
.setVisibility(Notification.VISIBILITY_PUBLIC)
.setOngoing(true)
.setSmallIcon(R.drawable.abc_ic_menu_share_mtrl_alpha)
.setContentTitle("title text")
.setContentText("content text");
Intent openIntent = new Intent(MyMainActivity.this, MyMainActivity.class);
openIntent.setAction("some_string");
PendingIntent pOpenIntent = PendingIntent.getActivity(this, 0, openIntent, 0);
builder.setContentIntent(pOpenIntent);
RemoteViews view = new RemoteViews(getPackageName(), R.layout.notification);
builder.setContent(view);
NotificationManager mNotificationManager =
(NotificationManager) getSystemService(NOTIFICATION_SERVICE);
mNotificationManager.notify(id, builder.build());
}
As said, I also tried with the service as florian suggested, with this as a call:
Intent yepIntent = new Intent(this, MyIntentService.class);
yepIntent.setAction("test");
yepIntent.putExtra("foo", true);
yepIntent.putExtra("bar", "more info");
PendingIntent yepPendingIntent = PendingIntent.getService(this, notificationId, yepIntent, PendingIntent.FLAG_CANCEL_CURRENT);
//builder.addAction(R.drawable.abc_ic_menu_share_mtrl_alpha, "My Action", yepPendingIntent);
builder.setContentIntent(yepPendingIntent);
The action didn't show up on the lock-screen, so I changed it to the setContentIntent you see above. The result is the same though, no action for me :(
Try using an IntentService.
Replace your intent target with your intent service:
Intent yepIntent = new Intent(context, MyIntentService.class);
yepIntent.putExtra("foo", true);
yepIntent.putExtra("bar", "more info");
PendingIntent yepPendingIntent = PendingIntent.getService(context, notificationId, yepIntent, PendingIntent.FLAG_CANCEL_CURRENT);
notificationBuilder.addAction(R.drawable.icon_of_choice, "My Action", yepPendingIntent);
Register your service in the Manifest:
<service
android:name="app.great.mypackage.MyIntentService"
android:exported="false"/>
Your Service could look like this:
public class MyIntentSerice extends IntentService {
#Override
protected void onHandleIntent(Intent intent) {
Log.d("myapp", "I got this awesome intent and will now do stuff in the background!");
// .... do what you like
}
}
UPDATE with feedback from Nanne
The trick seems to be to
Use a service
Add the intent not as an action or a contentIntent, but with the RemoteViews method.
Combined it will be:
NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
.setVisibility(Notification.VISIBILITY_PUBLIC)
.setOngoing(true)
.setSmallIcon(R.drawable.abc_ic_menu_share_mtrl_alpha)
.setContentTitle("My notification")
.setContentText("Hello World!");
int notificationId = 1;
Intent yepIntent = new Intent(this, MyIntentService.class);
yepIntent.setAction("test");
yepIntent.putExtra("foo", true);
yepIntent.putExtra("bar", "more info");
PendingIntent yepPendingIntent = PendingIntent.getService(this, notificationId, yepIntent, PendingIntent.FLAG_CANCEL_CURRENT);
// doesn't show up on my lock-screen
//builder.addAction(R.drawable.abc_ic_menu_share_mtrl_alpha, "My Action", yepPendingIntent);
// asks for unlock code for some reason
//builder.setContentIntent(yepPendingIntent);
// Bingo
RemoteViews view = new RemoteViews(getPackageName(), R.layout.notification);
view.setOnClickPendingIntent(R.id.notification_closebtn_ib, yepPendingIntent);
builder.setContent(view);
Combining the answer from the question I linked (Notification action button not clickable in lock screen) and the one #florian_barth gave above, I got it working
The trick seems to be to
Use a service
Add the intent not as an action or a contentIntent, but with the RemoteViews method.
Combined it will be:
NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
.setVisibility(Notification.VISIBILITY_PUBLIC)
.setOngoing(true)
.setSmallIcon(R.drawable.abc_ic_menu_share_mtrl_alpha)
.setContentTitle("My notification")
.setContentText("Hello World!");
int notificationId = 1;
Intent yepIntent = new Intent(this, MyIntentService.class);
yepIntent.setAction("test");
yepIntent.putExtra("foo", true);
yepIntent.putExtra("bar", "more info");
PendingIntent yepPendingIntent = PendingIntent.getService(this, notificationId, yepIntent, PendingIntent.FLAG_CANCEL_CURRENT);
// doesn't show up on my lock-screen
//builder.addAction(R.drawable.abc_ic_menu_share_mtrl_alpha, "My Action", yepPendingIntent);
// asks for unlock code for some reason
//builder.setContentIntent(yepPendingIntent);
// Bingo
RemoteViews view = new RemoteViews(getPackageName(), R.layout.notification);
view.setOnClickPendingIntent(R.id.notification_closebtn_ib, yepPendingIntent);
builder.setContent(view);
It also works with Broadcast receiver and setAction
PendingIntent pendingIntent = PendingIntent.getBroadcast(..
builder.addAction(..
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
On the lock screen swipe down on the notification to expand it and tap the action area to invoke the broadcast receiver without unlocking the phone.
I am seriously confused now, I have been reading several SE examples and they all seem to be doing slightly different things.
What i want to do: Is have a single Activity called NotificationActivity, when I click on a notification it must open that activity and provide the activity with a DeviceId. I don't want to override or update any pending activities. Each activity should be its own intent.
There should only be once instance of NotificationActivity.
here is the code I have so far:
MyGcmListenerService:
Intent intent = new Intent(this, NotificationActivity.class);
intent.setAction(Intent.ACTION_VIEW);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
//ADD My Extras
intent.putExtra(CommonBundleAttributes.CONNECTING_ACTIVITY_DEVICE_ID, content.DeviceId);
intent.putExtra(CommonBundleAttributes.CONNECTING_ACTIVITY_DEVICE_TYPE_ID, content.DeviceTypeId);
intent.putExtra(CommonBundleAttributes.CONNECTING_ACTIVITY_DEVICE_NAME, content.DeviceName);
//
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle(content.DeviceName)
.setContentText("Notification")
.setAutoCancel(true)
.setSound(ingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION))
.setGroup("Mi:" + content.DeviceId)
.setContentIntent(pendingIntent);
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(NotificationID++, notificationBuilder.build());
and my NotificationActivity:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_notification);
deviceId = getIntent().getExtras().getLong(CommonBundleAttributes.CONNECTING_ACTIVITY_DEVICE_ID, -1);
deviceName = getIntent().getExtras().getString(CommonBundleAttributes.CONNECTING_ACTIVITY_DEVICE_NAME, "");
deviceTypeId = getIntent().getExtras().getInt(CommonBundleAttributes.CONNECTING_ACTIVITY_DEVICE_TYPE_ID, 0);
What am I missing here/ I think I am getting mixed up with all the different flags and launcher types.
If there is already an NotificationActivty in memory, I want to close it and open a new one with the latest intent. If there are 3 notifications on the users phones, and they click on all three. it must open the NotificationActivty for the last clicked Notification.
There must be an issue with my pending intent?
In NotificationActivity, you collect int or long value using following code i.e.
notificationID = getIntent().getExtras().getInt(CommonBundleAttributes.CONNECTING_ACTIVITY_NOTIFICATIONID, 0);
then please pass a proper value with putExtra() i.e. if collect int then pass Integer.parseInt(content.DeviceId) or collect long then pass Long.parseLong(content.DeviceId)
hope it's helpful to you
In Notification class add this line
intent.putExtra(CommonBundleAttributes.CONNECTING_ACTIVITY_NOTIFICATIONID, NotificationID);
In NotificationActivity
notificationID = getIntent().getExtras().getInt(CommonBundleAttributes.CONNECTING_ACTIVITY_NOTIFICATIONID, 0);
I'm having trouble in figuring out the Intent, PendingIntent Filters and Flags for notifications.
Notification are working and are getting generated as they should, but the problem is only the last notification created keeps the Bundle Data.
I want all notification to keep the Bundle Data of each notification in it until a user click on them.
Consider an application for a moment when different user send you a message a new notification gets created and when you click on any notification the app launches and takes you to some specific Activity. I want the same thing but when there are more than one notification the last notification keeps the Data where as previous notification loose their Bundle Data and Intent.
There is another thing which Filters to use to restrict the app from launching a new instance of MainActivity everytime a notification is clicked at.
The Notification_ID are different for each notification.
public class AlarmSchedulingService extends IntentService {
private NotificationManager mNotificationManager;
public AlarmSchedulingService() {
super("SchedulingService");
}
protected void onHandleIntent(Intent intent) {
Bundle extras = intent.getExtras();
sendNotification(extras.getInt(KEY_EXTRAS_NOTIFICATION_ID));
}
public void sendNotification(int NOTIFICATION_ID) {
mNotificationManager = (NotificationManager) this
.getSystemService(Context.NOTIFICATION_SERVICE);
Intent intent = new Intent(this, MainActivity.class);
intent.putExtra(keyName, extraData);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
intent, PendingIntent.FLAG_UPDATE_CURRENT);
// use the right class it should be called from the where alarms are set
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(
this)
.setAutoCancel(true)
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle(titleString)
.setStyle(
new NotificationCompat.BigTextStyle()
.bigText(messageString))
.setDefaults(
Notification.DEFAULT_SOUND
| Notification.DEFAULT_LIGHTS)
.setContentText(messageString);
mBuilder.setContentIntent(contentIntent);
mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build());
}
}
This is Showing that :
PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
intent, PendingIntent.FLAG_UPDATE_CURRENT);
You are giving request code 0 to all notifications.
0 should be replaced by each unique number, otherwise, each new notification will override the old one.
I am using a service to receive some GCM messages from the could. I put the message into an extra and passing it to the class I want to start, there I display the message inside a dialog.
But the next time I get a message it should update the content of the intent opened earlier, the problem is that I get an exception and my app crashes, eclipse is forcing me to use "FLAG_ACTIVITY_NEW_TASK" to solve the crash, but this way my "PendingIntent.FLAG_UPDATE_CURRENT" will be ignored.
How could I update the previously opened intent? Creating a third activity and passing the data back and fort seems to me a bad solution.
Service class:
...
private void sendNotification(String msg, Bundle extras)
{
mNotificationManager = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
Intent intent = new Intent(this, DriverDetails.class);
intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
// If this is a notification type message include the data from the message
// with the intent
if (extras != null)
{
intent.putExtras(extras);
intent.putExtra("message", msg);
intent.setAction("com.myGcm.NOTIFICATION");
startActivity(intent);
}
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_stat_cloud)
.setContentTitle("GCM Notification")
.setStyle(new NotificationCompat.BigTextStyle().bigText(msg))
.setContentText(msg)
.setTicker(msg)
.setAutoCancel(true)
.setSound(Settings.System.DEFAULT_NOTIFICATION_URI);
mBuilder.setContentIntent(contentIntent);
mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build());
}
...
You're solution should be LocalBroadcastManager. It is pretty simple: just register a listener in the onResumeof your Activity and fire an Intent with the Update-Information from anywhere else. I attached two links wich should guide you ;)
how to use LocalBroadcastManager?
http://www.intertech.com/Blog/using-localbroadcastmanager-in-service-to-activity-communications/