Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make notification resume and not recreate activity?

Tags:

I thought I had this figured out, but after some debugging on this question: How to make notification uncancellable/unremovable I just realized my activity is still getting onCreated() and onDestroyed(), in random order.

My manifest for the activity:

<activity         android:name="***.***.***.*****"         android:configChanges="orientation|keyboardHidden"         android:label="@string/app_name"         android:screenOrientation="portrait"         android:launchMode="singleTop" >         <intent-filter>             <action android:name="android.intent.action.MAIN" />              <category android:name="android.intent.category.LAUNCHER" />         </intent-filter>     </activity> 

I've also tried launchmodes singleTask, singleInstance.

My intent code for the notification:

Intent intent = new Intent(context, MyClass.class);     intent.setAction(Intent.ACTION_MAIN);     intent.addCategory(Intent.CATEGORY_LAUNCHER);     //intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);     //intent.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);     //intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);     //intent.setFlags(Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY);     //intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); 

As you can see, I've tried every flag that seemed like it could be relevant, but no luck...

This gives some unwanted artifacts, like restarting my AlarmManager and firing the alarmmanager start-task every time the notification is clicked. I'd like to avoid this.

Any suggestions?

Edit: I know there are a ton of questions like this, but none of the solutions offered seem to do the trick here... :/

Edit2: By request, here's my class:

