For my push notifications, I am sending some data which I will then choose which fragment I want to open. I am trying to do this by adding an Intent Extra to the Pending Intent but whenever I try to use this extra in the next Activity, it returns NULL.
I have read here I need to change the PendingActivity flag, but I have changed it a few times and made no difference. I must be making a silly mistake somewhere.
private void sendNotification(String title, String msg, String fragment) {
mBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.logo_m_white)
// .setLargeIcon(((BitmapDrawable) getResources().getDrawable(R.drawable.icon_filled_m)).getBitmap())
.setContentTitle(title)
.setContentText(msg)
.setSound(Uri.EMPTY)
.setPriority(1)
.setLights(Color.RED, 300, 5000)
.setAutoCancel(true);
Intent intent = new Intent(this, LoginActivity.class);
intent.putExtra("fragment", fragment);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent pi = PendingIntent.getActivity(this,0,intent,PendingIntent.FLAG_CANCEL_CURRENT);
mBuilder.setContentIntent(pi);
mNotificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(0, mBuilder.build());
}
fetch extras in your LoginActivity using intent extras as
Intent intent = getIntent() ;
if(intent != null){
String fragment = intent.getStringExtra("fragment"); //if 'fragment' type is String (see other methods for appropriate type)
}
Related
I want to open the particular fragment on the click of the push notification message.In my case fragment is open when the notification occurs.but i want to open the fragment on the click of the notification message instead of arriving the message.
This is my sendNotification() method :-
private void sendNotification(String msg) {
mNotificationManager = (NotificationManager) this
.getSystemService(Context.NOTIFICATION_SERVICE);
Intent intent = new Intent(this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra("data", "fromoutside");
getApplicationContext().startActivity(intent);
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, intent, 0);
NotificationCompat.Builder mBuilder = (NotificationCompat.Builder) new NotificationCompat.Builder(this)
.setSmallIcon(getNotificationIcon())
.setContentTitle("Telepoh")
.setStyle(new NotificationCompat.BigTextStyle().bigText(msg))
.setContentText(msg)
.setDefaults(Notification.DEFAULT_SOUND | Notification.DEFAULT_VIBRATE);
mBuilder.setContentIntent(contentIntent);
mBuilder.getNotification().flags |= Notification.FLAG_AUTO_CANCEL;
mBuilder.setAutoCancel(true);
mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build());
}
This is my onNewIntent() method which override in the MainActivity where i open the fragment :-
#Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
Fragment fragment = new NotificationActivity();
getSupportFragmentManager().beginTransaction().replace(R.id.container, fragment).addToBackStack(null).commit();
}
My Problem is I want to open this fragment on the click of the push notification message but in my case the fragment is open when the push notification message is arrive.
I found the mistake and solved it on my own way :-
change the flags in sendNotification() method like this :-
Intent intent = new Intent(this, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP);
intent.putExtra("data", "fromoutside");
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
and in MainActivity change the code in override method onNewIntent() as like this :-
#Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
if (intent != null) {
String data = intent.getStringExtra("data");
if (data != null) {
Fragment fragment = new NotificationActivity();
getSupportFragmentManager().beginTransaction().replace(R.id.container, fragment).addToBackStack(null).commit();
}
}
}
Happy Coding :))
These lines of code right here are starting a new activity immediately since they are outside of a listener or some other condition.
Intent intent = new Intent(this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra("data", "fromoutside");
getApplicationContext().startActivity(intent);
From what I see, you just need to remove the 4 lines above.
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, intent, 0);
...
mBuilder.setContentIntent(contentIntent);
These lines should be enough to get your notification to start the intent when clicked.
For reference: the developer guide for notifications
I have 3 types of notifications in android.Audio/Video call and msg. How to differentiate based on notification type and open different activity on different notification. THis is hoW I open activity on click of notification.
private void sendNotification(long when,String msg) {
String notificationContent ="Notification Content Click Here to go more details";
String notificationTitle ="This is Notification";
//large icon for notification,normally use App icon
Bitmap largeIcon = BitmapFactory.decodeResource(getResources(),R.drawable.ic_launcher);
int smalIcon =R.drawable.hcp;
String notificationData="This is data : "+msg;
/*create intent for show notification details when user clicks notification*/
Intent intent =new Intent(getApplicationContext(), NotificationDetailsActivity.class);
intent.putExtra("DATA", notificationData);
/*create unique this intent from other intent using setData */
intent.setData(Uri.parse("http://www.google.com"));
/*create new task for each notification with pending intent so we set Intent.FLAG_ACTIVITY_NEW_TASK */
PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(), 0, intent, Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
Log.d(TAG, "Preparing to send notification...: " + msg);
mNotificationManager = (NotificationManager) this
.getSystemService(Context.NOTIFICATION_SERVICE);
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(
this).setSmallIcon(R.drawable.hcp)
.setContentTitle("GCM Notification")
.setContentIntent(pendingIntent)
.setAutoCancel(true)
.setSmallIcon(smalIcon)
.setTicker(notificationTitle)
.setLargeIcon(largeIcon)
.setContentText(notificationContent)
.setStyle(new NotificationCompat.BigTextStyle().bigText(msg))
.setContentIntent(pendingIntent);
;
Notification notification=mBuilder.build();
mBuilder.setContentIntent(pendingIntent);
mNotificationManager.notify((int) when, notification);
Log.d(TAG, "Notification sent successfully.");
}
Assuming that the data (msg) your receiving is from a web service. Now along with the msg parameter, you must be getting some other parameters by which you can distinguish that the following notification is Audio/Video call or message.
So you can create a method that will return the class name which can be used instead of NotificationDetailsActivity.class
private Class<?> getClassFromType(String type) {
if(type.equals("Audio")
return AudioActivity.class;
else if(type.equals("Video")
return VideoActivity.class;
else if(type.equals("Message")
return MessageActivity.class;
}
The final code will be something like this:
Intent intent =new Intent(getApplicationContext(), getClassFromType(type));
Here type will be the variable that distinguishes the notification.
Hope this will solve your problem.
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 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
I am trying to create a notification that when clicked will open an external app. I've seen the documentation for creating notifications and for sending the user to another app. But I can't seem to figure out how to combine the two. The problem is that the advised way to launch an app from a notification, is to creating the pending intent like this:
Intent intent = new Intent(this, MyActivity.class);
TaskStackBuilder stackBuidler = TaskStackBuilder.create(context);
stackBuilder.addParentStack(MyActivity.class);
stackBuilder.addNextIntent(intent);
PendingIntent pendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
But to launch an external app, you have to create an implicit intent like this:
String uri = ...
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
As far as I can tell, there is no way to create the TaskStackBuilder with this kind of intent, because addParentStack() will only take an Activity, a Class, or a ComponentName.
I guess the question boils down to... is it possible to create a intent that is both pending and implicit?
The only workaround I can think of right now is to create an Activity in my app that does nothing but launch the external app.
I did try creating the intent from the URI then doing the following, but nothing happens when you click the notification:
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
Well, a lot later, I think I have the solution for you.
For all the other guys who are searching for an answer to launching an external app from your own custom notification.
Here it is:
public void createMyNotification(String titl, String titlcont, String conti){
Context context = getApplicationContext();
PackageManager pm = context.getPackageManager();
Intent LaunchIntent = null;
String apppack = "com.mycompany.appack.apname.app";
String name = "";
try {
if (pm != null) {
ApplicationInfo app = context.getPackageManager().getApplicationInfo(apppack, 0);
name = (String) pm.getApplicationLabel(app);
LaunchIntent = pm.getLaunchIntentForPackage(apppack);
}
Toast.makeText(context,"Found it:" + name,Toast.LENGTH_SHORT).show();
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
Intent intent = LaunchIntent; // new Intent();
PendingIntent pIntent = PendingIntent.getActivity(this, 0, intent, 0);
Notification noti = new Notification.Builder(this)
.setTicker(titl)
.setContentTitle(titlcont)
.setContentText(conti)
.setSmallIcon(R.drawable.ic_launcher)
.setContentIntent(pIntent).getNotification();
noti.flags = Notification.FLAG_AUTO_CANCEL;
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
notificationManager.notify(0, noti);
}
This does not use an additional Activity to launch the external app.
If you know packageName what you want start it, You can get Intent for startActivity.
Read this link start application knowing package name
I don't know if this is the best approach, but this is the solution that ended up working:
Create the notification
//Create the pending intent
Intent intent = new Intent(context, MyActivity.class);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);
stackBuilder.addParentStack(MyActivity.class);
stackBuilder.addNextIntent(intent);
PendingIndent pendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
//Create the notification builder
NotificationCompat.Builder builder = new NotificationCompat.Builder(context)
.setContentTitle("Notification Title")
.setContentText("Hello world!")
.setContentIntent(pendingIntent); //Attach the pending intent to launch when notification is clicked
//Send the notification
NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(mId, builder.build());
MyActivity.java
public class MyActivity extends Activity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Create implicit intent - see http://developer.android.com/training/basics/intents/sending.html
String uri = "...";
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
startActivity(intent);
}
}
I'd still be interested to know if there's a way to bypass having an additional Activity that does nothing but launch an implicit intent.