ios – Swift utilizing Household Controls to restrict apps and get title of app

0
15
ios – Swift utilizing Household Controls to restrict apps and get title of app


I’m making an attempt to make use of the familycontrols module to restrict display screen time of apps. The limiter works accurately however I need to have the ability to see the names of the apps which might be restricted in my Flutter app. I’ve tried all the pieces and I can not determine easy methods to get the bundle ids of those apps.
I do know that that is potential as a result of there are app blockers that do that.

    for (index, token) in functions.applicationTokens.enumerated() {
        NSLog("Debug: check 1: (functions)")
        NSLog("Debug: check 2: (kind(of: functions.applicationTokens.enumerated()))")
        NSLog("Debug: index: (index)")
        NSLog("Debug: token: (token)")
    }

This code offers the next output:

Debug: check 1: FamilyActivitySelection(includeEntireCategory: false, applicationTokens: Set([ApplicationToken(data: 128 bytes: `D^R’įÅyñxnÆøH4sr;Øý³¶ï(DA^_ÒÖÜÄ~
Å^A¨u^O^ÎÕ^WÆG.aBÍEiÿ_n!jÜj¾U^Hi¼ý^[,H2v7cî·(o[Þò¤¤Þ^[ã/^Ní;ÿÙL^P=Ý ^]®+>¹·Á)]), categoryTokens: Set([]), webDomainTokens: Set([]), untokenizedApplicationIdentifiers: Set([]), untokenizedCategoryIdentifiers: Set([]), untokenizedWebDomainIdentifiers: Set([]))

Debug: check 2: EnumeratedSequence>

Debug: index: 0

Debug: token: ApplicationToken(information: 128 bytes)

Right here is a few of my code (I added lots as a result of I don’t know what is going on):

DeviceActivityMonitorExtension.swift:

typealias ApplicationToken = ManagedSettings.Token
typealias ActivityCategoryToken = ManagedSettings.Token

class DeviceActivityMonitorExtension: DeviceActivityMonitor {
    override func intervalDidStart(for exercise: DeviceActivityName) {
        tremendous.intervalDidStart(for: exercise)
    }
    
    override func intervalDidEnd(for exercise: DeviceActivityName) {
        tremendous.intervalDidEnd(for: exercise)
    }
    
        override func eventDidReachThreshold(_ occasion: DeviceActivityEvent.Title, exercise: DeviceActivityName) {
        tremendous.eventDidReachThreshold(occasion, exercise: exercise)
        
        NSLog("Threshold reached for occasion: (occasion.rawValue)")
        
        // Retrieve saved tokens from shared UserDefaults
        guard let defaults = UserDefaults(suiteName: appGroupID) else {
            NSLog("No app group defaults accessible.")
            return
        }
        
        let decoder = JSONDecoder()
        var applicationTokens: [ApplicationToken] = []
        var categoryTokens: [ActivityCategoryToken] = []
        
        // Decode utility tokens from the brand new key
        if let appTokensData = defaults.information(forKey: Constants.limitedApplicationTokensKey) {
            if let tokens = strive? decoder.decode([ApplicationToken].self, from: appTokensData) {
                applicationTokens = tokens
                NSLog("Decoded (tokens.depend) utility tokens.")
            } else {
                NSLog("Did not decode utility tokens.")
            }
        } else {
            NSLog("No utility tokens present in UserDefaults.")
        }
        
        // Decode class tokens if accessible
        if let catTokensData = defaults.information(forKey: Constants.limitedCategoryIdentifiersKey) {
            if let cats = strive? decoder.decode([ActivityCategoryToken].self, from: catTokensData) {
                categoryTokens = cats
                NSLog("Decoded (cats.depend) class tokens.")
            } else {
                NSLog("Did not decode class tokens.")
            }
        } else {
            NSLog("No class tokens present in UserDefaults.")
        }

        // Apply restrictions now that the brink is reached
        let retailer = ManagedSettingsStore()
        
        // If we've no utility tokens, set nil; in any other case, set them as a Set
        retailer.defend.functions = applicationTokens.isEmpty ? nil : Set(applicationTokens)
        
        // For classes, we use a particular coverage if we've any
        retailer.defend.applicationCategories = categoryTokens.isEmpty
            ? nil
            : ShieldSettings.ActivityCategoryPolicy.particular(Set(categoryTokens))
        
        NSLog("Restrictions utilized. The chosen apps and classes ought to now present the Restricted display screen.")
    }

    override func intervalWillStartWarning(for exercise: DeviceActivityName) {
        tremendous.intervalWillStartWarning(for: exercise)
    }
    
    override func intervalWillEndWarning(for exercise: DeviceActivityName) {
        tremendous.intervalWillEndWarning(for: exercise)
    }
    
    override func eventWillReachThresholdWarning(_ occasion: DeviceActivityEvent.Title, exercise: DeviceActivityName) {
        tremendous.eventWillReachThresholdWarning(occasion, exercise: exercise)
    }
}

MyModel:

import Basis
import FamilyControls
import ManagedSettings

personal let _MyModel = MyModel()

class MyModel: ObservableObject {
    let retailer = ManagedSettingsStore()
    
    @Printed var selectionToDiscourage: FamilyActivitySelection
    @Printed var selectionToEncourage: FamilyActivitySelection
    @Printed var selectionToLimit: FamilyActivitySelection
    
    init() {
        selectionToDiscourage = FamilyActivitySelection()
        selectionToEncourage = FamilyActivitySelection()
        selectionToLimit = FamilyActivitySelection()
    }
    
    class var shared: MyModel {
        return _MyModel
    }
    func setShieldRestrictions() {
        NSLog("Debug: Setting defend restrictions for discouraged apps: (selectionToDiscourage.applicationTokens)")
        let functions = self.selectionToDiscourage
        retailer.defend.functions = functions.applicationTokens.isEmpty ? nil : functions.applicationTokens
        retailer.defend.applicationCategories = functions.categoryTokens.isEmpty
            ? nil
            : ShieldSettings.ActivityCategoryPolicy.particular(functions.categoryTokens)
    }

    // Used to encode codable to UserDefaults
    personal let encoder = PropertyListEncoder()

    // Used to decode codable from UserDefaults
    personal let decoder = PropertyListDecoder()
    
    func saveFamilyActivitySelection(choice: FamilyActivitySelection) {
        NSLog("Debug: chosen app up to date: ", choice.applicationTokens.depend," class: ", choice.categoryTokens.depend)
        let defaults = UserDefaults.commonplace

        defaults.set(
            strive? encoder.encode(choice),
            forKey: "limitedApplicationTokens"
        )
        
        //test is information saved to consumer defaults
        getSavedFamilyActivitySelection()
    }
    
    //get saved household exercise choice from UserDefault
    func getSavedFamilyActivitySelection() -> FamilyActivitySelection? {
        let defaults = UserDefaults.commonplace
        guard let information = defaults.information(forKey: "limitedApplicationTokens") else {
            return nil
        }
        var selectedApp: FamilyActivitySelection?
        let decoder = PropertyListDecoder()
        selectedApp = strive? decoder.decode(FamilyActivitySelection.self, from: information)
        
        NSLog("Debug: saved chosen app up to date: ", selectedApp?.categoryTokens.depend ?? "0")
        return selectedApp
    }

}

AppDelegate.swift:

func clearLimitedAppsData() {
    guard let defaults = UserDefaults(suiteName: Constants.appGroupID) else { return }
    defaults.removeObject(forKey: Constants.limitedApplicationBundleIdentifiersKey)
    defaults.synchronize()
    NSLog("Debug: Cleared limitedApplicationBundleIdentifiersKey information.")
}

var globalMethodCall = ""

@essential
@objc class AppDelegate: FlutterAppDelegate {
    override func utility(
        _ utility: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
    ) -> Bool {

        // clearLimitedAppsData()

        guard let controller = window?.rootViewController as? FlutterViewController else {
            return tremendous.utility(utility, didFinishLaunchingWithOptions: launchOptions)
        }
        
        let METHOD_CHANNEL_NAME = "flutter_screentime"
        
        let mannequin = MyModel.shared
        let retailer = ManagedSettingsStore()
        
        let methodChannel = FlutterMethodChannel(title: METHOD_CHANNEL_NAME, binaryMessenger: controller.binaryMessenger)
        
        methodChannel.setMethodCallHandler { (name: FlutterMethodCall, consequence: @escaping FlutterResult) in
            Activity {
                // Request authorization for Household Controls if accessible
                if #accessible(iOS 16.0, *) {
                    do {
                        strive await AuthorizationCenter.shared.requestAuthorization(for: .particular person)
                        NSLog("Debug: Authorization request succeeded.")
                    } catch {
                        NSLog("Debug: Authorization request failed with error: (error)")
                        consequence(FlutterError(code: "AUTH_ERROR", message: "Authorization failed", particulars: nil))
                        return
                    }
                } else {
                    NSLog("Debug: iOS model is under 16.0, can't proceed.")
                    consequence(FlutterError(code: "iOS_VERSION_ERROR", message: "iOS 16.0 or newer is required", particulars: nil))
                    return
                }
                
                swap name.methodology {
                case "blockApp":
                    globalMethodCall = "selectAppsToDiscourage"
                    NSLog("Debug: Presenting blockApp picker.")
                    let vc = UIHostingController(rootView: ContentView()
                        .environmentObject(mannequin)
                        .environmentObject(retailer))
                    controller.current(vc, animated: true, completion: nil)
                    consequence("blockApp invoked")
                    
                case "unblockApp":
                    globalMethodCall = "selectAppsToEncourage"
                    NSLog("Debug: Presenting unblockApp picker.")
                    let vc = UIHostingController(rootView: ContentView()
                        .environmentObject(mannequin)
                        .environmentObject(retailer))
                    controller.current(vc, animated: true, completion: nil)
                    consequence("unblockApp invoked")
                    
                case "limitApp":
                    globalMethodCall = "selectAppsToLimit"
                    NSLog("Debug: Presenting limitApp picker.")
                    let vc = UIHostingController(rootView: ContentView()
                        .environmentObject(mannequin)
                        .environmentObject(retailer))
                    controller.current(vc, animated: true, completion: nil)
                    consequence("limitApp invoked")
                    
                case "getLimitedApps":
                    if #accessible(iOS 16.0, *) {
                        let limitedApps = self.decodeLimitedApps()
                        NSLog("Debug: Returning restricted apps: (limitedApps)")
                        consequence(limitedApps)
                    } else {
                        NSLog("Debug: iOS < 16.0, can't get restricted apps.")
                        consequence(["No limited apps or iOS < 16.0"])
                    }
                    
                default:
                    NSLog("Debug: Unhandled methodology name: (name.methodology)")
                    consequence(FlutterMethodNotImplemented)
                }
            }
        }
        
        GeneratedPluginRegistrant.register(with: self)
        return tremendous.utility(utility, didFinishLaunchingWithOptions: launchOptions)
    }
    
    @accessible(iOS 16.0, *)
func decodeLimitedApps() -> [String] {
    guard let defaults = UserDefaults(suiteName: Constants.appGroupID) else {
        NSLog("Debug: No app group defaults accessible.")
        return ["No limited apps found."]
    }
    
    let decoder = JSONDecoder()
    var limitedApps: [String] = []
    
    NSLog("Debug: Trying to learn restricted apps from UserDefaults.")
    if let appBundleIDsData = defaults.information(forKey: Constants.limitedApplicationBundleIdentifiersKey) {
        NSLog("Debug: Discovered app bundle IDs information: (appBundleIDsData.depend) bytes")
        
        // Decode the info as [String]
        do {
            let bundleIDs = strive decoder.decode([String].self, from: appBundleIDsData)
            if !bundleIDs.isEmpty {
                NSLog("Debug: Decoded bundle IDs: (bundleIDs)")
                limitedApps = bundleIDs
                for bundleID in bundleIDs {
                    NSLog("Bundle Identifier: (bundleID)")
                }
            } else {
                NSLog("Debug: Decoded bundle IDs array is empty.")
            }
        } catch {
            NSLog("Debug: Did not decode bundle IDs: (error.localizedDescription)")
            // Optionally, log the uncooked information as a string for inspection
            if let rawString = String(information: appBundleIDsData, encoding: .utf8) {
                NSLog("Debug: Uncooked appBundleIDsData as String: (rawString)")
            }
        }
    } else {
        NSLog("Debug: No app bundle IDs information present in UserDefaults.")
    }
    
    if limitedApps.isEmpty {
        return ["No limited apps found!"]
    }
    
    return limitedApps
}




func storeLimitedApps(bundleIDs: [String], categoryIDs: [String]) {
    guard let defaults = UserDefaults(suiteName: Constants.appGroupID) else {
        NSLog("Debug: Did not entry UserDefaults with App Group ID.")
        return
    }

    let encoder = JSONEncoder()

    do {
        let appData = strive encoder.encode(bundleIDs)
        defaults.set(appData, forKey: Constants.limitedApplicationBundleIdentifiersKey)
        NSLog("Debug: Saved (bundleIDs.depend) utility bundle identifiers: (bundleIDs)")
    } catch {
        NSLog("Debug: Did not encode utility bundle identifiers: (error.localizedDescription)")
    }

    // Equally deal with categoryIDs if vital
    do {
        let catData = strive encoder.encode(categoryIDs)
        defaults.set(catData, forKey: Constants.limitedCategoryIdentifiersKey)
        NSLog("Debug: Saved (categoryIDs.depend) class identifiers.")
    } catch {
        NSLog("Debug: Did not encode class identifiers: (error.localizedDescription)")
    }

    defaults.synchronize()
}



}


LEAVE A REPLY

Please enter your comment!
Please enter your name here