You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Xamarin.Android:如何从EventHandler传值到后台服务并监听BLE连接状态

我来帮你一步步搞定这个需求,分三个核心部分来实现:改造GattCallback触发状态事件、完善后台服务监听事件并发送通知、实现事件向服务传值的逻辑。

1. 改造BluetoothGattCallback,添加连接状态变化事件

咱们先给你的GattCallback类加一个EventHandler,这样当设备连接/断开时,能把状态信息抛出去。修改后的代码如下:

public class CustomGattCallback : BluetoothGattCallback
{
    // 定义事件,用来传递连接状态信息
    public event EventHandler<ConnectionStateChangedEventArgs> ConnectionStateChanged;

    public override void OnConnectionStateChange(BluetoothGatt gatt, [GeneratedEnum] GattStatus status, [GeneratedEnum] ProfileState newState)
    {
        base.OnConnectionStateChange(gatt, status, newState);
        
        // 触发事件,把状态信息传出去
        ConnectionStateChanged?.Invoke(this, new ConnectionStateChangedEventArgs
        {
            Gatt = gatt,
            Status = status,
            NewState = newState
        });
    }
}

// 自定义事件参数类,用来携带状态数据
public class ConnectionStateChangedEventArgs : EventArgs
{
    public BluetoothGatt Gatt { get; set; }
    public GattStatus Status { get; set; }
    public ProfileState NewState { get; set; }
}

简单说下:这里创建了一个自定义的事件参数类,把Gatt对象、状态码和新状态都封装进去,然后在OnConnectionStateChange里触发事件,这样任何订阅这个事件的对象(比如你的后台服务)都能收到状态变化通知。

2. 完善DemoService,监听状态变化并发送本地通知

接下来要修改你的后台服务,让它能订阅上面的事件,并且在收到状态变化时发送本地通知。还要注意Android 8.0+必须创建通知渠道,不然通知弹不出来。修改后的服务代码:

[Service]
public class DemoService : Service
{
    private CustomGattCallback _gattCallback;
    private NotificationManager _notificationManager;
    private const string ChannelId = "BLE_Connection_Channel";
    private const int NotificationId = 1001;

    public override void OnCreate()
    {
        base.OnCreate();
        
        // 初始化通知管理器和渠道
        _notificationManager = (NotificationManager)GetSystemService(NotificationService);
        CreateNotificationChannel();
        
        // 初始化GattCallback并订阅事件
        _gattCallback = new CustomGattCallback();
        _gattCallback.ConnectionStateChanged += OnGattConnectionStateChanged;
    }

    public override StartCommandResult OnStartCommand(Android.Content.Intent intent, StartCommandFlags flags, int startId)
    {
        // 这里不要马上StopSelf,保持服务运行来监听BLE状态
        Log.Debug("DemoService", "Service started, listening for BLE connection changes");
        return StartCommandResult.Sticky;
    }

    private void OnGattConnectionStateChanged(object sender, ConnectionStateChangedEventArgs e)
    {
        string notificationTitle;
        string notificationContent;

        // 根据新状态判断是连接还是断开
        if (e.NewState == ProfileState.Connected)
        {
            notificationTitle = "BLE设备已连接";
            notificationContent = $"设备: {e.Gatt.Device.Name}";
        }
        else if (e.NewState == ProfileState.Disconnected)
        {
            notificationTitle = "BLE设备已断开";
            notificationContent = $"设备: {e.Gatt.Device.Name}";
        }
        else
        {
            return; // 其他状态忽略
        }

        // 发送本地通知
        SendNotification(notificationTitle, notificationContent);
    }

    private void CreateNotificationChannel()
    {
        if (Build.VERSION.SdkInt >= BuildVersionCodes.O)
        {
            var channel = new NotificationChannel(ChannelId, "BLE连接状态通知", NotificationImportance.Default)
            {
                Description = "用于展示BLE设备的连接/断开状态"
            };
            _notificationManager.CreateNotificationChannel(channel);
        }
    }

    private void SendNotification(string title, string content)
    {
        var notificationBuilder = new NotificationCompat.Builder(this, ChannelId)
            .SetContentTitle(title)
            .SetContentText(content)
            .SetSmallIcon(Android.Resource.Drawable.IcDialogInfo)
            .SetAutoCancel(true);

        var notification = notificationBuilder.Build();
        _notificationManager.Notify(NotificationId, notification);
    }

    public override void OnDestroy()
    {
        // 取消事件订阅,避免内存泄漏
        _gattCallback.ConnectionStateChanged -= OnGattConnectionStateChanged;
        base.OnDestroy();
    }

    public override IBinder OnBind(Intent intent)
    {
        return null; // 如果不需要绑定服务,返回null即可
    }
}

重点说明:

  • 在OnCreate里初始化了GattCallback并订阅了它的ConnectionStateChanged事件,服务一创建就能监听状态变化
  • 实现了通知渠道的创建,适配Android 8.0+的系统要求
  • OnGattConnectionStateChanged方法里根据状态生成不同的通知内容,然后调用SendNotification发送
  • OnStartCommand里去掉了StopSelf,因为要保持服务运行来监听BLE状态,返回Sticky让系统在内存不足杀死服务后自动重启它
3. 实现EventHandler向后台服务传递值的逻辑

其实上面的代码已经实现了传值功能:CustomGattCallback的ConnectionStateChanged事件通过ConnectionStateChangedEventArgs把Gatt对象、状态码和新状态都传递给了DemoService的OnGattConnectionStateChanged方法。如果需要传递更多自定义数据,只需要修改ConnectionStateChangedEventArgs类,添加你需要的属性即可。

举个例子,如果要传递设备MAC地址,只需要修改事件参数类:

public class ConnectionStateChangedEventArgs : EventArgs
{
    public BluetoothGatt Gatt { get; set; }
    public GattStatus Status { get; set; }
    public ProfileState NewState { get; set; }
    public string DeviceMacAddress { get; set; } // 新增的属性
}

然后在GattCallback的OnConnectionStateChange里赋值:

ConnectionStateChanged?.Invoke(this, new ConnectionStateChangedEventArgs
{
    Gatt = gatt,
    Status = status,
    NewState = newState,
    DeviceMacAddress = gatt.Device.Address // 赋值MAC地址
});

这样服务就能在OnGattConnectionStateChanged里拿到DeviceMacAddress并使用了。

内容的提问来源于stack exchange,提问作者crazydev

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 08:46:30