一.引言
随着移動網際網路的不斷發展,移動端的軟體越來越受到重視。為了滿足使用者不同平台的需求,開發者需要同時開發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中,不同的背景保活方案都有各自的優缺點。根據實際業務需求,選擇最适合的方案。開發者可以根據自身應用的需求選擇最适合的方案來在應用程式在背景保持運作狀态,并提高使用者的使用體驗。在進行背景保活的過程中需要注意各種平台的不同規則和機制,并且合理使用背景保活方案以減少對手機電量的影響。
作者:純愛掌門人
出處:https://juejin.cn/post/7229157003427905594