im trying to make an alert screen in the phones lockscreen. im currently using flutter_local_notifications to try and run the screen on fullscreen intent and route to another screen. the problem im having is in the firebasemessaging onbackgroundmessage, as i try to run the methodchannel in the onbackgroundmessage it gives me this error MissingPluginException(No implementation found for method turnScreenOnAndKeyguardOff on channel com.example.myapp/actions) ive been trying lots of ways also for the routing tried with flutter local notifications use didnotificaitonlaunchapp and i want didnotificaitonopenapp.
so the questions are: 1.how can i run in the onbackgroundmessage a methodchannel and invoke a function in mainactivity.kt 2.how can i route from if message recieved.
thanks in advance!
this is my code:
main.dart:
FlutterLocalNotificationsPlugin notificationsPlugin =
FlutterLocalNotificationsPlugin();
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
await FirebaseAuthImpl().signInAnonymously();
FirebaseAlert().initNotifications();
runApp(
const App(),
);
}
firebase_alert.dart:
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:alarmplayer/alarmplayer.dart';
import 'package:flutter/services.dart';
import 'package:myapp/services/notification_service.dart';
Future<void> handleBackgroundMessage(RemoteMessage message) async {
await Firebase.initializeApp();
print('Title : ${message.notification?.title}');
print('Body : ${message.notification?.body}');
print('Payload : ${message.data}');
Future<void> playAudio(String soundName) async {
Alarmplayer alarmplayer = Alarmplayer();
bool playing = false;
void switchPlaying() {
playing = !playing;
}
try {
await alarmplayer.Alarm(
url: "assets/sounds/$soundName.wav",
volume: 1,
looping: false,
callback: switchPlaying,
);
} catch (e) {
print('Error playing sound: $e');
}
}
if (message.data.containsKey('alert_type_name')) {
final String alertTypeName = message.data['alert_type_name'];
print('Alert Type: $alertTypeName');
}
if (message.data.containsKey("alert_type_name")) {
final String alertTypeName = message.data["alert_type_name"];
// await playAudio(alertTypeName);
}
await futureShowNotification();
}
class FirebaseAlert {
Future<void> initNotifications() async {
FirebaseMessaging firebaseMessaging = FirebaseMessaging.instance;
await firebaseMessaging.requestPermission(
alert: true,
announcement: false,
badge: true,
carPlay: true,
criticalAlert: true,
provisional: false,
sound: true,
);
FirebaseMessaging.onBackgroundMessage(handleBackgroundMessage);
final fCMToken = await firebaseMessaging.getToken();
print('token: $fCMToken');
}
}
notification_service.dart:
import 'package:flutter/services.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:myapp/main.dart';
Future<void> initNotifications() async {
AndroidInitializationSettings initializationSettingsAndroid =
const AndroidInitializationSettings("darohicon");
var initializationSettingsIOS = const DarwinInitializationSettings(
requestAlertPermission: true,
requestBadgePermission: true,
requestCriticalPermission: true,
requestProvisionalPermission: true,
requestSoundPermission: true
);
var initializationSettings = InitializationSettings(
android: initializationSettingsAndroid,
iOS: initializationSettingsIOS
);
await notificationsPlugin.initialize(initializationSettings,onDidReceiveBackgroundNotificationResponse:(NotificationResponse notificationResponse) async {
});
}
notificationDetails(){
return const NotificationDetails(
android: AndroidNotificationDetails("high_importance_channel", "High Importance Notifications",icon:"@mipmap/darohicon",importance: Importance.max,fullScreenIntent: true),
iOS: DarwinNotificationDetails()
);
}
Future<void> futureShowNotification({
int id = 0, String? title, String? body, String? payload
}) async {
MethodChannel platform = await const MethodChannel('com.example.myapp/actions');
await _turnScreenOnAndKeyguardOff(platform);
// The screen-related action is complete at this point
// Perform other tasks
notificationsPlugin.cancelAll();
return notificationsPlugin.show(id, title, body, await notificationDetails());
}
Future<void> _turnScreenOnAndKeyguardOff(MethodChannel platform) async {
try {
await platform.invokeMethod('turnScreenOnAndKeyguardOff');
} on PlatformException catch (e) {
print("Error: ${e.message}");
}
}
Future<void> _restoreDefaultFlags(MethodChannel platform) async {
try {
await platform.invokeMethod('restoreDefaultFlags');
} on PlatformException catch (e) {
print("Error: ${e.message}");
}
}
mainActivity.kt
package com.example.myapp
import android.content.Context
import android.os.Build
import android.os.Bundle
import android.view.WindowManager
import android.app.KeyguardManager
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugins.firebase.messaging.FlutterFirebaseMessagingPlugin
class MainActivity : io.flutter.embedding.android.FlutterActivity() {
private val CHANNEL = "com.example.myapp/actions"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
flutterEngine?.plugins?.add(FlutterFirebaseMessagingPlugin())
}
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL)
.setMethodCallHandler { call, result ->
when (call.method) {
"turnScreenOnAndKeyguardOff" -> {
turnScreenOnAndKeyguardOff()
result.success(null)
}
"restoreDefaultFlags" -> {
restoreDefaultFlags()
result.success(null)
}
else -> result.notImplemented()
}
}
}
private fun turnScreenOnAndKeyguardOff() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
setShowWhenLocked(true)
setTurnScreenOn(true)
} else {
window.addFlags(
WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
or WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON
)
}
with(getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
requestDismissKeyguard(this@MainActivity, null)
}
}
}
private fun restoreDefaultFlags() {
// Remove the flags that were set in turnScreenOnAndKeyguardOff
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
setShowWhenLocked(false)
setTurnScreenOn(false)
} else {
window.clearFlags(
WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
or WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON
)
}
}
}
for the fullscreenintent notification i tried onbackgroundmessage with methodchannel, tried to get context in the function but it did not work. i think all did not work because its a static function unless im wrong.
for the routing i tried from the firebasemessaging plugin : onintialmessage, onmessage, onbackgroundmessage, from flutter_local_notifications : ondidlaunchapp