I have problem my MainActivity can be created by 3 ways:
1) standart launch App
2) from Service
3) from notification click.
How I can check when it starts from notification click?
Notification code:
private void createNotification()
{
Log.d("service createNotification",MainActivity.TAG);
Context context = getApplicationContext();
Intent notificationIntent = new Intent(this,MainActivity.class);
intent.putExtra(AppNames.IS_NOTIFICATION_INTENT,true);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0,
notificationIntent, Intent.FLAG_ACTIVITY_NEW_TASK);
NotificationCompat.Builder builder = new NotificationCompat.Builder(context)
.setContentTitle(this.getString(R.string.notification_title))
.setContentText(this.getString(R.string.notification_text))
.setContentIntent(pendingIntent)
.setSmallIcon(R.drawable.ic_launcher);
getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(AppNames.APP_NOTIFICATION, builder.getNotification());
}
add
intent.putExtra("started_from","notification");
to the code that starts the intent from the notifications, and the same thing to the other startActivity calls just change the value, then inside your activity
String startedFrom = getIntent().getStringExtra("started_from");
for more refer to this question: How do I get extra data from intent on Android?
Related
Im testing the push notification with my app.
when App in the foreground:
Step 1. Received the notification (in system tray).
2. now, I'm in some other screen than the home screen.
3. Actual Problem: On tap on the notification, it is going to the home screen.
4. Expected: If the app is in the foreground, just I need to cancel on tap of the notification. (No need to swipe.)
when App in background/killed: (Works well)
Step 1. Received the notification (in the system tray)
2. On tap, open the home screen of the app.
Tried with setting launch mode flags in intent. Not helped. Below is my code. Please suggest the solution guys.
Intent resultIntent = new Intent(this, MainActivity.class);
//resultIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
// resultIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_CLEAR_TASK);
PendingIntent resultPendingIntent =
PendingIntent.getActivity(
this,
0,
resultIntent,
PendingIntent.FLAG_UPDATE_CURRENT
);
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(this);
mBuilder.setContentIntent(resultPendingIntent);
mBuilder.setSmallIcon(R.mipmap.ic_launcher);
mBuilder.setContentTitle(title);
mBuilder.setContentText(body);
mBuilder.setAutoCancel(true);
mBuilder.setStyle(new NotificationCompat.BigTextStyle().bigText(body));
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
mBuilder.setChannelId(TestUtils.creatChanel(this).getId());
}
NotificationManager mNotificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(642, mBuilder.build());
Not sure about dismiss notification on tap, but since your concern is wrong navigation.
We can check app is in foreground or not and prevent new activity to be opened from notification click, if app is in foreground.
//If app is in foreground setting pending intent to null
PendingIntent pendingIntent;
Intent notificationIntent = new Intent(getApplicationContext(), Main2Activity.class);
if(isAppInForeground()){
Log.e("--^","inForeground");
pendingIntent = null;
}else{
Log.e("--^","inBackground");
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
pendingIntent = PendingIntent.getActivity(getApplicationContext(), 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
}
Add this function (SOURCE: link)
private boolean isAppInForeground() {
ActivityManager activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningAppProcessInfo> services = activityManager.getRunningAppProcesses();
boolean isActivityFound = false;
if (services.get(0).processName
.equalsIgnoreCase(getPackageName()) && services.get(0).importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
isActivityFound = true;
}
return isActivityFound;
}
In this case if notification came when app is in foreground, it will do nothing if clicked. So user has only one option left to swipe it to remove.
You can create Custom Notification with close button to close notification using RemoteViews
// create Notification with RemoteViews:
RemoteViews remoteViews= new RemoteViews(getApplicationContext().getPackageName(), R.layout.your_custom_notification);
Intent closeIntent = new Intent(context, CloseNotificationService.class);
hangUpIntent.setAction("close");
PendingIntent pendingCloseIntent = PendingIntent.getBroadcast(this, 0, closeNotification, PendingIntent.FLAG_UPDATE_CURRENT);
remoteViews.setOnClickPendingIntent(R.id.cancel_notification, pendingCloseIntent);
// create notification here..
Notification customNotification = new NotificationCompat.Builder(context, CHANNEL_ID)
.setSmallIcon(R.drawable.notification_icon)
.setStyle(new NotificationCompat.DecoratedCustomViewStyle())
.setCustomContentView(remoteViews)
.build();
OnClick of close button it will redirect to service class:
public class CloseNotificationService extends IntentService {
/**
* Creates an IntentService. Invoked by your subclass's constructor.
*/
public CloseNotificationService() {
super("notificationIntentService");
}
#Override
protected void onHandleIntent(#Nullable Intent intent) {
switch (intent.getAction()) {
case "close":
Handler hangUpHandler = new Handler(Looper.getMainLooper());
hangUpHandler.post(new Runnable() {
#Override
public void run() {
NotificationManager notifManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notifManager.cancel(notificationId); // get notification id from intent.
}
});
break;
}
}
}
For more information of RemoteViews you can refer official google developer website https://developer.android.com/training/notify-user/custom-notification
Instead of this:
Intent resultIntent = new Intent(this, MainActivity.class);
do this:
Intent resultIntent = getPackageManager().getLaunchIntentForPackage("your.package.name");
and put that in your Notification. This will launch the app if it is not already running, otherwise it will just bring the app's task to the foreground in whatever state it was when the user last used it. If the user is already in the app (ie: on another screen), this will do nothing when the user clicks the Notification.
Should be exactly what you are looking for.
Inside your launcher activity have you tried notification manager class cancelAll() method??
In this way if there is already a notification on launch then it will cancelled automatically
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 want to open an activity when user clicking on a notification. I can do it with a pending intent which works fine even if the activity already running. But I want to do some thing on the click operation. now I am doing that in onCreate method. it only works when the activity not running. I tried with onNewIntent method which is not reaching on above condition. What I can do now ?
NOTIFICATION_ID => A number used to identify the notification to do further operations.
mContext => Application context.
ResultActivity => Activity to be opened.
//creating intent
Intent resultIntent = new Intent(mContext, ResultActivity.class);
resultIntent.putExtra("update_request", true);
resultIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
//creating pending intent
PendingIntent resultPendingIntent =
PendingIntent.getActivity(
mContext,
0,
resultIntent,
PendingIntent.FLAG_UPDATE_CURRENT
);
//Build the notification using Notification.Builder
Notification.Builder builder = new Notification.Builder(mContext)
.setSmallIcon(R.drawable.icon)
.setAutoCancel(true)
.setContentTitle("Title")
.setContentIntent(resultPendingIntent) //adding pending intent
.setContentText("content");
NotificationManager mNotificationManager =
(NotificationManager)mContext.getSystemService(Context.NOTIFICATION_SERVICE);
//Get current notification
Notification mNotification = builder.getNotification();
//Show the notification
mNotificationManager.notify(NOTIFICATION_ID, mNotification);
Now you can do your operations on protected void onNewIntent(Intent intent) function of the Resulting activity.
And you also can set the new intent as intent of the activity as setIntent(intent) from the newIntent function.
Use PendingIntent.FLAG_UPDATE_CURRENT flag in pending intent to update the current activity. And then implement your login in onResume()
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 am able to create push notifications, and to send the user to whichever Activity I want, but I notice that whenever the user lands on that Activity, the onCreate function does not get called.
Is that supposed to be the case? How do I set it so that the onCreate of the Activity is called?
Here is my Activity:
public class QuestionActivity extends BaseListActivity
{
#Override
public void onCreate(Bundle savedInstanceState)
and here is how the notification is generated:
Intent notificationIntent = new Intent(context, MainActivity.class);
if ( notification_type != null && notification_type.equals("question"))
{
notificationIntent = new Intent(context, QuestionActivity.class);
}
else
if ( notification_type != null && notification_type.equals("plan"))
{
notificationIntent = new Intent(context, TopicActivity.class);
}
// set intent so it does not start a new activity
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent intent = PendingIntent.getActivity(context, 0, notificationIntent, 0);
Uri defaultSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
Notification notification = new NotificationCompat.Builder(context)
.setContentTitle(title)
.setContentText(message)
.setContentIntent(intent)
.setSmallIcon(icon)
.setLights(Color.YELLOW, 1, 2)
.setAutoCancel(true)
.setSound(defaultSound)
.build();
notificationManager.notify(0, notification);
Thanks!
The flags that you are using Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP mean that if the activity is already running in the current task, then instead of launching a new instance of that activity, the old existing activity will be used. In that case onCreate won't be called, since the activity already exists.