您的位置:首页 > 移动开发 > IOS开发

IOS开发模块总结(二)后台运行程序(1) 后台运行程序详解

2016-10-28 23:04 537 查看



 


IOS开发模块总结(二)后台运行程序(1) 后台运行程序详解(二) 


 分类:

IOS功能模块(8) 


三、IOS长时间后台运行的实现代码

1、检查设备是否支持多任务
Apple出于性能的考虑,并不是所有的iOS设备升级到iOS4以后都支持多任务,比如iPhone 3G。如果你的应用在没有多任务特性时会出问题,为了保持应用的健壮性,你应该对此进行判断并处理。你可以通过调用UIDevice对象的multitaskingSupported属性来获取当前设备是否支持多任务。

[cpp] view
plaincopy

if(![UIDevicecurrentDevice].multitaskingSupported)  

{  

    //不支持多任务时应做的处理  

}  

通常,当用户按一下Home键,当前应用就会被进入后台,应用处在后台运行状态一小段时间后,就会进入挂起(suspend)状态,此时应用不会再执行任何代码。如果系统在运行其他应用时内存资源不足,这个挂起的应用甚至有可能被系统退出,释放内存以供活动的应用使用。只有当用户再次运行此应用,应用才会从挂起状态唤醒,代码得以继续执行。这就是iOS4带来的基本的多任务特性,这个特性是一般应用默认支持的,就是说你的应用不需要任何修改就能支持基本多任务特性。2、基本多任务特性
既然是多任务你应该会在应用进入后台时做一些处理,比如暂停一些界面的定时刷新或网络请求。同时,或者你会在程序进入前台时执行一些恢复操作。在你的应用的application delegate里有2个消息用于处理这些消息:

[cpp] view
plaincopy

- (void)applicationDidEnterBackground:(UIApplication*)application   

{  

     //进入后台时要进行的处理  

}  

- (void)applicationWillEnterForeground:(UIApplication*)application  

{  

     //进入前台时要进行的处理  

}  

也许你需要更多的多任务特性,比如后台播放音乐或者是后台进行GPS跟踪。这会是下面介绍的内容。当然你也许不会都在application delegate处理所有的事情。如果你要在其他对象中处理,那么你就需要注册系统通知了,这两个通知分别是UIApplicationDidEnterBackgroundNotification和UIApplicationWillEnterForegroundNotification。

3、声明你需要的后台任务
在Info.plist中添加UIBackgroundModes键值,它包含一个或多个string的值,包括:
audio:在后台提供声音播放功能,包括音频流和播放视频时的声音
location:在后台可以保持用户的位置信息
voip:在后台使用VOIP功能
前面的每个value让系统知道你的应用程序应该在适当的时候被唤醒。例如,一个应用程序,开始播放音乐,然后移动到后台仍然需要执行时间,以填补音频输出缓冲区。添加audio键用来告诉系统框架,需要继续播放音频,并且可以在合适的时间间隔下回调应用程序;如果应用程序不包括此项,任何音频播放在移到后台后将停止运行。
除了添加键值的方法,IOS还提供了两种途径使应用程序在后台工作:
Task completion—应用程序可以向系统申请额外的时间去完成给定的任务
Local notifications—应用程序可以预先安排时间执行local notifications 传递
4、后台播放音乐
通常,一般应用在进入后台时,任何声音就将会停止。这也许不是我们所想要的。要想让自己的应用支持后台播放,首先要修改应用的Info.plist文件,你需要在Info.plist文件中添加UIBackgroundModes字段,该字段的值是应用支持的所有后台模式,是一个数值类型。目前此数组可以包含“audio”、“location”和“voip”这三个字符串常量,如果要支持后台音乐播放,你就需要包含“audio”,其余两个会将在后面讲到。
同时,你也应该设置一下应用程序的Audio Sesstion。这个是必需的,如果不设置Audio Sesstion,应用就可能进入后台时Audio Sesstion失活而停止播放。一般需要这么设置就可以了:

[cpp] view
plaincopy

[[AVAudioSessionsharedInstance]setCategory:AVAudioSessionCategoryPlaybackerror:nil];  

5、后台GPS跟踪
和后台播放音乐类似,若要支持后台GPS跟踪,你就需要在Info.plist文件中UIBackgroundModes字段对应的数组中增加“location”字符串。
6、后台voip支持
由于voip应用需要一个长连接到服务器,为了让这类应用能正常工作,iOS中加入后台voip支持特性。为支持这一特性,需要在Info.plist文件中UIBackgroundModes字段对应的数组中增加“voip”字符串。
此外你仍然需要配置一下你的网络连接,以便支持后台连接。iOS提供的网络连接库有几种,下面一一说明:
a、如果你使用的是NSStream,如NSInputStream或NSOutputStream,需要调用setProperty:forKey:将Key为NSStreamNetworkServiceType的value设置为

