iOS保持App真后台運行


https://www.jianshu.com/p/d466f2da0d33

在我看來,蘋果系統與安卓系統最直觀的區別就是后台處理方式了吧,安卓手機一旦開啟了很多app放到后台,即使前台什么也不做,就是切換一下系統界面都會覺得卡;蘋果手機不論開多少app在后台都感覺很流暢.

 

這是因為安卓默認處理app為真后台,可以一直在后台處理操作;

而iOS為了讓設備盡量省電,減少不必要的開銷,保持系統流暢,因而對后台機制采用墓碑式的“假后台”。除了系統官方極少數程序可以真后台,一般開發者開發出來的應用程序后台受到以下限制:

1.用戶按Home之后,App轉入后台進行運行,此時擁有180s后台時間(iOS7)或者600s(iOS6)運行時間可以處理后台操作

2.當180S或者600S時間過去之后,可以告知系統未完成任務,需要申請繼續完成,系統批准申請之后,可以繼續運行,但總時間不會超過10分鍾

3.當10分鍾時間到之后,無論怎么向系統申請繼續后台,系統會強制掛起App,掛起所有后台操作、線程,直到用戶再次點擊App之后才會繼續運行

 

iOS系統app如何實現在后台長時間運行

比較常用的可以實現“真后台”的方法:

1.VOIP 2.定位服務 3.后台下載 4.在后台循環播放無聲音樂

目前我接手的項目是視頻點播類項目,需要在app進入后台也可以保持電視播放劇集,並在回到前台后更新進度條進度,並且每60s對后台發送心跳包,保持長連接,所以需要實現真后台.

使用了第4種方式,靜音播放,上架之前多次被拒但最終通過了審核.

如何通過了審核

上架的時候,標注是視頻點播類app,此app類似於電視遙控器,

起初一進入后台就循環播放無聲音樂,所以蘋果方一直以播放視頻和音頻沒有聲音拒絕.

但是為了保持真后台,必須是類似音樂播放器一類的可以后台播放聲音的app.

所以第一次上架時,點擊播放后退到后台會在后台循環播放一個有聲音的MP3,

在通過了審核后,立刻更新一個版本,把有聲音的MP3文件換成一個無聲音的MP3

此時蘋果測試人員審核不會像第一次審核那么嚴格,通過了.


 

 

 

 

 

 

 

具體實現:首先我們看看app進入后台進入前台的幾個常用方法

#pragma mark - 程序將要進入后台(墓碑狀態)

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

}

#pragma mark - 程序進入后台

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

}

#pragma mark - 程序將要進入前台

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

}

#pragma mark - 程序進入前台

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

}

 

配置plist文件背景播放的支持:

 

在AppDelegate中實現大概:

//進入后台

- (void)applicationDidEnterBackground:(UIApplication *)application

{

    NSLog(@"%s",__FUNCTION__);

    //設置永久后台運行

    UIApplication *app = [UIApplication sharedApplication];

    __block   UIBackgroundTaskIdentifier bgTask;

    bgTask = [app beginBackgroundTaskWithExpirationHandler:^{

        //不管有沒有完成,結束bgTask任務

        [application endBackgroundTask:bgTask];

        dispatch_async(dispatch_get_main_queue(), ^{

            if (bgTask != UIBackgroundTaskInvalid)

            {

                bgTask = UIBackgroundTaskInvalid;

            }

        });

    }];

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

        dispatch_async(dispatch_get_main_queue(), ^{

            if (bgTask != UIBackgroundTaskInvalid)

            {

                bgTask = UIBackgroundTaskInvalid;

            }

        });

    });

    

    //當只有點播了時才會退到后台,如果不點播則后台不開啟,以省電

    if ([CJGloblePlayer defaultGloblePlayer].runningPlayer.isPlaying)

    {

        //開啟后台任務 

        [self applyBackgrounTaskTime];

        //UI停止更新

        [[CJTopPlayView sharePlayView].rotaionView stopRotation];

    }

 

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

        NSLog(@"Starting background task with %0.1f seconds remaining", application.backgroundTimeRemaining);

        [NSThread sleepForTimeInterval:600];

        NSLog(@"Finishing background task with %0.1f seconds remaining",application.backgroundTimeRemaining);

        

        //告訴系統我們完成了 也就是要告訴應用程序:“好借好還”嘛。

        //將任務標記為完成

        [application endBackgroundTask:bgTask];

         // 銷毀后台任務標識符

        bgTask = UIBackgroundTaskInvalid;

    });

}

 

//開啟后台任務

- (void)applyBackgrounTaskTime

{

    //__block UIBackgroundTaskIdentifier background_task;

    UIApplication *application = [UIApplication sharedApplication];

    //注冊一個后台任務,告訴系統我們需要向系統借一些事件

    background_task = [application beginBackgroundTaskWithExpirationHandler:^ {

        

        //不管有沒有完成,結束background_task任務

        [application endBackgroundTask: background_task];

        background_task = UIBackgroundTaskInvalid;

    }];

    

    //異步

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

        

        //### background task starts

        NSLog(@"Running in the background\n");

        

        //循環播放無聲的MP3

        [[CJBackGroundAudioVC shareInstance] backGroundStart];

        

        [NSThread sleepForTimeInterval:2];

        //結束background_task任務

        [application endBackgroundTask: background_task];

        background_task = UIBackgroundTaskInvalid;

    });

}

 

//播放MP3

- (void)backGroundStart

{

   [self playAudio:[[NSBundle mainBundle] pathForResource:@"silence" ofType:@"mp3"]];

}

 

//程序進入前台

- (void)applicationDidBecomeActive:(UIApplication *)application

{

    //后台保持app一直運作的播放器停止工作

    [[CJBackGroundAudioVC shareInstance] backGroundStop];

    //全局播放器開始播放,更新UI

    if ([CJGloblePlayer defaultGloblePlayer].runningPlayer.playstate == psPlaying)

    {

        [[CJTopPlayView sharePlayView].rotaionView startRotation];

    }

}

 

若有不妥之處,恭請評論多多指教.

參考相關鏈接:

http://www.jianshu.com/p/174fd2673897

http://blog.csdn.net/weiwangchao_/article/details/8316641

http://blog.sina.com.cn/s/blog_7b9d64af0101cjci.html

 

作者:oldSix_Zhu

鏈接:https://www.jianshu.com/p/d466f2da0d33

來源:簡書

簡書著作權歸作者所有,任何形式的轉載都請聯系作者獲得授權並注明出處。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM