Skip to content

Instantly share code, notes, and snippets.

@ivanburlakov
Last active July 17, 2021 14:56
Show Gist options
  • Save ivanburlakov/19b95fc3586967719defa34a1d21fb1b to your computer and use it in GitHub Desktop.
Save ivanburlakov/19b95fc3586967719defa34a1d21fb1b to your computer and use it in GitHub Desktop.
Flutter Android Foreground Example
<manifest ...>
// add following line
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<application
...
// add following line
<service android:name=".ExampleService" />
</application>
</manifest>
// change 'flutter_foreground_example' to your app name
package com.example.flutter_foreground_example
import androidx.annotation.RequiresApi
import android.content.Context
import android.graphics.Color
import android.app.Notification
import android.app.NotificationManager
import android.app.NotificationChannel
import android.app.Service
import android.content.Intent
import android.os.Build
import android.os.IBinder
import androidx.core.app.NotificationCompat
import java.util.Timer
import java.util.TimerTask
class ExampleService : Service() {
val notificationId = 1
var serviceRunning = false
lateinit var builder: NotificationCompat.Builder
lateinit var channel: NotificationChannel
lateinit var manager: NotificationManager
override fun onCreate() {
super.onCreate()
startForeground()
serviceRunning = true
Timer().schedule(object : TimerTask() {
override fun run() {
if (serviceRunning == true) {
updateNotification("I got updated!")
}
}
}, 5000)
}
override fun onDestroy() {
super.onDestroy()
serviceRunning = false
}
@RequiresApi(Build.VERSION_CODES.O)
private fun createNotificationChannel(channelId: String, channelName: String): String {
channel = NotificationChannel(channelId,
channelName, NotificationManager.IMPORTANCE_NONE)
channel.lightColor = Color.BLUE
channel.lockscreenVisibility = Notification.VISIBILITY_PRIVATE
manager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
manager.createNotificationChannel(channel)
return channelId
}
private fun startForeground() {
val channelId =
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
createNotificationChannel("example_service", "Example Service")
} else {
// If earlier version channel ID is not used
// https://developer.android.com/reference/android/support/v4/app/NotificationCompat.Builder.html#NotificationCompat.Builder(android.content.Context)
""
}
builder = NotificationCompat.Builder(this, channelId)
builder
.setOngoing(true)
.setOnlyAlertOnce(true)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle("Example Service")
.setContentText("Example Serivce is running")
.setCategory(Notification.CATEGORY_SERVICE)
startForeground(1, builder.build())
}
private fun updateNotification(text: String) {
builder
.setContentText(text)
manager.notify(notificationId, builder.build());
}
override fun onBind(intent: Intent): IBinder? {
return null
}
}
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'dart:async';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Foreground Example',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Foreground Example Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
static const platform = const MethodChannel('example_service');
String _serverState = 'Did not make the call yet';
Future<void> _startService() async {
try {
final result = await platform.invokeMethod('startExampleService');
setState(() {
_serverState = result;
});
} on PlatformException catch (e) {
print("Failed to invoke method: '${e.message}'.");
}
}
Future<void> _stopService() async {
try {
final result = await platform.invokeMethod('stopExampleService');
setState(() {
_serverState = result;
});
} on PlatformException catch (e) {
print("Failed to invoke method: '${e.message}'.");
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
children: [
Text(_serverState),
ElevatedButton(
child: Text('Start Service'),
onPressed: _startService,
),
ElevatedButton(
child: Text('Stop Service'),
onPressed: _stopService,
),
],
),
),
);
}
}
// change 'flutter_foreground_example' to your app name
package com.example.flutter_foreground_example
import android.content.Intent
import androidx.annotation.NonNull
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugins.GeneratedPluginRegistrant
class MainActivity : FlutterActivity() {
private val CHANNEL = "example_service"
override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler {
// Note: this method is invoked on the main thread.
call, result ->
when (call.method) {
"startExampleService" -> {
startService(Intent(this, ExampleService::class.java))
result.success("Started!")
}
"stopExampleService" -> {
stopService(Intent(this, ExampleService::class.java))
result.success("Stopped!")
}
else -> {
result.notImplemented()
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment