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

如何实现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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.23 14:33:19