DeviceActivityCenter is not working in iOS 17

47 Views Asked by At

startMonitoring is not working in iOS 17 and its extension methods also are not being called intervalDidStart(for activity: DeviceActivityName), it is working fine in iOS 16. Sometimes it freezes the app for a while and sometime throws the errors like:-

"This application is monitoring excessive activities"

and

System error occurred: related decl 'e' for USError(_nsError: Error Domain=UsageTrackingErrorDomain Code=101 "Failed to fetch a usage budget" UserInfo={NSLocalizedDescription=Failed to fetch a usage budget, NSLocalizedRecoverySuggestion=See Console for additional details.})

import Foundation
import FamilyControls
import DeviceActivity
import ManagedSettings
import SwiftUI

final class LockManager{
    
    let calendar = Calendar.current
    let appsModel = AppSelection()
    let deviceActivityCenter = DeviceActivityCenter()
    
    static let shared = LockManager()
    
    private init(){}
    
    func authorize(){
        Task{
            try? await AuthorizationCenter.shared.requestAuthorization(for: .individual)
        }
    }
    
    func activateOneOffLockSession(for duration: Duration, group: AppGroup, mode: AccountabilityMode, completion: @escaping(_ error: Error?) -> Void){
        authorize()
        guard let hours = duration.hours, let minutes = duration.minutes else {return}
        let id = UUID().uuidString
        let schedule = DeviceActivitySchedule(
            intervalStart: calendar.dateComponents([.calendar, .hour, .minute, .second], from: Date()),
            intervalEnd: calendar.dateComponents([.calendar, .hour, .minute, .second], from: Date().addingTimeInterval(TimeInterval(hours*3600 + minutes*60))),
            repeats: false
        )
        do {
            try deviceActivityCenter.startMonitoring(.init(id), during: schedule)
            if var lockSessions = UserDefaults.getLockSessions(){
                lockSessions.oneOffSessions.append(.init(id: id, startTime: Date(), timeInterval: TimeInterval(hours*3600 + minutes*60), mode: mode, group: group))
                UserDefaults.storeLockSessions(lockSessions: lockSessions)
            }
            else{
                UserDefaults.storeLockSessions(lockSessions: .init(oneOffSessions: [.init(id: id, startTime: Date(), timeInterval: TimeInterval(hours*3600 + minutes*60), mode: mode, group: group)], scheduledSessions: []))
            }
            completion(nil)
        } catch let error {
            completion(error)
        }
        
    }
    
    func scheduleLock(for lockSession: ScheduleLockSession, completion: @escaping(_ error: Error?) -> Void){
        authorize()
        let startTimeComponents = calendar.dateComponents([.hour, .minute], from: lockSession.startTime)
        let endTimeComponents = calendar.dateComponents([.hour, .minute], from: lockSession.endTime)
        
        stopScheduledLockSession(for: lockSession.id)
        
        for (index, daysIndex) in lockSession.daysIndex.enumerated() {
            let schedule = DeviceActivitySchedule(
                intervalStart: DateComponents(calendar: .current, hour: startTimeComponents.hour, minute: startTimeComponents.minute, weekday: daysIndex+1),
                intervalEnd: DateComponents(calendar: .current, hour: endTimeComponents.hour, minute: endTimeComponents.minute, weekday: daysIndex+1),
                repeats: true
            )
            do {
                try deviceActivityCenter.startMonitoring(.init("\(lockSession.id)\(index)"), during: schedule)
                if index == lockSession.daysIndex.count-1{
                    
                    if var lockSessions = UserDefaults.getLockSessions(){
                        if let index = lockSessions.scheduledSessions.firstIndex(where: {$0.id == lockSession.id}){
                            lockSessions.scheduledSessions[index] = lockSession
                            UserDefaults.storeLockSessions(lockSessions: lockSessions)
                        }
                        else{
                            lockSessions.scheduledSessions.append(lockSession)
                            UserDefaults.storeLockSessions(lockSessions: lockSessions)
                        }
                    }
                    else{
                        UserDefaults.storeLockSessions(lockSessions: .init(oneOffSessions: [], scheduledSessions: [lockSession]))
                    }
                    
                }
                completion(nil)
                
            } catch let error {
                completion(error)
            }
        }
        
    }
    
    func removeOneOffLockSession(for id: String){
        deviceActivityCenter.stopMonitoring([.init(id)])
        ManagedSettingsStore.init(named: .init(id)).clearAllSettings()
        
        if var lockSessions = UserDefaults.getLockSessions(){
            lockSessions.oneOffSessions.removeAll(where: {$0.id == id})
            UserDefaults.storeLockSessions(lockSessions: lockSessions)
        }
    }
    
    func removeScheduledLockSession(for id: String){
        stopScheduledLockSession(for: id)
        
        if var lockSessions = UserDefaults.getLockSessions(){
            lockSessions.scheduledSessions.removeAll(where: {$0.id == id})
            UserDefaults.storeLockSessions(lockSessions: lockSessions)
        }
    }
    
    func stopScheduledLockSession(for id: String){
        deviceActivityCenter.stopMonitoring(
            [.init("\(id)\(0)"),
             .init("\(id)\(1)"),
             .init("\(id)\(2)"),
             .init("\(id)\(3)"),
             .init("\(id)\(4)"),
             .init("\(id)\(5)"),
             .init("\(id)\(6)")])
    }
    
}

class AppSelection: ObservableObject {
    @Published var selectedApps = FamilyActivitySelection()
}

Tried every possible way but not worked for iOS 17

0

There are 0 best solutions below