如何在Flutter中创建一个服务,让应用程序始终在后台运行?

问题描述 投票:0回答:5

我想让我的 Flutter 应用程序始终在后台运行。对于android,我们必须创建一个始终在后台运行的Service。我在 Flutter 文档中没有找到有关服务的内容。

Flutter 可以做这样的事情吗?

service dart flutter
5个回答
31
投票

目前还没有办法直接从 flutter 执行此操作,尽管这可能会在某些时候发生变化 - 请参阅此错误/功能请求。不过,您确实有几个选择。

第一种方法是使用 MethodChannels 并简单地编写您想要创建后台服务的 Android 代码(或者如果您希望它始终是后台服务,您可能可以做到这一点,而无需与 flutter 端进行通信)。

第二个是这两个插件的某种组合 - android_alarm_managerandroid_intent。但这并不适用于所有用例。

编辑 2021 年 2 月:

Flutter 现在支持运行后台进程。详情请参阅此页


11
投票
  • 创建新的 Flutter 项目。
    • 在 android 目录中的
      BroadcastReceiver
      旁边创建
      MainActivity
      类。
    • 像这样改变
      MainActivity.java
      main.dart
      AndroidManifest.xml

我的接收者

    package com.example.flutter_broadcastreceiver_alarmmanager_repeat;
    import android.content.BroadcastReceiver;
    import android.content.Context;
    import android.content.Intent;
    public class MyReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            MainActivity.callFlutter();
        }
    }

主要活动

package com.example.flutter_broadcastreceiver_alarmmanager_repeat;

import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Intent;
import android.os.Bundle;
import io.flutter.app.FlutterActivity;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugins.GeneratedPluginRegistrant;
import io.flutter.view.FlutterView;

public class MainActivity extends FlutterActivity {

    private PendingIntent pendingIntent;
    private AlarmManager alarmManager;
    private static  FlutterView flutterView;
    private static final String CHANNEL = "com.tarazgroup";

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        flutterView=getFlutterView();
        GeneratedPluginRegistrant.registerWith(this);

        Intent intent = new Intent(this, MyReceiver.class);
        pendingIntent = PendingIntent.getBroadcast(this, 1019662, intent, 0);
        alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
        alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 1000, pendingIntent);

    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        alarmManager.cancel(pendingIntent);
    }

    static void callFlutter(){
        MethodChannel methodChannel=new MethodChannel(flutterView, CHANNEL);
        methodChannel.invokeMethod("I say hello every minute!!","");
    }
}

main.dart

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key}) : super(key: key);

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {

  static const methodChannel = const MethodChannel('com.tarazgroup');

  _MyHomePageState() {
    methodChannel.setMethodCallHandler((call) {
      print(call.method);
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
      ),
      body: Container() 
    );
  }
}

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.flutter_broadcastreceiver_alarmmanager_repeat">

    <application
        android:name="io.flutter.app.FlutterApplication"
        android:icon="@mipmap/ic_launcher"
        android:label="flutter_broadcastreceiver_alarmmanager_repeat">
        <activity
            android:name=".MainActivity"
            android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
            android:hardwareAccelerated="true"
            android:launchMode="singleTop"
            android:theme="@style/LaunchTheme"
            android:windowSoftInputMode="adjustResize">

            <meta-data
                android:name="io.flutter.app.android.SplashScreenUntilFirstFrame"
                android:value="true" />

            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <receiver android:name=".MyReceiver"></receiver>

    </application>

</manifest>

你的 flutter 代码平均调用 1 分钟。即使您的应用程序最小化或切换到另一个应用程序或关闭屏幕。


6
投票

这是一个可以做到这一点的库background_fetch

Background Fetch 是一个非常简单的插件,大约每 15 分钟就会在后台唤醒一个应用程序,提供较短的后台运行时间。每当发生后台获取事件时,该插件就会执行您提供的callbackFn。 参考


5
投票

flutter_background_service
Timer
中的
dart:async
结合。

参见:


0
投票

Flutter 可以做这样的事情吗?

是的,现在 dart 可以通过在原生 android 服务组件中运行 flutter 引擎来在后台运行。 (原链接

注意:您无法替换android提供的原生服务组件。相反,您必须在该服务组件中运行 flutter 引擎。

您可以按照本文中的方式手动执行此操作:文章链接

或者

您可以使用第三方软件包,例如工作管理器插件

© www.soinside.com 2019 - 2024. All rights reserved.