如何实现Flutter应用系统重启后自动运行后台服务?现有方案编译报错
Flutter应用开机自启报错解决与替代方案
问题描述
尝试实现手机重启后自动运行Flutter应用后台服务,按方案实现后出现以下编译错误:
AndroidStudioProjects\db_app\android\app\src\main\kotlin\com\example\laravel_login\MainActivity.kt: (14, 22): Unresolved reference: Uri AndroidStudioProjects\db_app\android\app\src\main\kotlin\com\example\laravel_login\MainActivity.kt: (14, 28): Unresolved reference: Uri FAILURE: Build failed with an exception. * What went wrong: Execution failed for task ':app:compileDebugKotlin'. > Compilation error. See log for more details * Try: > Run with --stacktrace option to get the stack trace. > Run with --info or --debug option to get more log output. > Run with --scan to get full insights.
当前使用的代码如下:
MainActivity.kt
package com.example.laravel_login import android.os.Bundle import android.provider.Settings import io.flutter.embedding.android.FlutterActivity import android.content.BroadcastReceiver import android.content.Context; import android.content.Intent; class MainActivity: FlutterActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) var REQUEST_OVERLAY_PERMISSIONS = 100 if (!Settings.canDrawOverlays(getApplicationContext())) { val myIntent = Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION) val uri: Uri = Uri.fromParts("com.example.laravel_login.BootReceiver", getPackageName(), null) myIntent.setData(uri) startActivityForResult(myIntent, REQUEST_OVERLAY_PERMISSIONS) return } } } class BootReceiver: BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { if (intent.action == Intent.ACTION_BOOT_COMPLETED) { val i = Intent(context, MainActivity::class.java) i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) context.startActivity(i) } } }
AndroidManifest.xml
<!-- app auto restart on phone restart --> <receiver android:enabled="true" android:exported="true" android:name="com.example.laravel_login.BootReceiver" android:permission="android.permission.RECEIVE_BOOT_COMPLETED"> <intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED" /> <action android:name="android.intent.action.QUICKBOOT_POWERON" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </receiver> <!-- app auto restart on phone restart -->
报错原因
编译错误源于Uri类未导入,Uri属于android.net.Uri包,当前代码未添加该类的导入语句,导致编译器无法解析引用。此外原代码中Uri.fromParts的参数也存在错误,无法正确跳转至悬浮窗权限设置页面。
修复当前方案
1. 修正代码错误
在MainActivity.kt的导入区域添加Uri类导入,并修正Uri.fromParts的参数:
package com.example.laravel_login import android.os.Bundle import android.provider.Settings import android.net.Uri // 新增Uri类导入 import io.flutter.embedding.android.FlutterActivity import android.content.BroadcastReceiver import android.content.Context; import android.content.Intent; class MainActivity: FlutterActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val REQUEST_OVERLAY_PERMISSIONS = 100 // 用val代替var,避免意外修改 if (!Settings.canDrawOverlays(applicationContext)) { val myIntent = Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION) val uri: Uri = Uri.fromParts("package", packageName, null) // 修正scheme为"package" myIntent.data = uri startActivityForResult(myIntent, REQUEST_OVERLAY_PERMISSIONS) return } } } class BootReceiver: BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { if (intent.action == Intent.ACTION_BOOT_COMPLETED) { val i = Intent(context, MainActivity::class.java) i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) context.startActivity(i) } } }
2. 补充权限配置
在AndroidManifest.xml的<manifest>标签内添加必要权限:
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
3. 处理厂商限制
国内小米、华为、OPPO等厂商会限制应用开机自启,需引导用户手动在系统设置中开启应用的「自启动权限」,否则广播接收者可能无法触发。
替代方案:使用Flutter插件简化实现
如果原生实现过于繁琐,可使用flutter_background_service插件快速实现开机自启与后台服务,步骤如下:
1. 添加插件依赖
在pubspec.yaml中添加:
dependencies: flutter_background_service: ^4.2.2 # 以最新版本为准
执行flutter pub get完成安装。
2. 配置AndroidManifest.xml
在<application>标签内添加服务与广播接收者配置:
<service android:name="id.flutter.flutter_background_service.BackgroundService" android:enabled="true" android:exported="false" android:foregroundServiceType="location|mediaPlayback|phoneCall" /> <receiver android:name="id.flutter.flutter_background_service.BackgroundServiceReceiver" android:exported="true"> <intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED" /> <action android:name="android.intent.action.QUICKBOOT_POWERON" /> </intent-filter> </receiver>
同时添加必要权限:
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> <uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <uses-permission android:name="android.permission.WAKE_LOCK" />
3. 初始化后台服务
在main.dart中初始化服务并编写后台逻辑:
import 'package:flutter/material.dart'; import 'package:flutter_background_service/flutter_background_service.dart'; import 'dart:async'; void main() async { WidgetsFlutterBinding.ensureInitialized(); await initializeService(); runApp(const MyApp()); } Future<void> initializeService() async { final service = FlutterBackgroundService(); await service.configure( androidConfiguration: AndroidConfiguration( onStart: onStart, autoStart: true, // 开机自动启动 isForegroundMode: true, // 前台服务避免被系统杀死 ), iosConfiguration: IosConfiguration( autoStart: true, onForeground: onStart, onBackground: onIosBackground, ), ); } @pragma('vm:entry-point') void onStart(ServiceInstance service) async { // 后台服务逻辑示例:每隔10秒更新通知 Timer.periodic(const Duration(seconds: 10), (timer) { if (service is AndroidServiceInstance) { service.setNotificationInfo( title: "后台服务运行中", content: "当前时间: ${DateTime.now()}", ); } }); // 监听停止服务指令 service.on('stopService').listen((event) { service.stopSelf(); }); } @pragma('vm:entry-point') bool onIosBackground(ServiceInstance service) { WidgetsFlutterBinding.ensureInitialized(); return true; } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar(title: const Text("开机自启示例")), body: Center( child: ElevatedButton( onPressed: () { FlutterBackgroundService().invoke('stopService'); }, child: const Text("停止后台服务"), ), ), ), ); } }
注意事项
- Android前台服务必须显示通知,这是系统要求,用于告知用户应用在后台运行。
- 国内厂商的自启限制仍需用户手动开启,需在应用内添加引导提示。
内容的提问来源于stack exchange,提问作者Azhar Ali
相关产品推荐
相关产品推荐

