package xn.hxp.receiver import android.content.Context import android.content.SharedPreferences import android.view.InputDevice import android.view.KeyEvent import com.blankj.utilcode.util.LogUtils /** * 外置超高频RFID读卡器管理器(单例) * 负责:设备学习、开关管理、白名单管理、设备识别 */ object UhfRfidManager { private const val PREF_NAME = "uhf_rfid_config" private const val KEY_ENABLED = "uhf_enabled" private const val KEY_DEVICE_VENDOR_ID = "uhf_vendor_id" private const val KEY_DEVICE_PRODUCT_ID = "uhf_product_id" private const val KEY_DEVICE_NAME = "uhf_device_name" private const val KEY_WHITELIST = "uhf_whitelist" // 白名单业务标识 const val PAGE_STORAGE_RFID = "storage_rfid" // 存储模块RFID绑定 const val PAGE_LABEL_RFID = "label_rfid" // 标签管理RFID绑定/更换 const val PAGE_INQUIRY = "inquiry" // 查询模块 // 学习模式 var isLearning = false var learningCallback: ((deviceName: String) -> Unit)? = null private fun getPrefs(context: Context): SharedPreferences { return context.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE) } fun isEnabled(context: Context): Boolean { return getPrefs(context).getBoolean(KEY_ENABLED, false) } fun setEnabled(context: Context, enabled: Boolean) { getPrefs(context).edit().putBoolean(KEY_ENABLED, enabled).apply() } fun getDeviceVendorId(context: Context): Int { return getPrefs(context).getInt(KEY_DEVICE_VENDOR_ID, -1) } fun getDeviceProductId(context: Context): Int { return getPrefs(context).getInt(KEY_DEVICE_PRODUCT_ID, -1) } fun getDeviceName(context: Context): String? { return getPrefs(context).getString(KEY_DEVICE_NAME, null) } fun saveDeviceInfo(context: Context, vendorId: Int, productId: Int, deviceName: String) { getPrefs(context).edit() .putInt(KEY_DEVICE_VENDOR_ID, vendorId) .putInt(KEY_DEVICE_PRODUCT_ID, productId) .putString(KEY_DEVICE_NAME, deviceName) .apply() LogUtils.i("UhfRfidManager: 学习设备成功 vendorId=$vendorId productId=$productId name=$deviceName") } fun hasLearnedDevice(context: Context): Boolean { return getDeviceVendorId(context) != -1 && getDeviceProductId(context) != -1 } /** * 获取白名单集合 */ fun getWhitelist(context: Context): Set { val str = getPrefs(context).getString(KEY_WHITELIST, "") ?: "" if (str.isEmpty()) return emptySet() return str.split(",").toSet() } fun saveWhitelist(context: Context, whitelist: Set) { getPrefs(context).edit().putString(KEY_WHITELIST, whitelist.joinToString(",")).apply() } /** * 开始学习模式,等待外置读卡器刷卡 */ fun startLearning(callback: (deviceName: String) -> Unit) { isLearning = true learningCallback = callback } fun stopLearning() { isLearning = false learningCallback = null } fun isPageWhitelisted(context: Context, pageTag: String): Boolean { return getWhitelist(context).contains(pageTag) } /** * 判断KeyEvent是否来自已学习的外置超高频RFID读卡器 */ fun isUhfRfidEvent(context: Context, event: KeyEvent): Boolean { if (!isEnabled(context)) return false if (!hasLearnedDevice(context)) return false val device = event.device ?: return false val vendorId = getDeviceVendorId(context) val productId = getDeviceProductId(context) return device.vendorId == vendorId && device.productId == productId } /** * 学习模式下处理KeyEvent,记录设备信息 * 返回true表示已消费该事件 */ fun handleLearningEvent(context: Context, event: KeyEvent): Boolean { if (!isLearning) return false val device = event.device ?: return false // 学习期间统一消费设备按键,避免触发页面按钮导致误操作或重启 if (!isCandidateLearningDevice(device, event)) return true // 只在ACTION_DOWN时记录,避免重复 if (event.action != KeyEvent.ACTION_DOWN) return true val vendorId = device.vendorId val productId = device.productId val deviceName = device.name ?: "Unknown" saveDeviceInfo(context, vendorId, productId, deviceName) isLearning = false learningCallback?.invoke(deviceName) learningCallback = null return true } /** * 允许学习的候选设备: * 1. 明确标记为 external 的输入设备 * 2. 或具备 vendorId / productId 的 HID 键盘类设备 * * 不再强依赖 isExternal,避免部分 Android 设备把 USB HID 识别成普通键盘导致学习失败。 */ private fun isCandidateLearningDevice(device: InputDevice, event: KeyEvent): Boolean { if (device.isVirtual) return false val hasVidPid = device.vendorId > 0 || device.productId > 0 val keyboardLike = device.sources and InputDevice.SOURCE_KEYBOARD == InputDevice.SOURCE_KEYBOARD val validKey = event.keyCode != KeyEvent.KEYCODE_UNKNOWN return device.isExternal || (hasVidPid && keyboardLike && validKey) } }