iOS讓App后臺運行

一般來說,如果不進行后臺申請,在iOS系統上,當應用退到后臺后,只有5s的時間去執行代碼,之后將進入掛起狀態。只有像音頻播放、定位、newsstand、VoIP等功能才能持續在后臺運行。但是開發其它應用是我們可以通過申請后臺,來獲得3分鐘的后臺執行代碼時間(iOS7以前是10分鐘)。

最近,我搜集了一些關于iOS程序后臺運行的方法,在此整理一下。本篇文章,我會貼出,后臺運行3分鐘和無限后臺的方法。

在此之前,?你得了解iOS應用程序的生命周期:

Not running 未運行 程序沒啟動
Inactive 未激活 程序在前臺運行,不過沒有接收到事件。在沒有事件處理情況下程序通常停留在這個狀態
Active 激活 程序在前臺運行而且接收到了事件。這也是前臺的一個正常的模式
Backgroud 后臺 程序在后臺而且能執行代碼,大多數程序進入這個狀態后會在在這個狀態上停留一會。時間到之后會進入掛起狀態(Suspended)。有的程序經過特殊的請求后可以長期處于Backgroud狀態
Suspended 掛起 程序在后臺不能執行代碼。系統會自動把程序變成這個狀態而且不會發出通知。當掛起時,程序還是停留在內存中的,當系統內存低時,系統就把掛起的程序清除掉,為前臺程序提供更多的內存。
iOS應用程序生命周期(前后臺切換,應用的各種狀態)詳解

一般App進入后臺之后,超過了后臺運行時間,便進入了掛起狀態,無法執行代碼,但是內存并沒有清除。

主要用到2個方法:
beginBackgroundTaskWithExpirationHandler://申請后臺,該方法只有在App處于激活時調用才有效。 endBackgroundTask://注銷后臺

后臺執行3分鐘方法:

#import "AppDelegate.h"

@interface AppDelegate (){
    NSInteger count;
}
@property(strong, nonatomic)NSTimer *mTimer;
@property(assign, nonatomic)UIBackgroundTaskIdentifier backIden;

@end

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.
    
    count=0;
    return YES;
}

- (void)applicationDidEnterBackground:(UIApplication *)application {
    _mTimer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(countAction) userInfo:nil repeats:YES];
    [[NSRunLoop currentRunLoop] addTimer:_mTimer forMode:NSRunLoopCommonModes];
    [self beginTask];
}

- (void)applicationWillEnterForeground:(UIApplication *)application {
    NSLog(@"進入前臺");
    [self endBack];
}

//計時
-(void)countAction{
    NSLog(@"%li",count++);
}

//申請后臺
-(void)beginTask
{
    NSLog(@"begin=============");
    _backIden = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
        //在時間到之前會進入這個block,一般是iOS7及以上是3分鐘。按照規范,在這里要手動結束后臺,你不寫也是會結束的(據說會crash)
        NSLog(@"將要掛起=============");
        [self endBack];
    }];
}

//注銷后臺
-(void)endBack
{
    NSLog(@"end=============");
    [[UIApplication sharedApplication] endBackgroundTask:_backIden];
    _backIden = UIBackgroundTaskInvalid;
}

@end

無限后臺的方法,慎用!因為這個需要申請后臺播放音頻的權限。如果你的應用不是相關應用,AppStore審核可能不會通過。

好了,看方法!
先在info.plist文件里添加如此一條記錄:

AppDelegate.m文件

#import "AppDelegate.h"

@interface AppDelegate (){
    NSInteger count;
}
@property(strong, nonatomic)NSTimer *mTimer;
@property(assign, nonatomic)UIBackgroundTaskIdentifier backIden;

@end

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.
    
    count=0;
    return YES;
}

- (void)applicationDidEnterBackground:(UIApplication *)application {
    _mTimer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(countAction) userInfo:nil repeats:YES];
    [[NSRunLoop currentRunLoop] addTimer:_mTimer forMode:NSRunLoopCommonModes];
    [self beginTask];
}

- (void)applicationWillEnterForeground:(UIApplication *)application {
    NSLog(@"進入前臺");
    [self endBack];
}

//計時
-(void)countAction{
    NSLog(@"%li",count++);
}

//申請后臺
-(void)beginTask
{
    NSLog(@"begin=============");
    _backIden = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
     
        NSLog(@"將要掛起=============");
        [self endBack];
    }];
}

//注銷后臺
-(void)endBack
{
    NSLog(@"end=============");
    [[UIApplication sharedApplication] endBackgroundTask:_backIden];
    _backIden = UIBackgroundTaskInvalid;
}

@end

ViewController.m文件

#import "ViewController.h"
#import <AVFoundation/AVFoundation.h>

@interface ViewController ()

@property(strong, nonatomic)AVAudioPlayer *mPlayer;

@property(assign, nonatomic)CGFloat mCount;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    
    _mCount = 0;
    
    NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:10 target:self selector:@selector(countTime) userInfo:nil repeats:YES];
    [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
}

-(void)countTime{
    _mCount+=10;
    NSLog(@"%f",_mCount);
    
    if ([[UIApplication sharedApplication] backgroundTimeRemaining] < 60.) {//當剩余時間小于60時,開如播放音樂,并用這個假前臺狀態再次申請后臺
        NSLog(@"播放%@",[NSThread currentThread]);
        [self playMusic];
        //申請后臺
        [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
            NSLog(@"我要掛起了");
        }];
    }
}

-(void)playMusic{
    //1.音頻文件的url路徑,實際開發中,用無聲音樂
    NSURL *url=[[NSBundle mainBundle]URLForResource:@"歡沁.mp3" withExtension:Nil];
    
    //2.創建播放器(注意:一個AVAudioPlayer只能播放一個url)
    _mPlayer=[[AVAudioPlayer alloc]initWithContentsOfURL:url error:Nil];
    
    //3.緩沖
    [_mPlayer prepareToPlay];
    
    //4.播放
    [_mPlayer play];
}

@end

好了,就這些,不懂的私信我!如用錯誤,請指教!

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容