3

AFNetworking 3.0 を使用して、アプリケーションで大きなビデオ ファイルをダウンロードしようとしています。AFNetworking を使用してバックグラウンドでファイルをダウンロードする方法に関する特定のドキュメントは見つかりませんでした。

AFNetworking はAFURLSessionManagerAFHTTPSessionManagerを使用し、それ自体がNSURLSessionのすべてのデリゲートを実装していることを知っています。

これまでに行ったことは、 backgroundSessionConfugarationを作成し、これを使用してダウンロードするファイルを開始することです。

self.manager = [[AFHTTPSessionManager alloc] initWithSessionConfiguration:[NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:bgDownloadSessionIdentifier]];

[self.manager downloadTaskWithRequest:request progress:nil destination:nil completionHandler:nil];

ダウンロードが開始したら、アプリケーションをバックグラウンドに置きます。私がこれまでに見つけたのは、アプリが 20 分までバックグラウンドで実行され、ダウンロードが成功したことです。しかし、appDelegate のapplication:handleEventsForBackgroundURLSessionは呼び出されないため、setDidFinishEventsForBackgroundURLSessionBlockも呼び出されません。

setDidFinishEventsForBackgroundURLSessionBlockが呼び出されたときにのみ通知を表示したい。

これを使用してマネージャーを初期化すると。( backgroundSessionConfigurationの代わりに)

self.manager = [AFHTTPSessionManager manager];

Still アプリは、バックグラウンドで 20 分後にファイル全体をダウンロードできます。

私の問題は、アプリケーションが 20 分まで実行され、ダウンロードが完了した理由です。理想的には、iOS は 10 分後にアプリを強制終了する必要があります。また、セッションの完了後にapplication:handleEventsForBackgroundURLSessionが呼び出されない理由。

このAFNetworking 2.0 とバックグラウンド転送については既に言及しましたが、うまくいかないようです。

機能からのバックグラウンド モードは、ON または OFF のいずれかであり、アプリケーションには何の影響もありません。

私を助けてください、または私がここで間違っていることを教えてください。

サンプルコードをここにアップロードしました。 https://www.dropbox.com/s/umwicuta2qzd3k1/RSNetworkKitExample.zip?dl=0

AppDelegate.m

-(void)application:(UIApplication *)application handleEventsForBackgroundURLSession:(NSString *)identifier completionHandler:(void (^)())completionHandler {

  NSLog(@"===== background session completed in AppDelegate ===== ");

  if([identifier isEqualToString:bgDownloadSessionIdentifier]){
      [RSDownloadManager sharedManager].backgroundSessionCompletionHandler = completionHandler;
  }
}

================================================== ==

ViewController.m


- (IBAction)downloadVideoInBackground:(id)sender {

  NSString *videoURL = @"http://videos1.djmazadownload.com/mobile/mobile_videos/Tum%20Saath%20Ho%20(Tamasha)%20(DJMaza.Info).mp4";

 [RSDownloadManager sharedManager].backgroundSessionCompletionHandler = ^{

    NSLog(@"===== background session completed in ViewController ===== ");

    UILocalNotification* localNotification = [[UILocalNotification alloc] init];
    localNotification.alertBody = @"Download Complete!";
    localNotification.alertAction = @"Background Transfer Download!";

    //On sound
    localNotification.soundName = UILocalNotificationDefaultSoundName;

    //increase the badge number of application plus 1
    localNotification.applicationIconBadgeNumber = [[UIApplication sharedApplication] applicationIconBadgeNumber] + 1;

    [[UIApplication sharedApplication] presentLocalNotificationNow:localNotification];

};

  [[RSDownloadManager sharedManager] downloadInBackgroundWithURL:videoURL downloadProgress:^(NSNumber *progress) {

     NSLog(@"Video download progress %.2f", [progress floatValue]);

  } success:^(NSURLResponse *response, NSURL *filePath) {

     NSLog(@"Video download completed at Path %@", filePath);

  } andFailure:^(NSError *error) {

     NSLog(@"Error in video download %@", error.description);
  }];

}

================================================== ==

RSDownloadManager.h


#import <Foundation/Foundation.h>
#import "AFHTTPSessionManager.h"

static NSString *bgDownloadSessionIdentifier = @"com.RSNetworkKit.bgDownloadSessionIdentifier";

@interface RSDownloadManager : NSObject

@property (nonatomic, strong) AFHTTPSessionManager *manager;

@property (nonatomic, copy) void (^backgroundSessionCompletionHandler)(void);

+(instancetype)sharedManager;

