优化蓝牙连接

This commit is contained in:
“虞渠成” 2026-06-23 15:19:47 +08:00
parent fb67d4b324
commit 655afe81f3
10 changed files with 376 additions and 135 deletions

View File

@ -1006,7 +1006,7 @@
},
{
"key": "100202",
"zh": "修改密码",
"zh": "请输入用户ID",
"en": "Please enter User ID"
},
{
@ -1017,7 +1017,7 @@
{
"key": "100204",
"zh": "请输入要共享的用户ID",
"en": "Enter shared user ID"
"en": "Please Enter shared user ID"
},
{
"key": "100205",

View File

@ -969,6 +969,7 @@ GameObject:
- component: {fileID: 1519237044948379669}
- component: {fileID: 4142448484629704935}
- component: {fileID: 4921898416580924308}
- component: {fileID: 1825025902833908675}
m_Layer: 5
m_Name: Text (Legacy) (1)
m_TagString: Untagged
@ -1036,7 +1037,20 @@ MonoBehaviour:
m_HorizontalOverflow: 1
m_VerticalOverflow: 0
m_LineSpacing: 1
m_Text: Please enter User ID
m_Text: Enter shared user ID
--- !u!114 &1825025902833908675
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5444693722322422585}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 89f1d49b50a31514787b4e268b1c73bb, type: 3}
m_Name:
m_EditorClassIdentifier:
textKey: 100204
--- !u!1 &5524717387086965381
GameObject:
m_ObjectHideFlags: 0

View File

@ -3517,7 +3517,7 @@ RectTransform:
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 1}
m_AnchorMax: {x: 0, y: 1}
m_AnchoredPosition: {x: 345, y: -564}
m_AnchoredPosition: {x: 345, y: -172}
m_SizeDelta: {x: 690, y: 0}
m_Pivot: {x: 0.5, y: 1}
--- !u!222 &854871756318895437
@ -10811,7 +10811,7 @@ RectTransform:
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 1}
m_AnchorMax: {x: 0, y: 1}
m_AnchoredPosition: {x: 345, y: -2408}
m_AnchoredPosition: {x: 345, y: -466}
m_SizeDelta: {x: 690, y: 0}
m_Pivot: {x: 0.5, y: 1}
--- !u!222 &6739308067368723960
@ -11868,7 +11868,7 @@ RectTransform:
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 1}
m_AnchorMax: {x: 0, y: 1}
m_AnchoredPosition: {x: 345, y: -1918}
m_AnchoredPosition: {x: 345, y: -368}
m_SizeDelta: {x: 690, y: 0}
m_Pivot: {x: 0.5, y: 1}
--- !u!222 &5027863063353656364
@ -12732,7 +12732,7 @@ RectTransform:
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 1}
m_AnchorMax: {x: 0, y: 1}
m_AnchoredPosition: {x: 345, y: -1286}
m_AnchoredPosition: {x: 345, y: -270}
m_SizeDelta: {x: 690, y: 0}
m_Pivot: {x: 0.5, y: 1}
--- !u!222 &4389568299256833371

View File

@ -3270,67 +3270,67 @@ PrefabInstance:
- target: {fileID: 1507386632888176871, guid: 52c284b3dc8d7b94297736ede9ad1f7e,
type: 3}
propertyPath: m_AnchorMax.y
value: 0
value: 1
objectReference: {fileID: 0}
- target: {fileID: 1507386632888176871, guid: 52c284b3dc8d7b94297736ede9ad1f7e,
type: 3}
propertyPath: m_AnchorMin.y
value: 0
value: 1
objectReference: {fileID: 0}
- target: {fileID: 1507386632888176871, guid: 52c284b3dc8d7b94297736ede9ad1f7e,
type: 3}
propertyPath: m_SizeDelta.x
value: 0
value: 590
objectReference: {fileID: 0}
- target: {fileID: 1507386632888176871, guid: 52c284b3dc8d7b94297736ede9ad1f7e,
type: 3}
propertyPath: m_SizeDelta.y
value: 0
value: 90
objectReference: {fileID: 0}
- target: {fileID: 1507386632888176871, guid: 52c284b3dc8d7b94297736ede9ad1f7e,
type: 3}
propertyPath: m_AnchoredPosition.x
value: 0
value: 295
objectReference: {fileID: 0}
- target: {fileID: 1507386632888176871, guid: 52c284b3dc8d7b94297736ede9ad1f7e,
type: 3}
propertyPath: m_AnchoredPosition.y
value: 0
value: -312
objectReference: {fileID: 0}
- target: {fileID: 4296973555611399213, guid: 52c284b3dc8d7b94297736ede9ad1f7e,
type: 3}
propertyPath: m_AnchorMax.y
value: 0
value: 1
objectReference: {fileID: 0}
- target: {fileID: 4296973555611399213, guid: 52c284b3dc8d7b94297736ede9ad1f7e,
type: 3}
propertyPath: m_AnchorMin.y
value: 0
value: 1
objectReference: {fileID: 0}
- target: {fileID: 4296973555611399213, guid: 52c284b3dc8d7b94297736ede9ad1f7e,
type: 3}
propertyPath: m_SizeDelta.x
value: 0
value: 590
objectReference: {fileID: 0}
- target: {fileID: 4296973555611399213, guid: 52c284b3dc8d7b94297736ede9ad1f7e,
type: 3}
propertyPath: m_SizeDelta.y
value: 0
value: 45
objectReference: {fileID: 0}
- target: {fileID: 4296973555611399213, guid: 52c284b3dc8d7b94297736ede9ad1f7e,
type: 3}
propertyPath: m_AnchoredPosition.x
value: 0
value: 295
objectReference: {fileID: 0}
- target: {fileID: 4296973555611399213, guid: 52c284b3dc8d7b94297736ede9ad1f7e,
type: 3}
propertyPath: m_AnchoredPosition.y
value: 0
value: -55
objectReference: {fileID: 0}
- target: {fileID: 4685927451915885120, guid: 52c284b3dc8d7b94297736ede9ad1f7e,
type: 3}
propertyPath: m_SizeDelta.y
value: 0
value: 342
objectReference: {fileID: 0}
- target: {fileID: 5819498693055166909, guid: 52c284b3dc8d7b94297736ede9ad1f7e,
type: 3}
@ -3340,7 +3340,7 @@ PrefabInstance:
- target: {fileID: 5819498693055166909, guid: 52c284b3dc8d7b94297736ede9ad1f7e,
type: 3}
propertyPath: m_IsActive
value: 1
value: 0
objectReference: {fileID: 0}
- target: {fileID: 6314676893636565267, guid: 52c284b3dc8d7b94297736ede9ad1f7e,
type: 3}
@ -3450,32 +3450,32 @@ PrefabInstance:
- target: {fileID: 6936886167337472632, guid: 52c284b3dc8d7b94297736ede9ad1f7e,
type: 3}
propertyPath: m_AnchorMax.y
value: 0
value: 1
objectReference: {fileID: 0}
- target: {fileID: 6936886167337472632, guid: 52c284b3dc8d7b94297736ede9ad1f7e,
type: 3}
propertyPath: m_AnchorMin.y
value: 0
value: 1
objectReference: {fileID: 0}
- target: {fileID: 6936886167337472632, guid: 52c284b3dc8d7b94297736ede9ad1f7e,
type: 3}
propertyPath: m_SizeDelta.x
value: 0
value: 590
objectReference: {fileID: 0}
- target: {fileID: 6936886167337472632, guid: 52c284b3dc8d7b94297736ede9ad1f7e,
type: 3}
propertyPath: m_SizeDelta.y
value: 0
value: 42
objectReference: {fileID: 0}
- target: {fileID: 6936886167337472632, guid: 52c284b3dc8d7b94297736ede9ad1f7e,
type: 3}
propertyPath: m_AnchoredPosition.x
value: 0
value: 295
objectReference: {fileID: 0}
- target: {fileID: 6936886167337472632, guid: 52c284b3dc8d7b94297736ede9ad1f7e,
type: 3}
propertyPath: m_AnchoredPosition.y
value: 0
value: -140
objectReference: {fileID: 0}
- target: {fileID: 7452104535586638788, guid: 52c284b3dc8d7b94297736ede9ad1f7e,
type: 3}

View File

