CustomActivityOnCrash Android程序崩溃处理

前言
相信大家都遇到过测试人员测试的时候一些偶发性的bug导致程序崩溃,实在是难以复现,所以只能通过一遍遍的检查代码然后猜测可能出现问题的代码,非常难受,因为难以复现所以很多时候改完也难以验证,接下来就为大家介绍一个“轮子”,可以帮助我们在程序崩溃的时候跳转到指定页面,并且输出日志,可复制到粘贴板,然后保留下来,有了崩溃日志,问题出在哪儿就好分析啦。

首先肯定是先感谢大神的分享

https://github.com/Ereza/CustomActivityOnCrash

好了接下来就是实现的方法,第一步是导入处理崩溃的依赖

implementation 'cat.ereza:customactivityoncrash:2.3.0'//崩溃处理依赖

然后是在自己的Application中的onCreate()中添加以下代码

@Override
public void onCreate() {
    
    
    super.onCreate();
/**
//此方法定义当应用程序在后台崩溃时是否应启动错误活动。共有三种模式:
//CaocConfig.BACKGROUND_MODE_SHOW_CUSTOM:即使应用程序在后台运行,也会启动错误活动。
//CaocConfig.BACKGROUND_MODE_CRASH:当应用程序在后台运行时,启动默认系统错误。
//CaocConfig.BACKGROUND_MODE_SILENT:当应用程序在后台运行时,它会以静默方式崩溃。
//默认值为CaocConfig.BACKGROUND_MODE_SHOW_CUSTOM。
*/
    CaocConfig.Builder.create()
        .backgroundMode(CaocConfig.BACKGROUND_MODE_SILENT) //default: CaocConfig.BACKGROUND_MODE_SHOW_CUSTOM
        .enabled(false) //是否启用 default: true
        .showErrorDetails(false) //default: true 隐藏错误活动中的“错误详细信息”按钮
        .showRestartButton(false) //default: true 是否可以重启页面
        .logErrorOnRestart(false) //default: true 
        .trackActivities(true) //default: false
        .minTimeBetweenCrashesMs(2000) //default: 3000
        .errorDrawable(R.drawable.ic_custom_drawable) //default: bug image
        .restartActivity(YourCustomActivity.class) //默认程序崩溃时重启的的activity default: null (your app's launch activity)
        .errorActivity(YourCustomErrorActivity.class) //默认程序崩溃时跳转的activity default: null (default error activity)
        .eventListener(new YourCustomEventListener()) //default: null
        .apply();
}

然后是实现CustomEventListener

class CustomEventListener implements CustomActivityOnCrash.EventListener {
    
    
        @Override
        public void onLaunchErrorActivity() {
    
    
            Log.i(TAG, "onLaunchErrorActivity()");
        }

        @Override
        public void onRestartAppFromErrorActivity() {
    
    
            Log.i(TAG, "onRestartAppFromErrorActivity()");
        }

        @Override
        public void onCloseAppFromErrorActivity() {
    
    
            Log.i(TAG, "onCloseAppFromErrorActivity()");
        }
    }

重启页面就不多介绍了

.restartActivity(YourCustomActivity.class) //默认程序崩溃时重启的的activity default: null (your app's launch activity)

主要介绍一下,崩溃时跳转的页面,然后这个页面UI和流程设计的的好的话,其实还是比较好的,最起码比程序崩溃了闪退就好多了

.errorActivity(YourCustomErrorActivity.class) //默认程序崩溃时跳转的activity default: null (default error activity)

这是我的,因为我只是用作测试阶段的时候供测试人员提供崩溃日志,所以就随便写了;
首先是布局文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:ignore="MissingDefaultResource">

    <View
        android:id="@+id/V_statusBar"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:background="@color/colorPrimary" />


    <TextView
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:background="@color/colorPrimary"
        android:gravity="center"
        android:text="出错啦"
        android:textColor="#FFFFFF"
        android:textSize="17sp"
        android:textStyle="bold" />


    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#FFFFFF">

        <ImageView
            android:id="@+id/IMG_null"
            android:layout_width="248dp"
            android:layout_height="248dp"
            android:layout_centerInParent="true"
            android:layout_marginTop="100dp"
            android:src="@drawable/ic_null_page" />

        <TextView
            android:id="@+id/data_null_tip"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@+id/IMG_null"
            android:layout_centerHorizontal="true"
            android:gravity="center"
            android:textSize="16dp"
            android:text="@string/error_occurred"
            android:textColor="#FFD0DDF8" />
        <Button
            android:id="@+id/restart_button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"
            android:layout_alignParentRight="true"
            android:layout_margin="30dp"
            android:layout_centerHorizontal="true"
            android:text="@string/close_app" />
        <Button
            android:id="@+id/more_info_button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"
            android:layout_alignParentLeft="true"
            android:layout_margin="30dp"
            android:layout_centerHorizontal="true"
            android:text="@string/error_details" />

    </RelativeLayout>
