android - savedinstancestate - ¿Cómo hacer reanudar la notificación y no recrear la actividad?
onstart android example (5)
¿Has anulado onBackPressed en tu actividad? Creo que si no anula onBackPressed, el valor predeterminado de Android es destruir (terminar ()) la Actividad. Entonces, probablemente, si regresa, su notificación verifica si la Actividad ya existe, no encuentra ninguna y luego crea una nueva.
Pensé que me había dado cuenta de esto, pero después de un poco de depuración en esta pregunta: cómo hacer que la notificación no se pueda cancelar o no se pueda quitar, me di cuenta de que mi actividad todavía se está realizando en Created () y onDestroyed (), en orden aleatorio.
Mi manifiesto para la actividad:
<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>
También he intentado launchmodes singleTask, singleInstance.
Mi código de intención para la notificación:
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);
Como puede ver, he probado todas las banderas que parecían relevantes, pero no hubo suerte ...
Esto proporciona algunos artefactos no deseados, como reiniciar mi AlarmManager y disparar la tarea de inicio de alarmmanager cada vez que se hace clic en la notificación. Me gustaría evitar esto.
¿Alguna sugerencia?
Edit: Sé que hay un montón de preguntas como esta, pero ninguna de las soluciones ofrecidas parece hacer el truco aquí ...: /
Edit2: Por solicitud, aquí está mi clase:
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);
}
}
Como se mencionó en los comentarios, después de iniciar loginActivity, onResume () aquí se vuelve a llamar inmediatamente. Lo mismo después de iniciar el alarmManager.
Además, cada vez que se activa el alarmManager, parece llevar la aplicación al primer plano. ¿Alguna forma de evitar eso?
En mi caso, la respuesta de CeeRo funcionó de manera extraña. ¡Tuve que reiniciar el teléfono! :)
No sé si mi caso me gusta o no. Intenté crear intenciones como tú. Estoy usando pageviewer + fragmento. En mi caso, haga clic en el mensaje de notificación para ir a la aplicación y luego a la página principal, luego vuelva a iniciar la aplicación, actividad recreada (este código en fragmento de clase)
Intent intent = new Intent(getActivity(),MainActivity.class);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(getActivity(), 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
Ahora está bien, cambiado a este código:
Intent intent = getActivity().getIntent();
PendingIntent pendingIntent = PendingIntent.getActivity(getActivity(), 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
Espero que esta ayuda ^ _ ^
Parece que el problema fue causado por estas líneas en el código de notificación (tomado directamente de la guía de Android en las notificaciones:
TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);
stackBuilder.addParentStack(FieldAgent.class);
stackBuilder.addNextIntent(intent);
PendingIntent pendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
Reemplazándolos con un pendiente regular como este lo resolvió:
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
Un ejemplo completo
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);
Tienes un montón de código que se está ejecutando varias veces.
Retirar:
saveVariables();
setVisible(false);
Desde onStop () y onDestroy (). Este código siempre se habrá ejecutado primero ya en onPause ().
loadVariables (); También se puede ejecutar dos veces. Una vez en onCreate () y una vez en onResume ().
Puede ser conveniente cambiar un poco su lógica de carga.
Es posible que su código init () se ejecute dos veces. Una vez en onCreate () y una vez en onActivityResult ().
TL; DR En cuanto a su problema real:
onActivityResult () es un poco raro a veces, ya que no siempre se dispara cuando crees que debería. Intente cargar sus variables antes de init () en onActivityResult ().
Para experimentar con esto, coloque un registro en onCreate (), onStart (), onResume () y onActivityResult () y observe cuándo se inicia cada uno.