Android Force Close 出现的异常原因分析及解决方法

一、原因:

forceclose,意为强行关闭,当前应用程序发生了冲突。

NullPointExection(空指针),IndexOutOfBoundsException(下标越界),就连Android API使用的顺序错误也可能导致(比如setContentView()之前进行了findViewById()操作)等等一系列未捕获异常

二、如何避免

如何避免弹出Force Close窗口 ,可以实现Thread.UncaughtExceptionHandler接口的uncaughtException方法 代码如下:

public class MainActivity extends Activity implements Thread.UncaughtExceptionHandler,
View.OnClickListener {
private List<String> mList = new ArrayList<String>();
private Button btn;
private int pid;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.i("tag", "--->>onCreate");
initView();
//设置处理异常的handler
Thread.setDefaultUncaughtExceptionHandler(this);
}
/**
* 初始化控件
*/
private void initView() {
btn = (Button) findViewById(R.id.main_btn);
btn.setOnClickListener(this);
}
@Override
public void uncaughtException(Thread arg0, Throwable arg1) {
// TODO Auto-generated method stub
Log.i("tag", "截获到forceclose,异常原因为:" + "\n" +
arg1.toString()+" Thread:"+arg0.getId());
// finish();//结束当前activity
android.os.Process.killProcess(android.os.Process.myPid());
}
@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
switch (arg0.getId()) {
case R.id.main_btn:
mList.get(1) ;//产生异常
break;
default:
break;
}
}
@Override
protected void onPause() {
super.onPause();
Log.i("tag", "--》onpause");
}
@Override
protected void onStop() {
// TODO Auto-generated method stub
super.onStop();
Log.i("tag", "--->onstop");
}
@Override
protected void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
Log.i("tag", "-->ondestroy");
}
} 

 再补充一句,想要哪个线程可以处理未捕获异常,Thread.setDefaultUncaughtExceptionHandler( this); 这句代码都要在那个线程中执行一次

在uncaughtException方法中,第一个参数是线程,第二个参数是异常。

public void uncaughtException(Thread arg0, Throwable arg1) {
// TODO Auto-generated method stub
Log.i("tag", "截获到forceclose,异常原因为:" + "\n" +
arg1.toString()+" Thread:"+arg0.getId());
// finish();//结束当前activity
android.os.Process.killProcess(android.os.Process.myPid());
} 

 接下来,看log日志的结果:

08-0918:50:27.87410739-10739/example.com.force_anrI/tag:--->>onCreate
08-0918:50:31.66410739-10739/example.com.force_anrI/tag:截获到forceclose,异常原因为:

java.lang.IndexOutOfBoundsException:Invalidindex1,sizeis0Thread:1

成功捕获到了异常,而且activity也退出了,可是并不是安全退出,因为当你再次点击打开apk时,发现程序无响应。

为了解决上述问题,我在uncaughtException方法里将进程杀死,杀死进程有好多中方法,在此列举一个自杀式方法

修改如下:

@Override
public void uncaughtException(Thread arg0, Throwable arg1) {
// TODO Auto-generated method stub
Log.i("tag", "截获到forceclose,异常原因为:" + "\n" +
arg1.toString());
android.os.Process.killProcess(android.os.Process.myPid()); //
}

其他程序未变。。

3,我们不仅可以在主线程中这么做,还可以在子线程中进行:

然后在activity的生命周期中开启子线程,监听未捕获异常的发生。

class MyRunnable extends Thread implements Thread.UncaughtExceptionHandler {
@Override
public void run() {
// TODO Auto-generated method stub
Thread.setDefaultUncaughtExceptionHandler(this);
}
@Override
public void uncaughtException(Thread arg0, Throwable arg1) {
// TODO Auto-generated method stub
Log.i("tag", "childThread:截获到forceclose,异常原因为:" + "\n" +
arg1.toString()+" Thread->"+arg0.getId()+" 本线程id->"+Thread.currentThread().getId()+" "+
Thread.currentThread().getName());
android.os.Process.killProcess(android.os.Process.myPid());
}
}

  这里有个问题:我们明明是在子线程捕获的异常,但是怎么Thread的id->1 本线程id->1,为什么线程是主线程!在下面探讨这个问题。

08-09 19:02:47.734 14483-14483/example.com.force_anr I/tag: --->>onCreate
08-09 19:02:51.304 14483-14483/example.com.force_anr I/tag: childThread:截获到forceclose,异常原因为:
java.lang.IndexOutOfBoundsException: Invalid index 1, size is 0 Thread->1 本线程id->1 main 

4.解决第三步的问题

我们重写子线程:在子线程里设置异常,同时别忘把activity中的捕获异常的代码和发生异常的代码删除。

class MyRunnable extends Thread implements Thread.UncaughtExceptionHandler {
int a[];
@Override
public void run() {
// TODO Auto-generated method stub
Thread.setDefaultUncaughtExceptionHandler(this);
int i = a[0];//异常
}
@Override
public void uncaughtException(Thread arg0, Throwable arg1) {
// TODO Auto-generated method stub
Log.i("tag", "childThread:截获到forceclose,异常原因为:" + "\n" +
arg1.toString()+" Thread->"+arg0.getId()+" 本线程id->"+Thread.currentThread().getId()+" "+
Thread.currentThread().getName());
android.os.Process.killProcess(android.os.Process.myPid());
}
}

  在启动程序看到下面的log:

08-09 19:08:20.124 16308-16308/example.com.force_anr I/tag: --->>onCreate
08-09 19:08:20.124 16308-16341/example.com.force_anr I/tag: childThread:截获到forceclose,异常原因为:
java.lang.NullPointerException: Attempt to read from null array Thread->44829 本线程id->44829 Thread-44829
08-09 19:08:20.254 16349-16349/example.com.force_anr I/tag: --->>onCreate
08-09 19:08:20.354 16376-16376/example.com.force_anr I/tag: --->>onCreate
08-09 19:08:20.354 16376-16411/example.com.force_anr I/tag: childThread:截获到forceclose,异常原因为:
java.lang.NullPointerException: Attempt to read from null array Thread->44839 本线程id->44839 Thread-44839 

 好像是尝试启动了两次,看下Thread已经变了。所以在这个方法uncaughtException(Thread arg0, Throwable arg1)中的arg0指的是发生异常的那个Thread,而不一定是uncaughtException注册的Thread。

以上所述是小编给大家介绍的Android Force Close 出现的异常原因分析及解决方法,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对我们网站的支持!

(0)

相关推荐

  • C#中判断、验证字符串是否为日期格式的实现代码

    本文介绍C#编程时,给定一个字符串,如何判断它是不是一个日期.本文将介绍两种方法,一个是判断字符串是否是时间,如果是就转换为一个时间变量,第二个方法是只作判断. 在C#中,对格式的判断有一类专门函数,那就是TryParse.TryParse在各个不同的类型类(如int,string,DateTime)中,都是存在的.在TryParse中一般有两个参数,一个是待判断的字符串,另外一个是转换后的结果保存变量. 复制代码 代码如下: string strDate = "2014-4-3";

  • c#中判断字符串是不是数字或字母的方法

    一.判断字母 复制代码 代码如下: string str = Console.ReadLine();if (char.isLetter(str)){}else if (char.IsDigit(str)){} if(ch>='a'&&ch<='z') 小写字母if(ch>='A'&&ch<='Z') 大写字母数字也一样.判断汉字一般是输入 >255 因为汉字是大字符集二.判断输入的是不是数字 复制代码 代码如下: try{int n = 0;n

  • C#判断字符串是否是int/double(实例)

    话不多说,请看代码 using System.Text.RegularExpressions; /// <summary> /// 判断字符串是否是int/double /// </summary> public static bool IsIntOrDouble(string strNumber) { Regex objNotNumberPattern = new Regex("[^0-9.-]"); Regex objTwoDotPattern = new

  • C#判断字符串是否是数字(实例)

    话不多说,请看代码 /// <summary> /// 判断字符串是否是数字 /// </summary> public static bool IsNumber(string s) { if (string.IsNullOrWhiteSpace(s)) return false; const string pattern = "^[0-9]*$"; Regex rx = new Regex(pattern); return rx.IsMatch(s); } 以

  • asp.ent(C#)中判断空字符串的3种方法以及性能分析

    3种方法分别是: string a=""; 1.if(a=="") 2.if(a==String.Empty) 3.if(a.Length==0) 3种方法都是等效的,那么究竟那一种方法性能最高呢?本人用实验说明问题. 建立3个aspx页面(为什么用网页,主要是利用Microsoft Application Center Test ) WebForm1.aspx 复制代码 代码如下: private void Page_Load(object sender, Sys

  • C# 判断字符串为空的几种办法

    1. 三种常用的字符串判空串方法:Length法:bool isEmpty = (str.Length == 0);Empty法:bool isEmpty = (str == String.Empty);General法:bool isEmpty = (str == "");2. 深入内部机制:要探讨这三种方法的内部机制,我们得首先看看.NET是怎样实现的,也就是要看看.NET的源代码!然而,我们哪里找这些源代码呢?我们同样有三种方法:Rotor法:一个不错的选择就是微软的Rotor,

  • C#中判断字符串是全角还是半角的实现代码

    C#字符串的全角是指用二个字节来表示的一个字符 C#字符串的半角是用一个字节来表示的一个字符 这样的话我们就可以用string.length 和System.text.Encoding.Default.GetByteCount来判断 其中string.length表示C#字符串字符串的字符数, System.text.Encoding.Default.GetByteCount表示字符串的字节数. 判断半角如下: 复制代码 代码如下: if (checkString.Length == Encod

  • C#判断字符串是否存在字母及字符串中字符的替换实例

    本文实例讲述了C#判断字符串是否存在字母及字符串中字符的替换的方法.分享给大家供大家参考.具体实现方法如下: 首先要添加对命名空间"using System.Text.RegularExpressions;"的引用 下面以一个字符串为例: 复制代码 代码如下: string ss = "aaZ31 dd2f3"; string sss = ss.Replace(" ", "");//将字符串ss中的空格去掉 string ss

  • C# 判断字符串第一位是否为数字

    复制代码 代码如下: using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Windows.Forms;using System.Text.RegularExpressions; namespace WindowsFormsApp

  • C#判断一个字符串是否包含另一个字符串的方法

    本文实例讲述了C#判断一个字符串是否包含另一个字符串的方法.分享给大家供大家参考.具体如下: string a="china"; string b="i"; if (a.IndexOf(b) > -1) { //包含指定的字符串,执行相应的代码 } 希望本文所述对大家的C#程序设计有所帮助.

  • C#实现判断字符串中是否包含中文的方法

    本实例展示了C#实现判断字符串中是否包含中文的方法,是一个非常实用的功能,对初学者来说有一定的借鉴学习价值,具体实现方法如下: 主要功能代码如下: /// <summary> /// 判断字符串中是否包含中文 /// </summary> /// <param name="str">需要判断的字符串</param> /// <returns>判断结果</returns> public static bool Has

  • C#自动判断Excel版本使用不同的连接字符串

    用OLEDB通过设置连接字符串可以像读取sqlserver一样将excel中的数据读取出来,但是excel2003和excel2007/2010的连接字符串是不同的. /// <summary> /// 把数据从Excel装载到DataTable /// </summary> /// <param name="pathName">带路径的Excel文件名</param> /// <param name="sheetName

随机推荐