如何在Flutter中创建Service以实现应用常驻后台运行?
Flutter实现Android常驻后台服务方案
当然可以实现!Flutter本身并没有直接提供原生后台Service的封装API,但我们可以通过**平台通道(Platform Channel)**对接Android原生代码,或者借助成熟的第三方插件来快速实现常驻后台的需求。下面分两种方案详细说明:
一、自行实现原生后台Service(适合高度定制场景)
如果需要完全控制后台逻辑,建议自己编写Android原生代码,再通过Flutter的MethodChannel调用。
步骤1:创建Android后台Service
在Android项目的app/src/main/kotlin/[你的包名]下新建BackgroundService.kt:
import android.app.Notification import android.app.NotificationChannel import android.app.NotificationManager import android.app.Service import android.content.Intent import android.os.Build import android.os.IBinder class BackgroundService : Service() { private val CHANNEL_ID = "background_service_channel" override fun onBind(intent: Intent): IBinder? = null override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { // 创建通知渠道(Android 8.0+必需) createNotificationChannel() // 构建前台通知(Android要求前台服务必须显示通知) val notification: Notification = Notification.Builder(this, CHANNEL_ID) .setContentTitle("应用后台服务") .setContentText("正在后台运行") .setSmallIcon(R.mipmap.ic_launcher) .build() // 启动前台服务 startForeground(1, notification) // 这里写你的后台逻辑,比如定时任务、数据同步等 Thread { while (true) { Thread.sleep(10000) println("后台服务运行中...") } }.start() // 返回START_STICKY,确保服务被系统杀死后尝试重启 return START_STICKY } private fun createNotificationChannel() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { val channel = NotificationChannel( CHANNEL_ID, "后台服务通知", NotificationManager.IMPORTANCE_LOW ).apply { description = "显示后台服务运行状态" } val notificationManager = getSystemService(NotificationManager::class.java) notificationManager.createNotificationChannel(channel) } } }
步骤2:注册Service并申请权限
打开app/src/main/AndroidManifest.xml,添加权限和Service注册:
<manifest ...> <!-- 前台服务权限 --> <uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <!-- Android 13+需要通知权限 --> <uses-permission android:name="android.permission.POST_NOTIFICATIONS" /> <application ...> <!-- 注册后台Service --> <service android:name=".BackgroundService" android:foregroundServiceType="dataSync" /> </application> </manifest>
步骤3:Flutter端调用Service
在Flutter代码中创建通道,调用启动服务的方法:
import 'package:flutter/services.dart'; class BackgroundServiceHandler { static const MethodChannel _channel = MethodChannel('com.your.app/background_service'); // 启动后台服务 static Future<void> startBackgroundService() async { try { await _channel.invokeMethod('start_service'); } on PlatformException catch (e) { print("启动后台服务失败: ${e.message}"); } } }
然后在Android的MainActivity.kt中注册MethodChannel回调:
import android.content.Intent import android.os.Build import io.flutter.embedding.android.FlutterActivity import io.flutter.embedding.engine.FlutterEngine import io.flutter.plugin.common.MethodChannel class MainActivity : FlutterActivity() { private val CHANNEL = "com.your.app/background_service" override fun configureFlutterEngine(flutterEngine: FlutterEngine) { super.configureFlutterEngine(flutterEngine) MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler { call, result -> when (call.method) { "start_service" -> { val intent = Intent(this, BackgroundService::class.java) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { startForegroundService(intent) } else { startService(intent) } result.success(null) } else -> result.notImplemented() } } } }
二、使用第三方插件(快速实现,适合多数场景)
如果不想写原生代码,可以用flutter_background_service这类成熟插件,它已经封装了Android和iOS的后台逻辑,使用更简单。
步骤1:添加依赖
在pubspec.yaml中添加:
dependencies: flutter_background_service: ^2.4.5
步骤2:初始化并启动后台服务
import 'package:flutter/material.dart'; import 'package:flutter_background_service/flutter_background_service.dart'; import 'dart:async'; void main() async { WidgetsFlutterBinding.ensureInitialized(); // 初始化后台服务 await initializeBackgroundService(); runApp(const MyApp()); } Future<void> initializeBackgroundService() async { final service = FlutterBackgroundService(); await service.configure( androidConfiguration: AndroidConfiguration( // 后台服务启动时的回调 onStart: onBackgroundStart, // 是否自动启动服务 autoStart: true, // 是否以前台服务模式运行(必须开启才能常驻后台) isForegroundMode: true, // 通知渠道ID(Android 8.0+必需) notificationChannelId: "background_service_channel", // 初始通知内容 initialNotificationTitle: "应用后台运行中", initialNotificationContent: "正在执行后台任务", // 通知ID foregroundServiceNotificationId: 999, ), iosConfiguration: IosConfiguration( autoStart: true, // iOS前台运行时的回调 onForeground: onBackgroundStart, // iOS后台运行时的回调 onBackground: onIosBackground, ), ); } // 后台服务入口(必须加@pragma注解确保被编译器保留) @pragma('vm:entry-point') void onBackgroundStart(ServiceInstance service) { // 这里写你的后台逻辑 Timer.periodic(const Duration(seconds: 10), (timer) { print("后台服务持续运行中..."); // 如果需要更新通知内容 service.setNotificationInfo( title: "后台服务更新", content: "上次更新时间: ${DateTime.now().toLocal()}", ); }); } // iOS后台回调 @pragma('vm:entry-point') Future<bool> onIosBackground(ServiceInstance service) async { // 处理iOS后台逻辑,返回true表示允许后台运行 return true; }
重要注意事项
- Android系统限制:Android 6.0+的Doze模式、App Standby,以及国内厂商(小米、华为、OPPO等)的电池优化策略,可能会杀死后台服务。需要引导用户关闭对应应用的电池优化,或者将应用加入“白名单”。
- 前台服务必须显示通知:这是Android的强制要求,不能隐藏,只能设置通知的优先级为低,减少对用户的干扰。
- 权限申请:Android 13+需要动态申请
POST_NOTIFICATIONS权限,否则通知无法显示,前台服务启动会失败。
内容的提问来源于stack exchange,提问作者camilleB
相关产品推荐
相关产品推荐

