Androidでクラッシュ異常を処理し、プログラムを再起動してページが重なる問題
22411 ワード
Android開発ではプログラム異常に遭遇することが多いが、異常アプリが現れると自動的に再起動することが多い.ただ、プロジェクトにFragmentの切り替えを適用すると、移動ページが重なる現象がある.今日はこの問題を解決するためにたくさんの牛のブログを見ました.最後にやっと問題を解決したので、解決方法を紹介します.全体的な問題解決の方向性はクラッシュ異常を処理する方法である.まず私が前に試した成功しない方法を話します.一、クラス実装UncaughtExceptionHandlerインタフェースを書く
二、androidアプリケーションというグローバルクラスで異常を処理することで、一般的には自分たちのアプリケーション継承アプリケーションを書き換えることができます.
人為的に異常を起こす
試行2:汎用アプリケーション1、すべてのavtivityを収集してアプリケーションを完全に終了する2、クラッシュ異常をキャプチャし、エラーログを保存し、アプリケーションを再起動する
例外取得の簡単な使い方:
以上の試みは成功しなかったが,次の方法は成功した.ステップ1.自分のアプリケーションクラスのonCreate()メソッドにコードを追加して異常をキャプチャし、異常を処理します.Thread.setDefaultUncaughtExceptionHandler(restartHandler);//プログラムクラッシュ時にトリガーされるスレッドの下には、プログラムクラッシュ異常をキャプチャするために使用されます.
ステップ2、作成方法作成サービス崩壊異常をキャプチャし、処理する
問題の解決に成功した.
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.Looper;
import android.util.Log;
import android.widget.Toast;
/**
* Created by willkong on 2016/12/14.
*/
public class UnCeHandler implements Thread.UncaughtExceptionHandler {
private Thread.UncaughtExceptionHandler mDefaultHandler;
public static final String TAG = "CatchExcep";
MyApplication application;
public UnCeHandler(MyApplication application){
// UncaughtException
mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
this.application = application;
}
@Override
public void uncaughtException(Thread thread, Throwable ex) {
if(!handleException(ex) && mDefaultHandler != null){
//
mDefaultHandler.uncaughtException(thread, ex);
}else{
try{
Thread.sleep(2000);
}catch (InterruptedException e){
Log.e(TAG, "error : ", e);
}
Intent intent = new Intent(application.getApplicationContext(), MainActivity.class);
PendingIntent restartIntent = PendingIntent.getActivity(
application.getApplicationContext(), 0, intent, Intent.FLAG_ACTIVITY_NEW_TASK);
//
AlarmManager mgr = (AlarmManager)application.getSystemService(Context.ALARM_SERVICE);
mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 1000,
restartIntent); // 1
application.finishActivity();
}
}
/**
* , .
*
* @param ex
* @return true: ; false.
*/
private boolean handleException(Throwable ex) {
if (ex == null) {
return false;
}
// Toast
new Thread(){
@Override
public void run() {
Looper.prepare();
Toast.makeText(application.getApplicationContext(), " , , .",
Toast.LENGTH_SHORT).show();
Looper.loop();
}
}.start();
return true;
}
}
二、androidアプリケーションというグローバルクラスで異常を処理することで、一般的には自分たちのアプリケーション継承アプリケーションを書き換えることができます.
import android.app.Activity;
import android.app.Application;
import java.util.ArrayList;
/**
* Created by willkong on 2016/12/14.
*/
public class MyApplication extends Application {
ArrayList list = new ArrayList();
@Override
public void onCreate() {
super.onCreate();
// CrashHandler
UnCeHandler catchExcep = new UnCeHandler(this);
Thread.setDefaultUncaughtExceptionHandler(catchExcep);
}
/**
* Activity , Activity Activity */
public void removeActivity(Activity a){
list.remove(a);
}
/**
* Activity Activity */
public void addActivity(Activity a){
list.add(a);
}
/**
* Activity Activity*/
public void finishActivity(){
for (Activity activity : list) {
if (null != activity) {
activity.finish();
}
}
//
android.os.Process.killProcess(android.os.Process.myPid());
}
}
人為的に異常を起こす
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
Button btn;
TextView tv;
private MyApplication application;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn = (Button)findViewById(R.id.btn);
tv = (TextView)findViewById(R.id.tv);
application = (MyApplication) getApplication();
application.addActivity(this);
btn.setOnClickListener(this);
}
/**
* */
public void press(){
new Thread(new Runnable() {
@Override
public void run() {
tv.setText("dfsd");
}
}).start();
}
@Override
public void onClick(View v) {
press();
}
}
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.testapplication.MainActivity">
<TextView
android:id="@+id/tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!" />
<Button
android:id="@+id/btn"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
LinearLayout>
試行2:汎用アプリケーション1、すべてのavtivityを収集してアプリケーションを完全に終了する2、クラッシュ異常をキャプチャし、エラーログを保存し、アプリケーションを再起動する
public class HKBaseApplication extends Application {
// activity , activity
private List activityList;
//
protected boolean isNeedCaughtExeption = true;//
private PendingIntent restartIntent;
private MyUncaughtExceptionHandler uncaughtExceptionHandler;
private String packgeName;
@Override
public void onCreate() {
super.onCreate();
activityList = new ArrayList();
packgeName = getPackageName();
if (isNeedCaughtExeption) {
cauchException();
}
}
// ------------------- ----- -----------------//
private void cauchException() {
Intent intent = new Intent();
// 1: , 2: activity
intent.setClassName(packgeName, packgeName + ".LoginActivity");
restartIntent = PendingIntent.getActivity(getApplicationContext(), -1, intent,
Intent.FLAG_ACTIVITY_NEW_TASK);
//
uncaughtExceptionHandler = new MyUncaughtExceptionHandler();
Thread.setDefaultUncaughtExceptionHandler(uncaughtExceptionHandler);
}
//
private class MyUncaughtExceptionHandler implements UncaughtExceptionHandler {
@Override
public void uncaughtException(Thread thread, Throwable ex) {
//
saveCatchInfo2File(ex);
// 1
AlarmManager mgr = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 1000, restartIntent);
//
finishAllActivity();
finishProgram();
}
};
/**
*
*
* @return
*/
private String saveCatchInfo2File(Throwable ex) {
Writer writer = new StringWriter();
PrintWriter printWriter = new PrintWriter(writer);
ex.printStackTrace(printWriter);
Throwable cause = ex.getCause();
while (cause != null) {
cause.printStackTrace(printWriter);
cause = cause.getCause();
}
printWriter.close();
String sb = writer.toString();
try {
DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
String time = formatter.format(new Date());
String fileName = time + ".txt";
System.out.println("fileName:" + fileName);
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
String filePath = Environment.getExternalStorageDirectory() + "/HKDownload/" + packgeName
+ "/crash/";
File dir = new File(filePath);
if (!dir.exists()) {
if (!dir.mkdirs()) {
// : SD
return "";
}
}
System.out.println("filePath + fileName:" + filePath + fileName);
FileOutputStream fos = new FileOutputStream(filePath + fileName);
fos.write(sb.getBytes());
fos.close();
// , , ,
}
return fileName;
} catch (Exception e) {
System.out.println("an error occured while writing file..." + e.getMessage());
}
return null;
}
// ------------------------------activity -----------------------//
// activity : activity
public void removeActivity(Activity activity) {
activityList.remove(activity);
}
// activity : activity
public void addActivity(Activity activity) {
activityList.add(activity);
}
// activity : activity
public void finishAllActivity() {
for (Activity activity : activityList) {
if (null != activity) {
activity.finish();
}
}
}
// , finishAllActivity()
// : finishAllActivity;finishProgram();
public void finishProgram() {
android.os.Process.killProcess(android.os.Process.myPid());
}
}
例外取得の簡単な使い方:
public class MyApplication extends Application implements
Thread.UncaughtExceptionHandler {
@Override
public void onCreate() {
super.onCreate();
// Thread Exception Handler
Thread.setDefaultUncaughtExceptionHandler(this);
}
@Override
public void uncaughtException(Thread thread, Throwable ex) {
System.out.println("uncaughtException");
System.exit(0);
Intent intent = new Intent(this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP |
Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
}
以上の試みは成功しなかったが,次の方法は成功した.ステップ1.自分のアプリケーションクラスのonCreate()メソッドにコードを追加して異常をキャプチャし、異常を処理します.Thread.setDefaultUncaughtExceptionHandler(restartHandler);//プログラムクラッシュ時にトリガーされるスレッドの下には、プログラムクラッシュ異常をキャプチャするために使用されます.
@Override
public void onCreate() {
super.onCreate();
Thread.setDefaultUncaughtExceptionHandler(restartHandler); //
}
ステップ2、作成方法作成サービス崩壊異常をキャプチャし、処理する
//
private UncaughtExceptionHandler restartHandler = new UncaughtExceptionHandler() {
public void uncaughtException(Thread thread, Throwable ex) {
restartApp();// ,
}
};
// App
public void restartApp(){
Intent intent = new Intent(this,MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
this.startActivity(intent);
android.os.Process.killProcess(android.os.Process.myPid()); //
}
問題の解決に成功した.