53

I would like to make my Flutter application to run always in background. With android, we have to create a Service that runs always in background. I don't find something about Services in the Flutter documentation.

Is it possible to do this kind of things with Flutter?

camilleB
  • 1,961
  • 4
  • 15
  • 20

5 Answers5

28

There isn't a way to do this directly from flutter right now although that may change at some point - see this bug/feature request. You do have a couple of options though.

The first is to use MethodChannels and simply write the android code you want to create a background service (or if you want it to always be a background service you can probably do that without needing communication from the flutter side).

The second is some combination of these two plugins - android_alarm_manager and android_intent. But that won't help for all use-cases.

EDIT Feb 2021:

Flutter now supports running background processes. See this page for details.

rmtmckenzie
  • 37,718
  • 9
  • 112
  • 99
  • If I understand well, MethodChannels enables just to send information from Android to Flutter but not the other way? – camilleB May 03 '18 at 19:34
  • 1
    You can use a Method Channel to send information to Android and also to receive information - you just have to [set the method call handler](https://docs.flutter.io/flutter/services/MethodChannel/setMethodCallHandler.html) from the flutter side and send the message from the android side. – rmtmckenzie May 03 '18 at 19:40
  • And we have to use a Method Channel only in the MainActivity? We can't use it in a Service for example? – camilleB May 03 '18 at 20:11
  • 1
    TBH I don't know if it would work from a service - but if you can get the reference to the methodchannel over to it, I don't see why not *while the UI is open*. Once the UI is closed I have no idea what would happen. FYI though - all communication with a methodchannel must be done from the main thread. So if your service doesn't run on the main thread you'd have to make sure you switch back over before sending the message. – rmtmckenzie May 03 '18 at 20:25
  • 1
    @rmtmckenzie is there anyway to call flutter code from native android when app is minimised or killed. I tried method channel but getting PlatformException(NO_ACTIVITY, null, null) error, – Shahbaz Hashmi Aug 03 '20 at 08:35
  • @ShahbazHashmi that probably warrants a full new question, but I can tell you that if the app is killed there's no possible of running code until you have something special like an alarm, service, or possibly notification set up. However, take a look at this: https://medium.com/flutter/executing-dart-in-the-background-with-flutter-plugins-and-geofencing-2b3e40a1a124 – rmtmckenzie Aug 04 '20 at 23:44
  • @rmtmckenzie thanks. I tried alarm manger, but still its not working. Can you answer my question over https://stackoverflow.com/questions/63228013/how-to-use-flutter-method-channel-in-background-app-minimised-closed – Shahbaz Hashmi Aug 05 '20 at 07:32
  • MethodChannel is available also for ios? – dam034 Aug 16 '20 at 13:32
  • @dam034 yes, if you look at the [link in the post](https://flutter.dev/docs/development/platform-integration/platform-channels#step-4-add-an-ios-platform-specific-implementation) it's right in there. – rmtmckenzie Aug 18 '20 at 06:57
10
  • create new Flutter project.
    • create BroadcastReceiver class beside MainActivity in android dir.
    • change MainActivity.java and main.dart and AndroidManifest.xml like this

MyReceiver

    package com.example.flutter_broadcastreceiver_alarmmanager_repeat;
    import android.content.BroadcastReceiver;
    import android.content.Context;
    import android.content.Intent;
    public class MyReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            MainActivity.callFlutter();
        }
    }

MainActivity

package com.example.flutter_broadcastreceiver_alarmmanager_repeat;

import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Intent;
import android.os.Bundle;
import io.flutter.app.FlutterActivity;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugins.GeneratedPluginRegistrant;
import io.flutter.view.FlutterView;

public class MainActivity extends FlutterActivity {

    private PendingIntent pendingIntent;
    private AlarmManager alarmManager;
    private static  FlutterView flutterView;
    private static final String CHANNEL = "com.tarazgroup";

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        flutterView=getFlutterView();
        GeneratedPluginRegistrant.registerWith(this);

        Intent intent = new Intent(this, MyReceiver.class);
        pendingIntent = PendingIntent.getBroadcast(this, 1019662, intent, 0);
        alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
        alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 1000, pendingIntent);

    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        alarmManager.cancel(pendingIntent);
    }

    static void callFlutter(){
        MethodChannel methodChannel=new MethodChannel(flutterView, CHANNEL);
        methodChannel.invokeMethod("I say hello every minute!!","");
    }
}

main.dart

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key}) : super(key: key);

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {

  static const methodChannel = const MethodChannel('com.tarazgroup');

  _MyHomePageState() {
    methodChannel.setMethodCallHandler((call) {
      print(call.method);
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
      ),
      body: Container() 
    );
  }
}

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.flutter_broadcastreceiver_alarmmanager_repeat">

    <application
        android:name="io.flutter.app.FlutterApplication"
        android:icon="@mipmap/ic_launcher"
        android:label="flutter_broadcastreceiver_alarmmanager_repeat">
        <activity
            android:name=".MainActivity"
            android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
            android:hardwareAccelerated="true"
            android:launchMode="singleTop"
            android:theme="@style/LaunchTheme"
            android:windowSoftInputMode="adjustResize">

            <meta-data
                android:name="io.flutter.app.android.SplashScreenUntilFirstFrame"
                android:value="true" />

            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <receiver android:name=".MyReceiver"></receiver>

    </application>

</manifest>

your flutter code calls avery 1 min. even your app minimized or switch to another app or screen off.

geeekfa
  • 1,169
  • 1
  • 10
  • 15
  • 1
    Background services will be throttled to checks every 15 minutes. If I use the code above, will the os also throttled to 15 min if the app is in background to save the battery? – Şükriye Jun 04 '19 at 11:34
  • unfortunately yes.maybe 15 min or less or more , depends on your android os.if your app went to DOZE Mode . there is no certain conditions for running background services. – geeekfa Jun 19 '19 at 13:30
  • 3
    Hey, is there a way to periodically run some code (and generate notification) even when the flutter app gets killed? – Abhishek Mehandiratta Jul 21 '19 at 05:03
  • @geeekfa how do we do it for ios? – BIS Tech Nov 01 '20 at 04:16
  • @AbhishekMehandiratta To generate Notification, you can use push notification service like firebase cloud messaging (FCM). Which can generate notification even if your app is killed – Krunal Sonparate Jan 03 '21 at 18:50
  • @KrunalSonparate FCM is banned for some countries like IRAN , unfortunately – geeekfa Jan 11 '21 at 17:52
  • @AbhishekMehandiratta Did you find any way out of this problem??? – Ismail Shah Oct 26 '21 at 17:00
6

This is a library to do just that background_fetch.

Background Fetch is a very simple plugin which will awaken an app in the background about every 15 minutes, providing a short period of background running-time. This plugin will execute your provided callbackFn whenever a background-fetch event occurs. ref

CircleOnCircles
  • 3,646
  • 1
  • 25
  • 30
5

flutter_background_service combined with Timer from dart:async.

see :

0

Is it possible to do this kind of things with Flutter?

Yes, now the dart can run in the background by running the flutter engine within the native android service component. (original link)

NOTE: you cannot replace the native service component provided by android. Instead, you have to run the flutter engine within that service component.

You can manually do this as in this article : Article link

Or

You can use third-party packages, like work manager plugin

dilshan
  • 2,045
  • 20
  • 18