Androidアプリは強制終了後に再起動されます。20個のアクティビティで構成されるアプリケーション全体で、メインアクティビティで作成された静的データに依存しています。静的データは失われつつあり、アプリが実際に自動再起動すると、操作する必要のあるデータはなくなります。
私の質問は、クラッシュしたとき、私はこのことが起こるようにしたいです
アクティビティがクラッシュするタイミングを知っているAndroidシステムはスタック内の次のアクティビティをフォアグラウンドに移動します。これが私のアプリが冗長な結果を生成する理由です。また、Android =開発者ですが、知っているのはマニフェストで属性を設定することだけでしたAndroid:finishOnTaskLaunch="true"
。しかし、残念ながらこれは私には何の助けにもなりません。この問題を解決し、原因と分析を教えてください。
静的データを使用する代わりに、Shared Preferences
またはDatabase
にデータを保存し、もしあればuncaught Exception
が発生し、Application has crashed and a report is sent to the admin
そして、クラッシュの原因となったアクティビティを再起動します。このようにして、ユーザーはアプリケーションを引き続き使用できます。
同じことを行いますが、例外の原因となったアクティビティを再起動する代わりに、アプリケーションを再起動します。
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);
}
}
すべてのアクティビティでこのクラスのオブジェクトを作成し、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....
(参照:Archie.bpgc)
静的フィールドにデータを保存しないでください。低メモリイベントでプロセスが停止し、すべてが失われる可能性があります。ユーザーがアプリに再度切り替えると、アクティビティは保存された状態から復元されますが、静的変数は復元されません。
ユーザーがアプリを強制的に停止している場合([設定]> [アプリ]> [アプリ情報]または最近のアプリのリストから)、またはオペレーティングシステムがアプリを停止している場合は、 onSaveInstanceState()
。
ただし、アプリがクラッシュする場合は、(重要なものを設定/データベース/などに定期的に保存することを除いて)それに対してできることはあまりありません。クラッシュを処理しようとするよりも、クラッシュの防止に集中する方がおそらく良いでしょう!
さて、アプリケーションはインターフェース(アクティビティ)だけではありません。 SQLトランザクション、セキュリティ、Web認証などを使用する複雑なエンタープライズアプリケーションがあるとします。SharedPreferencesのみを使用して各アクティビティがアプリコンテキスト全体を回復できるようにすることはほとんど不可能です。したがって、この場合、次のコードを使用します。
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();
/*
....
*/
}
/*
....
*/
}
アプリがクラッシュしたときに、空白の画面で再開されました。これを解決するために、メインアクティビティのonCreateメソッドでsavedInstanceStateオブジェクトをチェックし、nullでない場合(Android system)によって再起動されることを意味する場合)、アクティビティを終了しました。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState != null) {
finish();
}
}
あなたの場合にも役立つかもしれません。