Skip to content

Commit 9785865

Browse files
author
yangtianci
committed
1、工具类:Logutils\ToastUtil;
2、子线程拦截提示
1 parent 0709d4e commit 9785865

File tree

10 files changed

+399
-37
lines changed

10 files changed

+399
-37
lines changed

app/src/main/java/com/aiyang/android_crashx/MainActivity.java

+9-3
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,19 @@ public class MainActivity extends AppCompatActivity {
1111
protected void onCreate(Bundle savedInstanceState) {
1212
super.onCreate(savedInstanceState);
1313
setContentView(R.layout.activity_main);
14-
15-
16-
1714
}
1815

1916
public void clickNullPointerException(View view) {
2017

2118
throw new NullPointerException();
2219
}
20+
21+
public void clickIndexOutOfBoundsException(View view) {
22+
new Thread(new Runnable() {
23+
@Override
24+
public void run() {
25+
throw new IndexOutOfBoundsException();
26+
}
27+
}).start();
28+
}
2329
}

app/src/main/res/layout/activity_main.xml

+4-3
Original file line numberDiff line numberDiff line change
@@ -15,32 +15,33 @@
1515
<LinearLayout
1616
android:layout_width="match_parent"
1717
android:layout_height="match_parent"
18-
android:paddingTop="30dp"
1918
android:gravity="center_horizontal"
2019
android:orientation="vertical">
2120

2221

2322
<TextView
2423
android:layout_width="match_parent"
2524
android:layout_height="wrap_content"
25+
android:padding="10dp"
2626
android:background="@color/gray"
2727
android:text="——————java 崩溃"/>
2828
<Button
2929
android:layout_width="wrap_content"
3030
android:layout_height="wrap_content"
3131
android:text="(主线程)空指针异常"
32+
android:layout_marginTop="30dp"
3233
android:background="@color/colorPrimary"
3334
android:textColor="@color/white"
3435
android:onClick="clickNullPointerException" />
3536

3637
<Button
3738
android:layout_width="wrap_content"
3839
android:layout_height="wrap_content"
39-
android:text="子线程"
40+
android:text="子线程) 数组越界异常"
4041
android:layout_marginTop="30dp"
4142
android:background="@color/colorPrimary"
4243
android:textColor="@color/white"
43-
android:onClick="clickNullPointerException" />
44+
android:onClick="clickIndexOutOfBoundsException" />
4445

4546

4647
<TextView

crashx/src/main/java/com/aiyang/crashx/CrashX.java

+9-5
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,24 @@
33
import android.content.Context;
44

55
import com.aiyang.crashx.init.RealCrash;
6+
import com.aiyang.crashx.inter.ICrash;
67

78
public final class CrashX{
89

9-
private static RealCrash rCrash;
10+
private static ICrash rCrash;
1011

1112

1213
public static void install(Context mContext) {
14+
//实例一次,安装一次
1315
if (rCrash==null){
14-
rCrash = new RealCrash();
16+
rCrash = new RealCrash(mContext);
17+
rCrash.setUncaughtCrash();
1518
}
16-
rCrash.setUncaughtCrash(mContext);
1719
}
1820

19-
//扩展功能:设置正式环境、debug环境
20-
public static void setDebug(){}
21+
//扩展功能:设置正式环境、debug环境功能提示不同
22+
public static void setDebug(){
23+
24+
}
2125

2226
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package com.aiyang.crashx.init;
2+
3+
import android.content.Context;
4+
import android.os.Looper;
5+
6+
import com.aiyang.crashx.R;
7+
import com.aiyang.crashx.inter.IKeepLoop;
8+
import com.aiyang.crashx.util.LogUtils;
9+
import com.aiyang.crashx.util.ToastUtil;
10+
11+
/**
12+
* @author aiyang
13+
*/
14+
public final class KeepLoop implements IKeepLoop {
15+
16+
/**
17+
* 是否已轮询
18+
*/
19+
private static boolean isWhile = true;
20+
21+
private static KeepLoop mInstance;
22+
23+
public static synchronized KeepLoop getInstance(){
24+
if (mInstance ==null){
25+
mInstance = new KeepLoop();
26+
}
27+
return mInstance;
28+
}
29+
30+
/**
31+
* 主线程或子线程抛出异常后,迫使主线程Looper持续loop()
32+
*/
33+
@Override
34+
public void keepLoop(final Context mContext,Thread t) {
35+
if (t == Looper.getMainLooper().getThread()){
36+
if (isWhile){
37+
isWhile = false;
38+
ToastUtil.show(mContext,mContext.getString(R.string.crash_tip2));
39+
while (true) {
40+
try {
41+
Looper.loop();
42+
} catch (Throwable e) {
43+
//再次出错,打印错误并提示,接着死循环,再次拉起loop
44+
e.printStackTrace();
45+
ToastUtil.show(mContext,mContext.getString(R.string.crash_over));
46+
}
47+
}
48+
}
49+
}else{
50+
LogUtils.d(mContext.getString(R.string.crash_tip1));
51+
new Thread() {
52+
@Override
53+
public void run() {
54+
Looper.prepare();
55+
ToastUtil.show(mContext,mContext.getString(R.string.crash_tip1));
56+
Looper.loop();
57+
}
58+
}.start();
59+
60+
}
61+
}
62+
}

crashx/src/main/java/com/aiyang/crashx/init/RealCrash.java

+26-24
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,35 @@
11
package com.aiyang.crashx.init;
22

33
import android.content.Context;
4+
import android.os.Handler;
45
import android.os.Looper;
5-
import android.util.Log;
6-
import android.widget.Toast;
76

7+
import com.aiyang.crashx.R;
88
import com.aiyang.crashx.inter.ICrash;
9+
import com.aiyang.crashx.util.LogUtils;
10+
import com.aiyang.crashx.util.ToastUtil;
911

12+
/**
13+
* @author aiyang
14+
*/
1015
public class RealCrash implements Thread.UncaughtExceptionHandler, ICrash {
1116

12-
1317
private Context mContext;
1418

1519
private Thread.UncaughtExceptionHandler mDefaultCaughtExceptionHandler;
1620

21+
private KeepLoop keepLoop;
1722

18-
public void setUncaughtCrash(Context mContext) {
23+
public RealCrash(Context mContext) {
1924
this.mContext = mContext;
25+
keepLoop = KeepLoop.getInstance();
26+
}
2027

28+
/**
29+
* 拦截系统异常捕获器
30+
*/
31+
@Override
32+
public void setUncaughtCrash() {
2133
//获取默认的系统异常捕获器
2234
if (mDefaultCaughtExceptionHandler == null){
2335
mDefaultCaughtExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();
@@ -30,40 +42,30 @@ public void setUncaughtCrash(Context mContext) {
3042

3143
@Override
3244
public void uncaughtException(Thread thread, Throwable throwable) {
33-
Log.d("aaa",thread.getName()+"线程");
45+
LogUtils.d("出现异常:"+thread.toString());
3446
if (!handleException(throwable) && mDefaultCaughtExceptionHandler != null) {
3547
//如果无法拦截处理,则让系统默认的异常处理器来处理
3648
mDefaultCaughtExceptionHandler.uncaughtException(thread, throwable);
3749

38-
//重启应用
39-
Log.d("aaa","handleException: 异常未拦截,待重启");
50+
//建议重启应用
51+
ToastUtil.show(mContext,mContext.getString(R.string.carsh_noway));
52+
}else{
53+
keepLoop.keepLoop(mContext,thread);
4054
}
41-
4255
}
4356

4457
/**
45-
* 自定义错误处理
46-
* @return true:处理了该异常; 否则返回false
58+
* 错误处理检测
59+
* @return true:可以拦截该异常; 否则返回false
4760
*/
4861
@Override
4962
public boolean handleException(Throwable ex) {
5063
if (ex == null) {
5164
return false;
5265
}
53-
final String msg = ex.getLocalizedMessage();
54-
if (msg == null) {
55-
return false;
56-
}
57-
Log.d("aaa","handleException: 异常被拦截,待处理");
58-
// //使用Toast来显示异常信息
59-
// new Thread() {
60-
// @Override
61-
// public void run() {
62-
// Looper.prepare();
63-
// Toast.makeText(mContext, "异常被拦截,待处理", Toast.LENGTH_LONG).show();
64-
// Looper.loop();
65-
// }
66-
// }.start();
66+
String msg = ex.toString();
67+
68+
LogUtils.d("异常允许被拦截:"+msg);
6769
return true;
6870
}
6971

Original file line numberDiff line numberDiff line change
@@ -1,9 +1,15 @@
11
package com.aiyang.crashx.inter;
22

33
public interface ICrash {
4+
5+
/**
6+
* 拦截异常捕获
7+
*/
8+
void setUncaughtCrash();
49
/**
5-
* 自定义错误处理
6-
* @return true:处理了该异常; 否则返回false
10+
* 错误处理检测
11+
* @return true:可以处理该异常; 否则返回false
712
*/
813
boolean handleException(Throwable ex);
14+
915
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package com.aiyang.crashx.inter;
2+
3+
import android.content.Context;
4+
5+
public interface IKeepLoop {
6+
/**
7+
* 主线程或子线程抛出异常后,迫使主线程Looper持续loop()
8+
*/
9+
void keepLoop(Context mContext,Thread t);
10+
}

0 commit comments

Comments
 (0)