Flutter Background/Foreground service - How to Run Background Task?

Last updated Jul 22, 2021

In 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!

 

Flutter Background Service

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 :
https://www.rrtutors.com/site_assets/profile/assets/img/avataaars.svg

29136 Views