gpt4 book ai didi

objective-c - NSURLSessionConfiguration 背景SessionConfigurationWithIdentifier : Download stops after the app is pushed into background

转载 作者:行者123 更新时间:2023-12-01 14:59:23 29 4
gpt4 key购买 nike

  1. 此方法设置背景对象。

    - (void) downloadWithURL: (NSMutableArray *)urlArray
    pathArr: (NSMutableArray *)pathArr
    mediaInfo: (MediaInfo *)mInfo
    {
    bgDownloadMediaInfo = mInfo;
    reqUrlCount = urlArray.count;
    dict = [NSDictionary dictionaryWithObjects:pathArr
    forKeys:urlArray];
    mutableDictionary = [dict mutableCopy];
    backgroundConfigurationObject = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:@"XXXXX"];
    backgroundConfigurationObject.sessionSendsLaunchEvents = YES;
    backgroundConfigurationObject.discretionary = YES;
    backgroundSession = [NSURLSession sessionWithConfiguration: backgroundConfigurationObject
    delegate: self delegateQueue: [NSOperationQueue currentQueue]];
    self.requestUrl = [urlArray objectAtIndex:0];
    download = [backgroundSession downloadTaskWithURL:self.requestUrl];
    [download resume];

    }
  2. 这些是完成处理程序。

    #pragma Mark - NSURLSessionDownloadDelegate

    - (void)URLSession: (NSURLSession *)session
    downloadTask: (NSURLSessionDownloadTask *)downloadTask
    didFinishDownloadingToURL: (NSURL *)location
    {
    LogDebug(@"Download complete for request url (%@)", downloadTask.currentRequest.URL);
    NSString *temp = [mutableDictionary objectForKey:downloadTask.currentRequest.URL];
    NSString *localPath = [NSString stringWithFormat: @"%@",temp];
    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSURL *destinationURL = [NSURL fileURLWithPath: localPath];
    NSError *error = nil;
    [fileManager moveItemAtURL:location toURL:destinationURL error:&error];
    LogDebug(@"Moving download file at url : (%@) to : (%@)", downloadTask.currentRequest.URL, destinationURL);
    reqUrlCount --;
    downloadSegment ++;
    // Handover remaining download requests to the OS
    if ([finalUrlArr count] != 0) {
    // remove the request from the array that got downloaded.
    [finalUrlArr removeObjectAtIndex:0];
    [finalPathArr removeObjectAtIndex:0];
    if ([finalUrlArr count] > 0) {
    // proceed with the next request on top.
    self.requestUrl = [finalUrlArr objectAtIndex:0];
    download = [backgroundSession downloadTaskWithURL:self.requestUrl];
    [download resume];
    }
    }
    if ([adsArray count] > 0) {
    adsArrayCount --;
    // delegate back once all the ADs segments have been downloaded.
    if (adsArrayCount == 0) {
    for (int i = 0; i < [adsArray count]; i++) {
    NSArray *ads = [adsArray objectAtIndex: i];
    for (int j = 0; j < [ads count]; j++) {
    MediaInfo *ad = [ads objectAtIndex: j];
    [self setDownloadComplete: ad];
    // skip sending downloadFinish delegate if the media is marked as downloadDone
    if (!ad.downloadDone) {
    [delegate MediaDownloadDidFinish: ad.mediaId error: NO];
    }
    ad.downloadDone = YES;
    }
    }
    downloadSegment = 0;
    }
    }

    // delegate back once all the main media segments have been downloaded.
    if (reqUrlCount == 0) {
    [self setDownloadComplete: mediaInfo];
    state = DownloadState_Done;
    // skip sending downloadFinish delegate if the media is marked as downloadDone
    if (!bgDownloadMediaInfo.downloadDone) {
    [delegate MediaDownloadDidFinish: bgDownloadMediaInfo.mediaId error: NO];
    }
    bgDownloadMediaInfo.downloadDone = YES;
    [urlArr release];
    [pathArr release];
    [finalUrlArr release];
    [finalPathArr release];
    // invalidate the NSURL session once complete
    [backgroundSession invalidateAndCancel];
    }
    }



    - (void)URLSession: (NSURLSession *)session
    task: (NSURLSessionTask *)task
    didCompleteWithError: (NSError *)error
    {
    if (error) {
    NSLog(@"Failure to download request url (%@) with error (%@)", task.originalRequest.URL, error);
    }
    }

    - (void)URLSession:(NSURLSession *)session
    downloadTask:(NSURLSessionDownloadTask *)downloadTask
    didWriteData:(int64_t)bytesWritten
    totalBytesWritten:(int64_t)totalBytesWritten
    totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
    {
    // save the total downloaded size
    [self downloaderDidReceiveData:bytesWritten];
    // enable the log only for debugging purpose.
    // LogDebug(@"totalBytesExpectedToWrite %llu, totalBytesWritten %llu, %@", totalBytesExpectedToWrite, totalBytesWritten, downloadTask.currentRequest.URL);
    }
  3. 如果没有此代码 (beginBackgroundTaskWithExpirationHandler),当应用程序被插入后台时下载会停止。

    //  AppDelegate_Phone.m
    - (void)applicationDidEnterBackground: (UIApplication *)application
    {
    NSLog(@"applicationDidEnterBackground");
    UIApplication *app = [UIApplication sharedApplication];
    UIBackgroundTaskIdentifier bgTask;

    bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
    [app endBackgroundTask:bgTask];
    }];
    }

最佳答案

你实现了吗application:handleEventsForBackgroundURLSession:completionHa‌​ndler:在你的应用程序委托(delegate)中?这应该保存完成处理程序并使用指定的标识符启动后台 session 。

如果您不实现该方法,则在应用挂起(或随后在正常应用生命周期过程中终止)后下载完成时,您的应用将不会收到通知。因此,下载看起来可能没有完成,但实际上已经完成了。

(顺便说一句,请注意,如果用户强制退出应用程序,这不仅会终止下载,而且显然不会通知您的应用程序下载已终止,直到用户稍后手动重新启动应用程序并且您的应用会重新实例化后台 session 。这是次要问题,您可能不会担心,直到您让主要后台处理正常工作,但这是需要注意的事情。)

此外,您的 URLSessionDidFinishEventsForBackgroundURLSession:必须调用保存的完成处理程序(并将其分派(dispatch)到主队列)。


此外,您的设计看起来一次只会发出一个请求。 (我不建议这样做,但让我们假设它就像您上面概述的那样。)因此,假设您已经发出第一个请求并且应用程序在完成之前被暂停。然后,下载完成后,应用程序会在后台重新启动并调用 handleEventsForBackgroundURLSession。假设您修复了该问题以确保它重新启动后台 session ,以便可以调用各种委托(delegate)方法。确保当您为第二次下载发出第二个请求时,您使用现有的后台 session ,而不是实例化一个新的。每个标识符只能有一个后台 session 。最重要的是,后台 session 的实例化应该与 downloadWithURL:pathArr:mediaInfo: 分离。仅实例化一次后台 session 。

关于objective-c - NSURLSessionConfiguration 背景SessionConfigurationWithIdentifier : Download stops after the app is pushed into background,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47515873/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com