diff --git a/app/src/main/java/com/xiaoqu/watch/app/MainActivity.kt b/app/src/main/java/com/xiaoqu/watch/app/MainActivity.kt index 64107b2..2a8fd9b 100644 --- a/app/src/main/java/com/xiaoqu/watch/app/MainActivity.kt +++ b/app/src/main/java/com/xiaoqu/watch/app/MainActivity.kt @@ -7,8 +7,13 @@ import android.view.View import androidx.navigation.fragment.NavHostFragment import androidx.activity.OnBackPressedCallback import androidx.appcompat.app.AppCompatActivity +import com.google.gson.Gson import com.xiaoqu.watch.R +import com.xiaoqu.watch.data.device.WatchBindInfo +import com.xiaoqu.watch.data.prefs.DevicePrefs import com.xiaoqu.watch.databinding.ActivityMainBinding +import com.xiaoqu.watch.network.api.CommonApi +import com.xiaoqu.watch.network.safeApiCall import com.xiaoqu.watch.event.AppEvent import com.xiaoqu.watch.event.EventBus import com.xiaoqu.watch.data.prefs.UserPrefs @@ -52,6 +57,9 @@ class MainActivity : AppCompatActivity() { /** NFC 任务打卡管理器 */ @Inject lateinit var nfcTaskManager: NfcTaskManager @Inject lateinit var userPrefs: UserPrefs + @Inject lateinit var devicePrefs: DevicePrefs + @Inject lateinit var commonApi: CommonApi + @Inject lateinit var gson: Gson /** OTA 更新弹窗 */ lateinit var updateDialog: UpdateDialogView lateinit var notificationBanner: NotificationBannerView @@ -121,6 +129,11 @@ class MainActivity : AppCompatActivity() { notificationBanner.show(count) } } + 2 -> { + // 绑定成功 → 存用户信息 → 跳首页 + Timber.d("MainActivity: 收到绑定消息") + handleBindMessage(event.rawJson) + } 3 -> { // 解绑 → 清除数据 → 跳绑定页(从任何页面都能跳) Timber.d("MainActivity: 收到解绑消息") @@ -229,6 +242,53 @@ class MainActivity : AppCompatActivity() { } } + // ===== 绑定处理 ===== + + /** 防止重复处理绑定消息 */ + private var bindHandled = false + + /** 处理 MQTT type=2 绑定消息(Activity 级别,不受 Fragment 生命周期影响) */ + private fun handleBindMessage(rawJson: String) { + if (bindHandled) return + bindHandled = true + + try { + val bindInfo = gson.fromJson(rawJson, WatchBindInfo::class.java) + + // 存入 UserPrefs + userPrefs.saveUser( + userId = bindInfo.userId, + mobile = bindInfo.mobile, + userName = bindInfo.userName, + headUrl = bindInfo.headUrl + ) + + // 异步调 API 确认(不阻塞导航) + activityScope.launch { + try { + val params = hashMapOf( + "imei" to devicePrefs.imei, + "userId" to bindInfo.userId + ) + safeApiCall { commonApi.bindWatchConfirm(params) } + Timber.d("MainActivity: 绑定确认 API 已调用") + } catch (e: Exception) { + Timber.w(e, "MainActivity: 绑定确认 API 异常") + } + } + + // 导航到首页 + val navHost = supportFragmentManager + .findFragmentById(R.id.nav_host_fragment) as NavHostFragment + navHost.navController.navigate(R.id.action_global_to_home) + Timber.d("MainActivity: 绑定成功,已导航到首页") + + } catch (e: Exception) { + Timber.e(e, "MainActivity: 绑定处理异常") + bindHandled = false + } + } + // ===== OTA 更新 ===== /** 设置更新弹窗按钮回调 */ diff --git a/app/src/main/java/com/xiaoqu/watch/ui/bind/BindFragment.kt b/app/src/main/java/com/xiaoqu/watch/ui/bind/BindFragment.kt index 9a8c637..0539295 100644 --- a/app/src/main/java/com/xiaoqu/watch/ui/bind/BindFragment.kt +++ b/app/src/main/java/com/xiaoqu/watch/ui/bind/BindFragment.kt @@ -6,20 +6,14 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.lifecycle.lifecycleScope -import androidx.navigation.fragment.findNavController import com.google.gson.Gson import com.google.zxing.BarcodeFormat import com.google.zxing.MultiFormatWriter import com.google.zxing.common.BitMatrix -import com.xiaoqu.watch.R -import com.xiaoqu.watch.data.device.WatchBindInfo import com.xiaoqu.watch.data.prefs.DevicePrefs -import com.xiaoqu.watch.data.prefs.UserPrefs import com.xiaoqu.watch.databinding.FragmentBindBinding import com.xiaoqu.watch.event.AppEvent import com.xiaoqu.watch.event.EventBus -import com.xiaoqu.watch.network.api.CommonApi -import com.xiaoqu.watch.network.safeApiCall import com.xiaoqu.watch.ui.common.BaseFragment import dagger.hilt.android.AndroidEntryPoint import kotlinx.coroutines.launch @@ -36,9 +30,7 @@ import javax.inject.Inject class BindFragment : BaseFragment() { @Inject lateinit var devicePrefs: DevicePrefs - @Inject lateinit var userPrefs: UserPrefs @Inject lateinit var eventBus: EventBus - @Inject lateinit var commonApi: CommonApi @Inject lateinit var gson: Gson override fun createBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentBindBinding { @@ -51,7 +43,8 @@ class BindFragment : BaseFragment() { // 生成并显示二维码 generateQrCode() - // 监听 MQTT 绑定消息 + // 绑定消息由 MainActivity 统一处理(Activity 级别,不受 Fragment 生命周期影响) + // 这里只监听用于显示 Loading 状态 observeBindEvent() } @@ -148,54 +141,10 @@ class BindFragment : BaseFragment() { * 3. 调用 bindWatchConfirm API 确认 * 4. 导航到首页 */ - /** 防重复处理标记 */ - private var bindHandled = false - + /** 收到绑定消息 → 仅切换 Loading 状态(导航由 MainActivity 统一处理) */ private fun handleBindSuccess(rawJson: String) { - // 防止重复处理(MQTT 可能重发) - if (bindHandled) return - bindHandled = true - - try { - Timber.d("绑定: 收到绑定消息 $rawJson") - - // 切换到配对中状态 - showLoading() - - // 解析用户信息 - val bindInfo = gson.fromJson(rawJson, WatchBindInfo::class.java) - - // 存入 UserPrefs - userPrefs.saveUser( - userId = bindInfo.userId, - mobile = bindInfo.mobile, - userName = bindInfo.userName, - headUrl = bindInfo.headUrl - ) - - // 调用 API 确认绑定(异步,不阻塞导航) - viewLifecycleOwner.lifecycleScope.launch { - try { - val params = hashMapOf( - "imei" to devicePrefs.imei, - "userId" to bindInfo.userId - ) - safeApiCall { commonApi.bindWatchConfirm(params) } - Timber.d("绑定: 确认 API 已调用") - } catch (e: Exception) { - Timber.w(e, "绑定: 确认 API 异常,不影响导航") - } - } - - // 导航到首页(不等 API 返回,用户信息已存本地) - findNavController().navigate(R.id.action_bind_to_home) - - } catch (e: Exception) { - Timber.e(e, "绑定: 处理绑定消息异常") - bindHandled = false // 异常时允许重试 - // 异常时恢复二维码显示 - showQrCode() - } + Timber.d("绑定: 收到绑定消息,显示 Loading") + showLoading() } /** 显示二维码状态 */ diff --git a/app/src/main/res/navigation/nav_main.xml b/app/src/main/res/navigation/nav_main.xml index ce15a38..e121adb 100644 --- a/app/src/main/res/navigation/nav_main.xml +++ b/app/src/main/res/navigation/nav_main.xml @@ -9,6 +9,11 @@ app:destination="@id/bindFragment" app:popUpTo="@id/nav_main" app:popUpToInclusive="true" /> + + +