【发布时间】:2018-10-10 22:08:32
【问题描述】:
我想让我的 Flutter 应用程序始终在后台运行。使用 android,我们必须创建一个始终在后台运行的服务。我在 Flutter 文档中找不到有关服务的内容。
Flutter 可以做这种事情吗?
【问题讨论】:
我想让我的 Flutter 应用程序始终在后台运行。使用 android,我们必须创建一个始终在后台运行的服务。我在 Flutter 文档中找不到有关服务的内容。
Flutter 可以做这种事情吗?
【问题讨论】:
目前还没有办法直接从 Flutter 中执行此操作,尽管这可能会在某些时候发生变化 - 请参阅 this bug/feature request。不过,您确实有几个选择。
第一种是使用MethodChannels 并简单地编写您想要创建后台服务的android 代码(或者如果您希望它始终是后台服务,您可以这样做而无需来自flutter 端的通信)。
第二个是这两个插件的某种组合 - android_alarm_manager 和 android_intent。但这并不适用于所有用例。
Flutter 现在支持运行后台进程。详情请见this page。
【讨论】:
MainActivity 旁边创建 BroadcastReceiver 类。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>
您的颤振代码每 1 分钟调用一次。甚至您的应用程序已最小化或切换到另一个应用程序或屏幕关闭。
【讨论】:
这是一个可以做到这一点的库background_fetch。
Background Fetch 是一个非常简单的插件,它大约每 15 分钟会在后台唤醒一个应用程序,提供较短的后台运行时间。每当后台获取事件发生时,此插件将执行您提供的 callbackFn。 ref
【讨论】:
flutter_background_service 与来自dart:async 的Timer 结合。
见:
【讨论】: