Browse Source

上传提醒提示

newdev_shunjiawei
liwei1dao 1 year ago
parent
commit
54aabb7804
  1. 4
      local_plugins/ble_service/android/src/main/kotlin/com/yunqiinnovation/ble_service/BleServicePlugin.kt
  2. 161
      local_plugins/chat_api/ios/chat_api/Sources/chat_api/SystemFunctionHandler.swift

4
local_plugins/ble_service/android/src/main/kotlin/com/yunqiinnovation/ble_service/BleServicePlugin.kt

@ -302,8 +302,8 @@ class BleServicePlugin : FlutterPlugin, MethodCallHandler, ActivityAware,
} }
} }
"startScan" -> { "startScan" -> {
val devicename = call.argument<String>("devicename")?:"" val uuids = call.argument<List<String>>("uuids")?:emptyList()
val connected = BleService.startScan(devicename) val connected = BleService.startScan(uuids)
result.success(connected) result.success(connected)
} }
"getDeviceInfo" -> { "getDeviceInfo" -> {

161
local_plugins/chat_api/ios/chat_api/Sources/chat_api/SystemFunctionHandler.swift

@ -8,6 +8,7 @@ import user_portrait // 添加这行
import MediaPlayer import MediaPlayer
import AVFoundation import AVFoundation
import UserNotifications
// 在文件顶部添加通知名称定义 // 在文件顶部添加通知名称定义
extension Notification.Name { extension Notification.Name {
@ -693,12 +694,12 @@ private class MakePhoneCallHandler: FunctionHandler {
/// 设置提醒处理器 /// 设置提醒处理器
private class SetReminderHandler: FunctionHandler { private class SetReminderHandler: FunctionHandler {
private let eventStore: EKEventStore? private var eventStore: EKEventStore? = EKEventStore()
init(eventStore: EKEventStore?) { init(eventStore: EKEventStore?) {
self.eventStore = eventStore self.eventStore = eventStore
} }
func handle(arguments: [String: Any]) async throws -> String { func handle(arguments: [String: Any]) async throws -> String {
guard let title = arguments["title"] as? String, guard let title = arguments["title"] as? String,
let timeString = arguments["time"] as? String else { let timeString = arguments["time"] as? String else {
@ -706,99 +707,113 @@ private class SetReminderHandler: FunctionHandler {
} }
let content = arguments["content"] as? String ?? "" let content = arguments["content"] as? String ?? ""
let result = await setReminder(title: title, content: content, time: timeString) let result = await setAlarmReminder(title: title, content: content, time: timeString)
return "{\"result\": \"\(result.message)\"}" return "{\"result\": \"\(result.message)\"}"
} }
private func setReminder(title: String, content: String, time: String) async -> Result { // 设置闹钟级提醒(主方法)
guard let eventStore = eventStore else { func setAlarmReminder(title: String, content: String, time: String) async -> Result {
return Result(success: false, message: "事件存储未初始化") // 1. 请求日历权限
let calendarStatus = await EKEventStore.authorizationStatus(for: .reminder)
guard calendarStatus == .authorized else {
let message = calendarStatus == .denied
? "日历权限已拒绝,请前往「设置 → 隐私与安全 → 日历」开启"
: "日历权限不足"
return Result(success: false, message: message)
} }
// 请求日历权限 // 2. 请求关键通知权限(闹钟级提醒必需)
let status = await requestCalendarAccess() let notificationCenter = UNUserNotificationCenter.current()
print("[SetReminder] 权限检查结果: \(status.rawValue) - \(statusDescription(status))") do {
let granted = try await notificationCenter.requestAuthorization(options: [.alert, .sound, .criticalAlert])
switch status { guard granted else {
case .authorized: return Result(success: false, message: "请在「设置 → 你的App → 通知」中开启关键通知权限")
// 权限已授权,继续执行 }
break } catch {
case .denied: return Result(success: false, message: "通知权限请求失败:\(error.localizedDescription)")
return Result(success: false, message: "日历权限被拒绝,请前往 设置 > 隐私与安全 > 日历 中开启权限")
case .restricted:
return Result(success: false, message: "日历权限受限制,可能由于家长控制或企业策略限制")
case .notDetermined:
return Result(success: false, message: "日历权限未确定,请重试")
@unknown default:
return Result(success: false, message: "日历权限状态未知")
} }
// 解析时间 // 3. 解析并验证时间(必须在当前时间10秒后)
let formatter = DateFormatter() let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd HH:mm" formatter.dateFormat = "yyyy-MM-dd HH:mm"
guard let date = formatter.date(from: time) else { formatter.timeZone = TimeZone.current
guard let targetDate = formatter.date(from: time), targetDate.timeIntervalSinceNow > 10 else {
return Result(success: false, message: "时间格式错误") return Result(success: false, message: "时间格式错误")
} }
// 创建提醒 // 4. 创建日历提醒(作为备份)
let calendarResult = await createCalendarReminder(title: title, content: content, date: targetDate)
guard calendarResult.success else {
return calendarResult
}
// 5. 创建关键通知(闹钟级效果核心)
return await createCriticalNotification(title: title, content: content, date: targetDate)
}
// 创建日历提醒(备份用)
private func createCalendarReminder(title: String, content: String, date: Date) async -> Result {
guard let eventStore = eventStore else {
return Result(success: false, message: "日历服务不可用")
}
let reminder = EKReminder(eventStore: eventStore) let reminder = EKReminder(eventStore: eventStore)
reminder.title = title reminder.title = title
reminder.notes = content reminder.notes = content
reminder.calendar = eventStore.defaultCalendarForNewReminders()
let alarm = EKAlarm(absoluteDate: date) // 获取可用日历
reminder.addAlarm(alarm) guard let targetCalendar = eventStore.defaultCalendarForNewReminders()
?? eventStore.calendars(for: .reminder).first(where: { $0.allowsContentModifications }) else {
return Result(success: false, message: "无可用日历,请先在系统日历中创建日历")
}
reminder.calendar = targetCalendar
reminder.addAlarm(EKAlarm(absoluteDate: date))
// 保存提醒
do { do {
try eventStore.save(reminder, commit: true) try eventStore.save(reminder, commit: true)
return Result(success: true, message: "提醒设置成功") return Result(success: true, message: "日历提醒已创建")
} catch { } catch {
return Result(success: false, message: "设置提醒失败:\(error.localizedDescription)") return Result(success: false, message: "日历提醒保存失败:\(error.localizedDescription)")
}
}
private func requestCalendarAccess() async -> EKAuthorizationStatus {
return await withCheckedContinuation { continuation in
// 首先检查当前权限状态
let currentStatus = EKEventStore.authorizationStatus(for: .reminder)
print("[Calendar] 当前权限状态: \(currentStatus.rawValue) - \(statusDescription(currentStatus))")
// 如果已经授权,直接返回
if currentStatus == .authorized {
continuation.resume(returning: currentStatus)
return
}
// 如果被拒绝,也直接返回(避免重复请求)
if currentStatus == .denied {
print("[Calendar] 权限已被拒绝,需要用户手动在设置中开启")
continuation.resume(returning: currentStatus)
return
}
// 请求权限
eventStore?.requestAccess(to: .reminder) { granted, error in
let finalStatus = EKEventStore.authorizationStatus(for: .reminder)
print("[Calendar] 权限请求完成 - granted: \(granted), error: \(error?.localizedDescription ?? "无")")
print("[Calendar] 最终权限状态: \(finalStatus.rawValue) - \(self.statusDescription(finalStatus))")
continuation.resume(returning: finalStatus)
}
} }
} }
// 添加状态描述辅助方法 // 创建关键通知(实现闹钟级效果)
private func statusDescription(_ status: EKAuthorizationStatus) -> String { private func createCriticalNotification(title: String, content: String, date: Date) async -> Result {
switch status { let notificationContent = UNMutableNotificationContent()
case .notDetermined: notificationContent.title = title
return "未确定" notificationContent.body = content
case .restricted: notificationContent.badge = 1
return "受限制"
case .denied: // 关键配置:闹钟级声音(突破静音,最大音量)
return "被拒绝" notificationContent.sound = UNNotificationSound.criticalSoundNamed(
case .authorized: UNNotificationSoundName("default"),
return "已授权" withAudioVolume: 1.0
@unknown default: )
return "未知状态"
// 关键配置:最高优先级(突破勿扰,全屏弹窗)
notificationContent.interruptionLevel = .critical
notificationContent.relevanceScore = 1.0 // 最高相关性分数
// 设置触发时间(精确到秒)
let components = Calendar.current.dateComponents(
[.year, .month, .day, .hour, .minute, .second],
from: date
)
let trigger = UNCalendarNotificationTrigger(dateMatching: components, repeats: false)
// 发送通知请求
let request = UNNotificationRequest(
identifier: "Alarm_\(UUID().uuidString)",
content: notificationContent,
trigger: trigger
)
do {
try await UNUserNotificationCenter.current().add(request)
return Result(success: true, message: "闹钟级提醒已设置,到点将强制响铃")
} catch {
return Result(success: false, message: "通知创建失败:\(error.localizedDescription)")
} }
} }
} }

Loading…
Cancel
Save