Android开发中的异常统一处理

来源:互联网 发布:中国烟草待遇 知乎 编辑:程序博客网 时间:2024/05/16 12:03

                                                              Android开发中的异常统一处理

实际开发中为了防止程序异常奔溃,而使得开发人员不知道奔溃原因,且影响用户体验:所以我们应该在app中统一处理异常,拦截异常信息,上报服务器。

一自定义异常拦截实现Thread.UncaughtExceptionHandler重写拦截异常方法

public class CrashHandler implements Thread.UncaughtExceptionHandler{    public static final String TAG = "CrashHandler";    //系统默认的UncaughtException处理类    private Thread.UncaughtExceptionHandler mDefaultHandler;    //CrashHandler实例    private static volatile CrashHandler instance;    //程序的Context对象    private Context mContext;    //创建警告对话框    private   Dialog dialog;    //异常文件存储路径    private static final String PATH = Environment.getExternalStorageDirectory().getPath() + "/myExceptionCatch/log/";    //异常文件存储名字    private static final String FILE_NAME = "catch";    //异常文件存储后缀    private static final String FLIE_NAME_SUFFIX = ".log";    /**     * 无参构造     */    public CrashHandler() {    }    /**     * 获取CrashHandler实例 ,单例模式     */    public static CrashHandler getInstance() {        if (instance == null)            synchronized (CrashHandler.class) {                if (instance == null) {                    instance = new CrashHandler();                }            }        return instance;    }    /**     * 初始化     */    public void init(Context context) {        mContext = context.getApplicationContext();        //获取系统默认的UncaughtException处理器        mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();        //设置该CrashHandler为程序的默认处理器        Thread.setDefaultUncaughtExceptionHandler(this);    }    /**     * 程序崩溃会被该方法捕获到   在此添加逻辑是自己处理还是交给系统异常处理     * handleException是自己处理异常的方法     */    @Override    public void uncaughtException(Thread thread, Throwable throwable) {        if (!handleException(throwable) && mDefaultHandler != null) {            //如果用户没有处理则让系统默认的异常处理器来处理            mDefaultHandler.uncaughtException(thread, throwable);        } else {            Log.d("flag","----------------获取到异常了else");//            try {//                Thread.sleep(3000);//            } catch (InterruptedException e) {//                Log.e(TAG, "error : ", e);//            }//            //退出程序//            android.os.Process.killProcess(android.os.Process.myPid());//            System.exit(1);        }    }    /**     * 添加自己处理异常的方法    在这里收集收集的设备信息   保存异常文件     */    private boolean handleException(final Throwable ex) {        if (ex == null || mContext == null) {            return false;        }        new Thread(new Runnable() {            @Override            public void run() {                Looper.prepare();                try {                    //先获取手机的基本信息  将异常信息一起写入文件   上传服务器                    savcExceptionToSDCard(ex);                } catch (IOException e) {                    e.printStackTrace();                }                Toast.makeText(mContext, "很抱歉,程序出现异常,即将退出.", Toast.LENGTH_SHORT).show();                try {                    Thread.sleep(3000);                } catch (InterruptedException e) {                    Log.e(TAG, "error : ", e);                }                //退出程序                android.os.Process.killProcess(android.os.Process.myPid());                System.exit(1);                Looper.loop();            }        }).start();        return true;    }    /**     *  出现异常写到内存卡上   然后读文件上传到服务器     */    private void savcExceptionToSDCard(final Throwable ex) throws IOException {        if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {            Log.w("TAG", "sdcard unmounted,skip save exception");        }        File dir = new File(PATH);        if (!dir.exists()) {            dir.mkdirs();        }        long current = System.currentTimeMillis();        final String time = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(current));        File file = new File(PATH + FILE_NAME + FLIE_NAME_SUFFIX);        try {            //写入时间            PrintWriter pw = new PrintWriter(new BufferedWriter(new FileWriter(file)));            pw.println(time);            //写入手机信息            savePhoneInfo(pw, ex);        } catch (Exception e) {        }        //上传服务器        uploadToServer(file);    }    /**     *   写入手机基本信息   异常机型   异常原因等     */    private void savePhoneInfo(PrintWriter pw, Throwable ex) throws PackageManager.NameNotFoundException {        PackageManager pm = mContext.getPackageManager();        PackageInfo pi = pm.getPackageInfo(mContext.getPackageName(), PackageManager.GET_ACTIVITIES);        pw.print("App version: ");        pw.print(pi.versionName);        pw.print('_');        pw.println(pi.versionCode);        //Android版本号        pw.print("OS Version: ");        pw.print(Build.VERSION.RELEASE);        pw.print(" _ sdk: ");        pw.println(Build.VERSION.SDK_INT);        //手机制造商        pw.print("Vendor: ");        pw.println(Build.MANUFACTURER);        //手机型号        pw.print("Model: ");        pw.println(Build.MODEL);        //CPU架构        pw.print("CPU ABI : ");        pw.println(Build.CPU_ABI);        pw.println();        //异常信息        ex.printStackTrace(pw);        pw.close();    }    /**     * 读取文件转换成字符串     * 参数一 输入文件file     *     * @return     */    public String readFromFile(File file) {        BufferedReader bufferedReader = null;        try {            bufferedReader = new BufferedReader(new FileReader(file));            StringBuilder stringBuilder = new StringBuilder();            String content;            while ((content = bufferedReader.readLine()) != null) {                stringBuilder.append(content);            }            return stringBuilder.toString();        } catch (FileNotFoundException e) {            // TODO Auto-generated catch block            e.printStackTrace();            return null;        } catch (IOException e) {            // TODO Auto-generated catch block            e.printStackTrace();            return null;        } finally {            try {                if (bufferedReader != null) {                    bufferedReader.close();                }            } catch (IOException e) {                e.printStackTrace();            }        }    }    private void uploadToServer(File file) {        String ec=readFromFile(file);        OkhttpUtils.upEcInfo(ec,"服务器的url");    }}

二为了实现app全局监听  在App的application里进行注册

public class MyApplication extends Application {    private static MyApplication instance;    @Override    public void onCreate() {        super.onCreate();        //获取CrashHandler实例并初始化CrashHandler        CrashHandler.getInstance().init(getApplicationContext());    }    public static MyApplication getInstance() {        if (instance == null) {            instance = new MyApplication();        }        return instance;    }}

三清单文件

<manifest xmlns:android="http://schemas.android.com/apk/res/android"          package="com.example.wbxu.myexceptiondemo">     <uses-permission android:name="android.permission.INTERNET"/>    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>    <application        android:name=".MyApplication"        android:allowBackup="true"        android:icon="@mipmap/ic_launcher"        android:label="@string/app_name"        android:roundIcon="@mipmap/ic_launcher_round"        android:supportsRtl="true"        android:theme="@style/AppTheme">        <activity android:name=".MainActivity">            <intent-filter>                <action android:name="android.intent.action.MAIN"/>                <category android:name="android.intent.category.LAUNCHER"/>            </intent-filter>        </activity>    </application></manifest>

四上传工具本文使用okhttp

public class OkhttpUtils {    //上传字符串    private static final MediaType MEDIA_TYPE_MARKDOWN = MediaType.parse("text/x-markdown; charset=utf-8");    public static OkHttpClient mOkHttpClient;    //    public static String SessionKey;    // 1静态代码块初始化OkHttpClient    static {        // 2创建OkHttpClient构建器        OkHttpClient.Builder builder = new OkHttpClient.Builder();        // 3设置网络的链接超时时间        builder.connectTimeout(50, TimeUnit.SECONDS);        // 4使用构建器 构建出OkHttpClient        mOkHttpClient = builder.build();    }    //获取OkHttpClient的方法    public static OkHttpClient getOkHttpClient(){        return mOkHttpClient;    }    public static void upEcInfo(String ecInfo,String url){        RequestBody requestBody = RequestBody.create(MEDIA_TYPE_MARKDOWN, ecInfo);        //4创建请求对象        Request request = new Request.Builder()                .url(url)                .post(requestBody)                .build();        //5执行请求      enqueue异步请求        mOkHttpClient.newCall(request).enqueue(new Callback() {            @Override            public void onFailure(Call call, IOException e) {                Log.d("Flag","------上传异常失败错误信息为:e.getLocalizedMessage() = " + e.getLocalizedMessage());            }            @Override            public void onResponse(Call call, Response response) throws IOException {                String strInfo = response.body().string();                Log.d("flag", "----------------门店检查图片信息上传返回的请求体为" + strInfo);            }        });    }}

五mainActivity里创建异常进行测试

public class MainActivity extends AppCompatActivity {    private TextView ecTextView;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        ecTextView= (TextView) findViewById(R.id.tv);    }    /**     *  制造异常     */    public void buildEc(View view) {        new Thread(new Runnable() {            @Override            public void run() {                ecTextView.setText("异常捕获");            }        }).start();    }}

源码下载:http://download.csdn.net/detail/xuwb123xuwb/9872496





原创粉丝点击