DeviceActivityMonitorExtension 不被调用?排查指南
2025-01-12 19:57:09
DeviceActivityMonitorExtension 不被调用的排查指南
DeviceActivityMonitorExtension 用于监控设备活动并执行相应的操作。当此扩展不被调用时,通常是由几个关键配置或实现错误导致的。 下文将针对此问题,剖析可能的原因,并提供相应的解决方案。
常见问题与分析
最常见的现象是:虽然你在代码中调用了 DeviceActivityCenter().startMonitoring()
,期望扩展内的 intervalDidStart
, intervalDidEnd
或 eventDidReachThreshold
等方法被触发,实际却没有任何反应,如同石沉大海。
根本原因往往在于以下几个方面:
- 配置问题 :
DeviceActivityMonitorExtension
的配置不完整或者不正确。例如,缺少必要的功能声明、Info.plist 文件配置错误或权限不足。 - 代码逻辑问题 :
DeviceActivityMonitor
的调度配置或DeviceActivityEvent
定义存在问题。 监控启动、事件定义,乃至时间配置的不当,都会导致扩展程序无法正常工作。 - 模拟器/真机环境 : 某些测试行为在模拟器上可能与真机存在差异。因此需要切换环境,尝试解决某些由于模拟器特殊环境而引起的问题。
- 进程间通信问题 : DeviceActivity 机制运行在不同的进程中,因此任何可能阻碍进程间通信的问题都可能影响到 Extension 的正常执行。例如,app group设置或者证书签名错误都有可能会出现这类问题。
- 代码错误 : 例如:使用 Notification 相关函数时权限申请不及时或使用错误可能造成相关行为没有生效。
解决方案
以下提供几种解决 DeviceActivityMonitorExtension
不被调用的方法,并给出代码示例和步骤说明。
方案一: 确保 Info.plist 文件配置正确
DeviceActivityMonitorExtension
需要在 Info.plist 文件中正确声明其身份和所需的权限。
步骤:
- 检查你的
DeviceActivityMonitorExtension
的 Info.plist 文件:
* `NSExtension` 字典中必须有 `NSExtensionPointIdentifier` 键,且值必须为 `com.apple.deviceactivity-monitor`。
* `NSExtensionPrincipalClass` 键值必须匹配你的 `DeviceActivityMonitorExtension` 类名 (如 `DeviceActivityMonitorExtension`)。
方案二: 检查 App Groups 配置
使用 FamilyControls
和 DeviceActivity
时,应用和扩展必须共享同一个 App Group。
步骤:
- 打开Xcode,选中应用和 Extension target。在Signing & Capabilities 添加
App Groups
。确认两者使用了相同的App Group Identifier
。如果还不存在App Group Identifier
,点击+
号,新建即可。 - 代码示例 (仅示例检查,代码一般无需修改):
// 在您的扩展中
let sharedUserDefaults = UserDefaults(suiteName: "你的 App Group Identifier")
确保应用的 bundle id
存在与 app group identifier
相对应的prefix
。 例如你的应用的 bundle id
是com.example.app
。 如果app group identifier
是 group.example.share
那么此app group prefix
为 group.example
。 请注意,即使应用之间没有相互依赖,多个应用的app group identifier 前缀都应该相同。 确保这些在你的 Provisioning profile
文件中都得到了体现。
方案三:仔细检查 DeviceActivityCenter().startMonitoring()
参数
正确的调用 startMonitoring
是 DeviceActivityMonitorExtension
工作的基石。
步骤:
- 确认你声明
DeviceActivityName
的地方(static let daily = Self("daily")
)和startMonitoring()
里使用的name相同。 - 核查
intervalStart
和intervalEnd
是否按预期设置。 错误的开始和结束时间设置会导致监控无法正常进行。如以下代码中,时间被设置为零点至晚上的 11点 59,因此任何时候你测试这个设置,DeviceActivityMonitorExtension
都应该能监听到事件。 - 确保
DeviceActivityEvent
被正确的初始化。你的示例代码中初始化代码没有问题,但请记住applicationTokens
一定要有值。并且该applicationTokens
需要是符合FamilyControls
要求。
let schedule = DeviceActivitySchedule(
intervalStart: DateComponents(hour: 0, minute: 0),
intervalEnd: DateComponents(hour: 23, minute: 59),
repeats: true
)
let dailyEvent = DeviceActivityEvent(
applications: GlobalSelection.shared.selection.applicationTokens, threshold: threshold
)
do {
try DeviceActivityCenter().startMonitoring(.daily, during: schedule, events: ["dailyLimitEvent": dailyEvent])
}catch {
print("监控启动错误 \(error)")
}
此外确保事件的key 和事件名相同 (如 dailyLimitEvent
):
代码示例:
let eventName = DeviceActivityEvent.Name("dailyLimitEvent") //确保声明时key 和 startMonitoring 中事件名称相同。
do {
try DeviceActivityCenter().startMonitoring(.daily, during: schedule, events: [eventName: dailyEvent])
print("监控已启动")
}catch{
print("启动失败 \(error)")
}
确保传给 events
的参数为一个字典类型,key
为事件名字 DeviceActivityEvent.Name
结构的值, value为你的 DeviceActivityEvent
结构。 如果你需要监听多个事件,将对应的事件加到字典中即可。
方案四:Notification 配置与权限
如 `DeviceActivityMonitorExtension` 中需要展示本地通知,需要确认已向用户申请授权。并需要合理初始化本地通知配置。
步骤:
- 确保你在初始化通知之前进行了用户授权,以及对通知注册成功的回调做了合适的异常处理,示例代码如下所示。
代码示例:
func scheduleNotification(with title: String) {
let center = UNUserNotificationCenter.current()
center.requestAuthorization(options: [.alert, .sound, .badge]) { granted, error in
if granted {
// 构建通知 content
let request = UNNotificationRequest(identifier: "MyNotification", content: content, trigger: trigger)
center.add(request) { error in
if let error = error{
print("注册本地通知失败 \(error.localizedDescription)")
}else {
print("注册本地通知成功")
}
}
} else {
print("无通知授权: \(error?.localizedDescription ?? "")")
}
}
}
方案五:模拟器与真机测试对比
某些测试和模拟效果在模拟器中表现的可能与真实环境有差异。 例如一些测试方法, 可能会因为没有在真机安装证书或者 profile 而出现不生效情况。 在你的 debug 或者release 版本中使用真机进行测试,往往会提供给你更多有用信息。
额外建议:
- 在 debug 时开启控制台,将 debug 信息打印到 console, 便于排错。
- 可以考虑在 App 和 Extension 中引入同样的 Log 方法,更方便跟踪和问题排查。
- 合理使用断点调试 (breakpoint),并熟悉其调试方法,可以极大提高你寻找问题的效率。
通过系统排查这些方面的问题,通常能有效地定位并解决 DeviceActivityMonitorExtension
不被调用的问题。 如果你仍旧遇到难题,欢迎把错误代码和具体环境信息,贴到社区请求帮助,以便其他开发者能够更好的帮你解决问题。