</LinearLayout>

请添加图片描述
其中的文字,颜色和图片资源就自己替换一下哈;
加下来就是具体的activity,自定义的内容比较多,懒得一一复赘了,关键代码拷贝下来就可以哈;

public final class DefaultErrorActivity extends BaseActivity<ActivityErrorBinding> {
    
    


    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
    
    
        super.onCreate(savedInstanceState);
        viewBinding.VStatusBar.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, getStatusBarHeight(this)));
        QMUIStatusBarHelper.translucent(this);
        QMUIStatusBarHelper.setStatusBarDarkMode(this);
        //This is needed to avoid a crash if the developer has not specified
        //an app-level theme that extends Theme.AppCompat
        TypedArray a = obtainStyledAttributes(R.styleable.AppCompatTheme);
        if (!a.hasValue(R.styleable.AppCompatTheme_windowActionBar)) {
    
    
            setTheme(R.style.Theme_AppCompat_Light_DarkActionBar);
        }
        a.recycle();

        //Close/restart button logic:
        //If a class if set, use restart.
        //Else, use close and just finish the app.
        //It is recommended that you follow this logic if implementing a custom error activity.
        Button restartButton = viewBinding.restartButton;

        final CaocConfig config = CustomActivityOnCrash.getConfigFromIntent(getIntent());

        if (config == null) {
    
    
            //This should never happen - Just finish the activity to avoid a recursive crash.
            finish();
            return;
        }

        if (config.isShowRestartButton() && config.getRestartActivityClass() != null) {
    
    
            restartButton.setText(R.string.restart_app);
            restartButton.setOnClickListener(new View.OnClickListener() {
    
    
                @Override
                public void onClick(View v) {
    
    
                    CustomActivityOnCrash.restartApplication(DefaultErrorActivity.this, config);
                }
            });
        } else {
    
    
            restartButton.setOnClickListener(new View.OnClickListener() {
    
    
                @Override
                public void onClick(View v) {
    
    
                    CustomActivityOnCrash.closeApplication(DefaultErrorActivity.this, config);
                }
            });
        }

        Button moreInfoButton = viewBinding.moreInfoButton;

        if (config.isShowErrorDetails()) {
    
    
            moreInfoButton.setOnClickListener(new View.OnClickListener() {
    
    
                @Override
                public void onClick(View v) {
    
    
                    //We retrieve all the error data and show it

                    AlertDialog dialog = new AlertDialog.Builder(DefaultErrorActivity.this)
                            .setTitle(R.string.error_details)
                            .setMessage(CustomActivityOnCrash.getAllErrorDetailsFromIntent(DefaultErrorActivity.this, getIntent()))
                            .setPositiveButton(R.string.customactivityoncrash_error_activity_error_details_close, null)
                            .setNeutralButton(R.string.customactivityoncrash_error_activity_error_details_copy,
                                    new DialogInterface.OnClickListener() {
    
    
                                        @Override
                                        public void onClick(DialogInterface dialog, int which) {
    
    
                                            copyErrorToClipboard();
                                        }
                                    })
                            .show();
                    TextView textView = dialog.findViewById(android.R.id.message);
                    if (textView != null) {
    
    
                        textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, getResources().getDimension(R.dimen.error_details_text_size));
                    }
                }
            });
        } else {
    
    
            moreInfoButton.setVisibility(View.GONE);
        }

        Integer defaultErrorActivityDrawableId = config.getErrorDrawable();
        ImageView errorImageView = findViewById(R.id.customactivityoncrash_error_activity_image);

        if (defaultErrorActivityDrawableId != null) {
    
    
            errorImageView.setImageDrawable(ResourcesCompat.getDrawable(getResources(), defaultErrorActivityDrawableId, getTheme()));
        }
    }

    private void copyErrorToClipboard() {
    
    
        String errorInformation = CustomActivityOnCrash.getAllErrorDetailsFromIntent(DefaultErrorActivity.this, getIntent());

        ClipboardManager clipboard = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);

        //Are there any devices without clipboard...?
        if (clipboard != null) {
    
    
            ClipData clip = ClipData.newPlainText(getString(R.string.customactivityoncrash_error_activity_error_details_clipboard_label), errorInformation);
            clipboard.setPrimaryClip(clip);
            Toast.makeText(DefaultErrorActivity.this, R.string.customactivityoncrash_error_activity_error_details_copied, Toast.LENGTH_SHORT).show();
        }
    }
}

至此就可以了,程序遇到崩溃时就会自动跳转到自己定义的界面,和输出日志啦;

再次感谢分享,也可以查看原分享者的详细介绍

https://github.com/Ereza/CustomActivityOnCrash

猜你喜欢

转载自blog.csdn.net/gqg_guan/article/details/132106134