Currently I am working on GCM (Google Cloud message), it allow user to push the message to user device. And I would like achieve the following requirement :
if the user has already enter app , ignore it
if the user has not enter the app , click on notification to enter the app
And the work flow of my app is:
WelcomePage (download json and create data set from it) => MainPage (Display base on the data set)
The code to handle notification
private void sendNotification(String msg) {
mNotificationManager = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
String notifyMsg = "";
JSONTokener tokener = new JSONTokener(msg);
if (tokener != null) {
try {
notifyMsg = new JSONObject(tokener).getString("msg");
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Intent myintent = new Intent(this, WelcomePageActivity.class);
myintent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, myintent, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle(getResources().getString(R.string.notification_title))
.setStyle(new NotificationCompat.BigTextStyle()
.bigText(notifyMsg))
.setContentText(notifyMsg)
.setContentIntent(contentIntent);
mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build());
}
The problem is if I use WelcomePageActivity class , it will create a new activity if I am at the main page, how can I adjust the code to fit my requirement ?
Thanks
For
1. if the user has already enter app , ignore it:
in the onReceive() , check if your app is running, do not notify.
It can be checked with something like:
ActivityManager activityManager =(ActivityManager)gpsService.this.getSystemService(ACTIVITY_SERVICE);
List<ActivityManager.RunningServiceInfo> serviceList= activityManager.getRunningServices(Integer.MAX_VALUE);
if((serviceList.size() > 0)) {
boolean found = false;
for(int i = 0; i < serviceList.size(); i++) {
RunningServiceInfo serviceInfo = serviceList.get(i);
ComponentName serviceName = serviceInfo.service;
if(serviceName.getClassName().equals("Packagename.ActivityOrServiceName")) {
//Your service or activity is running
break;
}
}
if the user has not enter the app , click on notification to enter the app
from the code above, you'l know if you would like to resume the app or launch - call Splash Screen or in your case WelcomeActivity.
About the workflow of your app, i'd suggest check whether you need to download the data every time or not. Can save it maybe or update/download only when required, and rest of flow works as it is.
In your AndroidManifest.xml, define your WelcomePageActivity with the flag android:launchMode="singleTop". From the definition of this flag:
A new instance of a "singleTop" activity may also be created to handle
a new intent. However, if the target task already has an existing
instance of the activity at the top of its stack, that instance will
receive the new intent (in an onNewIntent() call); a new instance is
not created.
So with this flag, your activity will not be created again, rather it will receive a call in the onNewIntent() function with the Intent you used to create the PendingIntent for the notification. You could override this function, and use the intent to pass the activity new information.
You will not able to receive any notification click event so,
try this code :
Intent myintent = new Intent(this, TestActivity.class);
myintent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, myintent, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle(getResources().getString(R.string.notification_title))
.setStyle(new NotificationCompat.BigTextStyle()
.bigText(notifyMsg))
.setContentText(notifyMsg)
.setContentIntent(contentIntent);
mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build());
}
public class TestActivity extends Activity{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// check for your app state is running or not
if(appRunning == false) {
// start your WelcomePage activity.
}
}
}
1.Create an object in GcmIntentService
public static final Object CURRENTACTIVIYLOCK = new Object();
//for storing current activity
public static Activity currentActivity;
2.Update this object value in onPause and onResume of MainActivity to recognize Activity is running or not.
#Override
public void onResume() {
super.onResume();
System.out.println("onResume Home page");
synchronized (GcmIntentService.CURRENTACTIVIYLOCK) {
GcmIntentService.currentActivity = this;
}
}
#Override
public void onPause() {
super.onPause();
synchronized (GcmIntentService.CURRENTACTIVIYLOCK) {
GcmIntentService.currentActivity = null;
}
}
3.In GcmIntentService class, check for the current activity in onHandleIntent method.
synchronized (CURRENTACTIVIYLOCK) {
if (currentActivity != null) {
if (currentActivity.getClass() == HomePageActivity.class) {
} else {
sendNotification(extras.getString("message"));
}
} else {
sendNotification(extras.getString("message"));
}
I'm sure this will help you.
Related
I'm getting notification from fcm when app is in foreground or background.
I don't want to show the notification When app in a specific activity how to disable notification when app is in specific activity.
I'm using datapaylod to for notification
You can check current top activity by:
public static Activity getActivity() {
Class activityThreadClass = Class.forName("android.app.ActivityThread");
Object activityThread = activityThreadClass.getMethod("currentActivityThread").invoke(null);
Field activitiesField = activityThreadClass.getDeclaredField("mActivities");
activitiesField.setAccessible(true);
Map<Object, Object> activities = (Map<Object, Object>) activitiesField.get(activityThread);
if (activities == null)
return null;
for (Object activityRecord : activities.values()) {
Class activityRecordClass = activityRecord.getClass();
Field pausedField = activityRecordClass.getDeclaredField("paused");
pausedField.setAccessible(true);
if (!pausedField.getBoolean(activityRecord)) {
Field activityField = activityRecordClass.getDeclaredField("activity");
activityField.setAccessible(true);
Activity activity = (Activity) activityField.get(activityRecord);
return activity;
}
}
return null;
}
you can check if top activity is the activity in which you don't want to show notification and then return the call from service.
Try this,
private void sendNotification(String msg) {
Intent notificationIntent = null;
notificationIntent = new Intent(currentactivity.this, Main2Activity.class);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent contentIntent = PendingIntent.getActivity(GCMNotificationIntentService.this, 0, notificationIntent, PendingIntent.FLAG_CANCEL_CURRENT);
NotificationManager nm = (NotificationManager) GCMNotificationIntentService.this.getSystemService(Context.NOTIFICATION_SERVICE);
Resources res = GCMNotificationIntentService.this.getResources();
NotificationCompat.Builder builder = new NotificationCompat.Builder(GCMNotificationIntentService.this);
builder.setContentIntent(contentIntent)
.setSmallIcon(R.drawable.app_logo_small_trans)
.setColor(getResources().getColor(R.color.app_logo_color))
.setLargeIcon(BitmapFactory.decodeResource(res, R.drawable.app_logo))
.setTicker(msg)
.setWhen(System.currentTimeMillis())
.setAutoCancel(true)
.setContentTitle("Propreka")
.setLights(0xffff0000, 100, 2000)
.setPriority(Notification.DEFAULT_SOUND)
.setContentText(msg);
Notification n = builder.getNotification();
n.defaults |= Notification.DEFAULT_ALL;
nm.notify(0, n);
}
So you want to know which (if any) activity is in foreground at the moment. And depending on the class type, want to limit the showing of notifications.
You need to maintain this yourself. Easiest way is to write a new class and have public static functions in it to mark activity as active / inactive
public static Activity mCurrentActivity = null;
public static void SetActivity(Activtiy activity) { mCurrentActivity = activity };
public static void ClearActivity(Activtiy activity)
{
if (mCurrentActivity.equals(activity))
mCurrentActivity = null;
}
public static Activity GetCurrentActivity() { return mCurrentActivity; }
Once you have such an infra, you can call the SetActivity and ClearActivity functions in all of your onResume and onPause overrides respectively.
Finally, in your notification builder class, you will get the instance of current activity and compare the .class to check if your desired activity is the one in focus. If the Current activity returns null, it means your app is not in foreground.
There are better, more efficient and cleaner way to do this. E.g. Dependency Injection with Daggr.
I am sending push notification to users which when clicking on it opens the app.
My problem is that when the app is already open, clicking on the notification start the app again.
I only want it to start the app if its not already running.
I am using Pending Intent in the notification:
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new Intent(this, Splash.class), 0);
I saw posts which say use:
<activity
android:name=".Splash"
android:launchMode="singleTask"
but the thing is that my running app is running other activity then the splash which is finished after 7 seconds from app start, so when the app is running Splash is not the current activity
Use a "launch Intent" for your app, like this:
PackageManager pm = getPackageManager();
Intent launchIntent = pm.getLaunchIntentForPackage("your.package.name");
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, launchIntent, 0);
Replace "your.package.name" with the name of your package from the Android manifest.
Also, you should remove the special launchMode="singleTask" from your manifest. Standard Android behaviour will do what you want.
String appPackageName = "";
private void isApplicationInForeground() throws Exception {
ActivityManager am = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
final List<ActivityManager.RunningAppProcessInfo> processInfos = am
.getRunningAppProcesses();
ActivityManager.RunningAppProcessInfo processInfo = processInfos
.get(0);
// for (ActivityManager.RunningAppProcessInfo processInfo : processInfos) {
if (processInfo.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
// getting process at 0th index means our application is on top on all apps or currently open
appPackageName = (Arrays.asList(processInfo.pkgList).get(0));
}
// }
}
else {
List<ActivityManager.RunningTaskInfo> taskInfo = am.getRunningTasks(1);
ComponentName componentInfo = null;
componentInfo = taskInfo.get(0).topActivity;
appPackageName = componentInfo.getPackageName();
}
}
private void notifyMessage(String text) {
if (appPackageName.contains("com.example.test")) {
// do not notify
}
else {
// create notification and notify user
}
}
For those who use Xamarin.Android.
The Xamarin version of David Wasser's answer is below:
//Create notification
var notificationManager = GetSystemService(Context.NotificationService) as NotificationManager;
Intent uiIntent = PackageManager.GetLaunchIntentForPackage("com.company.app");
//Create the notification
var notification = new Notification(Android.Resource.Drawable.SymActionEmail, title);
//Auto-cancel will remove the notification once the user touches it
notification.Flags = NotificationFlags.AutoCancel;
//Set the notification info
//we use the pending intent, passing our ui intent over, which will get called
//when the notification is tapped.
notification.SetLatestEventInfo(this, title, desc, PendingIntent.GetActivity(this, 0, uiIntent, PendingIntentFlags.OneShot));
//Show the notification
notificationManager.Notify(0, notification);
Instead of showing the Splash activity on notification click, show your MainActivity because your splash activity will closed after some time but MainActivity will be remain open and
<activity
android:name=".MainActivity"
android:launchMode="singleTask"
Use Splash as Fragment instead of Activity. Keep Splash fragment(7 seconds), replace the same with the desired one(landing page).
Add launchMode="singleTask" to the manifest.
As already stated by Rahul, onNewIntent() get called if application is already running else onCreate()
#Override
protected void onNewIntent(Intent intent)
{
super.onNewIntent(intent);
}
OR
Go with David's answer, seems promising.
when notification clicked and your code that redirect to your desire screen just replace that code by calling this method and redirect to particular screen on "true/false" result basis.
private boolean isAppOnForeground(Context context) {
ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
List<RunningAppProcessInfo> appProcesses = activityManager.getRunningAppProcesses();
if (appProcesses == null) {
return false;
}
final String packageName = context.getPackageName();
for (RunningAppProcessInfo appProcess : appProcesses) {
if (appProcess.importance == RunningAppProcessInfo.IMPORTANCE_FOREGROUND && appProcess.processName.equals(packageName)) {
return true;
}
}
return false;
}
Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT
And maybe don't start the Splash Activity and reopen (bring to front) the MainActivity and update the UI with a listener that tells you, that you have a new notification (with a flag - boolean or with an Interface to make a listener).
You can use an ordered broadcast to accomplish this.
1) Change your PendingIntent to start a BroadcastReceiver which will decide whether to start the activity or do nothing:
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, new Intent(this, DecisionReceiver.class), 0);
2) Create the decision BroadcastReceiver:
public class DecisionReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
context.sendOrderedBroadcast(new Intent(MainActivity.NOTIFICATION_ACTION), null, new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if (getResultCode() == MainActivity.IS_ALIVE) {
// Activity is in the foreground
}
else {
// Activity is not in the foreground
}
}
}, null, 0, null, null);
}
}
3) Create a BroadcastReceiver in your activity that will signal that it is alive:
public static final String NOTIFICATION_ACTION = "com.mypackage.myapplication.NOTIFICATION";
public static final int IS_ALIVE = 1;
private BroadcastReceiver mAliveReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
setResultCode(IS_ALIVE);
}
};
// Register onResume, unregister onPause
// Essentially receiver only responds if the activity is the foreground activity
#Override
protected void onResume() {
super.onResume();
registerReceiver(mAliveReceiver, new IntentFilter(NOTIFICATION_ACTION));
}
#Override
protected void onPause() {
super.onPause();
unregisterReceiver(mAliveReceiver);
}
notificationIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP|Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_ACTIVITY_NEW_TASK );
notificationIntent.putExtras(bundle);
PendingIntent pintent = PendingIntent.getActivity(context, 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
try adding this to your intent to bring activity to front if it is running in the background
Intent intent = new Intent(this, Splash.class);
intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, intent, 0);
first of all set a default Task android:taskAffinity="com.example.testp.yourPreferredName" in your Application element in the Manifest file. Maintain your android:launchMode="singleTask" on your SplashActivity. Now since your SplashActivity is your main entry add this code to both onResume(), onNewIntent() and onCreate() (on a second thought onResume() is not recomended) -follow the comments in the code
//Note these following lines of code will work like magic only if its UPVOTED.
//so upvote before you try it.-or it will crash with SecurityException
ActivityManager am = (ActivityManager) this.getSystemService(ACTIVITY_SERVICE);
List< ActivityManager.RunningTaskInfo > taskInfo = am.getRunningTasks(1000);
for(int i =0; i< taskInfo.size(); i++){
String PackageName = taskInfo.get(i).baseActivity.getPackageName();
if(PackageName.equals("packagename.appname")){// suppose stackoverflow.answerer.Elltz
//if the current runing actiivity is not the splash activity. it will be 1
//only if this is the first time your <taskAffinity> is be called as a task
if(taskInfo.get(i).numActivities >1){
//other activities are running, so kill this splash dead!! reload!!
finish();
// i am dying in onCreate..(the user didnt see nothing, that's the good part)
//about this code. its a silent assassin
}
//Operation kill the Splash is done so retreat to base.
break;
}
}
This code will not work on api 21+; to make it work you need to use AppTask, this will save you extra lines of code as you will not be in a Loop to find your Task.
Hope it helps
I am trying to "resume" a single task activity so it appears in the foreground when a user clicks my notification. (Same behavior as if the user tapped on the app icon from the applications menu.)
My notification creates a PendingIntent which broadcasts an action that is received by my broadcast receiver. If the app is in not in the foreground, I try to resume the app. Additionally, I'm trying to pass a message to my onResume function through the intent. However, I'm hitting an error:
Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?
Despite this error, my app is being resumed...don't understand why. However, my extras are not being passed to my onResume function.
So first I create a notification.
public static class MyNotificationCreator {
private static final int MY_NOTIFICATION_ID = 987;
public static void createNotification(Context context) {
Intent openAppIntent = new Intent(context, MyReceiver.class);
openAppIntent.setAction("PleaseOpenApp");
PendingIntent pi = PendingIntent.getBroadcast(context, /*requestCode*/0, openAppIntent, /*flags*/0);
Notification notification = ne Notification.Builder(context)
.setContentTitle("")
.setContentText("Open app")
.setSmallIcon(context.getApplicationInfo().icon)
.setContentIntent(pi)
.build();
NotificationManager notificationManager = (NotificationManager) applicationContext.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(MY_NOTIFICATION_ID, notification); }
}
Which broadcasts "PleaseOpenApp" for MyReceiver.
public class MyReceiver extends BroadcastReceiver {
#Override
public void onRecieve(Context context, Intent intent) {
if (intent.action() == "PleaseOpenApp" && !MyPlugin.isForeground) {
PackageManager pm = context.getPackageManager();
//Perhaps I'm not supposed to use a "launch" intent?
Intent launchIntent = pm.getLaunchIntentForPackage(context.getPackageName());
//I'm adding the FLAG_ACTIVITY_NEW_TASK, but I'm still hitting an error saying my intent does not have the FLAG_ACTIVITY_NEW_TASK...
launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
launchIntent.putExtra("foo", "bar");
context.startActivity(launchActivity);
} else {
//do other stuff
}
}
}
My plugin keeps track of whether or not we're in the foreground. Also, it tries to get "food" after my receiver attempts to start the app.
public class MyPlugin extends CordovaPlugin {
public static boolean isForeground = false;
#Override
public void initialize(CordovaInterface cordova, CordovaWebView webview) {
super.initialize(cordova, webview);
isForeground = true;
}
#Override
public void onResume(boolean multitasking) {
isForeground = true;
String foo = activity.getIntent().getStringExtra("foo");
Log.d("MyPlugin", foo); //foo is null after clicking the notification!
}
#Override
public void onPause(boolean multitasking) {
isForeground = false;
}
#Override
public void onDestroy() {
isForeground = false;
}
}
Note: because I'm using cordova my activity has a singleTask launchMode.
Also, I'm new to Android development so any help about resuming activities not in the foreground vs resuming activities that have been destroyed and info about general concepts / best practices that I'm not understanding would be appreciated!
I don't think your Broadcast/Broadcast Receiver pattern is necessary.
Intents can be used to directly launch an activity, and when you build the Intent, you can add the extras. Then, your activity onResume() can extract them directly.
Here is a sample Intent and PendingIntent construction that can be sent in a notification:
Intent startActivity = new Intent(context, MyActivity.class);
// You can experiment with the FLAGs passed here to see what they change
startActivity.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_NEW_TASK)
.putExtra("Extra1", myExtra1)
.putExtra("Extra2", myExtra2)
// ADDING THIS MAKES SURE THE EXTRAS ATTACH
.setAction("SomeString");
// Then, create the PendingIntent
// You can experiment with the FLAG passed here to see what it changes
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, startActivity, PendingIntent.FLAG_UPDATE_CURRENT);
// Then, create and show the notification
Notification notif = new NotificationCompat.Builder(context)
.setSmallIcon(R.drawable.my_small_icon)
.setContentTitle(myTitle)
.setContentText(myContent)
.setOngoing(isOngoingNotif)
.setAutoCancel(shouldAutoCancel)
.setOnlyAlertOnce(shouldAlertOnce)
.setContentIntent(pendingIntent)
.build();
NotificationManagerCompat manager = NotificationManagerCompat.from(context);
manager.notify(MY_NOTIFICATION_ID, notif);
In your code you are using a "launch Intent" to resume your application. You've added "extras" to the Intent but they will never be seen.
If your app is running, but in the background, and you call startActivity() with a "launch Intent", all this does it bring your task from the background to the foreground. It does not deliver the Intent to the Activity!.
A "launch Intent" does exactly the same thing as when you press the app icon of an app on the HOME screen (if it is already running, but in the background). This just brings the existing task in its current state, from the background to the foreground.
If you want to delivery "extras" to your app, you cannot use a "launch Intent". You must use a regular 'Intent. Depending on your architecture, you could either start a newActivity(which would get the "extras" inonCreate(), or you could start an existingActivity(which would get the "extras" inonNewIntent()`.
I have implemented a download manager which shows the completion notification on the navigation bar and when users touch the notification it automatically lanches my main activity.
Now the problem is when I press back button on main activity, it returns to previous activity which I don't want to happen.
The CODES I have tried are:
on Main Class:
#Override
public void onBackPressed() {
super.onBackPressed();
finish();
}
and this:
#Override
public void onBackPressed() {
super.onBackPressed();
Intent startMain = new Intent(Intent.ACTION_MAIN);
startMain.addCategory(Intent.CATEGORY_HOME);
startMain.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(startMain);
}
This is my Download Receiver Code:
private BroadcastReceiver downloadReceiver = new BroadcastReceiver() {
public void onReceive(Context ctxt, Intent i) {
if (DownloadManager.ACTION_NOTIFICATION_CLICKED.equals(i.getAction()))
startActivity(new Intent(getApplicationContext(),MainActivity.class));
else if (DownloadManager.ACTION_DOWNLOAD_COMPLETE.equals(i.getAction())) {
Toast.makeText(ctxt,"Done!",Toast.LENGTH_SHORT).show();
Log.i("download status: ", "Download Completed!");
MyNotificationManager.ShowNotification((Activity) ctxt, MainActivity.GetTheActivity(), R.drawable.ic_launcher, "package " + downloadedFileName),
"package" + downloadedFileName + " is downloaded!"), MyNotificationManager.SoundsType.System);
Log.i("download status: ", "Notification shown!");
DoBackgroundDatabaseOperations proceedDownload = new DoBackgroundDatabaseOperations();
proceedDownload.execute();// Sending the package
}
}
};
This is my MyNotificationManager class which has the following method to show Notification:
public static enum SoundsType
{
System,
My
}
public SoundsType SoundType;
static Uri soundUri;
public static void ShowNotification(Activity curActivity,Activity targetActivity,int icon,String title,String decs,SoundsType sound)
{
if (sound == SoundsType.System)
soundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
else if (sound == SoundsType.My)
soundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
Intent notificationIntent = new Intent(curActivity, targetActivity.getClass());
PendingIntent contentIntent = PendingIntent.getActivity(curActivity, 0, notificationIntent,PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder builder = new NotificationCompat.Builder(curActivity)
.setSmallIcon(icon)
.setContentTitle(title)
.setContentText(decs)
.setSound(soundUri)
.setAutoCancel(true)
.setContentIntent(contentIntent);
NotificationManager manager = (NotificationManager) curActivity.getSystemService(Context.NOTIFICATION_SERVICE);
manager.notify(0, builder.build());
}
Now What should I do in order to handle back button properly so it goes to previous app which could have been running, or home screen if user has launched my app from there?
I know this is more of a question than a code problem but I suppose this is a question of many others...
When you create the notification, you need to set the following flags on the `Intent:
Intent notificationIntent = new Intent(curActivity, targetActivity.getClass());
notificationIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
If your application is not already running, this will launch the target activity. If your application is already running and your target activity is still active (ie: not finished) then this will clear all activities in the task that are on top of the target activity and start a new instance of the target activity.
From your description this sounds like what you want.
I have created a big view style notification in a service
I intend to put a button that will pass some info back to the activity but it seems the activity just can't get the extras I set before.
Here's the code that I used to show the notification:
public class TestService extends Service {
...
#Override
public void onCreate() {
showNotification();
}
private void showNotification() {
PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
new Intent(this, TestActivity.class), PendingIntent.FLAG_UPDATE_CURRENT);
Intent discardIntent = new Intent(this, TestActivity.class);
discardIntent.putExtra("piAction", "discard");
PendingIntent piDiscard = PendingIntent.getActivity(this, 0, discardIntent, PendingIntent.FLAG_CANCEL_CURRENT);
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this);
mBuilder.setSmallIcon(R.drawable.ic_launcher);
mBuilder.setContentTitle("Test Notification");
mBuilder.addAction(R.drawable.content_discard, "Discard", piDiscard);
mBuilder.setStyle(new NotificationCompat.BigTextStyle().bigText("Test service is running"));
mBuilder.setContentIntent(contentIntent);
Notification notification = mBuilder.build();
notification.flags |= Notification.FLAG_AUTO_CANCEL;
mNotificationManager.notify(0, notification);
}
...
}
And here's the activity that will catch the info sent by the button in notification
public class TestActivity extends Activity {
...
#Override
protected void onResume() {
super.onResume();
Log.i("Activity Resume", "onResume");
Bundle extras = getIntent().getExtras();
if (extras != null) {
Log.i(TAG, "extras not null");
if (extras.containsKey("piAction")) {
Log.i("Intent Received", "piAction");
}
}
}
...
}
Please note, when launching TestActivity, it will also start TestService. What I intend to do is when the discard button inside the notification is clicked, it will pass the previously put extra back to TestActivity. However, after a few tests, I found TestActivity can be launched successfully, but it can't get the extras I set before.
So where's the possible problems in my code?
If you require any other details, please state in the comment, I'll update my question with those details accordingly.
I had face same type of problem when I was passing string from my notification to my launching activity to solve that
1) take a one String e.g. public String temp field in your application extended class
now instead of this
discardIntent.putExtra("piAction", "discard");
use this
YourApplication app = (YourApplication)getApplicationContext();
app.temp = "discard";
in your activity
instead of this
Bundle extras = getIntent().getExtras();
if (extras != null) {
Log.i(TAG, "extras not null");
if (extras.containsKey("piAction")) {
Log.i("Intent Received", "piAction");
}
}
get your piAction status from YourApplication
YourApplication app = (YourApplication)getApplicationContext();
String stringFromNotification = app.temp;