我正在参加「掘金·启航计划」
一.引言
随着移动互联网的不断发展,移动端的软件越来越受到重视。为了满足用户不同平台的需求,开发者需要同时开发iOS
和Android
两个平台的应用,这对开发者来说是一项挑战。为了提高开发效率,Flutter
作为一种跨平台的技术框架,成为了主流开发工具之一。但是,Flutter
开发者面临的一个难题就是如何保持应用在后台长时间保活,本文将介绍Flutter 3.7
以上版本对于移动端软件跨平台后台保活的技术指南。
二.什么是后台保活
后台保活是指应用程序在后台运行而不被系统杀死的能力。一些应用需要在后台进行长时间的运行,例如下载管理、聊天应用、定位等等。如果应用在后台被系统杀死,用户将会失去对该应用的操作能力,对用户的使用体验造成很大影响。因此,实现后台保活非常重要。
三.Flutter 3.7以上版本的后台保活方案
Flutter 3.7
以上版本为了解决上述问题,提供了多种方案来保证应用在后台运行,主要包括Android
平台和iOS
平台。下面我们分别介绍这些方案。
1. Android 平台的后台保活方案
Android平台提供了以下三种后台保活方案供开发者选择:
- 资源管理器
Android系统中的资源管理器非常重要,它负责管理应用程序的资源和进程。在Android系统中,资源管理器是管理空闲内存和运行进程的一种机制。如果一个应用程序所需的内存超出了系统可用的内存空间,应用程序将被系统直接杀死。开发者可以通过以下两种方式防止应用被杀死:a.监听系统内存变化,并在系统内存过低时释放应用的内存。b.通过提高应用程序的进程优先级来避免被系统杀死
- WorkManager
WorkManager
是Android Jetpack
中提供的一种API
,它能够在满足条件的情况下在后台运行任务,同时它是一种能够在设备上能够保持活动状态的解决方法。在Flutter
中,WorkManager
可以用来调度后台任务,例如下载,上传,同步等等。WorkManager
会自动保存任务的状态,并在下次应用程序启动时恢复任务的状态,同时在应用程序杀死后也可以恢复任务的状态并继续执行。
- Flutter Isolate
Flutter Isolate
是一种灵活的机制,用于在Flutter
应用程序中运行同时。它允许开发者将计算分配给单独的工作线程,这些工作线程有自己的内存空间和运行时器。通过利用Flutter Isolate
,开发者可以避免执行I/O和计算密集型任务时,造成主线程阻塞和应用程序卡顿。
2. iOS 平台的后台保活方案
iOS平台提供了以下三种后台保活方案供开发者选择:
- Background Modes
Background Modes
是iOS 7
以后新增的功能,它让应用程序在不打断用户或在前台工作的情况下,在后台继续运行,例如播放音乐或者进行定位。Background Modes
可以取得当前时间、位置、推送信息等,在比如应用程序在后台运行时,当有新的信息时,应用程序可以发出一声声音提示用户并显示出信息。
- Background Fetch
Background Fetch
是以固定的周期去获取数据并重载最新数据的功能,可以在应用程序不活跃时进行数据更新。例如,一个新闻应用程序可以在后台每隔一定时间去获取最新的新闻内容,然后在应用程序被用户打开时,能够立即显示最新的新闻内容。
- Flutter Isolate
Flutter Isolate
也可以用于iOS
平台,与Android
平台相同,利用Flutter Isolate
,开发者可以避免执行I/O和计算密集型任务时,造成主线程阻塞和应用程序卡顿。
四. 后台保活的实现步骤
除了选择适合自己的后台保活方案,还需要按照以下步骤实现后台保活:
步骤1:编写保活代码
根据选择的后台保活方案编写保活代码,例如:
在Android
平台上使用WorkManager
:
void myBackgroundTask() {
// Do some work.
}
void enqueuMyBackgroundTask() async {
await Workmanager().initialize(
callbackDispatcher
);
await Workmanager().registerPeriodicTask(
"myUniqueName",
"Sync Data",
inputData: <String, dynamic>{
"someKey": "someValue"
},
frequency: Duration(minutes: 15),
);
}
复制代码
步骤2:注册保活代码
在Android
平台上,可以通过在AndroidManifest.xml
中注册你的服务或者广播,并且通过在WorkManager
中注册你的任务来保持应用程序后台运行。在iOS
平台上,你可以在Info.plist
中注册Background Fetch
、Background Modes
等等,具体注册方式可以参考官方文档。
步骤3:测试保活效果
测试后台保活的效果,可以使用一些模拟器或者真实设备测试。
五. 后台保活的注意事项
在进行后台保活的过程中,需要注意以下事项:
不同系统的不同表现
不同的操作系统在处理后台保活时有不同的规则和机制,例如在Android
系统中,系统会周期性的扫描后台程序,找出处理器和内存的占用情况,然后强制结束某些应用程序进程,从而清空空间。但是在iOS
系统中规则和机制不同,需要注意针对不同的平台进行不同的处理。
后台保活对手机电量的影响
后台保活的过程中,需要占用一定的系统资源和电量,因此应该合理运用后台保活的相关方案,尽量减少对电量的消耗。
六. 完整demo示例
WorkManager方案
如果需要在后台周期性地执行任务,可以选择WorkManager方案,在Android中使用WorkManager API进行任务调度,iOS中选择Background Fetch方案。示例代码如下:
import 'dart:io';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:workmanager/workmanager.dart';
void main() {
Workmanager().initialize(
callbackDispatcher,
isInDebugMode: false,
);
runApp(MyApp());
}
void callbackDispatcher() {
Workmanager().executeTask((task, inputData) {
print('Background running: $task');
return Future.value(true);
});
}
Future<void> registerPeriodicTask(
String uniqueName, String taskName, {int seconds = 15}) async {
await Workmanager().registerPeriodicTask(
uniqueName,
taskName,
frequency: Duration(seconds: seconds),
constraints: Platform.isAndroid
? Constraints(
networkType: NetworkType.connected,
requiresBatteryNotLow: false,
requiresCharging: false,
requiresDeviceIdle: false,
requiresStorageNotLow: false,
)
: null,
input: {},
initialDelay: Duration(seconds: 15),
existingWorkPolicy: Platform.isAndroid
? ExistingWorkPolicy.replace
: ExistingWorkPolicy.keep,
isPeriodic: true);
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('WorkManager Demo'),
),
body: Center(
child: ElevatedButton(
child: const Text('Register periodic task'),
onPressed: () =>
registerPeriodicTask('uniqueName', 'Task name'),
),
),
),
);
}
}
复制代码
如上述代码所示,WorkManager
提供了registerPeriodicTask
方法用于注册周期性执行任务。在iOS
中,不同于Android
的WorkManager
,使用Background Fetch
来实现周期性任务。同时我们需要在info.plist
中注册Background Modes
,并配置fetch
和Background Modes
的相关项。
具体配置方法可以参考苹果官方文档:developer.apple.com/documentati…
Background Fetch方案
下面是在Flutter
中使用Background Fetch
的示例代码:
import 'dart:async';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_background_fetch/flutter_background_fetch.dart';
void main() {
runApp(MyApp());
FlutterBackgroundFetch.initialize( // required
onFetch: _onFetch,
);
}
Future<void> _onFetch(String taskId) async {
print('Background running: $taskId');
FlutterBackgroundFetch.finish(taskId);
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Background fetch demo'),
),
body: Center(
child: ElevatedButton(
child: const Text('Start background fetch'),
onPressed: () async {
// Configure BackgroundFetch.
await FlutterBackgroundFetch.configure(
fetchInterval: 15,
minimumFetchInterval: 15,
stopOnTerminate: false,
startOnBoot: true,
);
// Start background fetch.
await FlutterBackgroundFetch.start();
},
),
),
),
);
}
}
复制代码
在iOS
中,当应用程序进入后台模式后,它会周期性的执行任务并在下一个时间段结束后再次唤醒应用程序。可以通过FlutterBackgroundFetch.configure
方法来配置fetchInterval
到15秒,以保证后台任务周期性执行。在startOnBoot
设置为true
之后,当设备重启后任务也会被自动触发执行。
七. 结论
Flutter 3.7
以上版本提供了多种后台保活方案,在Flutter中,不同的后台保活方案都有各自的优缺点。根据实际业务需求,选择最适合的方案。开发者可以根据自身应用的需求选择最适合的方案来在应用程序在后台保持运行状态,并提高用户的使用体验。在进行后台保活的过程中需要注意各种平台的不同规则和机制,并且合理使用后台保活方案以减少对手机电量的影响。