后台设备运动更新
Device motion updates in background
我正在尝试使用 CMMotionManager
在后台获取 iPhone 或 iPad 上的设备运动更新。我已经查看了有关此主题的所有以前的帖子,并认为我有可用的代码。我的应用程序还使用背景音频,这在前台和后台都能正常工作。在 Info.plist
中,我启用了背景音频和背景位置更新。
出于测试目的,我在 AppDelegate 中声明了 "var motionManager = CMMotionManager()"
,并在 didFinishLaunchingWithOptions
中包含了以下代码:
motionManager.deviceMotionUpdateInterval = 0.10
let queue = NSOperationQueue()
motionManager.startDeviceMotionUpdatesToQueue(queue, withHandler: {
data, error in
let accelerationVector = sqrt(pow(data!.userAcceleration.x, 2) + pow(data!.userAcceleration.y, 2) + pow(data!.userAcceleration.z, 2))
print("\(accelerationVector)")
})
当我 运行 我的设备上的应用程序时,代码按预期在前台执行,但是当我按下主页按钮时,我在停止之前获得了大约 10 个读数。当我点击应用程序图标时,读数又开始了。我还在处理程序中的代码上放置了断点,并得到了类似的结果。
我错过了什么?
经过更多研究,我发现了问题所在。我正在使用 mpmusicplayercontroller to play background audio. This will play the audio in the background, but this does not keep my app running in the background. When I switched to using avplayer 播放音频,应用程序在后台运行,包括设备动作更新。
我已经在 ViewDidlLoad 中声明了运动管理器
CMMotionManager *motionManager;
/*--Initialising Motion Manager--*/
motionManager = [[CMMotionManager alloc] init];
motionManager.deviceMotionUpdateInterval = 1.0;
在这种情况下,只要应用程序进入后台,motionManager 就会停止提供回调,您需要在应用程序进入后台或 foreground.To 时重新启动 motionmanager,我们需要遵循以下过程:
1) we first need to Register for the app transition notification :
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appDidEnterBackground) name:UIApplicationDidEnterBackgroundNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appDidBecomeActive) name:UIApplicationDidBecomeActiveNotification object:nil];
2)Notification callback functions, in which you will restart the motion manager
-(void)appDidEnterBackground{
[self restartMotionUpdates];
}
-(void)appDidBecomeActive{
[self restartMotionUpdates];
}
3)This function which will restart the motion manager
-(void)restartMotionUpdates{
[motionManager stopDeviceMotionUpdates];
[motionManager startDeviceMotionUpdatesToQueue:[NSOperationQueue mainQueue] withHandler:^(CMDeviceMotion *motion, NSError *error) {
NSLog(@"x=%f y=%f z=%f",fabs(motion.userAcceleration.x),fabs(motion.userAcceleration.y),fabs(motion.userAcceleration.z));
}];
}
不要相信 NSLog
或其他类似的日志输出
我以前遇到过这个问题。我想在后台收集运动数据,我做了一个演示。我发现当我的应用程序处于活动状态时我可以获取所有数据和日志,但是当应用程序处于后台时 xCode 日志控制台不输出任何内容。
我以前以为问题是CoreMotion数据只能在前台采集,但我错了。当应用程序进入后台时,所有回调仍在工作,只是 NSLog
停止告诉我数据 。
不信,把所有的数据收集到一个NSMutableArray
或者其他的集合里,然后查看app在后台收集的数据。
例如
@property (nonatomic, strong) NSMutableArray *arrAltimeters;
...
[self.altimeter startRelativeAltitudeUpdatesToQueue:self.operationQueue withHandler:^(CMAltitudeData * _Nullable altitudeData, NSError * _Nullable error) {
[self.arrAltimeters addObject:altitudeData];
NSLog(@"Altimate data count = %ld", self.arrAltimeters.count);
}];
我正在尝试使用 CMMotionManager
在后台获取 iPhone 或 iPad 上的设备运动更新。我已经查看了有关此主题的所有以前的帖子,并认为我有可用的代码。我的应用程序还使用背景音频,这在前台和后台都能正常工作。在 Info.plist
中,我启用了背景音频和背景位置更新。
出于测试目的,我在 AppDelegate 中声明了 "var motionManager = CMMotionManager()"
,并在 didFinishLaunchingWithOptions
中包含了以下代码:
motionManager.deviceMotionUpdateInterval = 0.10
let queue = NSOperationQueue()
motionManager.startDeviceMotionUpdatesToQueue(queue, withHandler: {
data, error in
let accelerationVector = sqrt(pow(data!.userAcceleration.x, 2) + pow(data!.userAcceleration.y, 2) + pow(data!.userAcceleration.z, 2))
print("\(accelerationVector)")
})
当我 运行 我的设备上的应用程序时,代码按预期在前台执行,但是当我按下主页按钮时,我在停止之前获得了大约 10 个读数。当我点击应用程序图标时,读数又开始了。我还在处理程序中的代码上放置了断点,并得到了类似的结果。
我错过了什么?
经过更多研究,我发现了问题所在。我正在使用 mpmusicplayercontroller to play background audio. This will play the audio in the background, but this does not keep my app running in the background. When I switched to using avplayer 播放音频,应用程序在后台运行,包括设备动作更新。
我已经在 ViewDidlLoad 中声明了运动管理器
CMMotionManager *motionManager;
/*--Initialising Motion Manager--*/
motionManager = [[CMMotionManager alloc] init];
motionManager.deviceMotionUpdateInterval = 1.0;
在这种情况下,只要应用程序进入后台,motionManager 就会停止提供回调,您需要在应用程序进入后台或 foreground.To 时重新启动 motionmanager,我们需要遵循以下过程:
1) we first need to Register for the app transition notification :
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appDidEnterBackground) name:UIApplicationDidEnterBackgroundNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appDidBecomeActive) name:UIApplicationDidBecomeActiveNotification object:nil];
2)Notification callback functions, in which you will restart the motion manager
-(void)appDidEnterBackground{
[self restartMotionUpdates];
}
-(void)appDidBecomeActive{
[self restartMotionUpdates];
}
3)This function which will restart the motion manager
-(void)restartMotionUpdates{
[motionManager stopDeviceMotionUpdates];
[motionManager startDeviceMotionUpdatesToQueue:[NSOperationQueue mainQueue] withHandler:^(CMDeviceMotion *motion, NSError *error) {
NSLog(@"x=%f y=%f z=%f",fabs(motion.userAcceleration.x),fabs(motion.userAcceleration.y),fabs(motion.userAcceleration.z));
}];
}
不要相信 NSLog
或其他类似的日志输出
我以前遇到过这个问题。我想在后台收集运动数据,我做了一个演示。我发现当我的应用程序处于活动状态时我可以获取所有数据和日志,但是当应用程序处于后台时 xCode 日志控制台不输出任何内容。
我以前以为问题是CoreMotion数据只能在前台采集,但我错了。当应用程序进入后台时,所有回调仍在工作,只是 NSLog
停止告诉我数据 。
不信,把所有的数据收集到一个NSMutableArray
或者其他的集合里,然后查看app在后台收集的数据。
例如
@property (nonatomic, strong) NSMutableArray *arrAltimeters;
...
[self.altimeter startRelativeAltitudeUpdatesToQueue:self.operationQueue withHandler:^(CMAltitudeData * _Nullable altitudeData, NSError * _Nullable error) {
[self.arrAltimeters addObject:altitudeData];
NSLog(@"Altimate data count = %ld", self.arrAltimeters.count);
}];