I am using latest Lollipop style Navigation drawer in my app.Please refer to this example for more info on that.I use Fragments to show different navigation tabs. Now, I need to open, let's say the 5th item in drawer when I click a certain notification from the notification bar in android device. I am stuck in as to how to switch directly to that Fragment by clicking notification. I am very much aware as how this can be done using Activity. Can anyone please suggest me any solution regarding this ?
Thanks in Advance.
Resolved:
I have resolved this issue by following Ziem's answer. I have just added following lines to open it as a new screen and clear older activity stack:
resultIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP
| Intent.FLAG_ACTIVITY_SINGLE_TOP);
resultIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_CLEAR_TASK);
You can add PendingIntent to notification's click:
PendingIntent resultPendingIntent;
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this)
...
.setContentIntent(resultPendingIntent);
Next you need to handle notification's Intent inside your activity.
Example:
// How to create notification with Intent:
Intent resultIntent = new Intent(this, MainActivity.class);
resultIntent.putExtra("open", 1);
PendingIntent resultPendingIntent = PendingIntent.getActivity(this, 0, resultIntent, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle("My notification")
.setContentText("Hello World!")
.setContentIntent(resultPendingIntent);
int mNotificationId = 33;
NotificationManager mNotifyMgr = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
mNotifyMgr.notify(mNotificationId, mBuilder.build());
//How to handle notification's Intent:
public class MainActivity extends ActionBarActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (getIntent() != null && getIntent().hasExtra("open")) {
int fragmentIndexToOpen = getIntent().getIntExtra("open", -1)
// show your fragment
}
}
}
Related
I launch an activity from a notification I receive. If that notification is pressed it launches an activity. If there are no previous activities on the back-stack, or only a certain one, I want to remove that certain activity and insert my main activity in there and than the new activity.
I found this Thread but I don't understand how he handles it with two intents and flags.
i.e. intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_ACTIVITY_NEW_TASK)
Is it wise to do it the way he did it or should I edit the activity stack for that?
I am fairly new to android dev, so some advice could help me here out.
Thanks a lot ;)
Update: so I went with the stackbuilder but somehow it doesn't get set right ... I don't find my error, my boolean noActivity gets set for sure, but I think somehow I misunderstood how the stack actually puts a previous activity in there.
private void sendNotification(messageType type, Map<String, String> data, boolean noActivities) {
Intent i;
String message = "";
switch (type) {
case newFOLLOWER:
User cur = new User(data.get("other.name"));
User.lookAT = User.getOtherUserByName(cur);
i = new Intent(this, other_profile.class);
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
message = data.get("other.name") + " is following you now. Click to see his profile";
i.putExtra("Notification", data.get("other.name") + " is following you now. Click to see his profile");
break;
default:
i = null;
break;
}
if (i != null) {
TaskStackBuilder stack = TaskStackBuilder.create(this);
if(noActivities){
stack.addParentStack(Photostream.class);
}
stack.addNextIntent(i);
PendingIntent pendingIntent = stack.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);//PendingIntent.getActivity(this, 0, i, PendingIntent.FLAG_ONE_SHOT);
Uri defaultSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle("PIC LOC")
.setContentText(message)
.setAutoCancel(true)
.setSound(defaultSound)
.setContentIntent(pendingIntent);
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0, notificationBuilder.build());
}
}
Update 2: So after searching quite a lot I found out that I missunderstood how the stack builder works. I found another thread where they described how the adding works. Editing the Manifest in order to have a previous stack.
I was to fast and skipped part of the tutorial you provided me so kindly ...
Thanks for your guys help ;)
You should make stack builder while creating notification like this.
Intent resultIntent = new Intent(this, NotificationTapActivity.class);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
// Adds the back stack
stackBuilder.addParentStack(MainActivity.class);
// Adds the Intent to the top of the stack
stackBuilder.addNextIntent(resultIntent);
// Gets a PendingIntent containing the entire back stack
PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(0,
PendingIntent.FLAG_UPDATE_CURRENT);
So whenever user will tap on notification, MainActivity will be inserted in stack.
One more solution in which you can handle the back press of NotoificationTapActivity. In which you can check if noting is there in stack then you can finish the current activity and starts MainActivity from there.
You should use TaskStackBuilder. This is the most efficient way and the TaskStackBuilder structure developed for that reason.
I allways use TaskStackBuilder when Push Notifications are included to my project.
Overriding onBackPress() is not good approach because it requires complex structures in your app and you need to handle many things.
Check this tutorial.
/**Just use below code inside onMessageReceived()**/
PendingIntent pendingIntent;
Uri defaultSoundUri;
Intent notification_intent;
String message = "Your Message";
notification_intent = new Intent(this, YourActivity.class);
notification_intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
pendingIntent = PendingIntent.getActivity(this, 0 , notification_intent, PendingIntent.FLAG_ONE_SHOT);
defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
notificationBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(getNotificationIcon(notificationBuilder))
.setContentTitle(this.getResources().getString(R.string.app_name))
.setContentText(message)
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setDefaults(Notification.DEFAULT_VIBRATE | Notification.DEFAULT_LIGHTS | Notification.DEFAULT_SOUND)
.setContentIntent(pendingIntent);
String[] multilineDescription = new String[]{message};
message = multilineDescription[0];
for (int i=1; i<multilineDescription.length; i++)
{
message += System.getProperty("line.separator");
message += multilineDescription[i];
}
notificationBuilder.setStyle(new NotificationCompat.BigTextStyle().bigText(message));
/***Above commented is for strecting the big message in Push Notification******/
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify((int)MESSAGE_NOTIFICATION_ID /* ID of notification */, notificationBuilder.build());
You can simply handle that in onBackPressed of notification activity.
With help of flag you may know that your notification activity is opened through notification click and then in onBackPressed go to your mainactivity as following:
Intent intent =new Intent(context,MainActivity.class)
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
PendingIntent can implement multi intent. Just create an array intent
Intent[] intents = new Intent[2];
Intent intent1 = new Intent(this, MainActivity.class);
Intent intent2 = new Intent(this, YourActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivities(this, 0, intents,PendingIntent.FLAG_ONE_SHOT);
And when you finish YouActivity, it will back to MainActivity.
Intent intent = getIntent();
String data= intent.getStringExtra("from");
if(data.equalsIgnoreCase("notificaton")
{
// call Mainactivity
}
else if(){}
There's my code to display content to notification bar :
NotificationManager mNotificationManager = (NotificationManager)
this.getSystemService(Context.NOTIFICATION_SERVICE);
PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
new Intent(this, MyActivity.class).putExtra("package.notification", 123).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK),
PendingIntent.FLAG_CANCEL_CURRENT);
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_launcher).setContentTitle("");
// Set Big View style to see full content of the message
NotificationCompat.BigTextStyle inboxStyle =
new NotificationCompat.BigTextStyle();
inboxStyle.setBuilder(mBuilder);
inboxStyle.bigText("");
inboxStyle.setBigContentTitle("");
inboxStyle.setSummaryText("");
// Moves the big view style object into the notification object.
mBuilder.setStyle(inboxStyle);
mBuilder.setContentText(msg);
mBuilder.setDefaults(Notification.DEFAULT_ALL);
mBuilder.setContentIntent(contentIntent);
mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build());
onStart() in MyActivity.class
#Override
protected void onStart() {
super.onStart();
if (getIntent().getIntExtra("package.notification", -1) == 123) {
//check in here
}
}
Issue is MyActitvity activity always created new when I click notification in notification bar (duplicate activity if MyActitvity activity existed).
I want apps opening (it mean MyActitvity activity is active), not create MyActitvity new.
Only start MyActitvity activity when app closing (MyActitvity is not active)
Please to me advise
When you are creating intent use this flag
Intent m_intent = new Intent(this, YourActivity.class);
m_intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
and then use this intent in pending intent
You can use flag
android:launchMode="singleTop"
in your activity in Manifest.xml:
<activity
android:name=[your_activity_name]
android:launchMode="singleTop"
android:theme=[your_theme] />
I know there are other similar questions, and I've tried them all, WITHOUT success. That's why I'm posting my code here, in case someone can visualize the proper solution for my case and suggest a specific action in the code, please help.
I've tried: Adding some tags to the manifest file in the activity called by the intent, adding flags and actions and categories to the actual intent in the code, creating a dummy activity to be call in the intent with finish(), etc.
Thanks for any suggestion.
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle(getString(R.string.app_name))
.setStyle(new NotificationCompat.BigTextStyle().bigText(getString(R.string.lampp)))
.setAutoCancel(true)
.setContentText(getString(R.string.lampp));
Intent resultIntent = new Intent(this, MainActivity.class);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
stackBuilder.addParentStack(MainActivity.class);
stackBuilder.addNextIntent(resultIntent);
PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(0,PendingIntent.FLAG_UPDATE_CURRENT);
mBuilder.setContentIntent(resultPendingIntent);
NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(0, mBuilder.build());
Thanks to a combination of the answer posted by #Merlevede and a previous post, this is how it was solved:
Use this code for your Notification:
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle(getString(R.string.app_name))
.setStyle(new NotificationCompat.BigTextStyle().bigText(getString(R.string.lampp)))
.setAutoCancel(false)
.setContentText(getString(R.string.lampp));
Intent resultIntent = new Intent(this, NotiActivity.class);
resultIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent resultPendingIntent = PendingIntent.getActivity(this,0,resultIntent,PendingIntent.FLAG_UPDATE_CURRENT);
mBuilder.setContentIntent(resultPendingIntent);
NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(0, mBuilder.build());
And this is the code for the dummy Activity called in the intent NotiActivity.class:
public class NotiActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
finish();
}
}
Hope this helps someone out there.
I don't know if this might be useful to you. You might be missing some flags on your notification intent, specially take a look at FLAG_ACTIVITY_CLEAR_TOP and FLAG_ACTIVITY_SINGLE_TOP.
I use a notification for a service using this code.
Intent notificationIntent = new Intent(this, ActivityMain.class);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
builder.setContentIntent(pendingIntent)
There are a few differences with your code. Also I'm using this notification from a service so I'm using startForeground to set the notification.
It's worth giving it a try.
I've made an app which manage sms, I've created the notifications but when I click on them it starts another activity, I would like to know how to check if an activity has been stopped and resume it.
Here is the code used to create the pendingintent:
private void createNotification(SmsMessage sms, Context context){
final NotificationManager nm = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);
String contentTitle = "";
// construct the Notification object.
final NotificationCompat.Builder builder = new NotificationCompat.Builder(context)
.setContentTitle(contentTitle)
.setContentText(sms.getMessageBody())
.setSmallIcon(R.drawable.ic_launcher)
.setLargeIcon(getIconBitmap())
.setNumber(nmessages);
builder.setAutoCancel(true);
//(R.drawable.stat_sample, tickerText,
// System.currentTimeMillis());
// Set the info for the views that show in the notification panel.
//notif.setLatestEventInfo(this, from, message, contentIntent);
/*
// On tablets, the ticker shows the sender, the first line of the message,
// the photo of the person and the app icon. For our sample, we just show
// the same icon twice. If there is no sender, just pass an array of 1 Bitmap.
notif.tickerTitle = from;
notif.tickerSubtitle = message;
notif.tickerIcons = new Bitmap[2];
notif.tickerIcons[0] = getIconBitmap();;
notif.tickerIcons[1] = getIconBitmap();;
*/
// Creates an explicit intent for an Activity in your app
Intent resultIntent = new Intent(context, BasicActivity.class);
resultIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
// Because clicking the notification opens a new ("special") activity, there's
// no need to create an artificial back stack.
PendingIntent resultPendingIntent =
PendingIntent.getActivity(
context,
0,
resultIntent,
PendingIntent.FLAG_UPDATE_CURRENT
);
// Ritardo in millisecondi
builder.setContentIntent(resultPendingIntent);
nm.notify(R.drawable.ic_drawer, builder.build());
You need to set flags in your PendingIntent's ...like FLAG_UPDATE_CURRENT.
Here is all on it.
http://developer.android.com/reference/android/app/PendingIntent.html
Edit 1: I misunderstood the question.
Here are links to topics that had the same issue but are resolved:
resuming an activity from a notification
Notification Resume Activity
Intent to resume a previously paused activity (Called from a Notification)
Android: resume app from previous position
Please read the above answers for a full solution and let me know if it works.
Add this line to the corresponding activity in manifest file of your app.
android:launchMode="singleTask"
eg:
<activity
android:name=".Main_Activity"
android:label="#string/title_main_activity"
android:theme="#style/AppTheme.NoActionBar"
android:launchMode="singleTask" />
Try with this.
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(
mContext).setSmallIcon(R.drawable.ic_launcher)
.setContentTitle(mContext.getString(R.string.notif_title))
.setContentText(mContext.getString(R.string.notif_msg));
mBuilder.setAutoCancel(true);
// Set notification sound
Uri alarmSound = RingtoneManager
.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
mBuilder.setSound(alarmSound);
Intent resultIntent = mActivity.getIntent();
resultIntent.addCategory(Intent.CATEGORY_LAUNCHER);
resultIntent.setAction(Intent.ACTION_MAIN);
PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 0, resultIntent, PendingIntent.FLAG_UPDATE_CURRENT);
mBuilder.setContentIntent(pendingIntent);
NotificationManager mNotificationManager = (NotificationManager) mContext
.getSystemService(Context.NOTIFICATION_SERVICE);
// mId allows you to update the notification later on.
mNotificationManager.notify(mId, mBuilder.build());
The only solution that actually worked for me after doing a lot of search is to do the following :
here you are simply launching of the application keeping the current stack:
//here you specify the notification properties
NotificationCompat.Builder builder = new NotificationCompat.Builder(this).set...(...).set...(..);
//specifying an action and its category to be triggered once clicked on the notification
Intent resultIntent = new Intent(this, MainClass.class);
resultIntent.setAction("android.intent.action.MAIN");
resultIntent.addCategory("android.intent.category.LAUNCHER");
PendingIntent resultPendingIntent = PendingIntent.getActivity(this, 0, resultIntent, PendingIntent.FLAG_UPDATE_CURRENT);
//building the notification
builder.setContentIntent(resultPendingIntent);
NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(0, builder.build());
If the aforementioned solution didn't work, try to change the activity launch mode in your androidManifest.xml file from standard to singleTask.
<activity>
...
android:launchMode="singleTask
...
</activity>
This will prevent the activity from having multiple instances.
I want to make my Android notification stay even if user clicks it or clicks clear all...
Right now it stays sometimes, and gets removed sometimes, and I'm not sure what causes it.
Here's my code for the notification:
#TargetApi(Build.VERSION_CODES.JELLY_BEAN)
public static void createNotification()
{
NotificationManager notificationManager = (NotificationManager)context.getSystemService(NOTIFICATION_SERVICE);
NotificationCompat.Builder builder = new NotificationCompat.Builder(context)
.setContentTitle("Wolftech Field Agent")
.setContentText("Getting Status")
.setSmallIcon(R.drawable.ic_launcher)
.setOngoing(true)
.setAutoCancel(false);
Intent intent = new Intent(context, FieldAgent.class);
intent.setAction(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);
stackBuilder.addParentStack(FieldAgent.class);
stackBuilder.addNextIntent(intent);
PendingIntent pendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
builder.setContentIntent(pendingIntent);
notificationManager.notify(NOTIFICATION_ID, builder.build());
}
public static void updateNotificationText(String inString)
{
NotificationManager notificationManager = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);
NotificationCompat.Builder builder = new NotificationCompat.Builder(context)
.setContentText(inString)
.setContentTitle("Wolftech Field Agent")
.setSmallIcon(R.drawable.ic_launcher)
.setOngoing(true)
.setAutoCancel(false);
Intent intent = new Intent(context, FieldAgent.class);
intent.setAction(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);
stackBuilder.addParentStack(FieldAgent.class);
stackBuilder.addNextIntent(intent);
PendingIntent pendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
builder.setContentIntent(pendingIntent);
notificationManager.notify(NOTIFICATION_ID, builder.build());
}
public static void cancelNotification()
{
NotificationManager notificationManager = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.cancel(NOTIFICATION_ID);
}
I think you are looking for ongoing notifications, in that case if you are using NotificationCompat.Builder , you can use :
NotificationCompat.Builder mNotifyBuilder = new NotificationCompat.Builder(this);
mNotifyBuilder.setOngoing(true);
I believe that you are looking for this flag:
Notification.FLAG_NO_CLEAR
Add that flag to your notification.
you try
PendingIntent pendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
notificationManager.cancel(pendingIntent);
Okey, I've realized the code I posted is actually good.
What is happening is that when I'm clicking the notification, it's calling onCreate() again, and then after a random interval it's calling onDestroy().
In onDestroy() I had my cancelNotification() method, so if onDestroy() got called after onCreate(), it removed my notification.
Which brings me to a new question: Why is it destroying and recreating my activity after I've followed every answer I could find on here on how to stop that from happening?
You can find that question here How to make notification resume and not recreate activity? if you want to help me solve it...
I had this issue too. My Solution is the add extra on the function that creates the intent
private void addNotification(String headLine, String info, Context context) {
mBuilder =
new NotificationCompat.Builder(context)
.setSmallIcon(R.drawable.icon) //R.drawable.icon
.setContentTitle(headLine)
.setContentText(info)
.setOngoing(true)
.setAutoCancel(false);
// Creates an explicit intent for an Activity in your app
Intent resultIntent = new Intent(context, MainActivity.class);
resultIntent.putExtra("FROM_NOTIF", true);
// 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(context);
// Adds the back stack for the Intent (but not the Intent itself)
// stackBuilder.addParentStack(MainActivity.class);
//Adds the Intent that starts the Activity to the top of the stack
stackBuilder.addNextIntent(resultIntent);
PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
mBuilder.setContentIntent(resultPendingIntent);
mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
// mId allows you to update the notification later on.
// mBuilder.setf |= Notification.FLAG_ONGOING_EVENT | Notification.FLAG_NO_CLEAR;
mNotificationManager.notify(mNotification_id, mBuilder.build());
}
and In MainActivity:
#Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
if (intent.getBooleanExtra("FROM_NOTIF", false)) {
addNotification(...)
... call the function that adds the notification again ..}
So thing is that the notification turns off after the user press on it, but than you can be notify on the activity that started using onNewIntent(), check the intent over there and if you find out that it came from the notification, set it again.