当 Unity 应用程序在后台时,如何在 iOS 中收集罗盘数据?

问题描述 投票:0回答:1

我对 Objective-C 和 Swift 知之甚少,但在花了几个小时编写了一个原生插件以在 iOS 中使用后台线程收集指南针数据后,下面是目前为止的插件

// MyPlugin.m
 
extern "C" {
#import <CoreLocation/CoreLocation.h>
#import "MyPlugin.h"
 
@implementation MyPlugin
 
NSThread *_magneticHeadThread;
BOOL _shouldStop;
NSMutableArray *readings;
 
- (void)startBackgroundThread {
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
        // Put your code here that should run in the background when the app enters background.
        NSLog(@"Background thread started!");
        readings = [NSMutableArray array];
        _magneticHeadThread = [[NSThread alloc] initWithTarget:self selector:@selector(retrieveMagneticHeadPosition) object:nil];
        [_magneticHeadThread start];
    });
}
 
- (void)applicationDidEnterBackground:(NSNotification *)notification {
    _shouldStop = NO;
    [self startBackgroundThread];
}
 
- (void)applicationWillEnterForeground:(NSNotification *)notification {
    _shouldStop = YES;
    [_magneticHeadThread cancel];
    NSLog(@"Magnetic head position: %lu", [readings count]);
}
 
+ (instancetype)sharedInstance {
    static MyPlugin *sharedInstance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedInstance = [[MyPlugin alloc] init];
    });
    return sharedInstance;
}
 
- (void)retrieveMagneticHeadPosition {
    CLLocationManager *locationManager = [[CLLocationManager alloc] init];
   
    locationManager.headingFilter = kCLHeadingFilterNone;
    [locationManager startUpdatingHeading];
    int c = 0;
    while (!_shouldStop) {
       
        NSLog(@"Magnetic head position: %i", c);
        c++;
        [readings addObject:@(locationManager.heading.magneticHeading)];
        [NSThread sleepForTimeInterval:0.1];
    }
   
    [locationManager stopUpdatingHeading];
}
 
@end
 
 
void UnityMyPlugin_StartBackgroundThread() {
    [[NSNotificationCenter defaultCenter] addObserver:[MyPlugin sharedInstance] selector:@selector(applicationDidEnterBackground:) name:UIApplicationDidEnterBackgroundNotification object:nil];
   
    [[NSNotificationCenter defaultCenter] addObserver:[MyPlugin sharedInstance] selector:@selector(applicationWillEnterForeground:) name:UIApplicationWillEnterForegroundNotification object:nil];
}
}

它在 Start 函数的 MonoBehaviour 中被调用:

void Start()
    {
        Application.runInBackground = true;
#if UNITY_IPHONE && !UNITY_EDITOR
        UnityMyPlugin_StartBackgroundThread();
#endif
    }

我读到 dispatch_async 预计在固定时间完成,但我没有找到无限线程的任何线索,也没有找到有关请求信息的服务信息,例如 magneticHeading,你能指出我在哪里检查或向谁询问吗一个办法?我在寻找任何可能的东西吗?我在这段代码中做出了错误的选择吗? 谢谢

这个解决方案,在被 SO 取消之前编译和工作约 2 秒,但我正在寻找一个收集更长时间数据的线程或一个服务来询问一系列时间戳并获取信息。

ios objective-c unity3d
1个回答
0
投票

你这里的做法是错误的。您不会不断地在线程上轮询 CLLocationManager。您启动 CLLocationManager 一次,只要您需要信息就让它运行。该应用程序将收到定期更新。不需要任何类型的线程,绝对不需要轮询循环。

有关获取权限和其他所需设置的信息,请参阅配置您的应用以使用位置服务。有关在后台读取位置信息的更多详细信息,请参阅在后台处理位置更新。您的应用不会在后台持续轮询信息。操作系统将在事件可用时提供事件,并可能在需要时启动您的应用程序。

© www.soinside.com 2019 - 2024. All rights reserved.