2012-03-16 126 views
45

我試圖在進入後臺狀態時將iOS應用程序保持活動狀態超過10分鐘。在後臺運行應用程序超過10分鐘

我該如何實現這一點。

+0

可能重複的[iOS4的創建背景定時器](http://stackoverflow.com/questions/4154332/ios4-create-background-timer) – 2012-03-16 14:01:42

+0

@ RichardJ.RossIII NOP,他希望在應用程序處於後臺時運行代碼,而不是在後臺線程中運行代碼。 – fbernardo 2012-03-16 14:04:19

回答

54

請參閱iPhoneAppProgrammingGuide的「後臺執行」部分。總之,您的應用程序必須是下列類型之一:

  • 應用程式播放音頻內容給用戶,同時在後臺運行,如音樂播放器應用程序
  • 應用程序,使用戶瞭解自己的位置在所有倍,如導航應用
  • 應用,支持互聯網語音協議(VoIP)是需要下載和處理新的內容,從外部附件接收定期更新
  • 應用
  • 書報亭應用

而且你必須按如下方式添加到Info.plist中: 添加UIBackgroundModes關鍵看你 Info.plist文件,並將其值設置爲包含下列字符串的一個或多個陣列:

  • 音頻 - 應用程序在後臺播放可聽內容給用戶。 (此內容包括使用AirPlay播放音頻或視頻內容。)
  • 位置 - 即使在後臺運行時,應用程序也會向用戶通知其位置。
  • voip-該應用程序提供用戶使用Internet連接撥打電話的功能。
  • 報刊亭內容該應用程序是一個新聞報道應用程序,在後臺下載和處理雜誌或報紙 內容。
  • 外部附件 - 該應用程序與需要通過外部附件框架以定期計劃傳遞更新的硬件附件配合使用。
  • 藍牙中央的應用支持藍牙附件,需要通過CoreBluetooth框架,提供一個 定期更新

注意審查過程的一部分將被檢查,以確保您的應用程序做它說它正在做的背景處理。

+2

請注意,只是設置這些類型不會使應用程序本身保持活動狀態。例如:當您播放音頻時,音樂會保持活躍狀態​​。但是當你的歌曲結束時,應用程序仍然可以被暫停。 – Jelle 2014-02-05 13:52:51

+0

如果我想運行alaram,一旦收到通知,我應該如何播放音樂,當應用程序在後臺?這段時間可以超過1小時 – 2016-01-27 12:34:27

+0

@ Mr.G:你有問題的解決方案嗎? – 2016-07-25 15:18:59

2

只允許某些類型的應用程序在後臺運行。請參閱this guide的「實施長時間運行的後臺任務」部分。

如果您沒有請求執行後臺處理的權限,則可以使用UIApplication的beginBackgroundTaskWithExpirationHandler,但無法獲得額外的時間。

+0

未找到。請更新。 – 2017-05-12 13:27:21

0

你不能。除非你的應用程序使用音頻,voip或gps。你可以做的是通知用戶(通過本地通知)時間快到了,並要求他打開/關閉應用程序。

此外,如果您只需要通知用戶,您可以使用推送通知。

19

這是我所做的使用beginBackgroundTaskWithExpirationHandler

  • 編寫一個啓動後臺任務的方法。
  • 在該後臺任務中,運行一個NSTimer,計劃(不重複)時間在10分鐘以內。爲了我的情況,我使用了5分鐘。
  • 一旦NStimer的選擇器激發,結束後臺任務,然後立即調用您之前編寫的方法開始另一個後臺任務。
  • 如果您想安排在特定時間運行的方法,您必須在後臺任務中檢查它們。

這個解決方案不是非常理想,仍然是電力飢餓,但會做你想做的。

編輯:自iOS7以來,我建議你閱讀這個excellent post

+2

蘋果是否批准了App Store的這個應用程序? – Hope4You 2013-01-01 15:48:36

+1

是的。我不知道這是否有幫助,但我將它作爲一種「節電器」模式發佈,作爲我們已經將GPS始終保持在後臺運行狀態的替代方案,但用戶現在可以選擇。正因爲如此,我仍然保留「GPS可以大幅降低電池壽命」的信息,他們讓你透露。 – 2013-01-01 18:39:25

+0

我原本打算使用GPS來保持應用程序的活躍,但這種方法對我來說更好,因爲那樣我就不必要求使用該人的位置。非常感謝你解釋你的情況。 – Hope4You 2013-01-02 14:50:34

2

此代碼使您的iOS應用程序在後臺無限期運行。將以下方法複製並粘貼到單例/管理器中,以處理需要在後臺執行的任務。

// @interface 

// Declare Private property 
@property (nonatomic) UIBackgroundTaskIdentifier backgroundTask; 

//@end 
// ... 

// Copy into 
//@implementation 

- (void)setupBackgrounding { 
    [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(appBackgrounding:) 
               name: UIApplicationDidEnterBackgroundNotification 
               object: nil]; 
    [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(appForegrounding:) 
               name: UIApplicationWillEnterForegroundNotification 
               object: nil]; 
} 

- (void)appBackgrounding: (NSNotification *)notification { 
    [self keepAlive]; 
} 

- (void) keepAlive { 
    self.backgroundTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{ 
     [[UIApplication sharedApplication] endBackgroundTask:self.backgroundTask]; 
     self.backgroundTask = UIBackgroundTaskInvalid; 
     [self keepAlive]; 
    }]; 
} 