@ -2,6 +2,7 @@ using UnityEngine;
using System;
using System.Collections.Generic;
using Kill.Core;
using Kill.UI;
using Kill.UI.Components;
namespace Kill.Bluetooth
@ -89,12 +90,23 @@ namespace Kill.Bluetooth
private bool _isConnecting;
private string _connectingAddress;
// 蓝牙启用提示相关
private Coroutine _enableBtCoroutine; // 等待蓝牙启用的协程
private bool _userDeniedBluetooth = false; // 用户已拒绝过蓝牙开启请求
private bool _pendingStartScan = false; // 是否有待执行的扫描
private float _pendingScanTimeout; // 待执行扫描的超时时间
private string _pendingConnectAddress; // 初始化后待连接的设备地址
private bool _wasBtOn = false; // 上一帧蓝牙是否开启(用于检测状态变化)
private Coroutine _stateMonitorCoroutine; // 蓝牙状态监控协程
private void Awake()
{
if (Instance == null)
{
Instance = this;
DontDestroyOnLoad(gameObject);
_stateMonitorCoroutine = StartCoroutine(MonitorBluetoothState());
OnDisconnected += OnSelfDisconnected;
}
else
{
@ -106,9 +118,31 @@ namespace Kill.Bluetooth
{
if (Instance == this)
{
OnDisconnected -= OnSelfDisconnected;
if (_stateMonitorCoroutine != null)
{
StopCoroutine(_stateMonitorCoroutine);
_stateMonitorCoroutine = null;
}
Instance = null;
}
}
/// <summary>
/// 蓝牙断开后延迟跳回主页
/// </summary>
private void OnSelfDisconnected(string address)
{
IsConnected=false;
// 延迟一下确保主页能读到最新的 IsConnected 状态
StartCoroutine(DelayedGoHome());
}
private System.Collections.IEnumerator DelayedGoHome()
{
yield return new WaitForSeconds(1f);
UIManager.Instance?.OpenMainPage(UIManager.PageName.homePage);
}
void Start()
{
Initialize();
@ -143,6 +177,20 @@ namespace Kill.Bluetooth
return;
}
// 如果已经在等待蓝牙启用,跳过(不取消旧请求,避免重复弹窗)
if (_enableBtCoroutine != null)
{
Log("已在等待用户启用蓝牙,跳过重复请求");
return;
}
// 用户已拒绝过蓝牙请求,不再自动弹出提示
if (_userDeniedBluetooth)
{
Log("用户已拒绝蓝牙开启,跳过初始化");
return;
}
Log("正在初始化蓝牙...");
// 先检查蓝牙是否开启,如果没有则尝试启用
@ -153,6 +201,15 @@ namespace Kill.Bluetooth
});
}
/// <summary>
/// 强制初始化蓝牙(清除用户拒绝标记,用于用户主动触发)
/// </summary>
public void ForceInitialize()
{
_userDeniedBluetooth = false;
Initialize();
}
/// <summary>
/// 检查并启用蓝牙
/// </summary>
@ -165,6 +222,7 @@ namespace Kill.Bluetooth
if (bluetoothAdapter == null)
{
_enableBtCoroutine = null;
OnError?.Invoke("设备不支持蓝牙");
OnInitialized?.Invoke(false);
return;
@ -174,22 +232,16 @@ namespace Kill.Bluetooth
if (!isEnabled)
{
Log("蓝牙未开启,尝试启用...");
// 尝试静默启用蓝牙
bool enableSuccess = bluetoothAdapter.Call<bool>("enable");
if (enableSuccess)
Log("蓝牙未开启,使用 Intent 请求用户启用...");
using (AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer"))
using (AndroidJavaObject currentActivity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity"))
{
Log("正在启用蓝牙,等待...");
// 等待蓝牙启用
StartCoroutine(WaitForBluetoothEnabled(onBluetoothReady));
}
else
{
// 静默启用失败,请求用户启用
RequestUserEnableBluetooth(onBluetoothReady);
AndroidJavaObject intent = new AndroidJavaObject("android.content.Intent", "android.bluetooth.adapter.action.REQUEST_ENABLE");
currentActivity.Call("startActivityForResult", intent, 1);
}
_enableBtCoroutine = StartCoroutine(WaitForBluetoothEnabled(onBluetoothReady));
}
else
{
@ -206,6 +258,65 @@ namespace Kill.Bluetooth
#endif
}
#if UNITY_ANDROID && !UNITY_EDITOR
/// <summary>
/// 轮询等待蓝牙启用Intent 之后最长10秒
/// </summary>
private System.Collections.IEnumerator WaitForBluetoothEnabled(System.Action onBluetoothReady)
{
float maxTimeout = 10f;
float timer = 0f;
int checkCount = 0;
bool wasUnfocused = false;
while (timer < maxTimeout)
{
checkCount++;
using (AndroidJavaClass btClass = new AndroidJavaClass("android.bluetooth.BluetoothAdapter"))
{
AndroidJavaObject adapter = btClass.CallStatic<AndroidJavaObject>("getDefaultAdapter");
if (adapter != null)
{
bool btOn = adapter.Call<bool>("isEnabled");
if (checkCount <= 4 || checkCount % 10 == 0)
Log($"第{checkCount}次: isEnabled={btOn}, 已等待{timer:F1}s");
if (btOn)
{
Log("蓝牙已成功启用");
_enableBtCoroutine = null;
_userDeniedBluetooth = false;
onBluetoothReady?.Invoke();
yield break;
}
}
}
// 检测用户是否关闭了系统对话框:对话框弹出时 App 失去焦点,关闭后恢复
if (!Application.isFocused)
{
wasUnfocused = true;
}
else if (wasUnfocused && timer > 0.5f)
{
// 焦点恢复但蓝牙仍未开启 → 用户拒绝了 / 关闭了对话框
Log("检测到用户关闭了蓝牙请求对话框,停止等待");
break;
}
yield return new WaitForSeconds(0.2f);
timer += 0.2f;
}
Log($"等待蓝牙启用结束 (共检查{checkCount}次,已等待{timer:F1}s)");
_enableBtCoroutine = null;
_userDeniedBluetooth = true;
_pendingStartScan = false;
_pendingConnectAddress = null;
OnError?.Invoke("蓝牙未开启");
OnInitialized?.Invoke(false);
}
#endif
#if UNITY_IOS && !UNITY_EDITOR
[System.Runtime.InteropServices.DllImport("__Internal")]
private static extern int GetBluetoothStateIOS();
@ -231,23 +342,23 @@ namespace Kill.Bluetooth
// 4 = PoweredOff (蓝牙关闭)
else if (state == 4)
{
Log("iOS 蓝牙未开启,提示用户");
// iOS 不能自动打开蓝牙,只能提示用户去设置中开启
Log("iOS 蓝牙未开启,跳转到系统设置...");
ShowIOSTurnOnBluetoothPrompt();
OnError?.Invoke("请在系统设置中开启蓝牙");
OnInitialized?.Invoke(false);
// 等待用户从设置返回(检测焦点变化 + 轮询蓝牙状态)
_enableBtCoroutine = StartCoroutine(WaitForIOSBluetoothEnabled(onBluetoothReady));
}
// 3 = Unauthorized (未授权)
else if (state == 3)
{
Log("iOS 蓝牙未授权");
OnError?.Invoke("请在设置中允许使用蓝牙");
OnInitialized?.Invoke(false);
Log("iOS 蓝牙未授权,跳转到系统设置...");
ShowIOSTurnOnBluetoothPrompt();
_enableBtCoroutine = StartCoroutine(WaitForIOSBluetoothEnabled(onBluetoothReady));
}
// 2 = Unsupported (不支持蓝牙)
else if (state == 2)
{
Log("设备不支持蓝牙");
_enableBtCoroutine = null;
OnError?.Invoke("设备不支持蓝牙");
OnInitialized?.Invoke(false);
}
@ -259,96 +370,142 @@ namespace Kill.Bluetooth
}
}
/// <summary>
/// iOS: 等待用户从设置返回并开启蓝牙(检测焦点 + 轮询)
/// </summary>
private System.Collections.IEnumerator WaitForIOSBluetoothEnabled(System.Action onBluetoothReady)
{
float maxTimeout = 15f;
float timer = 0f;
int checkCount = 0;
bool wasUnfocused = false;
while (timer < maxTimeout)
{
checkCount++;
int state = GetBluetoothStateIOS();
if (checkCount <= 4 || checkCount % 10 == 0)
Log($"iOS 第{checkCount}次: state={state}, 已等待{timer:F1}s");
// 5 = PoweredOn
if (state == 5)
{
Log("iOS 蓝牙已开启");
_enableBtCoroutine = null;
_userDeniedBluetooth = false;
onBluetoothReady?.Invoke();
yield break;
}
// 检测用户从设置返回
if (!Application.isFocused)
{
wasUnfocused = true;
}
else if (wasUnfocused && timer > 1f)
{
// 从系统设置返回但蓝牙仍未开启 → 用户未操作
Log("iOS: 从设置返回,蓝牙未开启,停止等待");
break;
}
yield return new WaitForSeconds(0.3f);
timer += 0.3f;
}
Log($"iOS 等待蓝牙启用结束 (共检查{checkCount}次,已等待{timer:F1}s)");
_enableBtCoroutine = null;
_userDeniedBluetooth = true;
_pendingStartScan = false;
_pendingConnectAddress = null;
OnError?.Invoke("请在系统设置中开启蓝牙");
OnInitialized?.Invoke(false);
}
/// <summary>
/// 显示 iOS 开启蓝牙提示
/// </summary>
private void ShowIOSTurnOnBluetoothPrompt()
{
// 可以在这里显示一个弹窗,引导用户去设置
// 或者使用原生插件跳转到设置页面
OpenBluetoothSettingsIOS();
}
#endif
/// <summary>
/// 监控蓝牙开关状态变化App运行时
/// </summary>
private System.Collections.IEnumerator MonitorBluetoothState()
{
yield return new WaitForSeconds(2f); // 初始延迟
while (true)
{
yield return new WaitForSeconds(2f);
bool btOn = CheckIfBluetoothIsOn();
if (!_wasBtOn && btOn)
{
if (!IsInitialized && !_userDeniedBluetooth)
{
Log("检测到蓝牙已开启,自动初始化...");
Initialize();
}
}
else if (_wasBtOn && !btOn)
{
Log("检测到蓝牙已关闭,清理状态...");
if (_enableBtCoroutine != null)
{
StopCoroutine(_enableBtCoroutine);
_enableBtCoroutine = null;
}
if (IsConnected)
{
Disconnect();
}
if (IsScanning)
{
StopScan();
}
IsInitialized = false;
_isFullyInitialized = false;
_pendingStartScan = false;
_pendingConnectAddress = null;
OnInitialized?.Invoke(false);
}
_wasBtOn = btOn;
}
}
/// <summary>
/// 跨平台检查蓝牙是否开启
/// </summary>
private bool CheckIfBluetoothIsOn()
{
#if UNITY_ANDROID && !UNITY_EDITOR
/// <summary>
/// 等待蓝牙启用
/// </summary>
private System.Collections.IEnumerator WaitForBluetoothEnabled(System.Action onBluetoothReady)
{
float timeout = 5f;
float timer = 0f;
while (timer < timeout)
try
{
using (AndroidJavaClass bluetoothAdapterClass = new AndroidJavaClass("android.bluetooth.BluetoothAdapter"))
using (AndroidJavaClass btClass = new AndroidJavaClass("android.bluetooth.BluetoothAdapter"))
{
AndroidJavaObject bluetoothAdapter = bluetoothAdapterClass.CallStatic<AndroidJavaObject>("getDefaultAdapter");
if (bluetoothAdapter != null && bluetoothAdapter.Call<bool>("isEnabled"))
{
Log("蓝牙已成功启用");
onBluetoothReady?.Invoke();
yield break;
}
AndroidJavaObject adapter = btClass.CallStatic<AndroidJavaObject>("getDefaultAdapter");
if (adapter != null)
return adapter.Call<bool>("isEnabled");
}
yield return new WaitForSeconds(0.5f);
timer += 0.5f;
}
Log("等待蓝牙启用超时");
OnError?.Invoke("蓝牙启用超时");
OnInitialized?.Invoke(false);
}
/// <summary>
/// 请求用户启用蓝牙
/// </summary>
private void RequestUserEnableBluetooth(System.Action onBluetoothReady)
{
Log("请求用户启用蓝牙...");
using (AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer"))
using (AndroidJavaObject currentActivity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity"))
catch (System.Exception ex)
{
AndroidJavaObject intent = new AndroidJavaObject("android.content.Intent", "android.bluetooth.adapter.action.REQUEST_ENABLE");
currentActivity.Call("startActivityForResult", intent, 1);
Log($"检查蓝牙状态异常: {ex.Message}");
}
// 等待用户响应
StartCoroutine(WaitForUserEnableBluetooth(onBluetoothReady));
}
/// <summary>
/// 等待用户启用蓝牙
/// </summary>
private System.Collections.IEnumerator WaitForUserEnableBluetooth(System.Action onBluetoothReady)
{
float timeout = 30f;
float timer = 0f;
while (timer < timeout)
{
using (AndroidJavaClass bluetoothAdapterClass = new AndroidJavaClass("android.bluetooth.BluetoothAdapter"))
{
AndroidJavaObject bluetoothAdapter = bluetoothAdapterClass.CallStatic<AndroidJavaObject>("getDefaultAdapter");
if (bluetoothAdapter != null && bluetoothAdapter.Call<bool>("isEnabled"))
{
Log("用户已启用蓝牙");
onBluetoothReady?.Invoke();
yield break;
}
}
yield return new WaitForSeconds(0.5f);
timer += 0.5f;
}
Log("用户未启用蓝牙或超时");
OnError?.Invoke("请启用蓝牙后重试");
OnInitialized?.Invoke(false);
}
return false;
#elif UNITY_IOS && !UNITY_EDITOR
return GetBluetoothStateIOS() == 5;
#else
return true;
#endif
}
/// <summary>
/// 执行蓝牙初始化
@ -365,8 +522,27 @@ namespace Kill.Bluetooth
{
IsInitialized = true;
_isFullyInitialized = true;
_enableBtCoroutine = null;
_userDeniedBluetooth = false;
Log("蓝牙初始化成功");
OnInitialized?.Invoke(true);
// 如果有待执行的扫描任务,立即执行
if (_pendingStartScan)
{
_pendingStartScan = false;
Log($"执行待处理的扫描,超时: {_pendingScanTimeout}秒");
DoStartScan(_pendingScanTimeout);
}
// 如果有待连接的设备地址,连接
if (!string.IsNullOrEmpty(_pendingConnectAddress))
{
var addr = _pendingConnectAddress;
_pendingConnectAddress = null;
Log($"执行待处理的连接: {addr}");
StartCoroutine(DelayedConnectAfterInit(addr));
}
},
(error) =>
{
@ -377,7 +553,26 @@ namespace Kill.Bluetooth
Log("继续初始化...");
IsInitialized = true;
_isFullyInitialized = true;
_enableBtCoroutine = null;
_userDeniedBluetooth = false;
OnInitialized?.Invoke(true);
// 如果有待执行的扫描任务,立即执行
if (_pendingStartScan)
{
_pendingStartScan = false;
Log($"执行待处理的扫描,超时: {_pendingScanTimeout}秒");
DoStartScan(_pendingScanTimeout);
}
// 如果有待连接的设备地址,连接
if (!string.IsNullOrEmpty(_pendingConnectAddress))
{
var addr = _pendingConnectAddress;
_pendingConnectAddress = null;
Log($"执行待处理的连接: {addr}");
StartCoroutine(DelayedConnectAfterInit(addr));
}
}
// 如果已经初始化完成,这是运行时错误,不是初始化错误
else if (_isFullyInitialized)
@ -388,6 +583,7 @@ namespace Kill.Bluetooth
else
{
Log($"蓝牙初始化失败: {error}");
_enableBtCoroutine = null;
OnError?.Invoke($"初始化失败: {error}");
OnInitialized?.Invoke(false);
}
@ -448,6 +644,15 @@ namespace Kill.Bluetooth
}
}
/// <summary>
/// 初始化完成后延迟连接设备
/// </summary>
private System.Collections.IEnumerator DelayedConnectAfterInit(string address)
{
yield return new WaitForSeconds(0.5f);
Connect(address);
}
@ -460,10 +665,21 @@ namespace Kill.Bluetooth
{
if (!IsInitialized)
{
OnError?.Invoke("蓝牙未初始化请先调用Initialize()");
Log("蓝牙未初始化,自动触发初始化流程...");
_pendingStartScan = true;
_pendingScanTimeout = timeout;
Initialize();
return;
}
DoStartScan(timeout);
}
/// <summary>
/// 实际执行扫描逻辑
/// </summary>
private void DoStartScan(float timeout)
{
if (IsScanning)
{
Log("已经在扫描中,先停止当前扫描...");
@ -546,7 +762,11 @@ namespace Kill.Bluetooth
{
if (!IsInitialized)
{
OnError?.Invoke("蓝牙未初始化");
Log("蓝牙未初始化,自动触发初始化流程...");
_pendingStartScan = true;
_pendingScanTimeout = 999f;
_pendingConnectAddress = deviceAddress;
Initialize();
return;
}

View File

@ -156,8 +156,7 @@ namespace Kill.Network
}
else
{
// 自动显示错误提示
ShowErrorTip(code.ToString());
ToastUI.ShowText(message);
}
}

View File

@ -150,7 +150,7 @@ public class ConnectDevicePageCtrl : MonoBehaviour
if (string.IsNullOrEmpty(ssid))
{
ToastUI.ShowText(LanguageManager.Instance.GetLanguage("100082") ?? "请输入WiFi名称");
ToastUI.Show("100082");
return;
}
@ -177,7 +177,7 @@ public class ConnectDevicePageCtrl : MonoBehaviour
}
else
{
ToastUI.ShowText(LanguageManager.Instance.GetLanguage("100083") ?? "WiFi配置失败");
ToastUI.Show("100083");;
}
});
});
@ -353,6 +353,8 @@ public class ConnectDevicePageCtrl : MonoBehaviour
deviceObjects.Clear();
}
deviceObjects = new List<GameObject>();
// 用户进入配网页面,强制初始化以触发蓝牙开启提示
BluetoothManager.Instance.ForceInitialize();
BluetoothManager.Instance.StartScan(999f); // 扫描999秒
}
}

