共计 2544 个字符,预计需要花费 7 分钟才能阅读完成。
典型错误表现
当 BluetoothUserService 参数错误时,常见的崩溃日志如下:

E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.bluetooth, PID: 12345
java.lang.IllegalArgumentException: Parameter "device" must not be null
at android.bluetooth.BluetoothUserService.connect(BluetoothUserService.java:123)
at com.example.bluetooth.MainActivity.startConnection(MainActivity.java:45)
这类错误会导致蓝牙功能完全不可用,用户会看到应用闪退或功能中断的提示,严重影响使用体验。
技术解析
参数传递机制
Android 蓝牙服务通过 Parcelable 接口实现跨进程参数传递:
- 调用
writeToParcel()序列化参数 - 通过 Binder 传输数据
- 接收方使用
CREATOR.createFromParcel()反序列化
// 典型 Parcelable 实现(以 BluetoothDevice 为例)public class BluetoothDevice implements Parcelable {public void writeToParcel(Parcel out, int flags) {out.writeString(mAddress);
}
public static final Creator<BluetoothDevice> CREATOR =
new Creator<>() {public BluetoothDevice createFromParcel(Parcel in) {return new BluetoothDevice(in.readString());
}
};
}
常见错误类型
- 空指针异常:未检查 nullable 参数
- 类型不匹配:传递了错误的 Parcelable 类型
- 权限缺失 :未声明
BLUETOOTH_CONNECT权限 - 版本不兼容:使用了新 API 但未检查 SDK 版本
解决方案
参数预校验工具类
public class BluetoothParamValidator {
/**
* 校验设备参数是否有效
* @throws IllegalArgumentException 当设备为 null 或未配对时抛出
*/
public static void validateDevice(@Nullable BluetoothDevice device) {if (device == null) {throw new IllegalArgumentException("BluetoothDevice cannot be null");
}
if (device.getBondState() != BluetoothDevice.BOND_BONDED) {throw new IllegalStateException("Device must be paired first");
}
}
// 单元测试用例
@Test(expected = IllegalArgumentException.class)
public void testNullDevice() {validateDevice(null);
}
}
Builder 模式重构
public class SafeBluetoothConnector {
private final BluetoothDevice device;
private int timeoutMs = 5000;
private SafeBluetoothConnector(Builder builder) {
this.device = builder.device;
this.timeoutMs = builder.timeoutMs;
}
public static class Builder {
private final BluetoothDevice device;
private int timeoutMs = 5000;
public Builder(@NonNull BluetoothDevice device) {BluetoothParamValidator.validateDevice(device);
this.device = device;
}
public Builder setTimeout(int milliseconds) {
this.timeoutMs = milliseconds;
return this;
}
public SafeBluetoothConnector build() {return new SafeBluetoothConnector(this);
}
}
}
生产环境实践
版本兼容处理
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
// Android 12+ 需要动态申请新权限
requestPermissions(new String[]{Manifest.permission.BLUETOOTH_CONNECT},
REQUEST_CODE
);
}
错误监控上报
try {bluetoothService.connect(device);
} catch (SecurityException e) {FirebaseCrashlytics.getInstance().log("Bluetooth permission denied");
showPermissionGuideDialog();} catch (IllegalArgumentException e) {FirebaseCrashlytics.getInstance().recordException(e);
Toast.makeText(this, R.string.invalid_device, Toast.LENGTH_SHORT).show();}
开放性问题
如何设计自动化测试方案来覆盖以下场景:
1. 模拟不同 Android 版本的参数校验行为
2. 自动生成异常参数组合(如 null 设备、未配对设备)
3. 验证跨进程序列化 / 反序列化的正确性
欢迎在评论区分享你的测试方案设计思路。
正文完
