You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter传感器插件非平台线程通信报错求助

解决Flutter sensors_plus插件在iOS 17/Xcode 15下因非平台线程发送消息导致的崩溃问题

问题背景

在MacOS Sonoma 14.0、iOS 17.0、Xcode 15环境下,使用Flutter稳定版3.13.6开发应用,部署到真机后点击特定按钮触发传感器功能时,应用崩溃,报错如下:

"[VERBOSE-2:shell.cc(1004)] The 'dev.fluttercommunity.plus/sensors/accelerometer' channel sent a message from native to Flutter on a non-platform thread. Platform channel messages must be sent on the platform thread. Failure to do so may result in data loss or crashes, and must be fixed in the plugin or application code creating that channel."
"[VERBOSE-2:shell.cc(1004)] The 'dev.fluttercommunity.plus/sensors/gyroscope' channel sent a message from native to Flutter on a non-platform thread. Platform channel messages must be sent on the platform thread. Failure to do so may result in data loss or crashes, and must be fixed in the plugin or application code creating that channel."

这是sensors_plus插件的已知问题:iOS端传感器回调默认在后台线程触发,插件未将消息发送切换到Flutter要求的平台线程(iOS平台线程为主线程),导致崩溃。

解决方案

方案1:修改插件iOS原生代码(本地修复)

如果你的项目直接依赖本地插件代码,或者愿意修改pub缓存里的插件文件,按以下步骤操作:

  1. 找到插件的iOS源码文件:SensorsPlusPlugin.m(Objective-C)或SensorsPlusPlugin.swift(Swift)
  2. 找到加速度计和陀螺仪的回调方法,将发送平台通道消息的代码包裹到主线程执行块中:

Objective-C版本修改示例

原加速度计回调:

- (void)accelerometerDataReceived:(CMAccelerometerData *)accelerometerData error:(NSError *)error {
    if (error) {
        NSLog(@"Error reading accelerometer data: %@", error);
        return;
    }
    [self.channel invokeMethod:@"accelerometer" arguments:@{
        @"x": @(accelerometerData.acceleration.x),
        @"y": @(accelerometerData.acceleration.y),
        @"z": @(accelerometerData.acceleration.z),
        @"timestamp": @(accelerometerData.timestamp)
    }];
}

修改后:

- (void)accelerometerDataReceived:(CMAccelerometerData *)accelerometerData error:(NSError *)error {
    if (error) {
        NSLog(@"Error reading accelerometer data: %@", error);
        return;
    }
    // 切换到主线程发送平台通道消息
    dispatch_async(dispatch_get_main_queue(), ^{
        [self.channel invokeMethod:@"accelerometer" arguments:@{
            @"x": @(accelerometerData.acceleration.x),
            @"y": @(accelerometerData.acceleration.y),
            @"z": @(accelerometerData.acceleration.z),
            @"timestamp": @(accelerometerData.timestamp)
        }];
    });
}

对陀螺仪的gyroDataReceived:error:方法做完全相同的修改,将invokeMethod调用包裹到dispatch_async(dispatch_get_main_queue(), ^{ ... })中。

Swift版本修改示例

原回调代码:

func gyroDataReceived(_ gyroData: CMGyroData, error: Error?) {
    if let error = error {
        print("Error reading gyroscope data: \(error)")
        return
    }
    channel.invokeMethod("gyroscope", arguments: [
        "x": gyroData.rotationRate.x,
        "y": gyroData.rotationRate.y,
        "z": gyroData.rotationRate.z,
        "timestamp": gyroData.timestamp
    ])
}

修改后:

func gyroDataReceived(_ gyroData: CMGyroData, error: Error?) {
    if let error = error {
        print("Error reading gyroscope data: \(error)")
        return
    }
    // 切换到主线程发送消息
    DispatchQueue.main.async { [weak self] in
        self?.channel.invokeMethod("gyroscope", arguments: [
            "x": gyroData.rotationRate.x,
            "y": gyroData.rotationRate.y,
            "z": gyroData.rotationRate.z,
            "timestamp": gyroData.timestamp
        ])
    }
}

加速度计的回调方法做同样修改即可。

方案2:等待插件官方修复或使用补丁包

  • 检查sensors_plus插件的最新版本,若已有修复该问题的版本,直接升级依赖:
    在pubspec.yaml中更新版本号,执行flutter pub upgrade
  • 若官方暂未发布修复版本,可使用GitHub上的修复分支作为临时依赖,或者通过patch工具对插件代码打补丁。

原理说明

Flutter要求平台通道(Platform Channel)的消息必须在平台线程发送:

  • iOS平台的平台线程就是主线程
  • 传感器框架(Core Motion)的回调默认在后台线程触发,直接在该线程发送Flutter平台消息会违反线程规则,导致崩溃或数据丢失

将消息发送逻辑切换到主线程,即可符合Flutter的线程要求,解决崩溃问题。

内容的提问来源于stack exchange,提问作者wjmetcalfiii

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 15:15:00