- (void)appForegrounding: (NSNotification *)notification { 
    if (self.backgroundTask != UIBackgroundTaskInvalid) { 
     [[UIApplication sharedApplication] endBackgroundTask:self.backgroundTask]; 
     self.backgroundTask = UIBackgroundTaskInvalid; 
    } 
} 
+7

不幸的是,在iOS7上,這對我來說只能工作大約三分鐘。 – Jelle 2014-02-05 13:28:57

+1

看起來像一個黑客 – 2016-03-23 09:59:02

+0

其實很多物聯網商業應用程序使用它。 – rismay 2016-05-10 15:13:59

0

https://github.com/yarodevuci/backgroundTask這裏查看我的代碼,我使用的播放空白的wav文件完美的作品在IOS 8電池使用10%的按24小時左右期間 如何使用音頻播放器:

var backgroundTask = BackgroundTask() 
backgroundTask.startBackgroundTask() //Starts playing blank audio file. You can run NSTimer() or whatever you need and it will continue executing in the background. 

backgroundTask.stopBackgroundTask() //Stops the task 

警告:如果您嘗試提交,蘋果會拒絕這個!

0

如果你的應用程序類型不是VOIP /音頻/地點之一....(檢查Background Modes),

,或者你不想指定應用程序的後臺程序,可以實現beginBackgroundTaskWithName :expirationHandlerbeginBackgroundTaskWithExpirationHandler要求更多時間在後臺運行您的流程。你可以找到詳細的描述here

Apps moving to the background are expected to put themselves into a quiescent state as quickly as possible so that they can be suspended by the system. If your app is in the middle of a task and needs a little extra time to complete that task, it can call the beginBackgroundTaskWithName:expirationHandler: or beginBackgroundTaskWithExpirationHandler: method of the UIApplication object to request some additional execution time. Calling either of these methods delays the suspension of your app temporarily, giving it a little extra time to finish its work. Upon completion of that work, your app must call the endBackgroundTask: method to let the system know that it is finished and can be suspended.

Each call to the beginBackgroundTaskWithName:expirationHandler: or beginBackgroundTaskWithExpirationHandler: method generates a unique token to associate with the corresponding task. When your app completes a task, it must call the endBackgroundTask: method with the corresponding token to let the system know that the task is complete. Failure to call the endBackgroundTask: method for a background task will result in the termination of your app. If you provided an expiration handler when starting the task, the system calls that handler and gives you one last chance to end the task and avoid termination.

0

由於2018年3月,iOS的11.x的,還有一個是我知道的,讓您的應用程序在後臺運行,而不作爲特殊類型的一種方式。 訣竅是,不要讓NSURLSession餓死通過保持委託回調創建一個新的DownloadTask

所以,保持你的應用程序運行下去

  • 創建背景NSURLSession,

  • 創建一個虛擬的下載任務(不是DataTask),用虛擬URL如http://localhost:12345/dummy.bin

  • 實現[ - (void)URLSession:(NSURLSession *)會話任務:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error] delegate並在委託中,創建另一個虛擬下載任務,並通過[resume]啓動它,最好有一個延遲。

您應該仍然準備應用程序將被系統終止。但是,如果應用程序被系統終止,則應該在後臺模式下重新啓動該應用程序,以處理後臺下載任務完成。您需要在應用程序委託中重新啓動 特殊的Keep alive NSURLSession。

樣品的編號:的

/* Author: Yi Wang @InstaTV */ 

@interface URLSessionKeepAlive() { 
    NSURLSession *_session; 
} 
@end 

@implementation URLSessionKeepAlive 

- (instancetype)init { 
    self = [super init]; 
    return self; 
} 

- (void)start { 
    NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:@"SpecialKeepAliveIdentifier"]; 
    [sessionConfiguration setAllowsCellularAccess:YES]; 
    sessionConfiguration.requestCachePolicy = NSURLRequestReloadIgnoringLocalAndRemoteCacheData; 
    sessionConfiguration.timeoutIntervalForRequest = 3.0; 
    sessionConfiguration.timeoutIntervalForResource = 3.0; 
    sessionConfiguration.URLCache = nil; 
    _session = [NSURLSession sessionWithConfiguration:sessionConfiguration delegate:self delegateQueue:nil]; 

    [self addTask]; 
} 

- (void)addTask { 
    NSURLSessionTask *task = [_session downloadTaskWithURL:[NSURL URLWithString:@"http://localhost:12345/dummy.bin"]]; 
    [task resume]; 
} 

- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error { 
    static NSInteger counter = 0; 

    if (error) { 
     NSLog(@"(%zd) Adding Keep Alive Task with error: '%@'", counter++, error); 
     [NSThread sleepForTimeInterval:3.0]; 
     [self addTask]; 
    } 
}