花义文 發表於 2024-7-16 16:27:00

iOS开发基础102-后台保活方案

<p>iOS系统在后台执行程序时,有严格的限制,为了更好地管理资源和电池寿命,iOS会限制应用程序在后台的运行时间。然而,iOS提供了一些特定的策略和技术,使得应用程序可以在特定场景下保持后台运行(即“后台保活”)。以下是iOS中几种常见的后台保活方案,并附上示例代码:</p>
<h3 id="一后台任务">一、后台任务</h3>
<p>利用<code>beginBackgroundTask</code>和<code>endBackgroundTask</code>来执行后台任务。后台任务将在应用程序进入后台时仍能保持有限的时间执行任务。</p>
<pre><code class="language-objective-c">#import &lt;UIKit/UIKit.h&gt;

@interface AppDelegate : UIResponder &lt;UIApplicationDelegate&gt;

@property (strong, nonatomic) UIWindow *window;
@property (assign, nonatomic) UIBackgroundTaskIdentifier bgTask;

@end

@implementation AppDelegate

- (void)applicationDidEnterBackground:(UIApplication *)application {
    self.bgTask = [ beginBackgroundTaskWithExpirationHandler:^{
      [ endBackgroundTask:self.bgTask];
      self.bgTask = UIBackgroundTaskInvalid;
    }];
   
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
      // 在这里执行你的后台任务
      for (int i = 0; i &lt; 100; i++) {
            NSLog(@"Background task running %d", i);
            ;
      }
      
      [ endBackgroundTask:self.bgTask];
      self.bgTask = UIBackgroundTaskInvalid;
    });
}

@end
</code></pre>
<h3 id="二使用background-fetch">二、使用Background Fetch</h3>
<p>利用Background Fetch,系统会间歇性地唤醒应用程序,以便它可以执行任务或获取数据。需要在Xcode的“Capabilities”中开启Background Modes,并勾选“Background fetch”。</p>
<pre><code class="language-objective-c">#import &lt;UIKit/UIKit.h&gt;

@interface AppDelegate : UIResponder &lt;UIApplicationDelegate&gt;

@property (strong, nonatomic) UIWindow *window;

@end

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    ;
    return YES;
}

- (void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
    // 在这里执行你的后台数据获取任务
    NSLog(@"Background fetch started");

    // 模拟数据获取
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
      NSLog(@"Background fetch completed");
      completionHandler(UIBackgroundFetchResultNewData);
    });
}

@end
</code></pre>
<h3 id="三使用远程通知silent-push-notification">三、使用远程通知(Silent Push Notification)</h3>
<p>利用远程通知,在接收到通知时,系统会唤醒应用程序执行指定的任务。需要开启Remote notifications,在Application Capabilities中勾选“Remote notifications”。</p>
<pre><code class="language-objective-c">#import &lt;UIKit/UIKit.h&gt;
#import &lt;UserNotifications/UserNotifications.h&gt;

@interface AppDelegate : UIResponder &lt;UIApplicationDelegate, UNUserNotificationCenterDelegate&gt;

@property (strong, nonatomic) UIWindow *window;

@end

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    .delegate = self;
    [ requestAuthorizationWithOptions:(UNAuthorizationOptionAlert | UNAuthorizationOptionSound | UNAuthorizationOptionBadge) completionHandler:^(BOOL granted, NSError * _Nullable error) {
      if (granted) {
            [ registerForRemoteNotifications];
      }
    }];
    return YES;
}

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
    // 在这里处理收到的远程通知
    NSLog(@"Received remote notification");

    // 模拟处理任务
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
      NSLog(@"Handled remote notification");
      completionHandler(UIBackgroundFetchResultNewData);
    });
}

@end
</code></pre>
<h3 id="四使用特定的后台模式background-modes">四、使用特定的后台模式(Background Modes)</h3>
<p>iOS提供了一些特定的后台模式,允许程序在后台持续运行。常见的后台模式包括:</p>
<ul>
<li>Audio: 允许应用程序在后台播放音频。</li>
<li>Location: 允许应用程序在后台持续获取位置更新。</li>
<li>VoIP: 允许应用程序在后台侦听VoIP事件。</li>
<li>Bluetooth: 允许应用程序与蓝牙设备通信。</li>
</ul>
<h4 id="1-audio后台模式">1. Audio后台模式</h4>
<p>需要在Xcode的“Capabilities”中开启Background Modes,并勾选“Audio, AirPlay, and Picture in Picture”。</p>
<pre><code class="language-objective-c">#import &lt;AVFoundation/AVFoundation.h&gt;

@interface AppDelegate ()

@property (nonatomic, strong) AVAudioPlayer *audioPlayer;

@end

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    NSError *error = nil;
    NSURL *audioURL = [ URLForResource:@"audioFileName" withExtension:@"mp3"];
    self.audioPlayer = [ initWithContentsOfURL:audioURL error:&amp;error];
    ;
   
    AVAudioSession *audioSession = ;
    ;
    ;
   
    return YES;
}

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

@end
</code></pre>
<h4 id="2-location后台模式">2. Location后台模式</h4>
<p>需要在Xcode的“Capabilities”中开启Background Modes,并勾选“Location updates”。</p>
<pre><code class="language-objective-c">#import &lt;CoreLocation/CoreLocation.h&gt;

@interface AppDelegate () &lt;CLLocationManagerDelegate&gt;

@property (nonatomic, strong) CLLocationManager *locationManager;

@end

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    self.locationManager = [ init];
    self.locationManager.delegate = self;
    ;
    return YES;
}

- (void)applicationDidEnterBackground:(UIApplication *)application {
    self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
    ;
}

- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray&lt;CLLocation *&gt; *)locations {
    CLLocation *location = ;
    NSLog(@"Background location: %@", location);
}

@end
</code></pre>
<h3 id="五使用后台urlsession">五、使用后台URLSession</h3>
<p>使用<code>NSURLSession</code>来执行后台下载和上传任务。需要在后台配置中开启Background Modes,并勾选“Background fetch”和“Remote notifications”。</p>
<pre><code class="language-objective-c">#import &lt;UIKit/UIKit.h&gt;

@interface AppDelegate : UIResponder &lt;UIApplicationDelegate, NSURLSessionDelegate, NSURLSessionDownloadDelegate&gt;

@property (strong, nonatomic) UIWindow *window;
@property (nonatomic, strong) NSURLSession *backgroundSession;

@end

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    NSURLSessionConfiguration *config = ;
    self.backgroundSession = ;
    return YES;
}

- (void)applicationDidEnterBackground:(UIApplication *)application {
    NSURL *url = ;
    NSURLSessionDownloadTask *downloadTask = ;
    ;
}

- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location {
    NSLog(@"Download completed: %@", location);
    // 处理下载结果,比如保存文件
}

@end
</code></pre>
<p>通过上述几种方案,我们可以在iOS应用程序中实现各种场景下的后台保活。每种方案都有其适用的场景和限制,开发者需要根据应用的实际需求和系统提供的特性,选择合适的后台保活方案。</p>


</div>
<div id="MySignature" role="contentinfo">
    将来的你会感谢今天如此努力的你!
版权声明:本文为博主原创文章,未经博主允许不得转载。<br><br>
来源:https://www.cnblogs.com/chglog/p/18305545
頁: [1]
查看完整版本: iOS开发基础102-后台保活方案