背景
(本文翻译自YouTube视频:https://www.youtube.com/watch?v=NXuAzXY_KOo&t=572s)
Android和iOS在后台服务的处理方式不同,因此Flutter并没有在这方面做统一处理,而是需要调用原生平台的代码来实现该功能,下面就简单介绍如何在Flutter中与Android的后台服务进行交互。
实现
- 在Flutter中有一个按钮,点击后会开启后台服务。此外建立了一个MethodChannel,通过该通道去调用Android原生代码里的 startService()。
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: RaisedButton(
child: Text("开启后台任务"),
onPressed: () {
startService();
},
),
)
);
}
void startService() async{
if(Platform.isAndroid) {
var methodChannel = MethodChannel("com.example.flutterapp");
String data = await methodChannel.invokeMethod("startService");
print("data: $data");
}
}
}
- 新建 MyApplication 继承自 FlutterApplication,并在 onCreate() 中创建 NotificationChannel 和 NotificationManager (Android 26 以上需要)。
public class MyApplication extends FlutterApplication {
@Override
public void onCreate() {
super.onCreate();
//Android 8.0 26
//一种 Notification 对应一个 NotificationChannel
//在 Application 注册 channel 可以在 app 启动时就完成注册
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel("messages", "Messages", NotificationManager.IMPORTANCE_LOW);
NotificationManager manager = getSystemService(NotificationManager.class);
manager.createNotificationChannel(channel);
}
}
}
- 新建 MyService 继承自 Service,并在 onCreate() 中进行 Android 版本判断,对 26以上进行特殊处理(记得在 AndroidManifest 里注册 service)。
public class MyService extends Service {
@Override
public void onCreate() {
super.onCreate();
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, "messages")
.setContentText("正在后台运行")
.setContentTitle("Flutter后台")
.setSmallIcon(R.drawable.launch_background);
startForeground(101, builder.build());
}
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
}
- 最后,在 MainActivity 中打开 注册 MethodChannel 并提供 startService() 给 Flutter 调用。
public class MainActivity extends FlutterActivity {
private Intent serviceIntent;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
GeneratedPluginRegistrant.registerWith(this);
serviceIntent = new Intent(MainActivity.this, MyService.class);
new MethodChannel(getFlutterView(), "com.example.flutterapp")
.setMethodCallHandler(new MethodChannel.MethodCallHandler() {
@Override
public void onMethodCall(@NonNull MethodCall methodCall, @NonNull MethodChannel.Result result) {
if(methodCall.method.equals("startService")) {
startService();
result.success("服务已启动");
}
}
});
}
@Override
protected void onDestroy() {
super.onDestroy();
stopService(serviceIntent);
}
private void startService() {
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForegroundService(serviceIntent);
} else {
startService(serviceIntent);
}
}
}
最终效果如下图所示,一开始没有后台任务,点击按钮后,再查看通知栏,发现后台服务已启动。