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

Flutter用bluetooth_print后台打印小票失败,startScan调用报错求解决

解决Flutter蓝牙打印后台报错问题

核心原因

安卓系统的后台进程限制会导致Flutter引擎在APP退到后台后被暂停,bluetooth_print插件的MethodChannel依赖Flutter引擎运行,此时调用原生方法就会出现找不到实现的错误。另外,普通后台服务插件可能未正确绑定Flutter引擎,或者没处理蓝牙权限的后台访问限制。

具体解决方案

1. 配置安卓后台权限

  • 在AndroidManifest.xml中添加必要权限:
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE_CONNECTED_DEVICE" />
    <uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
    
  • 引导用户关闭APP的电池优化,避免系统强制杀死后台进程,可在APP首次启动时弹窗提示用户手动操作。

2. 用前台服务绑定Flutter引擎

安卓高版本(API 26+)对普通后台服务限制严格,必须用前台服务保持进程存活,同时要确保Flutter引擎在服务内初始化:

  • 自定义安卓原生前台服务,在服务中初始化Flutter引擎并注册bluetooth_print的MethodChannel:
    1. 创建继承自FlutterService的服务类:
      class PrintBackgroundService : FlutterService() {
          private lateinit var flutterEngine: FlutterEngine
      
          override fun onCreate() {
              super.onCreate()
              flutterEngine = FlutterEngine(this)
              flutterEngine.dartExecutor.executeDartEntrypoint(
                  DartExecutor.DartEntrypoint.createDefault()
              )
              // 注册插件通道,关联原生实现
              MethodChannel(flutterEngine.dartExecutor.binaryMessenger, "bluetooth_print/methods")
                  .setMethodCallHandler { call, result ->
                      when (call.method) {
                          "startScan" -> {
                              // 调用bluetooth_print原生扫描逻辑
                              result.success(null)
                          }
                          // 其他蓝牙操作方法同理处理
                      }
                  }
              // 启动前台服务,显示常驻通知
              val notification = NotificationCompat.Builder(this, "print_channel")
                  .setContentTitle("订单打印服务")
                  .setContentText("正在监听新订单")
                  .setSmallIcon(R.drawable.ic_notification)
                  .build()
              startForeground(1, notification)
          }
      }
      
    2. 在AndroidManifest.xml中注册服务:
      <service
          android:name=".PrintBackgroundService"
          android:foregroundServiceType="connectedDevice" />
      
  • Flutter端启动前台服务后,将打印逻辑放在服务绑定的Isolate中执行,避免依赖主引擎。

3. 调整Firebase通知处理逻辑

收到Firebase通知时,不要直接在Flutter端触发打印,而是通过原生通知接收器启动前台服务,由服务内的Flutter引擎执行打印:

  • 在安卓原生的FirebaseMessagingService中处理通知:
    class MyFirebaseMessagingService : FirebaseMessagingService() {
        override fun onMessageReceived(remoteMessage: RemoteMessage) {
            super.onMessageReceived(remoteMessage)
            // 判断为订单通知时启动打印服务
            val intent = Intent(this, PrintBackgroundService::class.java)
            intent.putExtra("order_data", remoteMessage.data)
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                startForegroundService(intent)
            } else {
                startService(intent)
            }
        }
    }
    
  • 在前台服务中接收订单数据,调用蓝牙打印逻辑。

4. 规避UI线程依赖

bluetooth_print部分方法可能依赖UI线程,后台时UI线程会被挂起,要确保打印逻辑在后台线程执行,且不依赖Flutter的UI上下文。

额外注意事项

  • 测试使用安卓真机,模拟器后台行为与真机存在差异。
  • 针对API 31+版本,需动态申请BLUETOOTH_SCAN和BLUETOOTH_CONNECT权限,并明确告知用户权限用途。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 06:40:29