0.3 C
New York
Sunday, February 23, 2025

ios – Get background obtain duties initiated from the motion extension within the host app


Background:

I’ve an app that obtain massive information within the background and it really works completely effective. I’m creating an motion extension for my app which permits customers so as to add obtain activity with out opening the principle app.

Downside:

Once I add a obtain activity from the app extension, and are available again within the app to trace the progress of the duty. The duty will not present up within the app till I recreate the session with the identical identifier for 3~4 occasions. Secondly it solely return 1 activity at a time. If I added a number of duties from the extension and are available again within the app it solely present me the 1 activity. The subsequent one present up when the earlier one is accomplished. The obtain duties maintain operating within the background accurately however getTasksWithCompletionHandler does not return the duties. See the hooked up video.

Goal:

Record down all duties contained in the host app and present the progress which are initiated from the app extension.

Workflow:

I’ve 2 session identifiers for:

Shared container identifier is about correctly.

Only one session may be lively at a time for a similar session identifiers (both within the app or within the extension). That is why when consumer come again within the app. I at all times recreate the session as soon as with the identical identifier as that of extension.

Right here is how I’m establishing session:

public comfort init(sessionIdentifier: String,
                            delegate: MZDownloadManagerDelegate? = nil,
                            downloadDelegate: URLSessionDownloadDelegate? = nil,
                            completion: (() -> Void)? = nil) {
        self.init()
        self.delegate = delegate
        self.sessionManager = backgroundSession(identifier: sessionIdentifier,
                                                delegate: downloadDelegate ?? self)
        self.populateOtherDownloadTasks()
        
        if let completion {
            addSessionCompletion(identifier: sessionIdentifier,
                                 handler: completion)
        }
    }
    
    personal class func sessionConfig(identifier: String) -> URLSessionConfiguration {
        let configuration = URLSessionConfiguration.background(withIdentifier: identifier)
        configuration.sharedContainerIdentifier = MZUtility.getAppGroupIdentifier()
        return configuration
    }
    
    personal func backgroundSession(identifier: String,
                                   delegate: URLSessionDownloadDelegate) -> URLSession {
        let config = MZDownloadManager.sessionConfig(identifier: identifier)
        let session = URLSession(configuration: config,
                                 delegate: delegate,
                                 delegateQueue: nil)
        return session
    }

Right here is how I get the obtain duties contained in the session:

fileprivate func downloadTasks() -> [URLSessionDownloadTask] {
        var duties: [URLSessionDownloadTask] = []
        let semaphore = DispatchSemaphore(worth: 0)
        sessionManager.getTasksWithCompletionHandler { (dataTasks, uploadTasks, downloadTasks) -> Void in
            duties = downloadTasks
            semaphore.sign()
        }
        
        let _ = semaphore.wait(timeout: DispatchTime.distantFuture)
        
        let identifier = String(describing: sessionManager.configuration.identifier ?? "-")
        debugPrint("MZDownloadManager: confId: (identifier) pending duties (duties)")
        
        return duties
    }

Right here is the code for the motion extension:

@IBAction func downloadButtonTapped(sender: UIButton) {
        var titleString = (titleField.textual content ?? "")
        titleString = titleString.isEmpty ? UUID().uuidString : titleString
        
        let urlString = (inputUrlField.textual content ?? "").addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)
        
        guard let urlString,
              let url = URL(string: urlString) else {
            showAlert(title: "Invalid url", msg: "Please enter a sound url")
            return
        }
        
        let request = URLRequest(url: url)
        
        guard NSURLConnection.canHandle(request) else {
            showAlert(title: "Invalid url", msg: "Please enter a sound url")
            return
        }
        
        let identifier = MZUtility.sessionIdentifierExt
        var downloadManager = MZDownloadManager(sessionIdentifier: identifier)
        downloadManager.addDownloadTask(titleString, request: request)
        
        extensionContext?.completeRequest(returningItems: [])
    }

When applicationDidBecomeActive or handleEventsForBackgroundURLSession:

func setupDownloads() {
        downloadManager.setupExtensionManager()
        downloadManager.concatenateTasksWithExtensionSessions()
        downloadManager.sessionManager.getAllTasks { (duties) in
            DispatchQueue.principal.async {[weak self] in
                guard let self else { return }
                downloadManager.handleAppDidBecomeActive()
                tableView.reloadData()
                setupEmptyDataView()
            }
        }
    }

Within the obtain supervisor class:

func concatenateTasksWithExtensionSessions() {
        populateOtherDownloadTasks()
        appExtensionManager?.populateOtherDownloadTasks()
        for obtain in appExtensionManager?.downloadingArray ?? [] {
            distinctAppend(downloadModel: obtain)
        }
    }
    //When app goes in background and comeback in foreground the delegate change into indifferent till resume for every activity is known as
    func handleAppDidBecomeActive() {
        let downloads = downloadingArray.filter({$0.activity?.state == .operating})
        for obtain in downloads {
            obtain.activity?.resume()
        }
    }
    
    func populateOtherDownloadTasks() {
        for downloadTask in downloadTasks() {
            let downloadModel = modelFromTaskDescription(downloadTask: downloadTask)
            downloadModel.startTime = Date()
            
            if downloadTask.state == .operating {
                downloadModel.standing = TaskStatus.downloading.description()
                distinctAppend(downloadModel: downloadModel)
            } else if(downloadTask.state == .suspended) {
                downloadModel.standing = TaskStatus.paused.description()
                distinctAppend(downloadModel: downloadModel)
            } else {
                downloadModel.standing = TaskStatus.failed.description()
            }
        }
    }

Right here is the display recording

Related Articles

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Latest Articles