From dbc23459fdf4e8b74a5f955fbb9fc631b4babc70 Mon Sep 17 00:00:00 2001 From: 陈嘉乐 <cjl@hdlchina.com.cn> Date: 星期三, 17 三月 2021 11:56:16 +0800 Subject: [PATCH] Merge branch 'temp-wxr' into WJC --- HDL_ON/UI/UI0-Stan/Logic/HdlBluetoothAndroidLogic.cs | 590 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 590 insertions(+), 0 deletions(-) diff --git a/HDL_ON/UI/UI0-Stan/Logic/HdlBluetoothAndroidLogic.cs b/HDL_ON/UI/UI0-Stan/Logic/HdlBluetoothAndroidLogic.cs new file mode 100644 index 0000000..b416038 --- /dev/null +++ b/HDL_ON/UI/UI0-Stan/Logic/HdlBluetoothAndroidLogic.cs @@ -0,0 +1,590 @@ +锘縰sing Shared; +using System; +using System.Collections.Generic; +using System.Text; + +namespace HDL_ON.Stan +{ +#if __Android__ + public class HdlBluetoothLogic + { + #region 鈻� 鍙橀噺澹版槑___________________________ + + /// <summary> + /// 瀹夊崜钃濈墮鐨勯�昏緫 + /// </summary> + private static HdlBluetoothLogic m_Current = null; + /// <summary> + /// 瀹夊崜钃濈墮鐨勯�昏緫 + /// </summary> + public static HdlBluetoothLogic Current + { + get + { + if (m_Current == null) + { + m_Current = new HdlBluetoothLogic(); + } + return m_Current; + } + } + + /// <summary> + /// 褰撳墠钃濈墮瀹㈡埛绔� + /// </summary> + private Blufi.Espressif.BlufiClient nowBlufiClient = null; + /// <summary> + /// 鎺ユ敹浜嬩欢 + /// </summary> + private Action<string> ReceiveEvent = null; + /// <summary> + /// 鍙戦�佺姸鎬�(0:鍙戦�佸け璐� 1:鍙戦�佹垚鍔�) + /// </summary> + private int sendStatuValue = -1; + + #endregion + + #region 鈻� 钃濈墮鎵�闇�鍔熻兘妫�娴媉__________________ + + /// <summary> + /// 妫�娴嬫槸鍚﹁兘澶熸悳绱㈣摑鐗�(鍐呴儴浼氬脊鍑篗sg妗�,鍥犱负鍐呴儴闇�瑕佹娴嬬郴缁熸潈闄�,鎵�浠ュ弬鏁伴噰鐢ㄥ洖璋冪殑鏂瑰紡) + /// </summary> + /// <param name="resultEvent">妫�娴嬬粨鏋滀簨浠�</param> + public void CheckCanScanBluetooth(Action<bool> 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 鈻� 钃濈墮鎵弿___________________________ + + /// <summary> + /// 鎼滅储钃濈墮 + /// </summary> + /// <param name="waitTime">鎼滅储鏃堕棿(绉�)</param> + /// <param name="FinishEvent">鎼滅储缁撴潫鐨勪簨浠�</param> + public void ScanBluetooth(int waitTime, Action<List<BluetoothInfo>> FinishEvent) + { + HdlThreadLogic.Current.RunMain(() => + { + //鍐嶆妫�娴嬫槸鍚﹁兘澶熸悳绱㈣摑鐗� + this.CheckCanScanBluetooth((result) => + { + if (result == true) + { + HdlThreadLogic.Current.RunThread(() => + { + //寮�濮嬫悳绱㈣摑鐗� + this.DoScanBluetooth(waitTime, FinishEvent); + }); + } + }); + }); + } + + /// <summary> + /// 寮�濮嬫悳绱㈣摑鐗� + /// </summary> + /// <param name="waitTime">鎼滅储鏃堕棿(绉�)</param> + /// <param name="FinishEvent">鎼滅储缁撴潫鐨勪簨浠�</param> + private void DoScanBluetooth(int waitTime, Action<List<BluetoothInfo>> FinishEvent) + { + var listBluetoothInfo = new List<BluetoothInfo>(); + + 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); + }); + } + + /// <summary> + /// 钃濈墮鐨勫洖璋冨璞� + /// </summary> + private class BluetoothScanCallback : Android.Bluetooth.LE.ScanCallback + { + /// <summary> + /// 钃濈墮鍒楄〃 + /// </summary> + public List<BluetoothInfo> listData = new List<BluetoothInfo>(); + /// <summary> + /// 閲嶅妫�娴� + /// </summary> + private List<string> listCheck = new List<string>(); + + /// <summary> + /// 钃濈墮缁撴灉鎺ユ敹 + /// </summary> + /// <param name="listResult"></param> + public override void OnBatchScanResults(IList<Android.Bluetooth.LE.ScanResult> listResult) + { + foreach (var result in listResult) + { + this.AddBluetoothResult(result); + } + } + + /// <summary> + /// 钃濈墮缁撴灉鎺ユ敹 + /// </summary> + /// <param name="callbackType"></param> + /// <param name="result"></param> + public override void OnScanResult(Android.Bluetooth.LE.ScanCallbackType callbackType, Android.Bluetooth.LE.ScanResult result) + { + this.AddBluetoothResult(result); + } + + /// <summary> + /// 娣诲姞钃濈墮缂撳瓨 + /// </summary> + /// <param name="result"></param> + 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 鈻� 钃濈墮閾炬帴___________________________ + + /// <summary> + /// 钃濈墮閾炬帴(false:杩炴帴澶辫触 true:杩炴帴鎴愬姛) + /// </summary> + /// <param name="bluetooth">闇�瑕侀摼鎺ョ殑钃濈墮瀵硅薄</param> + /// <param name="connectEvent">鍥犱负闇�瑕佸鏂瑰弽棣�,鎵�浠ヤ娇鐢ㄥ洖璋�(閾炬帴缁撴灉 false:杩炴帴澶辫触 true:杩炴帴鎴愬姛)</param> + public void ContectBluetooth(BluetoothInfo bluetooth, Action<bool> 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:姝e父 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; + } + }); + } + + /// <summary> + /// 鍏堣繖涔堝畾涔変竴涓┖鐨勭户鎵� + /// </summary> + private class InnerGattCallback : Android.Bluetooth.BluetoothGattCallback + { + /// <summary> + /// 鐘舵�佷簨浠跺洖璋�(-1:寮傚父 1:OnConnectionStateChange) + /// </summary> + public Action<int,Android.Bluetooth.ProfileState> ConnectionStateEvent = null; + /// <summary> + /// 閾炬帴鐘舵�佹敼鍙� + /// </summary> + /// <param name="gatt"></param> + /// <param name="status"></param> + /// <param name="newState"></param> + 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); + } + } + + /// <summary> + /// 鎴愬姛鍙戠幇璁惧鐨剆ervices鏃讹紝璋冪敤姝ゆ柟娉� + /// </summary> + /// <param name="gatt"></param> + /// <param name="status"></param> + public override void OnServicesDiscovered(Android.Bluetooth.BluetoothGatt gatt, Android.Bluetooth.GattStatus status) + { + if (status != Android.Bluetooth.GattStatus.Success) + { + //鍥炶皟浜嬩欢 + this.ConnectionStateEvent?.Invoke(-1, 0); + } + } + + /// <summary> + /// 搴旇鏄啓鍏ヤ簨浠跺惂 + /// </summary> + /// <param name="gatt"></param> + /// <param name="characteristic"></param> + /// <param name="status"></param> + 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); + } + } + } + + /// <summary> + /// 鎶凷DK鐨勶紝鎴戜篃涓嶇煡閬撹繖涓槸浠�涔� + /// </summary> + private class BlufiCallbackMain : Blufi.Espressif.BlufiCallback + { + /// <summary> + /// 鐘舵�佷簨浠跺洖璋� 褰撶涓�涓弬鏁颁负"A钃濈墮鍙嶉"鏃�,绗簩涓弬鏁颁负钃濈墮杩斿洖鐨勪俊鎭� + /// </summary> + public Action<StatuEnum, string> StateEvent = null; + + /// <summary> + /// 鎶凷DK鐨勶紝鎴戜篃涓嶇煡閬撹繖涓槸浠�涔� + /// </summary> + /// <param name="client"></param> + /// <param name="gatt"></param> + /// <param name="service"></param> + /// <param name="writeChar"></param> + /// <param name="notifyChar"></param> + 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姝e父, null); ; + } + catch + { + StateEvent?.Invoke(StatuEnum.A寮傚父, null); + return; + } + } + + /// <summary> + /// 鎵嬫満绔彂閫佹暟鎹埌钃濈墮鐨勭粨鏋� + /// </summary> + /// <param name="client"></param> + /// <param name="status">0:鎴愬姛 鍏朵粬閮芥槸澶辫触</param> + /// <param name="data">鎵嬫満绔彂閫佺殑鏁版嵁</param> + public override void OnPostCustomDataResult(Blufi.Espressif.BlufiClient client, int status, byte[] data) + { + StateEvent?.Invoke(status == 0 ? StatuEnum.A鍙戦�佹垚鍔� : StatuEnum.A鍙戦�佸け璐�, null); + } + + /// <summary> + /// 钃濈墮鍥炲鐨勭粨鏋� + /// </summary> + /// <param name="client"></param> + /// <param name="status">0:鎴愬姛 鍏朵粬閮芥槸澶辫触</param> + /// <param name="data">钃濈墮鍥炲鐨勬暟鎹�</param> + 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 鈻� 钃濈墮鍏抽棴___________________________ + + /// <summary> + /// 鍏抽棴钃濈墮閾炬帴 + /// </summary> + public void DisContectBluetooth() + { + HdlThreadLogic.Current.RunMain(() => + { + this.nowBlufiClient?.RequestCloseConnection(); + this.nowBlufiClient = null; + + m_Current = null; + + }, ShowErrorMode.NO); + } + + /// <summary> + /// 鎽ф瘉 + /// </summary> + public void Dispone() + { + //鍏抽棴钃濈墮閾炬帴 + this.DisContectBluetooth(); + this.ReceiveEvent = null; + m_Current = null; + } + + #endregion + + #region 鈻� 鍙戦�佹暟鎹甠__________________________ + + /// <summary> + /// 鍙戦�佹暟鎹粰钃濈墮 + /// </summary> + /// <param name="i_data">鍙戦�佺殑鏁版嵁</param> + /// <param name="waiTime">绛夊緟鏃堕棿(绉�),濡傛灉璁剧疆涓�0,鍒欏彧瑕佸彂閫佷笉鍑虹幇寮傚父,鐩存帴鍒ゅ畾涓烘垚鍔�</param> + 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 鈻� 涓�鑸柟娉昣__________________________ + + /// <summary> + /// 娣诲姞钃濈墮鐨勬帴鏀朵簨浠� + /// </summary> + /// <param name="i_ReceiveEvent">钃濈墮鎺ユ敹浜嬩欢</param> + public void AddReceiveEvent(Action<string> i_ReceiveEvent) + { + this.ReceiveEvent = i_ReceiveEvent; + } + + /// <summary> + /// 绉婚櫎钃濈墮鐨勬帴鏀朵簨浠� + /// </summary> + public void RemoveReceiveEvent() + { + this.ReceiveEvent = null; + } + + #endregion + + #region 鈻� 缁撴瀯浣揰____________________________ + + /// <summary> + /// 钃濈墮杩斿洖鐨勪俊鎭� + /// </summary> + public class BluetoothInfo + { + /// <summary> + /// 鍚嶅瓧(姝ゅ悕瀛椾笉浼歯ull,濡傛灉瀹冩湰韬槸null,鍙細鏄痵tring.empty) + /// </summary> + public string Name = string.Empty; + /// <summary> + /// 鍦板潃 + /// </summary> + public string Address = string.Empty; + /// <summary> + /// 钃濈墮璁惧 + /// </summary> + public Android.Bluetooth.BluetoothDevice Device = null; + } + + /// <summary> + /// 鐘舵�佹灇涓� + /// </summary> + private enum StatuEnum + { + A寮傚父 = -1, + A姝e父 = 1, + A鍙戦�佹垚鍔� = 2, + A鍙戦�佸け璐� = 3, + A钃濈墮鍙嶉 = 4 + } + + #endregion + } +#endif +} + -- Gitblit v1.8.0