package ***.***.***;  import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.os.Build; import android.os.Bundle; import android.annotation.TargetApi; import android.app.Activity; import android.app.AlarmManager; import android.app.NotificationManager; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.graphics.PorterDuff; import android.support.v4.app.FragmentActivity; import android.support.v4.app.NotificationCompat; import android.support.v4.app.TaskStackBuilder; import android.util.Log; import android.view.Menu; import android.view.View; import android.widget.Button; import android.widget.TextView; import android.widget.Toast;   public class MyClass extends FragmentActivity {   private static String userName; String password; private static Boolean LoggedIn = false; private static Boolean RunningState = false; private static Boolean OnlineState = false; private static String LastReportTime;  private static Boolean isVisible = true; private static Boolean firstStart = true;  private static TextView onlineTextView; private static TextView reportTimeTextView; private static TextView runningStatusTextView; private static TextView userLoggedInTextView;  private static Context context;  public static final String PREFS_NAME = "Settings";  public static final String NOTIFICATION_RUNNING_OK = "Reporting Active"; public static final String NOTIFICATION_USER_STOPPED = "Reporting Stopped"; public static final String NOTIFICATION_NO_NETWORK = "No Network Connected"; public static final String NOTIFICATION_NO_CONNECTION = "No Connection To Server";  public static final int NOTIFICATION_ID = 10;  public static final int LOGIN_REQUEST_CODE = 1; public static final int WAKEUP_LOGIN_REQUEST_CODE = 2;  @Override protected void onCreate(Bundle savedInstanceState)  {     super.onCreate(savedInstanceState);      Log.d("MyClass", "Main onCreate() Called");      loadVariables();      com.remobjects.sdk.TypeManager.setPackage("com.remobjects.sdk");     //if (firstStart)     //{         Log.d("MyClass", "Main onCreate() firstStart Called");         if (RunningState && checkConnection())         {            // After runLogin(), onResume() gets called here again immediately             setLoginCode(LOGIN_REQUEST_CODE);             runLogin();         }         else             init();     //} }  @Override protected void onStart() {     // TODO Auto-generated method stub     super.onStart(); }  @Override public void onResume() {     super.onResume();      Log.d("MyClass", "Main onResume() Called");     //firstStart gets set to false during login     if (!firstStart)     {         Log.d("MyClass", "Main onResume() !firstStart Called");         loadVariables();         setVisible(true);         updateUI();     } }  @Override protected void onPause() {     super.onPause();     saveVariables();     setVisible(false); }  @Override protected void onStop() {     super.onStop();      saveVariables();     setVisible(false); }  @Override public void onDestroy() {     super.onDestroy();     //cancelNotification();     Log.e("MyClass", "onDestroy() called");     saveVariables();     setVisible(false);     //setFirstStart(true); }   private void loadVariables() {     SharedPreferences sharedPrefs = getSharedPreferences(PREFS_NAME, 0);      userName = sharedPrefs.getString("userName", "");     RunningState = sharedPrefs.getBoolean("RunningState", true);     LoggedIn = sharedPrefs.getBoolean("LoggedIn", false);     OnlineState = sharedPrefs.getBoolean("OnlineState", false);     LastReportTime = sharedPrefs.getString("LastReportTime", "");      context = this.getApplicationContext(); }  private static void saveVariables() {     SharedPreferences settings = context.getSharedPreferences(PREFS_NAME, 0);     SharedPreferences.Editor editor = settings.edit();      editor.putString("userName", userName);     editor.putBoolean("RunningState", RunningState);     editor.putBoolean("LoggedIn", LoggedIn);     editor.putBoolean("OnlineState", OnlineState);     editor.putString("LastReportTime", LastReportTime);      editor.commit(); }  @Override public boolean onCreateOptionsMenu(Menu menu) {     // Inflate the menu; this adds items to the action bar if it is present.     getMenuInflater().inflate(R.menu.activity_my_class, menu);     return true; }  private Boolean checkConnection() {     Log.d("MyClass", "checkConnection()");     ConnectivityManager cnnxManager = (ConnectivityManager)              getSystemService(Context.CONNECTIVITY_SERVICE);      NetworkInfo ni = cnnxManager.getActiveNetworkInfo();      if (ni != null && ni.isAvailable() && ni.isConnected())      {         OnlineState = true;         return true;     }     OnlineState = false;     return false; }  public void runLogin() {     Intent intent = new Intent(context, LoginActivity.class);     startActivityForResult(intent, getLoginCode());     Log.d("MyClass", "runLogin()"); }  private void init() {     Log.d("MyClass", "init()");     setContentView(R.layout.activity_field_agent);      onlineTextView = (TextView)findViewById(R.id.onlineStatusTextView);     reportTimeTextView = (TextView)findViewById(R.id.lastReportTimeTextView);     runningStatusTextView = (TextView)findViewById(R.id.runningStatusTextView);     userLoggedInTextView = (TextView)findViewById(R.id.userLoggedInTextView);      findViewById(R.id.button_online).getBackground().setColorFilter(0xFF00FF00, PorterDuff.Mode.MULTIPLY);     findViewById(R.id.button_highRisk).getBackground().setColorFilter(0xFFFFA500, PorterDuff.Mode.MULTIPLY);     findViewById(R.id.button_alarm).getBackground().setColorFilter(0xFFFF0000, PorterDuff.Mode.MULTIPLY);      setVisible(true);      updateUI();      if (RunningState)     {         setupAlarmManager(AlarmManager.INTERVAL_FIFTEEN_MINUTES);         // Here onResume() gets called again         updateNotificationText(NOTIFICATION_RUNNING_OK);          Button temp = (Button)findViewById(R.id.button_online);         temp.setCompoundDrawablesWithIntrinsicBounds(R.drawable.check_box, 0, R.drawable.check_box, 0);     }     else     {         //cancelAlarmManager();          updateNotificationText(NOTIFICATION_USER_STOPPED);          Button temp = (Button)findViewById(R.id.button_offline);         temp.setCompoundDrawablesWithIntrinsicBounds(R.drawable.check_box, 0, R.drawable.check_box, 0);     } }  private void updateUI()  {     Log.d("MyClass", "updateUI()");      updateUserLoggedInStatus(userName);      updateOnlineStatus(OnlineState);      updateRunningStatus(RunningState);      updateReportTimeStatus(LastReportTime); }  public void offDutyButton_click(View view) {     cancelAlarmManager();     Button temp = (Button)findViewById(R.id.button_offline);     temp.setCompoundDrawablesWithIntrinsicBounds(R.drawable.check_box, 0, R.drawable.check_box, 0);      temp = (Button)findViewById(R.id.button_online);     temp.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);      temp = (Button)findViewById(R.id.button_highRisk);     temp.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);      temp = (Button)findViewById(R.id.button_alarm);     temp.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0); }  public void onDutyButton_click(View view) {     Button temp = (Button)findViewById(R.id.button_online);     temp.setCompoundDrawablesWithIntrinsicBounds(R.drawable.check_box, 0, R.drawable.check_box, 0);      temp = (Button)findViewById(R.id.button_offline);     temp.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);      temp = (Button)findViewById(R.id.button_highRisk);     temp.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);      temp = (Button)findViewById(R.id.button_alarm);     temp.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);     //cancelAlarmManager();     setupAlarmManager(AlarmManager.INTERVAL_FIFTEEN_MINUTES); }  public void highRiskButton_click(View view) {     Button temp = (Button)findViewById(R.id.button_highRisk);     temp.setCompoundDrawablesWithIntrinsicBounds(R.drawable.check_box, 0, R.drawable.check_box, 0);      temp = (Button)findViewById(R.id.button_online);     temp.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);      temp = (Button)findViewById(R.id.button_offline);     temp.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);      temp = (Button)findViewById(R.id.button_alarm);     temp.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0); }  public void alarmButton_click(View view) {     Button temp = (Button)findViewById(R.id.button_alarm);     temp.setCompoundDrawablesWithIntrinsicBounds(R.drawable.check_box, 0, R.drawable.check_box, 0);      temp = (Button)findViewById(R.id.button_online);     temp.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);      temp = (Button)findViewById(R.id.button_highRisk);     temp.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);      temp = (Button)findViewById(R.id.button_offline);     temp.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0); }  public static void setButtonIcon(int inId) {  }  public static void showToast(String inString, Context context) {     Toast.makeText(context, inString.toString(), Toast.LENGTH_SHORT).show(); }  public static void updateOnlineStatus(Boolean inStatus) {     if (isVisible)     {         if (inStatus)             onlineTextView.setText("Online");         else             onlineTextView.setText("Offline");     } }  public static void updateReportTimeStatus(String inString) {     if (isVisible)         reportTimeTextView.setText(inString); }  public static void updateRunningStatus(Boolean inStatus) {     if (isVisible)     {         if (inStatus)             runningStatusTextView.setText("Reporting");         else             runningStatusTextView.setText("Not Reporting");     } }  public static void updateUserLoggedInStatus(String inString) {     if (isVisible)         userLoggedInTextView.setText(inString); }   // // // Getters and Setters // // public static void setLoggedIn(Boolean inBool) {     LoggedIn = inBool; }  public static Boolean getLoggedIn() {     return LoggedIn; }  public static void setRunningState(Boolean inBool) {     RunningState = inBool; }  public static Boolean getRunningState() {     return RunningState; }  public static void setVisible(Boolean inBool) {     isVisible = inBool; }  public static Boolean getVisible() {     return isVisible; }  public static void setUsername(String inString) {     userName = inString; }  public static String getUsername() {     return userName; }  public static void setLastReportTime(String inString) {     LastReportTime = inString; }  public static String getLastReportTime() {     return LastReportTime; }  public static Context getAppContext() {     return MyClass.context; }  public static void setLoginCode(int code) {     SharedPreferences settings = context.getSharedPreferences(PREFS_NAME, 0);     SharedPreferences.Editor editor = settings.edit();      editor.putInt("LoginCode", code);      editor.commit(); }  public static int getLoginCode() {     SharedPreferences sharedPrefs = context.getSharedPreferences(PREFS_NAME, 0);      return sharedPrefs.getInt("LoginCode", 1); }  public static void setFirstStart(Boolean inBool) {     firstStart = inBool; }  public static Boolean getFirstStart() {     return firstStart; }  // // // // // @Override public void onActivityResult(int requestCode, int resultCode, Intent data) {   super.onActivityResult(requestCode, resultCode, data);   switch(requestCode) {     case (LOGIN_REQUEST_CODE) : {       if (resultCode == Activity.RESULT_OK) {         LoggedIn = data.getBooleanExtra("LoggedIn", false);         userName = data.getStringExtra("Username");          init();       }       break;     }     case (WAKEUP_LOGIN_REQUEST_CODE) : {         if (resultCode == Activity.RESULT_OK) {           LoggedIn = data.getBooleanExtra("LoggedIn", false);           userName = data.getStringExtra("Username");            cancelAlarmManager();           setupAlarmManager(AlarmManager.INTERVAL_FIFTEEN_MINUTES);         }         break;     }   } }  // // // AlarmManager // //  public static void setupAlarmManager(long interval) {     AlarmManager alarmMgr = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);     Intent alarmIntent = new Intent(context, LaunchReceiver.class);      PendingIntent pendingAlarmIntent = PendingIntent.getBroadcast(context.getApplicationContext(), 0, alarmIntent, 0);     alarmMgr.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, 0, interval,  pendingAlarmIntent);      RunningState = true;     updateRunningStatus(RunningState);      updateNotificationText(NOTIFICATION_RUNNING_OK);      Log.d("MyClass", "AlarmManager Started"); }   public static void cancelAlarmManager() {     Intent intent = new Intent(context.getApplicationContext(), LaunchReceiver.class);     PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0);     AlarmManager alarmMgr = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);     alarmMgr.cancel(pendingIntent);      RunningState = false;     updateRunningStatus(RunningState);      updateNotificationText(NOTIFICATION_USER_STOPPED);      Log.d("MyClass", "AlarmManager Stopped");      Intent serviceIntent = new Intent(context, MonitorService.class);     context.stopService(serviceIntent);     Log.d("MyClass", "Stopping MonitorService"); }    // // // 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("blablabla")                             .setContentText("Getting Status")                             .setSmallIcon(R.drawable.ic_launcher)                             .setOngoing(true)                             .setAutoCancel(false);      Intent intent = new Intent(context, MyClass.class);     intent.setAction(Intent.ACTION_MAIN);     intent.addCategory(Intent.CATEGORY_LAUNCHER);     //intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);     //intent.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);     //intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);     //intent.setFlags(Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY);     //intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);      TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);     stackBuilder.addParentStack(MyClass.class);     stackBuilder.addNextIntent(intent);      PendingIntent pendingIntent = stackBuilder.getPendingIntent(0,  PendingIntent.FLAG_UPDATE_CURRENT);      builder.setContentIntent(pendingIntent);      /*Notification noti = builder.build();     noti.flags = Notification.FLAG_NO_CLEAR | Notification.FLAG_ONGOING_EVENT;*/      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("blablabla")                                             .setSmallIcon(R.drawable.ic_launcher)                                             .setOngoing(true)                                             .setAutoCancel(false);      Intent intent = new Intent(context, MyClass.class);     intent.setAction(Intent.ACTION_MAIN);     intent.addCategory(Intent.CATEGORY_LAUNCHER);     //intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);      TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);     stackBuilder.addParentStack(MyClass.class);     stackBuilder.addNextIntent(intent);      PendingIntent pendingIntent = stackBuilder.getPendingIntent(0,  PendingIntent.FLAG_UPDATE_CURRENT);      builder.setContentIntent(pendingIntent);      /*Notification noti = builder.build();     noti.flags = Notification.FLAG_NO_CLEAR | Notification.FLAG_ONGOING_EVENT;*/      notificationManager.notify(NOTIFICATION_ID, builder.build()); }  public static void cancelNotification() {     NotificationManager notificationManager = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);      notificationManager.cancel(NOTIFICATION_ID); } } 

As mentioned in the comments, after starting the loginActivity, onResume() here gets called again immediately. Same after starting the alarmManager.

Also, every time the alarmManager ticks, it seems to bring the app to the foreground. Any way to avoid that?

like image 408
CeeRo Avatar asked Jun 03 '13 13:06

CeeRo


People also ask

What is pending intent in notification?

In other words, PendingIntent lets us pass a future Intent to another application and allow that application to execute that Intent as if it had the same permissions as our application, whether or not our application is still around when the Intent is eventually invoked.

How do I manage multiple notifications on Android?

Set the unique id to let Notification Manager knows this is a another notification instead of same notification. If you use the same unique Id for each notification, the Notification Manager will assume that is same notification and would replace the previous notification.


2 Answers

Looks like the problem was caused by these lines in the notification-code (taken straight from Android's guide on notifications:

TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);     stackBuilder.addParentStack(FieldAgent.class);     stackBuilder.addNextIntent(intent);      PendingIntent pendingIntent = stackBuilder.getPendingIntent(0,  PendingIntent.FLAG_UPDATE_CURRENT); 

Replacing them with a regular pendingintent like this solved it:

PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); 

An complete example

Intent intent = new Intent(getApplicationContext(), myactivity.class); PendingIntent pIntent = PendingIntent.getActivity(getApplicationContext(), (int)System.currentTimeMillis(), intent, 0);  Notification myNotification  = new Notification.Builder(getApplicationContext())                         .setContentTitle("Title")                         .setContentText("Some text....")                         .setSmallIcon(R.drawable.myicon)                         .setContentIntent(pIntent)                         .setAutoCancel(true).build();   NotificationManager notificationManager =                         (NotificationManager) getSystemService(NOTIFICATION_SERVICE);  notificationManager.notify(0, myNotification); 
like image 177
CeeRo Avatar answered Sep 20 '22 14:09

CeeRo


In my case, the answer have by CeeRo worked but in a weird fashion. I HAD TO RESTART THE PHONE! :)

like image 39
zsolt világos Avatar answered Sep 20 '22 14:09

zsolt világos