objective c - NSURLSessionDataTask not called after NSURLSessionDownloadTask in the same NSURLSession in iOS background -
my ios app works in following way
i have array of audio file names, check whether file present. if it's present starts playing it. once finished start playing next audio.
if file not present make nsurlsessiondatatask post request returns me string url of file downloaded.(this url valid 1 minute).
once receive url, make nsurlsessiondownloadtask request , download file, save file , play audio.
this entire process works fine when app in foreground. works fine when audios present , app running in background.
the problem comes when audio files not present , app running in background
my code : backgroundfetchmanager.h
@interface backgroundfetchmanager : nsobject <nsurlsessiondownloaddelegate,nsurlsessiondatadelegate> @property bool isdownloading; @property nsurlsessiondownloadtask *download; @property nsurlsessiondatatask *datadownload; @property (nonatomic, strong)nsurlsession *backgroundsession; @property nsmutablearray *downloadqueue; @property fileaccessmanager *fileaccessmanager; @end
backgroundfetchmanager.m
initialization function
-(id) init { self = [super init]; nsurlsessionconfiguration *config = [nsurlsessionconfiguration backgroundsessionconfigurationwithidentifier:@"testconfiguration"]; config.sessionsendslaunchevents = yes; config.discretionary = yes; self.backgroundsession = [nsurlsession sessionwithconfiguration:config delegate:self delegatequeue:[nsoperationqueue mainqueue]]; download = [nsurlsessiondownloadtask new]; datadownload = [nsurlsessiondatatask new]; return self; }
data task
datadownload = [self.backgroundsession datataskwithrequest:request]; [datadownload settaskdescription:@"data task"];
delegates of datadownload (nsurlsessiondatatask)
- (void)urlsession:(nsurlsession *)session datatask:(nsurlsessiondatatask *)datatask didreceiveresponse:(nsurlresponse *)response completionhandler:(void (^)(nsurlsessionresponsedisposition disposition))completionhandler { completionhandler(nsurlsessionresponseallow); } - (void)urlsession:(nsurlsession *)session datatask:(nsurlsessiondatatask *)datatask didreceivedata:(nsdata *)data { nsstring * str = [[nsstring alloc] initwithdata:data encoding:nsutf8stringencoding]; nsstring *url = [[nsstring alloc] initwithdata:data encoding:nsutf8stringencoding]; nslog(@"this response received %@",url); //download nsurlsessiondownloadtask download = [self.backgroundsession downloadtaskwithurl:[nsurl urlwithstring:url]]; [download resume]; }
delegates of download (nsurlsessiondownloadtask)
these ones not called when app in background
- (void)urlsession:(nsurlsession *)session downloadtask:(nsurlsessiondownloadtask *)downloadtask didfinishdownloadingtourl:(nsurl *)location { appdelegate *a = (appdelegate *)[[uiapplication sharedapplication] delegate]; nsurl *destinationurl = [fileaccessmanager savefile:a.downloadqueue[0] fromlocation:location]; // save file code } - (void)urlsession:(nsurlsession *)session task:(nsurlsessiontask *)task didcompletewitherror:(nserror *)error { // audio playing stuff if (![task.taskdescription isequaltostring:@"data task"]) { nslog(@"this did complete error %@", task ); appdelegate *a = (appdelegate *)[[uiapplication sharedapplication] delegate]; if ([a.downloadqueue[0] isequaltostring:a.audiotobeplayed]) { nsdictionary* userinfo = @{@"file": a.downloadqueue[0]}; [[nsnotificationcenter defaultcenter] postnotificationname:@"playthisstuff" object:nil userinfo:userinfo]; } //starts next download [a pop]; isdownloading = false; if ([a.downloadqueue count] > 0) { isdownloading = true; [self downloadfile:a.downloadqueue[0]]; } } }
so in nutshell, downloadtask not called after datatask has finished. as know, nsurlsession when configured backgroundsession, os takes responsiblity of download, ideally should work. missing ?
the problem stems fact ios won't let start new task while app in background. believe done prevent apps continuously firing off new tasks , keeping app alive indefinitely.
background tasks suitable gracefully handling app transitioning foreground background while task in progress. it's reason you're seeing first task complete, not second.
one workaround request background execution time os when fire off initial data task:
uibackgroundtaskidentifier backgroundtaskid = [[uiapplication sharedapplication] beginbackgroundtaskwithexpirationhandler:^{ }];
that should @ least give app few minutes of background time initiate second task. sure call -endbackgroundtask:
after call -resume
on second task.
unfortunately, cannot guarantee of files download. if find you're running out of background time, may better off using silent push notifications wake app , download periodically.
Comments
Post a Comment