View File

@ -127,18 +127,18 @@ namespace Kill.UI.Pages
switch (nowChartIndex)
{
case 0:
startTime = now.AddDays(-1).ToString("yyyy-MM-dd");
startTime = now.AddDays(-1).ToString("yyyy-MM-dd 00:00:00");
break;
case 1:
startTime = now.AddDays(-((int)now.DayOfWeek + 1)).ToString("yyyy-MM-dd");
startTime = now.AddDays(-((int)now.DayOfWeek + 1)).ToString("yyyy-MM-dd 00:00:00");
break;
case 2:
startTime = new DateTime(now.Year, now.Month, 1).ToString("yyyy-MM-dd");
startTime = new DateTime(now.Year, now.Month, 1).ToString("yyyy-MM-dd 00:00:00");
break;
case 3:
startTime = new DateTime(now.Year, 1, 1).ToString("yyyy-MM-dd");
startTime = new DateTime(now.Year, 1, 1).ToString("yyyy-MM-dd 00:00:00");
break;
}

View File

@ -328,7 +328,7 @@ namespace Kill.UI.Pages
isQueryingStatus = false;
statusQueryQueue?.Clear();
UIManager.Instance?.ClearBackAction();
UIManager.Instance.OpenPage(UIManager.PageName.homePage, null, true);
// OpenPage 已移至 BluetoothManager.OnSelfDisconnected全局监听 + 延迟)
if(bluetoothDeviceInfoCoroutine!=null)
{
StopCoroutine(bluetoothDeviceInfoCoroutine);

View File

@ -26,7 +26,6 @@ namespace Kill.UI.Pages
{
this.isBluetooth = isBluetooth;
bluetoothStateIcon.color = stateBgColor[isBluetooth ? 1 : 0];
bluetoothSearchIcon.SetActive(!isBluetooth);
wifiStateIcon.color = stateBgColor[isWifi ? 1 : 0];
bool isOnline = isBluetooth || isWifi;
onlineStateIcon.sprite = onlineState[isOnline ? 1 : 0];
@ -44,9 +43,16 @@ namespace Kill.UI.Pages
}
public void ClickScan()
{
if(!BluetoothManager.Instance.IsConnected)
if (!BluetoothManager.Instance.IsConnected)
{
// 用户主动点击,强制初始化以触发蓝牙开启提示
BluetoothManager.Instance.ForceInitialize();
BluetoothManager.Instance.StartScan(10);
bluetoothSearchIcon.SetActive(true);
}
else
{
return;
}
}
}
}