Android使用UncaughtExceptionHandler捕获异常
16lz
2021-01-26
Android中的系统ANR(Application Not Responding)异常通常会使得我们很烦恼,为了捕获异常以更友好的界面显示,在Android系统中有Thread.UncaughtExceptionHandler()方法,将异常类处理到线程,通过线程处理异常,继承该类就可以。
以下是具体实现方法:
1:本实例是通过Button触发抛出异常,MainActivity.java代码如下。
package activity.exceptionhandler.com.exceptionhandler;import android.os.Bundle;import android.support.v7.app.AppCompatActivity;import android.util.Log;import android.view.Menu;import android.view.MenuItem;import android.view.View;public class MainActivity extends AppCompatActivity implements View.OnClickListener{ @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initUI(); // initData(); } private void initData() { CrashHandler catchExcep = new CrashHandler(this); Thread.setDefaultUncaughtExceptionHandler(catchExcep); } private void initUI() { findViewById(R.id.bt).setOnClickListener(this); findViewById(R.id.tv); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.menu_main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); //noinspection SimplifiableIfStatement if (id == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item); } @Override public void onClick(View v) { switch (v.getId()){ case R.id.bt:{ Thread thread = new Thread(new Runnable() { @Override public void run() { Log.d("abc", "I am a thread"); String s = null; s.toString(); //抛出NullPointException } }, "thread"); thread.start(); } break; } }}
2:button事件编写完成,上述MainActivity.java通过Button抛出空指针异常,下面编写CrashHandler.java文件处理异常。
package activity.exceptionhandler.com.exceptionhandler;import android.app.AlarmManager;import android.app.PendingIntent;import android.content.Context;import android.content.Intent;import android.os.Build;import android.os.Environment;import android.os.Looper;import android.os.StatFs;import android.text.format.Formatter;import android.util.Log;import android.widget.Toast;import java.io.BufferedReader;import java.io.File;import java.io.FileReader;import java.io.IOException;public class CrashHandler implements Thread.UncaughtExceptionHandler { private static CrashHandler instance; //单例引用,这里我们做成单例的,因为我们一个应用程序里面只需要一个UncaughtExceptionHandler实例 private static Context myContext; private String errorInfo; private Thread.UncaughtExceptionHandler defalutHandler; public CrashHandler(Context context) { myContext = context; defalutHandler = Thread.getDefaultUncaughtExceptionHandler(); Thread.setDefaultUncaughtExceptionHandler(this); } CrashHandler() { } public synchronized static CrashHandler getInstance() { //同步方法,以免单例多线程环境下出现异常 if (instance == null) { instance = new CrashHandler(); } return instance; } public void init(Context context) { //初始化,把当前对象设置成UncaughtExceptionHandler处理器 myContext = context; defalutHandler = Thread.getDefaultUncaughtExceptionHandler(); Thread.setDefaultUncaughtExceptionHandler(this); } @Override public void uncaughtException(Thread thread, Throwable ex) { //当有未处理的异常发生时,就会来到这里。。 final String threadName = thread.getName(); errorInfo = ex.toString();//错误信息 String ThreadInfoName = thread.getName();//线程名 String packageName = thread.getClass().getPackage().toString(); StackTraceElement[] stack = ex.getStackTrace(); for (int i = 0; i < stack.length; i++) { errorInfo = errorInfo + stack[i] + "\n"; } /** * 该处编写相应事件即可 * 通过线程捕捉异常(非线程方法可能导致事件不能正常运行) * 具体原因:涉及系统层,此处不方便讲解 */ new Thread() { @Override public void run() { Looper.prepare(); Toast.makeText(myContext,errorInfo,Toast.LENGTH_LONG).show(); Looper.loop(); } }.start(); }}
注意:上述代码在uncaughtException中处理异常,最好是采用线程的方法,这样系统在处理时可以及时分配内存以相应相应的处理事件,否者可能导致事件无法相应(开发者可自行测试)。
3:再编写一个OurApplication.java类,继承Application,设置我们的异常处理器为UncaughtExceptionHandler处理器,具体代码如下。
package activity.exceptionhandler.com.exceptionhandler;import android.app.Application;import android.widget.Toast;public class OurApplication extends Application { @Override public void onCreate() { super.onCreate(); CrashHandler handler = CrashHandler.getInstance(); handler.init(getApplicationContext()); //在Appliction里面设置我们的异常处理器为UncaughtExceptionHandler处理器 }}
4:附上xml布局文件代码,此处简单。
<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:context=".MainActivity"> <TextView android:id="@+id/tv" android:text="aaa" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <Button android:id="@+id/bt" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Button"/></LinearLayout>
5:附上执行后视图。
弹框显示是捕获异常信息。
Good luck!
Write by Jimmy.li
更多相关文章
- SpringBoot 2.0 中 HikariCP 数据库连接池原理解析
- Andriod Service
- Android(安卓)WIFI框架分析(2)
- android 去锯齿
- android velocityTracker 简介
- Android(安卓)monkey自动化/压力测试(一)
- android xml解析 - sax
- Android(安卓)JNI 之 JNIEnv 解析
- Android_Button