Schedule Task (Screen Time API) on iOS in background mode

I have developed a Flutter application to lock selected apps using the Screen Time API (iOS). My app has been registered in Family Control and currently successfully executes app restrictions in both emulators and devices through TestFlight. I intend to incorporate a countdown timer feature to ensure that the app restriction function is activated when the timer stops (e.g 15 minutes after function called).

However, the issue I'm facing is that on iOS, when the app goes into the background mode, all processes, including the countdown, halt, rendering the restriction function unusable. I have attempted various mechanisms, such as:

  1. DeviceActivityMonitor extension => Not triggered even though DeviceActivitySchedule is set.
  2. Cron => Stops when in background mode.
  3. Local notification => Only triggered when the user interacts with the notification, not automatically execute function in background

Is there a solution to address this matter?

Here is my snippet code, startAppRestrictions() is already work, but I need to started it after 15 minutes (I tried on schedulingRestrictions() function)

import Foundation

import FamilyControls
import ManagedSettings
import DeviceActivity

private let _MyModel = MyModel()

class MyModel: ObservableObject {
    let store = ManagedSettingsStore() 
    
    @Published var familyActivitySelection: FamilyActivitySelection
    
    var selectAppTitle: String = ""
    var cancelButtonTitle: String = ""
    var doneButtonTitle: String = ""
    
    
    init() {
        familyActivitySelection = FamilyActivitySelection()
    }
    
    class var shared: MyModel {
        return _MyModel
    }
    
    func startAppRestrictions() {
        print("setShieldRestrictions")
        
        // Pull the selection out of the app's model and configure the application shield restriction accordingly
        let applications = MyModel.shared.familyActivitySelection
        
        if applications.applicationTokens.isEmpty {
            print("empty applicationTokens")
        }                    
        
        if applications.categoryTokens.isEmpty {
            print("empty categoryTokens")
        }
        
        //lock application
        store.shield.applications = applications.applicationTokens.isEmpty ? nil : applications.applicationTokens
        store.shield.applicationCategories = applications.categoryTokens.isEmpty ? nil : ShieldSettings.ActivityCategoryPolicy.specific(applications.categoryTokens)
        
        //more rules
        store.media.denyExplicitContent = true
        
        //prevent app removal
        store.application.denyAppRemoval = true
        print("deny app removal: ",  store.application.denyAppRemoval ?? false)
        
        //prevent set date time
        store.dateAndTime.requireAutomaticDateAndTime = true
    }
    
    func stopAppRestrictions(){
        //lock application
        store.shield.applications = nil
        store.shield.applicationCategories = nil
        
        //more rules
        store.media.denyExplicitContent = false
        
        //prevent app removal
        store.application.denyAppRemoval = false
        print("deny app removal: ",  store.application.denyAppRemoval ?? false)
        
        //prevent set date time
        store.dateAndTime.requireAutomaticDateAndTime = false
    }
    
    func isAppLocked() -> Bool {
        let isShieldEmpty = (store.shield.applicationCategories == nil);
         return !isShieldEmpty
    }
    
    func countSelectedAppCategory() -> Int {
        let applications = MyModel.shared.familyActivitySelection
        return applications.categoryTokens.count
    }

    func countSelectedApp() -> Int {
        let applications = MyModel.shared.familyActivitySelection
        return applications.applicationTokens.count
    }
    
    func schedulingRestrictions() {
        
        print("Start monitor restriction")
        
        // Schedule restriction 15 minutes after started
        let now = Date()
        let fiveMinutesLater = Calendar.current.date(byAdding: .minute, value: 15, to: now)
        let schedule = DeviceActivitySchedule(intervalStart: Calendar.current.dateComponents([.hour, .minute], from: now),
                                              intervalEnd: Calendar.current.dateComponents([.hour, .minute], from: fiveMinutesLater ?? now),
                                              repeats: true,
                                              warningTime: nil)

        let center = DeviceActivityCenter()
        
        do {
            try center.startMonitoring(.restrictAppActivityName, during: schedule)
            
            print("Success with Starting Monitor Activity")
        }
        catch {
            print("Error with Starting Monitor Activity: \(error.localizedDescription)")
        }

        // Setting various properties of the ManagedSettingsStore instance
        let applications = MyModel.shared.familyActivitySelection
        if applications.applicationTokens.isEmpty {
            print("empty applicationTokens")
        }
        if applications.categoryTokens.isEmpty {
            print("empty categoryTokens")
        }
        print("monitoring model started")
    }
}

extension DeviceActivityName {
    static let restrictAppActivityName = Self("restrictApp")
}

My DeviceActivityMonitor extension

import UIKit
import MobileCoreServices
import ManagedSettings
import DeviceActivity

class MyMonitor: DeviceActivityMonitor {
    
    override init() {
        print("device activity monitor inited")
    }
    
    override func intervalDidStart(for activity: DeviceActivityName) {
        super.intervalDidStart(for: activity)
        print("device activity monitor start")
        let model = MyModel.shared
        model.stopAppRestrictions()
        print("monitor started")
    }

    override func intervalDidEnd(for activity: DeviceActivityName) {
        super.intervalDidEnd(for: activity)
        print("device activity monitor end")
        let model = MyModel.shared
        model.startAppRestrictions()
        print("monitor stopped")
    }
}

Fixed by recreating Target Extension & changing from print log to show from local notification, somehow Print log from the target extension is not showing on XCode even though I already do Debug > Attach to the Process

//
//  DeviceActivityMonitorExtension.swift
//  NewMonitor
//
//  Created by Mochammad Yusuf Fachroni on 18/08/23.
//

import DeviceActivity
import UserNotifications
import ManagedSettings


// Optionally override any of the functions below.
// Make sure that your class name matches the NSExtensionPrincipalClass in your Info.plist.

class DeviceActivityMonitorExtension: DeviceActivityMonitor {
    
    func showLocalNotification(title: String, desc: String) {
          let content = UNMutableNotificationContent()
          content.title = title
          content.body = desc
          content.sound = .default

          let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 1, repeats: false)
          let request = UNNotificationRequest(identifier: "localNotification", content: content, trigger: trigger)

          UNUserNotificationCenter.current().add(request) { error in
            if let error = error {
              print("Failed to show notification: \(error.localizedDescription)")
            }
          }

        let center = UNUserNotificationCenter.current()
        center.add(request) { (error) in
            if let error = error {
                print("Failed to add notification: \(error)")
            } else {
                print("Success add notification")
            }
        }
    }
    
    override func intervalDidStart(for activity: DeviceActivityName) {
        super.intervalDidStart(for: activity)
        showLocalNotification(title: "My Start Restrict App", desc: "Restriction App started successfully")
    }
    
    override func intervalDidEnd(for activity: DeviceActivityName) {
        super.intervalDidEnd(for: activity)
        showLocalNotification(title: "My Restriction Stopped", desc: "Restriction App is stopped")

        let socialStore = ManagedSettingsStore(named: .mySettingStore)
        socialStore.clearAllSettings()
    }
    
}
Schedule Task (Screen Time API) on iOS in background mode
 
 
Q