iOS"偽后台"機制下如何保持APP一直運行在后台(轉)(實踐通過)


 

最近在做番茄鍾的功能。首先簡單介紹一下番茄鍾吧,就是25分鍾工作番茄工作法。先說一下** 番茄工作法 **:

番茄工作法是簡單易行的時間管理方法,是由弗朗西斯科·西里洛於1992年創立的一種相對於GTD更微觀的時間管理方法。
使用番茄工作法,選擇一個待完成的任務,將番茄時間設為25分鍾,專注工作,中途不允許做任何與該任務無關的事,直到番茄時鍾響起,然后在紙上畫一個X短暫休息一下(5分鍾就行),每4個番茄時段多休息一會兒。
番茄工作法極大地提高了工作的效率,還會有意想不到的成就感。

那么功能就相當於一個25分鍾的鬧鍾,可以播放背景音樂,到點給用戶提醒。

功能聽起來很簡單是不是?其實挺多坑的。

開發過程中遇到了2個問題。

  1. 因為番茄鍾是25分鍾,那么當用戶開啟番茄鍾后很可能在中途就將APP切換到了后台,那么幾分鍾程序就會被系統kill掉。
  2. 當用戶開啟番茄鍾的背景音樂時,APP切換到后台或者鎖屏狀態時,音樂都會立即停止播放。

OK,下面我們一步一步來分析並解決這兩個問題。

** 首先要理解iOS系統的后台機制 **

我們都知道,蘋果對APP占用硬件資源管的很嚴,更不要說應用后台時候的資源占用了。正常情況下,使用應用時,APP從硬盤加載到內存,開始工作;當用戶按下home鍵,APP便被掛起,依然駐留在內存中,這種狀態下,不調用蘋果已開放的幾種后台方法,程序便不會運行;如果在這個時候,使程序繼續運行,則為后台狀態;如果當前內存將要不夠用時,系統會自動把之前掛起狀態下的APP請出內存。所以我們看到,有些時候打開APP時,還是上次退出時的那個頁面那些數據,有時則是重新從閃屏進入。

iOS系統后台機制大概可以分為5種狀態

  • Not Running:APP沒有啟動,也沒有后台運行。
  • Active:用戶正在使用APP,比如說我們聊微信看網頁的時候,APP就處於Active狀態。
  • Inactive:這是一個過渡的狀態,APP雖然打開了,但是用戶沒有跟APP有任何互動操作。
  • Background:APP在后台運行,微信會在沒有打開的時候接收消息。
  • Suspended:APP雖然在后台運行,但是處於休眠狀態,只占用一點內存。

** 那么我需要的是Background模式。即APP在后台運行同時保持程序active的狀態 **

首先去xCode里面設置。到info.plist中添加以下信息:

 
Snip20170301_13.png

然后到Capabilities里面打開后台模式,並根據項目的要求勾選對應的功能。我這里只需要保持后台運行並且播放背景音樂及通知功能。所以就勾選了第一個和最后一個

 
Snip20170301_14.png

以上這兩步是告訴系統我這個APP支持后台模式,對應的環境為音頻環境。

可是到這一步,APP還是不能長時間運行到后台。

為什么?我們思考一下。我們讓程序支持了后台運行的模式。那么我們是不是還需要系統知道我們的程序要在后台運行多久呢?我們需要告訴系統我們期望APP在后台存活的時間。

首先聲明一個屬性

 @property (nonatomic, assign) UIBackgroundTaskIdentifier bgTask; 

在進入后台的時候通過AppDelegate里面的方法:

-(void)applicationDidEnterBackground:(UIApplication *)application{ [ self comeToBackgroundMode]; } -(void)comeToBackgroundMode{ //初始化一個后台任務BackgroundTask,這個后台任務的作用就是告訴系統當前app在后台有任務處理,需要時間 UIApplication* app = [UIApplication sharedApplication]; self.bgTask = [app beginBackgroundTaskWithExpirationHandler:^{ [app endBackgroundTask:self.bgTask]; self.bgTask = UIBackgroundTaskInvalid; }]; //開啟定時器 不斷向系統請求后台任務執行的時間 self.timer = [NSTimer scheduledTimerWithTimeInterval:25.0 target:self selector:@selector(applyForMoreTime) userInfo:nil repeats:YES]; [self.timer fire]; } -(void)applyForMoreTime { //如果系統給的剩余時間小於60秒 就終止當前的后台任務,再重新初始化一個后台任務,重新讓系統分配時間,這樣一直循環下去,保持APP在后台一直處於active狀態。 if ([UIApplication sharedApplication].backgroundTimeRemaining < 60) { [[UIApplication sharedApplication] endBackgroundTask:self.bgTask]; self.bgTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{ [[UIApplication sharedApplication] endBackgroundTask:self.bgTask]; self.bgTask = UIBackgroundTaskInvalid; }]; } } 

現在就可以讓我們的APP一直運行在后台啦!總結下來的思路就是:通過一個后台任務(這個任務我們也不用管,它存在的意義就是和系統去請求后台運行的一定的時間),這個時間我們不知道也不用去管,我們可以通過該時間還剩下多少判斷是否繼續請求時間,如此循環,我們就可以不斷的請求時間來保持我們的app一直運行在后台。

接下來解決音樂在后台模式(切換到后台或者鎖屏狀態)下停止播放的問題。

其實很簡單。

//設置后台模式和鎖屏模式下依然能夠播放 [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback withOptions:AVAudioSessionCategoryOptionMixWithOthers error:nil]; [[AVAudioSession sharedInstance] setActive: YES error: nil]; //初始化播放器和兩個音頻(一個有聲 一個無聲) NSURL *urlSound = [[NSURL alloc]initWithString:[[NSBundle mainBundle]pathForResource:@"pomodoSound" ofType:@"m4a"]]; playerSound = [[AVAudioPlayer alloc] initWithContentsOfURL:urlSound error:&playerError]; NSURL *urlNoSound = [[NSURL alloc]initWithString:[[NSBundle mainBundle]pathForResource:@"backSound" ofType:@"mp3"]]; playerNoSound = [[AVAudioPlayer alloc] initWithContentsOfURL:urlNoSound error:&playerError]; playerSound.numberOfLoops = -1; playerNoSound.numberOfLoops = -1; player = playerSound; [player play]; 

下面解釋一下AVAudioSession的一些設置參數

  • NSString *const AVAudioSessionCategoryAmbient;
    靜音模式或者鎖屏下不再播放音樂,和其他app聲音混合。
  • NSString *const AVAudioSessionCategorySoloAmbient;
    默認模式,靜音模式或者鎖屏下不再播放音樂,不和其他app聲音混合。
  • NSString *const AVAudioSessionCategoryPlayback;
    表示對於用戶切換靜音模式或者鎖屏 都不理睬,繼續播放音樂。並且不播放來自其他app的音樂
  • NSString *const AVAudioSessionCategoryRecord;
    不播放音樂,鎖屏狀態繼續錄音
  • NSString *const AVAudioSessionCategoryPlayAndRecord;
    播放音樂,並錄音

Demo地址:https://github.com/BoYangZuo/KeepAppActive



作者:flightlessBirdT
鏈接:https://www.jianshu.com/p/d62c6d3ae8ff
來源:簡書
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。

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


免責聲明!

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



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