最近发现了谷歌安卓源生的一个bug,在这里记录一下。
操作步骤:
1、进入拨号界面,输入 *#*#4636#*#*
,然后会进入手机测试界面。
2、点击第三栏 Wi-Fi information 。
3、进入Wi-Fi information 界面后,点击第一栏 Wi-Fi API 。
4、进入Wi-Fi API 界面后,点击 enableNetwork 。这时会弹出一个输入栏,如果你输入为空或者输入为非数字,如何点击 OK ,连续操作俩次,就会显示 Settings keeps stopping。
分析:
从log中可以看到,有地方抛出了异常,追踪代码,发现异常为 java.lang.NumberFormatException 。
并且从log中也可以看出是 WifiAPITest 里出现了问题。另外从现象来看,导致 crash 的操作也是在WifiAPITest 中,那我们看代码。
从代码中可以看到,从 EditText 中输入内容后,要调用 Integer.parseInt() 来把string类型转换为int类型。因为enableNetwork 的参数是网络的ID,是数字。
packages/apps/Settings/src/com/android/settings/wifi/WifiAPITest.java
代码链接
public boolean onPreferenceClick(Preference pref) {
.......
} else if (pref == mWifiEnableNetwork) {
AlertDialog.Builder alert = new AlertDialog.Builder(getContext());
alert.setTitle("Input");
alert.setMessage("Enter Network ID");
// Set an EditText view to get user input
final EditText input = new EditText(getPrefContext());
alert.setView(input);
alert.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
Editable value = input.getText();
netid = Integer.parseInt(value.toString());
mWifiManager.enableNetwork(netid, false);
}
});
alert.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
// Canceled.
}
});
alert.show();
}
/libcore/ojluni/src/main/java/java/lang/Integer.java
看 parseInt 函数,可以看到当数据不符合规范时会抛出异常,比如你输入的是汉字或者十进制的字母,都是无法转换为 int 类型的,所以就会抛出异常。而对于这个异常,Integer 中并没有捕获,所以异常会抛给上层,也就是我们上面看的 WifiAPITest ,很明显 WifiAPITest 也没有处理这个异常。Java中如果异常没有处理,也没有 try catch捕获,会导致程序停止执行的。 所以当我们输入为空或者输入非数字,Settings 就会 crash 。
代码链接
public static int parseInt(String s, int radix)
throws NumberFormatException
{
...........
if (len > 0) {
char firstChar = s.charAt(0);
if (firstChar < '0') { // Possible leading "+" or "-"
if (firstChar == '-') {
negative = true;
limit = Integer.MIN_VALUE;
} else if (firstChar != '+')
throw NumberFormatException.forInputString(s);
if (len == 1) // Cannot have lone "+" or "-"
throw NumberFormatException.forInputString(s);
i++;
}
multmin = limit / radix;
while (i < len) {
// Accumulating negatively avoids surprises near MAX_VALUE
digit = Character.digit(s.charAt(i++),radix);
if (digit < 0) {
throw NumberFormatException.forInputString(s);
}
if (result < multmin) {
throw NumberFormatException.forInputString(s);
}
result *= radix;
if (result < limit + digit) {
throw NumberFormatException.forInputString(s);
}
result -= digit;
}
} else {
throw NumberFormatException.forInputString(s);
}
return negative ? result : -result;
}
解决:
谷歌的 pixel 源生机也存在这个问题,但是我用的这个小米手机没有这个问题。其实这个问题不难解决,在调用 Integer.parseInt 的地方,加一个 try catch 语句,将这个异常进行捕获就好了。
关注公众号,获取更多开发必备知识