using Shared;
using System;
using System.Collections.Generic;
using System.Text;
namespace HDL_ON.Stan
{
#if __Android__
public class HdlBluetoothLogic
{
#region ■ 变量声明___________________________
///
/// 安卓蓝牙的逻辑
///
private static HdlBluetoothLogic m_Current = null;
///
/// 安卓蓝牙的逻辑
///
public static HdlBluetoothLogic Current
{
get
{
if (m_Current == null)
{
m_Current = new HdlBluetoothLogic();
}
return m_Current;
}
}
///
/// 当前蓝牙客户端
///
private Blufi.Espressif.BlufiClient nowBlufiClient = null;
///
/// 接收事件
///
private Action ReceiveEvent = null;
///
/// 发送状态(0:发送失败 1:发送成功)
///
private int sendStatuValue = -1;
#endregion
#region ■ 蓝牙所需功能检测___________________
///
/// 检测是否能够搜索蓝牙(内部会弹出Msg框,因为内部需要检测系统权限,所以参数采用回调的方式)
///
/// 检测结果事件
public void CheckCanScanBluetooth(Action resultEvent)
{
var adapter = Android.Bluetooth.BluetoothAdapter.DefaultAdapter;
var scanner = adapter.BluetoothLeScanner;
if (adapter.IsEnabled == false || scanner == null)
{
HdlMessageLogic.Current.ShowMassage(ShowMsgType.Tip, Language.StringByID(StringId.PleaseTurnOnBluetooth));
resultEvent?.Invoke(false);
return;
}
//检测是否打开了系统功能
if (Android.OS.Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.M)
{
var locationManager = (Android.Locations.LocationManager)Application.Activity.GetSystemService(Android.Content.Context.LocationService);
if (locationManager == null)
{
//位置信息(GBS)不可用
HdlMessageLogic.Current.ShowMassage(ShowMsgType.Tip, Language.StringByID(StringId.GbsIsNotAvailable));
resultEvent?.Invoke(false);
return;
}
if (locationManager.IsProviderEnabled("network") == false)
{
HdlMessageLogic.Current.ShowMassage(ShowMsgType.Tip, Language.StringByID(StringId.NetworkIsNotAvailable));
resultEvent?.Invoke(false);
return;
}
if (locationManager.IsProviderEnabled("gps") == false)
{
//位置信息(GBS)不可用
HdlMessageLogic.Current.ShowMassage(ShowMsgType.Tip, Language.StringByID(StringId.GbsIsNotAvailable));
resultEvent?.Invoke(false);
return;
}
}
//检测蓝牙需要的权限
((BaseActivity)Application.Activity).SetPermission((result1) =>
{
if (result1 == false)
{
resultEvent?.Invoke(false);
return;
}
((BaseActivity)Application.Activity).SetPermission((result2) =>
{
if (result2 == false)
{
resultEvent?.Invoke(false);
return;
}
//全部通过
resultEvent?.Invoke(true);
}, "android.permission.ACCESS_FINE_LOCATION");
}, "android.permission.ACCESS_COARSE_LOCATION");
}
#endregion
#region ■ 蓝牙扫描___________________________
///
/// 搜索蓝牙
///
/// 搜索时间(秒)
/// 搜索结束的事件
public void ScanBluetooth(int waitTime, Action> FinishEvent)
{
HdlThreadLogic.Current.RunMain(() =>
{
//再次检测是否能够搜索蓝牙
this.CheckCanScanBluetooth((result) =>
{
if (result == true)
{
HdlThreadLogic.Current.RunThread(() =>
{
//开始搜索蓝牙
this.DoScanBluetooth(waitTime, FinishEvent);
});
}
});
});
}
///
/// 开始搜索蓝牙
///
/// 搜索时间(秒)
/// 搜索结束的事件
private void DoScanBluetooth(int waitTime, Action> FinishEvent)
{
var listBluetoothInfo = new List();
BluetoothScanCallback scanCallback = null;
Android.Bluetooth.BluetoothAdapter adapter = null;
Android.Bluetooth.LE.BluetoothLeScanner scanner = null;
//以防万一,蓝牙都丢在主线程中运行
HdlThreadLogic.Current.RunMain(() =>
{
adapter = Android.Bluetooth.BluetoothAdapter.DefaultAdapter;
scanner = adapter.BluetoothLeScanner;
scanCallback = new BluetoothScanCallback();
scanner.StartScan(null, new Android.Bluetooth.LE.ScanSettings.Builder().SetScanMode(Android.Bluetooth.LE.ScanMode.LowLatency).Build(), scanCallback);
}, ShowErrorMode.NO);
//等待
System.Threading.Thread.Sleep(waitTime * 1000);
HdlThreadLogic.Current.RunMain(() =>
{
scanner.StopScan(scanCallback);
adapter.Dispose();
foreach (var data in scanCallback.listData)
{
listBluetoothInfo.Add(data);
}
scanCallback.listData.Clear();
FinishEvent?.Invoke(listBluetoothInfo);
});
}
///
/// 蓝牙的回调对象
///
private class BluetoothScanCallback : Android.Bluetooth.LE.ScanCallback
{
///
/// 蓝牙列表
///
public List listData = new List();
///
/// 重复检测
///
private List listCheck = new List();
///
/// 蓝牙结果接收
///
///
public override void OnBatchScanResults(IList listResult)
{
foreach (var result in listResult)
{
this.AddBluetoothResult(result);
}
}
///
/// 蓝牙结果接收
///
///
///
public override void OnScanResult(Android.Bluetooth.LE.ScanCallbackType callbackType, Android.Bluetooth.LE.ScanResult result)
{
this.AddBluetoothResult(result);
}
///
/// 添加蓝牙缓存
///
///
private void AddBluetoothResult(Android.Bluetooth.LE.ScanResult result)
{
var device = result.Device;
if (device == null || listCheck.Contains(device.Address) == true)
{
return;
}
listCheck.Add(device.Address);
var data = new BluetoothInfo();
data.Name = device.Name;
if (data.Name == null) { data.Name = string.Empty; }
data.Address = device.Address;
data.Device = device;
listData.Add(data);
}
}
#endregion
#region ■ 蓝牙链接___________________________
///
/// 蓝牙链接(false:连接失败 true:连接成功)
///
/// 需要链接的蓝牙对象
/// 因为需要对方反馈,所以使用回调(链接结果 false:连接失败 true:连接成功)
public void ContectBluetooth(BluetoothInfo bluetooth, Action connectEvent)
{
HdlThreadLogic.Current.RunMain(() =>
{
try
{
this.nowBlufiClient = new Blufi.Espressif.BlufiClient(Application.Activity, bluetooth.Device);
//一个回调事件
var callback = new InnerGattCallback();
callback.ConnectionStateEvent += (div, newState) =>
{
if (div == 1)
{
if (newState == Android.Bluetooth.ProfileState.Connected)
{
//链接建立成功
connectEvent?.Invoke(true);
//只通知一次
connectEvent = null;
}
else if (newState == Android.Bluetooth.ProfileState.Disconnected)
{
//关闭链接
this.DisContectBluetooth();
connectEvent?.Invoke(false);
//只通知一次
connectEvent = null;
}
}
else if (div == -1)
{
//关闭链接
this.DisContectBluetooth();
connectEvent?.Invoke(false);
//只通知一次
connectEvent = null;
}
};
nowBlufiClient.SetGattCallback(callback);
//另外一个回调事件
var blufiCall = new BlufiCallbackMain();
blufiCall.StateEvent += (div, data) =>
{
//-1:异常 1:正常 2:发送数据成功 3:发送数据失败
if (div == StatuEnum.A异常)
{
//关闭链接
this.DisContectBluetooth();
connectEvent?.Invoke(false);
//只通知一次
connectEvent = null;
}
else if (div == StatuEnum.A发送成功 || div == StatuEnum.A发送失败)
{
sendStatuValue = div == StatuEnum.A发送成功 ? 1 : 0;
}
else if (div == StatuEnum.A蓝牙反馈)
{
//蓝牙返回的结果
this.ReceiveEvent?.Invoke(data);
}
};
nowBlufiClient.SetBlufiCallback(blufiCall);
//执行链接
nowBlufiClient.Connect();
}
catch
{
connectEvent?.Invoke(false);
connectEvent = null;
}
});
}
///
/// 先这么定义一个空的继承
///
private class InnerGattCallback : Android.Bluetooth.BluetoothGattCallback
{
///
/// 状态事件回调(-1:异常 1:OnConnectionStateChange)
///
public Action ConnectionStateEvent = null;
///
/// 链接状态改变
///
///
///
///
public override void OnConnectionStateChange(Android.Bluetooth.BluetoothGatt gatt, Android.Bluetooth.GattStatus status, Android.Bluetooth.ProfileState newState)
{
if (status == Android.Bluetooth.GattStatus.Success)
{
//回调事件
this.ConnectionStateEvent?.Invoke(1, newState);
}
else
{
//回调事件
this.ConnectionStateEvent?.Invoke(-1, 0);
}
}
///
/// 成功发现设备的services时,调用此方法
///
///
///
public override void OnServicesDiscovered(Android.Bluetooth.BluetoothGatt gatt, Android.Bluetooth.GattStatus status)
{
if (status != Android.Bluetooth.GattStatus.Success)
{
//回调事件
this.ConnectionStateEvent?.Invoke(-1, 0);
}
}
///
/// 应该是写入事件吧
///
///
///
///
public override void OnCharacteristicWrite(Android.Bluetooth.BluetoothGatt gatt, Android.Bluetooth.BluetoothGattCharacteristic characteristic, Android.Bluetooth.GattStatus status)
{
if (status != Android.Bluetooth.GattStatus.Success)
{
//回调事件
this.ConnectionStateEvent?.Invoke(-1, 0);
}
}
}
///
/// 抄SDK的,我也不知道这个是什么
///
private class BlufiCallbackMain : Blufi.Espressif.BlufiCallback
{
///
/// 状态事件回调 当第一个参数为"A蓝牙反馈"时,第二个参数为蓝牙返回的信息
///
public Action StateEvent = null;
///
/// 抄SDK的,我也不知道这个是什么
///
///
///
///
///
///
public override void OnGattPrepared(Blufi.Espressif.BlufiClient client, Android.Bluetooth.BluetoothGatt gatt, Android.Bluetooth.BluetoothGattService service,
Android.Bluetooth.BluetoothGattCharacteristic writeChar, Android.Bluetooth.BluetoothGattCharacteristic notifyChar)
{
if (service == null || writeChar == null || notifyChar == null)
{
StateEvent?.Invoke(StatuEnum.A异常, null);
return;
}
try
{
int mtu = 128;
if ((int)Android.OS.Build.VERSION.SdkInt == 29
&& Android.OS.Build.Manufacturer.ToLower().StartsWith("samsung") == true)
{
mtu = 23;
}
var requestMtu = gatt.RequestMtu(mtu);
if (!requestMtu)
{
//Request mtu failed
client.SetPostPackageLengthLimit(20);
}
StateEvent?.Invoke(StatuEnum.A正常, null); ;
}
catch
{
StateEvent?.Invoke(StatuEnum.A异常, null);
return;
}
}
///
/// 手机端发送数据到蓝牙的结果
///
///
/// 0:成功 其他都是失败
/// 手机端发送的数据
public override void OnPostCustomDataResult(Blufi.Espressif.BlufiClient client, int status, byte[] data)
{
StateEvent?.Invoke(status == 0 ? StatuEnum.A发送成功 : StatuEnum.A发送失败, null);
}
///
/// 蓝牙回复的结果
///
///
/// 0:成功 其他都是失败
/// 蓝牙回复的数据
public override void OnReceiveCustomData(Blufi.Espressif.BlufiClient client, int status, byte[] data)
{
if (status == 0)
{
var receiveData = System.Text.Encoding.UTF8.GetString(data);
StateEvent?.Invoke(StatuEnum.A蓝牙反馈, receiveData);
}
}
}
#endregion
#region ■ 蓝牙关闭___________________________
///
/// 关闭蓝牙链接
///
public void DisContectBluetooth()
{
HdlThreadLogic.Current.RunMain(() =>
{
this.nowBlufiClient?.RequestCloseConnection();
this.nowBlufiClient = null;
m_Current = null;
}, ShowErrorMode.NO);
}
///
/// 摧毁
///
public void Dispone()
{
//关闭蓝牙链接
this.DisContectBluetooth();
this.ReceiveEvent = null;
m_Current = null;
}
#endregion
#region ■ 发送数据___________________________
///
/// 发送数据给蓝牙
///
/// 发送的数据
/// 等待时间(秒),如果设置为0,则只要发送不出现异常,直接判定为成功
public bool SendData(string i_data, int waiTime = 0)
{
if (this.nowBlufiClient == null)
{
return false;
}
try
{
this.sendStatuValue = -1;
HdlThreadLogic.Current.RunMain(() =>
{
//发送数据
var byteData = System.Text.Encoding.UTF8.GetBytes(i_data);
this.nowBlufiClient.PostCustomData(byteData);
}, ShowErrorMode.NO);
if (waiTime == 0) { return true; }
waiTime *= 5;
while (this.sendStatuValue == -1 && waiTime > 0)
{
System.Threading.Thread.Sleep(200);
waiTime--;
}
return this.sendStatuValue == 1;
}
catch { return false; }
}
#endregion
#region ■ 一般方法___________________________
///
/// 添加蓝牙的接收事件
///
/// 蓝牙接收事件
public void AddReceiveEvent(Action i_ReceiveEvent)
{
this.ReceiveEvent = i_ReceiveEvent;
}
///
/// 移除蓝牙的接收事件
///
public void RemoveReceiveEvent()
{
this.ReceiveEvent = null;
}
#endregion
#region ■ 结构体_____________________________
///
/// 蓝牙返回的信息
///
public class BluetoothInfo
{
///
/// 名字(此名字不会null,如果它本身是null,只会是string.empty)
///
public string Name = string.Empty;
///
/// 地址
///
public string Address = string.Empty;
///
/// 蓝牙设备
///
public Android.Bluetooth.BluetoothDevice Device = null;
}
///
/// 状态枚举
///
private enum StatuEnum
{
A异常 = -1,
A正常 = 1,
A发送成功 = 2,
A发送失败 = 3,
A蓝牙反馈 = 4
}
#endregion
}
#endif
}