我需要iOS在应用程序处于前台/活动状态时可以提供的所有执行时间。大多数应用程序一旦被移动到后台状态就会暂停,但可以在后台请求更多的执行时间
beginBackgroundTaskWithName:expirationHandler:
或
beginBackgroundTaskWithExpirationHandler:
。即使系统可能在需要时暂停或终止应用程序,这个额外的后台执行时间可能会延长至三分钟。
这个过程在原生iOS应用程序上看起来很简单,但我在为React Native应用程序制作本机模块时遇到问题,可以启动/完成这些后台任务。
This article解释了非常类似的情况,其中要求系统有更多背景执行时间到范围信标。
我的目标是通过使用iOS的本机模块以类似的方式在React Native中的Javascript代码上请求执行时间。
我可以使用the documentation中描述的方法使更简单的本机模块与React Native一起使用。
我无法调用带有beginBackgroundTaskWithName
duo的UIApplication endBackgroundTask
或RCT_EXPORT_METHOD()
对相关后台任务的引用。
我也试过在上面的文章中导出代码方法就是这种方式,但它显然不起作用。
#import <CoreLocation/CoreLocation.h>
#import "BackgroundIOS.h"
#import <React/RCTLog.h>
#import <UIKit/UIKit.h>
@implementation BackgroundIOS
RCT_EXPORT_MODULE();
static BOOL _inBackground;
static _backgroundTask = nil;
RCT_EXPORT_METHOD(locationManager:(CLLocationManager *)manager didDetermineState:(CLRegionState)state forRegion:(CLRegion *)region)
{
if (_inBackground) {
[self extendBackgroundRunningTime];
}
}
RCT_EXPORT_METHOD(applicationDidEnterBackground:(UIApplication *)application)
{
[self extendBackgroundRunningTime];
_inBackground = YES;
}
RCT_EXPORT_METHOD(applicationDidBecomeActive:(UIApplication *)application)
{
_inBackground = NO;
}
RCT_EXPORT_METHOD(extendBackgroundRunningTime) {
if (_backgroundTask != UIBackgroundTaskInvalid) {
// if we are in here, that means the background task is already running.
// don't restart it.
return;
}
NSLog(@"Attempting to extend background running time");
__block Boolean self_terminate = YES;
_backgroundTask = [[UIApplication sharedApplication] beginBackgroundTaskWithName:@"DummyTask" expirationHandler:^{
NSLog(@"Background task expired by iOS");
if (self_terminate) {
[[UIApplication sharedApplication] endBackgroundTask:_backgroundTask];
_backgroundTask = UIBackgroundTaskInvalid;
}
}];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSLog(@"Background task started");
while (true) {
NSLog(@"background time remaining: %8.2f", [UIApplication sharedApplication].backgroundTimeRemaining);
[NSThread sleepForTimeInterval:1];
}
});
}
@end
编辑:
似乎设置这样的方法可以使用来自JS的调用:
BackgroundIOS.h:
#import <React/RCTBridgeModule.h>
#import <UIKit/UIKit.h>
@interface BackgroundIOS : NSObject <RCTBridgeModule>
@property UIBackgroundTaskIdentifier backgroundUpdateTask;
@end
BackgroundIOS.m:
#import "BackgroundIOS.h"
#import <React/RCTLog.h>
@implementation BackgroundIOS
RCT_EXPORT_MODULE();
RCT_EXPORT_METHOD(beginBackgroundTask){
NSLog(@"Background time in total: %f",[[UIApplication sharedApplication] backgroundTimeRemaining]);
[self beginBackgroundUpdateTask];
}
RCT_EXPORT_METHOD(endBackgroundTask){
[self endBackgroundUpdateTask];
NSLog(@"Background task ended.");
}
- (void) beginBackgroundUpdateTask
{
self.backgroundUpdateTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
[self endBackgroundUpdateTask];
}];
}
- (void) endBackgroundUpdateTask
{
[[UIApplication sharedApplication] endBackgroundTask: self.backgroundUpdateTask];
self.backgroundUpdateTask = UIBackgroundTaskInvalid;
}
@end