后台设备动态更新

Posted

技术标签:

【中文标题】后台设备动态更新【英文标题】:Device motion updates in background 【发布时间】:2016-07-17 16:26:35 【问题描述】:

我正在尝试使用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 个读数。当我点击应用程序图标时,读数会重新开始。我还在处理程序中的代码上放置了断点,并且得到了类似的结果。

我错过了什么?

【问题讨论】:

【参考方案1】:

我已经在 ViewDidlLoad 中声明了运动管理器

CMMotionManager              *motionManager;
/*--Initialising Motion Manager--*/
motionManager = [[CMMotionManager alloc] init];
motionManager.deviceMotionUpdateInterval = 1.0;

当应用程序进入后台时,motionManager 在这种情况下停止提供回调,您需要在应用程序进入后台或前台时重新启动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));
   ];

【讨论】:

【参考方案2】:

不要相信NSLog 或其他类似的日志输出

我曾经遇到过这个问题。我想在后台收集运动数据,我对此做了一个演示。我发现当我的应用程序处于活动状态时我可以获取所有数据并记录,但是当应用程序在后台时,xCode 日志控制台什么也不输出。

我以前认为问题是CoreMotion数据只能在前台收集,但我错了。当应用程序进入后台时,所有回调仍在工作,只是 NSLog 停止告诉我数据

如果您不相信,只需将所有数据收集到NSMutableArray 或其他集合中,然后检查应用程序在后台收集的数据。 例如

@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);
];

【讨论】:

【参考方案3】:

经过更多研究,我发现了问题所在。我正在使用mpmusicplayercontroller 播放背景音频。这将在后台播放音频,但这不会让我的应用程序在后台运行。当我切换到使用avplayer 播放音频时,应用程序在后台运行,包括设备动作更新。

【讨论】:

以上是关于后台设备动态更新的主要内容,如果未能解决你的问题,请参考以下文章

从背景音频代理更新动态磁贴?

动态网页和静态网页的最大区别是啥

wpf 动态更新 UI 而不会冻结 UI

Apple Wallet 动态更新值

Ajax动态网页技术:局部更新部分网页的原理与过程(附代码)

在 pyqt5 界面中动态更新 matplotlib 画布