Flutter Background/Foreground service - How to Run Background Task?
Last updated Jul 22, 2021In this post, we will Create and Run Background Services using Flutter code in Android. Running background task is one of the most important tasks that we can perform in an Android or iOS app. we can run background task as background service or foreground service. Flutter, being a very Versatile solution for programming, allows us to write platform-specific code to achieve your background tasks! Here is how we do it!
In Android "Orieo" and above versions background services will not work because of Doze mode. To run background service in Orieo and the above versions, we need to run service as a foreground service.
What is Foreground Service
We are just using Gmail app and listening to music that is being played by Music Player application. So Music Player is basically using the foreground service to play the music. The foreground service always uses the notification to notify the user and using the notification we can actually interact with the service or the ongoing operation such as pause the music or play the next music.
So whenever in an app we see a notification that is performing some long running tasks that service is basically the foreground service and Foreground Service is always noticeable to the user that is the user is aware of this ongoing process
Step up to writing implementation
Step 1: Create a Flutter application
Step 2: Go to the android folder and open MainActivity, it will show Open for Editing in Android Studio
Press on that, it will open an android project in another window.
Create a class App that extends Application.
Here we are creating a notification channel to show foreground notification.
package com.example.flutter_service
import android.app.Application
import android.app.NotificationChannel
import android.app.NotificationManager
import android.content.Context
import android.os.Build
class App: Application() {
override fun onCreate() {
super.onCreate()
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.O)
{
val notificationChannel=NotificationChannel("msgs","msgs",NotificationManager.IMPORTANCE_LOW)
val notificationManager=getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
notificationManager.createNotificationChannel(notificationChannel)
}
}
}
|
Step 3:
Create AppService class which extends Android Service class and implement our logic what we want to execute
package com.example.flutter_service
import android.app.NotificationManager
import android.app.Service
import android.content.Context
import android.content.Intent
import android.os.Build
import android.os.IBinder
import android.util.Log
import androidx.core.app.NotificationCompat
class AppService: Service() {
override fun onCreate() {
super.onCreate()
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.O)
{
val notificationBuilder=NotificationCompat.Builder(this,"msgs")
.setContentText("Notificaiton from background Service - Flutter")
.setContentTitle("Background Service")
.setSmallIcon(R.mipmap.ic_launcher)
.build()
Log.v("OnService","OnService")
//val manager=getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
//manager.notify((System.currentTimeMillis()%10000).toInt(),notificationBuilder)
startForeground((System.currentTimeMillis()%10000).toInt(),notificationBuilder)
Log.v("OnService","OnService")
}
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
startService()
return START_NOT_STICKY
}
override fun onBind(intent: Intent?): IBinder? {
return null;
}
fun startService()
{
Thread(Runnable {
var k=0;
for( k in 0.. 50)
{
Log.v("OnCalling","" +k)
Thread.sleep(1000)
}
}).start()
}
}
|
Step 4: Update Manifest file to declare Application and Service
android:name=".App"
android:label="flutter_service"
android:icon="@mipmap/ic_launcher">
|
<service android:name=".AppService"/>
|
Step 5: Write Start Service login in MainActivity
lateinit var intent:Any
fun startService()
{
intent=Intent(this,AppService::class.java)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForegroundService(intent as Intent)
}else
{
startService(intent as Intent)
}
}
|
Step 6:
How to call Android Native Methods from Flutter Code
To call Android methods from Flutter application we need to create Method Channel.
Now create a method in main.dart file to call Android Native code
Future startService()
async {
if(Platform.isAndroid)
{
var methodChannel=MethodChannel("com.example.messages");
String data=await methodChannel.invokeMethod("startService");
debugPrint(data);
}
}
|
Stop Service
fun stopServices()
{
intent=Intent(this,AppService::class.java)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
stopService(intent as Intent)
}else
{
stopService(intent as Intent)
}
}
|
Now create MethodChannel Interface in MainActivity onCreate() method
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
MethodChannel(flutterEngine!!.dartExecutor.binaryMessenger,"com.example.messages")
.setMethodCallHandler{call,result->
if(call.method=="startService")
{
startService()
}
}
}
|
Step 7: call startService() in on Button click event in main dart file
Step 8: Run Application
Complete code
main.dart
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Background Service',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: BackGroundService(),
);
}
}
class BackGroundService extends StatefulWidget{
@override
State<StatefulWidget> createState() {
return BackGroundServiceState();
}
}
class BackGroundServiceState extends State<BackGroundService>{
int START_SERVICE=0;
Future<void> startService()
async {
if(Platform.isAndroid)
{
var methodChannel=MethodChannel("com.example.messages");
String data=await methodChannel.invokeMethod("startService");
debugPrint(data);
}
}
Future<void> stopService()
async {
if(Platform.isAndroid)
{
var methodChannel=MethodChannel("com.example.messages");
String data=await methodChannel.invokeMethod("stopService");
debugPrint(data);
}
}
@override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
appBar: AppBar(title: Text("Flutter Background Service"),backgroundColor: Colors.green,),
body: Center(child: MaterialButton(
onPressed:(){
if(START_SERVICE==0)
{
startService();
setState(() {
START_SERVICE=1;
});
}else{
stopService();
setState(() {
START_SERVICE=0;
});
}
},
color: Colors.brown,
child: Text((START_SERVICE==0)?"Start Service":"Stop Service",style: TextStyle(color: Colors.white),),
),),
);
}
}
|
MainActivity
package com.example.flutter_service
import android.content.Context
import android.content.Intent
import android.os.Build
import android.os.Bundle
import androidx.core.content.ContextCompat
import io.flutter.embedding.android.FlutterActivity
import io.flutter.plugin.common.MethodChannel
class MainActivity: FlutterActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
MethodChannel(flutterEngine!!.dartExecutor.binaryMessenger,"com.example.messages")
.setMethodCallHandler{call,result->
if(call.method=="startService")
{
startService()
}
}
}
lateinit var intent:Any
fun startService()
{
intent=Intent(this,AppService::class.java)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForegroundService(intent as Intent)
}else
{
startService(intent as Intent)
}
}
override fun onDestroy() {
super.onDestroy()
//stopService(intent as Intent)
}
}
|
Tags: Flutter Background Services, Background Services in Flutter, Flutter Notifications, How to run Foreground service in flutter
Article Contributed By :
|
|
|
|
29855 Views |