-(NSURLSessionDownloadTask *)downloadInBackgroundWithURL:(NSString *)urlString downloadProgress:(void (^)(NSNumber *progress))progressBlock success:(void (^)(NSURLResponse *response, NSURL *filePath))completionBlock andFailure:(void (^)(NSError *error))failureBlock;

@end

================================================== ==

RSDownloadManager.m


@implementation RSDownloadManager

#pragma mark - Singleton instance
+(instancetype)sharedManager
{
   static RSDownloadManager *_downloadManager = nil;
   static dispatch_once_t token;

   dispatch_once(&token, ^{

     if (!_downloadManager) {
        _downloadManager = [[self alloc] init];
     }
  });
   return _downloadManager;
}

#pragma mark - Init with Session Configuration

-(void)initWithSessionConfiguration:(NSURLSessionConfiguration *)configuration {
   self.manager = [[AFHTTPSessionManager alloc] initWithSessionConfiguration:configuration];

   //self.manager = [AFHTTPSessionManager manager];
}


#pragma mark- Handle background session completion

- (void)configureBackgroundSessionCompletion {
  typeof(self) __weak weakSelf = self;

  [self.manager setDidFinishEventsForBackgroundURLSessionBlock:^(NSURLSession *session) {

     if (weakSelf.backgroundSessionCompletionHandler) {
         weakSelf.backgroundSessionCompletionHandler();
         weakSelf.backgroundSessionCompletionHandler = nil;
     }
  }];
}


#pragma mark- download in background request Method

-(NSURLSessionDownloadTask *)downloadInBackgroundWithURL:(NSString *)urlString downloadProgress:(void (^)(NSNumber *))progressBlock success:(void (^)(NSURLResponse *, NSURL *))completionBlock andFailure:(void (^)(NSError *))failureBlock {

  /* initialise session manager with background configuration */

  if(!self.manager){
     [self initWithSessionConfiguration:[NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:bgDownloadSessionIdentifier]];
  }

  [self configureBackgroundSessionCompletion];

  /* Create a request from the url */
  NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:urlString]];

  NSURLSessionDownloadTask *downloadTask = [self.manager downloadTaskWithRequest:request progress:^(NSProgress * _Nonnull downloadProgress) {

     if(progressBlock) {
         progressBlock ([NSNumber numberWithDouble:downloadProgress.fractionCompleted]);
     }

 } destination:^NSURL * _Nonnull(NSURL * _Nonnull targetPath, NSURLResponse * _Nonnull response) {

     NSURL *documentsDirectoryURL = [[NSFileManager defaultManager] URLForDirectory:NSDocumentDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:NO error:nil];
     return [documentsDirectoryURL URLByAppendingPathComponent:[response suggestedFilename]];

 } completionHandler:^(NSURLResponse * _Nonnull response, NSURL * _Nullable filePath, NSError * _Nullable error) {

    if(error) {
        if(failureBlock) {
            failureBlock (error);
        }
    }
    else {
        if(completionBlock) {
            completionBlock (response, filePath);
        }
    }

 }];

  [downloadTask resume];

  return downloadTask;
 }
4

2 に答える 2

4

このデリゲート メソッドは呼び出されないことがあります。

  • タスクの完了時にアプリケーションがすでに実行されている場合。
  • ホームボタンでアプリ終了。
  • 同じ識別子でバックグラウンド NSURLSession を開始できなかった場合。

: シミュレータでは動作が異なるため、実機で確認してください。

于 2016-02-11T18:08:21.340 に答える
0

downloadInBackgroundWithURL:downloadProgress: 関数でローカル通知ブロックを成功ブロックに置き換えないのはなぜですか? AppDelegate のメソッドは実際には呼び出されません。そして、通知を登録する必要があります

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.

    if ([UIApplication instancesRespondToSelector:@selector(registerUserNotificationSettings:)]){
         [application registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert|UIUserNotificationTypeBadge|UIUserNotificationTypeSound categories:nil]];
    }

    return YES;
}

ローカル通知には、発火日とタイムゾーンを追加します。

    UILocalNotification* localNotification = [[UILocalNotification alloc] init];
    localNotification.alertBody = @"Download Complete!";
    localNotification.alertAction = @"Background Transfer Download!";
    [localNotification setFireDate:[NSDate dateWithTimeIntervalSinceNow:1]];
    [localNotification setTimeZone:[NSTimeZone  defaultTimeZone]];
    //On sound
    localNotification.soundName = UILocalNotificationDefaultSoundName;

    //increase the badge number of application plus 1
    localNotification.applicationIconBadgeNumber = [[UIApplication sharedApplication] applicationIconBadgeNumber] + 1;

    [[UIApplication sharedApplication] presentLocalNotificationNow:localNotification];

今では動作します。乾杯。

于 2016-02-11T17:09:13.993 に答える