Mon Android est redémarrée après la fermeture forcée, à travers toute mon application qui se compose de 20 activités, je compte sur des données statiques créées sur une activité principale. Donc, une fois que l'application se bloque, toutes mes les données statiques se perdent et lorsque l'application redémarre automatiquement, elle n'a pas de données essentielles à exploiter.
Ma question est, en cas d'accident, je veux que ces choses se produisent
Je sais que l'activité se bloque Android mettra la prochaine activité de la pile au premier plan, et c'est la raison pour laquelle mon application produit des résultats redondants. J'ai également parcouru le Android = développeurs, mais la seule chose que j'ai connue était de mettre en place un attribut dans Manifest Android:finishOnTaskLaunch="true"
. Mais malheureusement, cela ne m'aide pas. J'apprécierais votre aide pour résoudre ce problème, et aussi me faire connaître la cause et l'analyse.
La meilleure solution serait au lieu d'utiliser des données statiques, utilisez Shared Preferences
ou stockez les données dans un Database
et le cas échéant uncaught Exception
se produit, affiche un message comme Application has crashed and a report is sent to the admin
, puis redémarrez l'activité à l'origine du crash. De cette façon, l'utilisateur peut continuer à utiliser l'application.
Faites de même mais au lieu de redémarrer l'activité qui a provoqué l'exception redémarrez l'application.
créer une classe utilisée pour gérer unCaughtException
public class MyExceptionHandler implements
Java.lang.Thread.UncaughtExceptionHandler {
private final Context myContext;
private final Class<?> myActivityClass;
public MyExceptionHandler(Context context, Class<?> c) {
myContext = context;
myActivityClass = c;
}
public void uncaughtException(Thread thread, Throwable exception) {
StringWriter stackTrace = new StringWriter();
exception.printStackTrace(new PrintWriter(stackTrace));
System.err.println(stackTrace);// You can use LogCat too
Intent intent = new Intent(myContext, myActivityClass);
String s = stackTrace.toString();
//you can use this String to know what caused the exception and in which Activity
intent.putExtra("uncaughtException",
"Exception is: " + stackTrace.toString());
intent.putExtra("stacktrace", s);
myContext.startActivity(intent);
//for restarting the Activity
Process.killProcess(Process.myPid());
System.exit(0);
}
}
et dans chaque activité, créez un objet de cette classe et définissez-le comme DefaultUncaughtExceptionHandler
Thread.setDefaultUncaughtExceptionHandler(new MyExceptionHandler(this,
YourCurrentActivity.class));
public class MyApp extends Application {
private static final String TAG = "MyApp";
private static final String KEY_APP_CRASHED = "KEY_APP_CRASHED";
@Override
public void onCreate() {
super.onCreate();
final UncaughtExceptionHandler defaultHandler = Thread.getDefaultUncaughtExceptionHandler();
Thread.setDefaultUncaughtExceptionHandler( new UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread thread, Throwable exception) {
// Save the fact we crashed out.
getSharedPreferences( TAG , Context.MODE_PRIVATE ).edit()
.putBoolean( KEY_APP_CRASHED, true ).apply();
// Chain default exception handler.
if ( defaultHandler != null ) {
defaultHandler.uncaughtException( thread, exception );
}
}
} );
boolean bRestartAfterCrash = getSharedPreferences( TAG , Context.MODE_PRIVATE )
.getBoolean( KEY_APP_CRASHED, false );
if ( bRestartAfterCrash ) {
// Clear crash flag.
getSharedPreferences( TAG , Context.MODE_PRIVATE ).edit()
.putBoolean( KEY_APP_CRASHED, false ).apply();
// Re-launch from root activity with cleared stack.
Intent intent = new Intent( this, MyRootActivity.class );
intent.addFlags( Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK );
startActivity( intent );
}
}
}
setContentView(R.layout.current);
Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread t, Throwable e) {
Android.os.Process.killProcess(Android.os.Process.myPid());
System.exit(0);
}
code....
(référence: Archie.bpgc)
Ne stockez pas de données dans des champs statiques. Votre processus pourrait être arrêté lors d'un événement de mémoire insuffisante et vous perdrez tout. Vos activités seront restaurées à partir de l'état enregistré si l'utilisateur bascule à nouveau vers votre application, mais vos variables statiques ne seront pas restaurées.
Si l'utilisateur arrête de force votre application (depuis Paramètres> Applications> Informations sur l'application ou depuis la liste des applications récentes) ou si le système d'exploitation arrête votre application, vous pouvez enregistrer tout ce dont vous avez besoin en utilisant onSaveInstanceState()
.
Cependant, si votre application se bloque, vous ne pouvez pas faire grand-chose (à part enregistrer périodiquement des éléments importants dans les préférences/bases de données/etc.). Il vaut probablement mieux se concentrer sur la prévention des plantages, plutôt que d'essayer de gérer les plantages!
Eh bien, une application n'est pas seulement une interface (activités). Imaginez que vous ayez une application d'entreprise complexe, utilisant des transactions SQL, la sécurité, l'authentification Web, etc. Il est presque impossible de rendre chaque activité capable de récupérer tout le contexte de l'application en utilisant uniquement les préférences partagées. Donc dans ce cas, j'utilise ce morceau de code:
public class MyApplication extends Application {
private static final String TAG = "my.app";
public static final String MainActivityName = "my.app.top.activity";
@Override
public void onCreate() {
try{
ActivityManager am = (ActivityManager) this .getSystemService(ACTIVITY_SERVICE);
List<ActivityManager.RunningTaskInfo> taskInfo = am.getRunningTasks(1);
ComponentName componentInfo = taskInfo.get(0).topActivity;
if (MainActivityName.length()>0 && !componentInfo.getClassName().equals(MainActivityName)){
Log.d(TAG, "Partial Restart Not Supported! : " +componentInfo.getClassName());
Android.os.Process.killProcess(Android.os.Process.myPid());
System.exit(0);
return;
}else
Log.d(TAG, "!!! BCSApplication topActivity=" +componentInfo.getClassName());
}catch(Exception eee){}
super.onCreate();
/*
....
*/
}
/*
....
*/
}
Mon application commençait également à reprendre avec un écran vide, lorsqu'elle se bloquait. Pour résoudre ce problème, j'ai vérifié l'objet savedInstanceState sur la méthode onCreate de mon activité principale et s'il n'est pas nul (signifie qu'il est redémarré par Android), j'ai alors terminé mon activité. Quelque chose comme ça:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState != null) {
finish();
}
}
Cela peut aussi aider dans votre cas.