Xamarin BluetoothLE插件运行异常:GattServer空引用异常排查
排查Xamarin.Forms中BluetoothLE插件的空引用异常
咱们一步步拆解这个问题,你碰到的空引用异常大概率是几个BLE开发常见坑叠加导致的,我帮你逐个排查:
1. 先修复异步方法调用的问题
你在OnCreate里调用BroadcastBluetooth时没有await,而且catch块是空的——这会导致两个关键问题:
- 方法可能在Activity还没完全初始化完成时就执行,系统BLE服务还没准备好
- 哪怕
CrossBleAdapter.Current本身就是null,这个异常也被你吞了,根本看不到真正的根源
修复方式:
在Activity里用异步包装方法调用,并且不要吞异常,打印完整错误日志:
protected override void OnCreate(Bundle savedInstanceState) { base.OnCreate(savedInstanceState); // 先初始化插件(后面会说),再调用异步方法 _ = StartBluetoothServerSafely(); } private async Task StartBluetoothServerSafely() { try { // 替换Task.Delay,等待蓝牙适配器真正就绪 await CrossBleAdapter.Current.WhenStatusChanged() .FirstOrDefault(status => status == AdapterStatus.Ready); var server = CrossBleAdapter.Current.CreateGattServer(); await server.Start(new AdvertisementData { LocalName = "TestServer", // 建议添加一个测试UUID,空列表可能导致部分设备广告失败 ServiceUuids = new List<Guid> { Guid.NewGuid() } }); } catch (Exception e) { // 打印完整异常栈,包括内部细节 Android.Util.Log.Debug("BLE_CRASH", e.ToString()); Console.WriteLine(e); } }
2. 关键遗漏:插件必须初始化
这个蓝牙LE插件必须在Android项目中手动初始化,否则CrossBleAdapter.Current内部的系统服务引用会是空的,后续生成的GattServer对象自然会出问题。
添加初始化代码:
在MainActivity的OnCreate最开始(LoadApplication之前)加上:
// 传入当前Activity上下文,让插件绑定系统BLE服务 CrossBleAdapter.Current.Init(this);
3. 检查BLE权限和蓝牙状态
Android对BLE的权限控制很严格,不同版本要求不同:
- Android 12+:需要
BLUETOOTH_ADVERTISE、BLUETOOTH_CONNECT、BLUETOOTH_SCAN权限 - Android 11及以下:需要
BLUETOOTH、BLUETOOTH_ADMIN、ACCESS_FINE_LOCATION权限
在AndroidManifest.xml中添加权限:
<!-- 声明设备支持BLE硬件 --> <uses-feature android:name="android.hardware.bluetooth_le" android:required="true" /> <!-- Android 12+ 专属权限 --> <uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" /> <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" /> <uses-permission android:name="android.permission.BLUETOOTH_SCAN" /> <!-- 兼容低版本Android的权限 --> <uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" /> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" android:maxSdkVersion="30" />
另外要确保蓝牙已开启,可在代码中检查并引导用户开启:
if (CrossBleAdapter.Current.Status == AdapterStatus.Off) { // 请求用户开启蓝牙 await CrossBleAdapter.Current.RequestEnable(); }
4. 关于异常路径指向插件本地目录的说明
这个是正常现象,你使用的是预编译插件包,调试时栈追踪会显示插件开发者的本地源码路径,不用在意,解决前面几个问题后,空引用异常自然会消失。
总结排查步骤
- 给异步方法添加正确的
await逻辑,不要吞异常,打印完整日志 - 在Android项目中初始化插件,传入Activity上下文
- 确认已添加对应Android版本的BLE权限
- 等待蓝牙适配器就绪后再创建GattServer
- 给广告数据添加非空的ServiceUUID列表
内容的提问来源于stack exchange,提问作者Drake
相关产品推荐
相关产品推荐