NSStreamNetworkServiceTypeVoIP;
b、如果你使用NSURLRequest,需要调用setNetworkServiceType:将网络类型设置为NSURLNetworkServiceTypeVoIP;
c、如果你使用CFStream,如CFReadStreamRef或CFWriteStreamRef,需要调用CFReadStreamSetProperty或CFWriteStreamSetProperty将
kCFStreamNetworkServiceType属性设置为kCFStreamNetworkServiceTypeVoIP。





IOS开发模块总结(二)后台运行程序(2)Task completion-UIBackgroundTaskIdentifier 


 分类:

IOS功能模块(8) 


版权声明:本文为博主原创文章,未经博主允许不得转载。

通过UIBackgroundTaskIdentifier可以实现有限时间内在后台运行程序

程序进入后台时调用applicationDidEnterBackground函数,

首先判断设置是否支付后台运行

通过beginBackgroundTaskWithExpirationHandler 获取UIBackgroundTaskIdentifier
后就可以在后台获取一定的时间去指行我们的代码,可以通过

NSTimeInterval backgroundTimeRemanging = [[UIApplication sharedApplication] backgroundTimeRemaining];

NSLog(@"backgroundTimeRemanging = %.02f", backgroundTimeRemanging);
来查看后台可以执行的时间,注意,在beginBackgroundTaskWithExpirationHandler代码块中一定要
调用UIApplication的endBackgroundTask:方法来结束后台任务


[app endBackgroundTask:_bgTask];

这里的_bgTask是通过beginBackgroundTaskWithExpirationHandler得到的.要保持一致。

最后,当我们的应用回到前台,如果我们的后台任务还在执行中,我们需要确保我们在干掉它: 

- (void)applicationWillEnterForeground:(UIApplication *)application{ 

if (self.backgroundTaskIdentifier != UIBackgroundTaskInvalid){ 

[self endBackgroundTask]; } 



[objc] view
plain copy

@interface AppDelegate : UIResponder <UIApplicationDelegate>  

@property (strong, nonatomic) UIWindow *window;  

@property (strong, nonatomic) ViewController *viewController;  

@property (nonatomic, unsafe_unretained) UIBackgroundTaskIdentifier backgroundTaskIdentifier;  

@property (nonatomic, strong) NSTimer * myTimer;  

- (BOOL)isMutiltaskingSupported;  

@end  

  

// 判断当前设备是否支持 后台多任务  

- (BOOL)isMutiltaskingSupported{  

    BOOL result = NO;  

    if ( [[UIDevice currentDevice] respondsToSelector:@selector(isMultitaskingSupported)]) {  

        result = [[UIDevice currentDevice] isMultitaskingSupported];  

    }  

    return result;  

}  

// 定时器调用方法  

- (void)timerMethod:(NSTimer *)paramSender{  

    NSTimeInterval backgroundTimeRemanging = [[UIApplication sharedApplication] backgroundTimeRemaining];  

    if ( backgroundTimeRemanging == DBL_MAX) {  

        NSLog(@"Background Time Remaining = Undeterminded");  

    }  

    //--显示后台任务还剩余的时间  

    NSLog(@"Background Timer Remaining = %.02f Seconds", backgroundTimeRemanging);  

}  

// 进入挂起状态时候,调用方法  

- (void)applicationDidEnterBackground:(UIApplication *)application  

{  

    // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.   

    // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.  

    if ( [self isMutiltaskingSupported] == NO) {  

        NSLog(@"---> 不支持后台多任务");  

        return;  

    }  

      

    self.backgroundTaskIdentifier = [application beginBackgroundTaskWithExpirationHandler:^{  

        [self endBackgroundTask];  

    }];<pre name="code" class="objc">    self.myTimer = [NSTimer scheduledTimerWithTimeInterval:1.0f  

                                                    target:self  

                                                  selector:@selector(timerMethod:)  

                                                  userInfo:nil  

                                                   repeats:YES];  

      



[objc] view
plain copy

}  

// 任务完成,处理释放对象  

- (void)endBackgroundTask{  

    dispatch_queue_t mainQueue = dispatch_get_main_queue();  

    __weak AppDelegate *weakSelf = self;  

    dispatch_async(mainQueue, ^{  

        AppDelegate * strongSelf = weakSelf;  

        if ( strongSelf != nil) {  

            [strongSelf.myTimer invalidate];  

            [[UIApplication sharedApplication] endBackgroundTask:self.backgroundTaskIdentifier];  

            strongSelf.backgroundTaskIdentifier = UIBackgroundTaskInvalid;  

        }  

    });  

}  

[objc] view
plain copy

- (void)applicationWillEnterForeground:(UIApplication *)application{   

if (self.backgroundTaskIdentifier != UIBackgroundTaskInvalid){   

[self endBackgroundTask]; }   

}   
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: