I want to bring an app in the background to the foreground. This link use a package that is not working and although the author has done a tremendous job it has seen no updates for 11 months.
So I am looking for a solution to bring the app in the background to the foreground or even (re)launch the app. I have spent countless hours trying different packages and none of them work, here is the list:
import 'package:bringtoforeground/bringtoforeground.dart';
import 'package:android_intent/android_intent.dart';
import 'package:flutter_appavailability/flutter_appavailability.dart';
import 'flutterIntent.dart';
flutterIntent.dart is thanks to this repository: https://github.com/sunsetjesus/flutter_intent
import 'dart:async';
import 'package:flutter/services.dart';
class FlutterIntent {
static const MethodChannel _channel = const MethodChannel('flutter_intent');
static Future<String> get platformVersion async {
final String version = await _channel.invokeMethod('getPlatformVersion');
return version;
}
static Future<void> openApp(String appId, String targetActivity) async {
await _channel.invokeMapMethod('openApp', {"appId": appId,"targetActivity": targetActivity});
}
}
Not to mention the last of solution for IOS.
I am quite astonished that there are so many good packages but there seems to be no default solution to open an app (which we can do by tapping twice on the icon...). It is very simple to start another app when coding for Windows or Linux platform so I am really amazed that it requires so much effort when it comes to mobile.
Thank you very much for any help,
PS: Actually I don't even need to bring the app back to the foreground, originally I was trying to have await launch(url); on notification received, so launching chrome/firefox/safari with the url (that I get with no problem) would be good enough in my usecase.
I solved it myself thanks to flutter local notification package, example below:
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
Future _showNotification(FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin) async {
var androidPlatformChannelSpecifics = new AndroidNotificationDetails(
'your channel id', 'your channel name', 'your channel description',
importance: Importance.max, priority: Priority.high);
var iOSPlatformChannelSpecifics = new IOSNotificationDetails();
var platformChannelSpecifics = new NotificationDetails(
android: androidPlatformChannelSpecifics, iOS: iOSPlatformChannelSpecifics);
await flutterLocalNotificationsPlugin.show(
0,
'New Notification',
'Flutter is awesome',
platformChannelSpecifics,
payload: 'This is notification detail Text...',
);
}
static FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin;
static onBackgroundMessage(SmsMessage message) async {
String encodedUrl = message.body;
debugPrint("onBackgroundMessage called $encodedUrl");
print('app available');
await _showNotification(flutterLocalNotificationsPlugin);
}
Future onSelectNotification(String payload) async {
showDialog(
context: context,
builder: (_) {
return new AlertDialog(
title: Text("Your Notification Detail"),
content: Text("Payload : $payload"),
);
},
);
}
void localNotification() {
var initializationSettingsAndroid =
new AndroidInitializationSettings('app_icon');
var initializationSettingsIOS = new IOSInitializationSettings();
var initializationSettings = new InitializationSettings(android: initializationSettingsAndroid, iOS: initializationSettingsIOS);
flutterLocalNotificationsPlugin = new FlutterLocalNotificationsPlugin();
flutterLocalNotificationsPlugin.initialize(initializationSettings,
onSelectNotification: onSelectNotification);
}
And in StatefulWidget:
#override
void initState() {
super.initState();
localNotification();
}
Related
I'm working on a communication app, and currently implementing Video and Voice calls.
I want when a notification arrives to the app, I want the app to open on specific screen.
I've done something like that by showing a notification and the app opens when user press on the notification.
But when a call arrives I want the app open without the action of the user.
I've tried to open the app with external_app_launcher but it doesn't open.
Here is the code.
Future<void> firebaseMessagingBackgroundHandler(RemoteMessage message) async {
await Firebase.initializeApp();
print('Message In background: ${message.data}');
LaunchApp.openApp(androidPackageName: "com.example.chat_app");
}
This is the code I tried to do to open the app.
And here is my old code that shows a notification(It works without any problem)
Future<void> firebaseMessagingBackgroundHandler(RemoteMessage message) async {
await Firebase.initializeApp();
print('Message In background: ${message.data}');
var initializationSettingsAndroid =
const AndroidInitializationSettings('#mipmap/ic_launcher');
var initializationSettingsIOs = const IOSInitializationSettings();
var initializationSettings = InitializationSettings(
android: initializationSettingsAndroid,
iOS: initializationSettingsIOs,
);
//when the app is in foreground state and you click on notification.
flutterLocalNotificationsPlugin.initialize(initializationSettings,
onSelectNotification: (String? payload) {
if (payload != null) {
Map<String, dynamic> data = json.decode(payload);
goToNextScreen(data, true);
}
});
flutterLocalNotificationsPlugin.show(
Random().nextInt(1000000000),
message.data['title'],
message.data["body"],
NotificationDetails(
android: AndroidNotificationDetails(channel.id, channel.name,
channelDescription: channel.description,
importance: Importance.max,
priority: Priority.high,
playSound: true,
sound: RawResourceAndroidNotificationSound("ringtone1"),
fullScreenIntent: true),
),
payload: json.encode(message.data));
}
As far as I know, it is not possible to automatically open an app on the receipt of an FCM message.
As a user, I'd probably immediately uninstall any app that does this.
I want to schedule daily notifications at a specific daytime with the android_alarm_manager_plus and the local_notifications plugins.
However, the notifications come in very irregulary. The delay of the notifications increases each consecutive day.
For example, the app should send a reminder everyday at 8:00 am. The first day, the notification comes in at around the right time. The next day, it sends it 15 minutes delayed and the following days, no notification gets send at all.
I tested this on a Motorola Moto G9 Play with Android 11 and I have deactivated the energy-saving mode and made sure that battery-optimizations are turned off for this app.
In the following I created a litte (hopefully) reproducable example:
// initializing similar to the official example
Future<FlutterLocalNotificationsPlugin> _initNotificationsPlugin() async {
FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();
const AndroidInitializationSettings initializationSettingsAndroid =
AndroidInitializationSettings('flutter_logo');
final IOSInitializationSettings initializationSettingsIOS =
IOSInitializationSettings();
final MacOSInitializationSettings initializationSettingsMacOS =
MacOSInitializationSettings();
final InitializationSettings initializationSettings = InitializationSettings(
android: initializationSettingsAndroid,
iOS: initializationSettingsIOS,
macOS: initializationSettingsMacOS);
await flutterLocalNotificationsPlugin.initialize(initializationSettings);
return flutterLocalNotificationsPlugin;
}
Future<void> scheduleNotifications() async {
int id = 0;
AndroidAlarmManager.periodic(Duration(days: 1), id, sendNotification,
exact: true,
allowWhileIdle: true,
rescheduleOnReboot: true,
wakeup: true);
log("Notifications scheduled");
}
// Top-level callback for the AndroidAlarmManager
Future<void> sendNotification() async {
FlutterLocalNotificationsPlugin flutterNotificationsPlugin =
await _initNotificationsPlugin();
await flutterNotificationsPlugin.cancelAll();
final now = DateTime.now();
int id =
now.second + now.minute * 60 + now.hour * 60 * 60; // Daytime in seconds
// Copied from the example with edited channel id, etc.
const AndroidNotificationDetails androidPlatformChannelSpecifics =
AndroidNotificationDetails(
'my very own channel id', 'my very own channel name',
channelDescription: 'my channel description',
importance: Importance.max,
priority: Priority.high,
ticker: 'ticker');
const NotificationDetails platformChannelSpecifics =
NotificationDetails(android: androidPlatformChannelSpecifics);
//
final body = "Notification sent at ${now.hour}:${now.minute}:${now.second}";
await flutterNotificationsPlugin.show(
id, "Test notification", body, platformChannelSpecifics);
log(body);
}
Future<void> cancelAllAlarmsAndNotifications() async {
await AndroidAlarmManager.cancel(0);
}
And when the user clicks a button, the following code is executed:
onPressed: () {
cancelAllAlarmsAndNotifications().then((value) {
scheduleNotifications();
});
},
Also, the main method:
void main() {
WidgetsFlutterBinding.ensureInitialized();
AndroidAlarmManager.initialize().then((value) {
runApp(const MyApp());
});
}
I really hope that you see some mistake I make that is easy fixable :)
Thanks in advance!
I am using Flutter Local Notification to trigger periodic notifications in my app.
It provides a callback, which is executed when user taps on the notification,
I want to use the callback to run a async function, but i don't want to launch the app when the user clicks on it. I simply want to dismiss the notification.
Is there any way to achieve it?
Here is my code.
var initializationSettingsAndroid =
AndroidInitializationSettings('#mipmap/ic_launcher');
var initializationSettingsIOS = IOSInitializationSettings();
var initializationSettings = InitializationSettings(
initializationSettingsAndroid, initializationSettingsIOS);
_notificationPlugin = FlutterLocalNotificationsPlugin();
_notificationPlugin.initialize(
initializationSettings,
onSelectNotification: onSelectNotification,
);
My callback function,
Future onSelectNotification(String payload) async {
showDialog(
context: context,
builder: (_) => AlertDialog(
title: Text("Hello"),
content: Text("content"),
),
);
AnAsyncFunction();
}
Notification triggering function,
Future getPeriodicNoification() async {
print("hello");
// // Show a notification every minute with the first appearance happening a minute after invoking the method
var androidPlatformChannelSpecifics = AndroidNotificationDetails(
'your channel id',
'your channel name',
'your channel description',
importance: Importance.Max,
priority: Priority.High,
);
var iOSPlatformChannelSpecifics = IOSNotificationDetails();
var platformChannelSpecifics = NotificationDetails(
androidPlatformChannelSpecifics, iOSPlatformChannelSpecifics);
await _notificationPlugin.periodicallyShow(0, 'repeating title',
'repeating body', RepeatInterval.EveryMinute, );
}
I am working on a project, I have used Flutter Local Notifications to show periodic notifications,
I'm trying to figure out if there is a way to not to launch the app on notification click, for example, when a user clicks on a notification, it should just disappear from the notification panel.
This is the code I tried so far,
Initialising,
var initializationSettingsAndroid =
AndroidInitializationSettings('#mipmap/ic_launcher');
var initializationSettingsIOS = IOSInitializationSettings();
var initializationSettings = InitializationSettings(
initializationSettingsAndroid, initializationSettingsIOS);
_notificationPlugin = FlutterLocalNotificationsPlugin();
_notificationPlugin.initialize(initializationSettings,
onSelectNotification: onSelectNotification);
Calling,
Future getPeriodicNoification() async {
print("hello");
// Show a notification every minute with the first appearance happening a minute after invoking the method
var androidPlatformChannelSpecifics = AndroidNotificationDetails(
'your channel id',
'your channel name',
'your channel description',
importance: Importance.Max,
priority: Priority.High,
);
var iOSPlatformChannelSpecifics = IOSNotificationDetails();
var platformChannelSpecifics = NotificationDetails(
androidPlatformChannelSpecifics, iOSPlatformChannelSpecifics);
await _notificationPlugin.periodicallyShow(0, 'repeating title',
'repeating body', RepeatInterval.EveryMinute, platformChannelSpecifics);
}
Callback function(On notification click)
Future onSelectNotification(String payload) async {
ThisisAnAsyncFunction();
}
Please help.
You can use the close function under BehaviourSubject that you use when adding the payload.
static final onNotifications = BehaviorSubject<String?>();
then call this when selecting the notification.
onSelectNotification() => onNotifications.close();
I need help, there's an error when calling Local Notification.
For the initState :
initState() {
super.initState();
flutterLocalNotificationsPlugin = new FlutterLocalNotificationsPlugin();
// initialise the plugin. app_icon needs to be a added as a drawable resource to the Android head project
var initializationSettingsAndroid =
new AndroidInitializationSettings('app_icon');
var initializationSettingsIOS = new IOSInitializationSettings();
var initializationSettings = new InitializationSettings(
initializationSettingsAndroid, initializationSettingsIOS);
FlutterLocalNotificationsPlugin().initialize(initializationSettings, onSelectNotification: onSelectNotification);
}
For the function :
showNotification() async {
var android = new AndroidNotificationDetails('Channel ID', 'Channel Name', 'channelDescription');
var iOS = new IOSNotificationDetails();
var platform = new NotificationDetails(android, iOS);
await flutterLocalNotificationsPlugin.show(
0, 'New Notification', 'Flutter Local Notif', platform,payload: 'test notification');
}
The error is "PlatformException (PlatformException(error, Attempt to invoke virtual method 'int java.lang.Integer.intValue()' on a null object reference, null))"
I've already tried on the documentation and also youtube, but I always get this error message
I have faced this, and in my case it was an icon problem app_icon
in your initState function replace this
var initializationSettingsAndroid = new AndroidInitializationSettings('app_icon');
with this
var initializationSettingsAndroid = new AndroidInitializationSettings('#mipmap/ic_launcher');
Hope this helps you.
Add your app_icon.png to MY_PROJECT\android\app\src\main\res\drawable\app_icon.png
However, for me the error was in androidInitialization. I was initializing it this way:
var androidInit = AndroidInitializationSettings('app_icon.png');
Here, the .png shouldn't be added. I know this might be silly but if it helps anyone out there facing the same problem then there you go! This is the correct method:
var androidInit = AndroidInitializationSettings('app_icon');
this one works for me you can give a chance
#override
initState() {
super.initState();
to the Android head project
var initializationSettingsAndroid =
AndroidInitializationSettings('app_icon');
var initializationSettingsIOS = IOSInitializationSettings(
onDidReceiveLocalNotification: onDidReceiveLocalNotification);
var initializationSettings = InitializationSettings(
initializationSettingsAndroid, initializationSettingsIOS);
flutterLocalNotificationsPlugin.initialize(initializationSettings,
onSelectNotification: onSelectNotification);
}
Future<void> _showNotification() async {
var androidPlatformChannelSpecifics = AndroidNotificationDetails(
'your channel id', 'your channel name', 'your channel description',
importance: Importance.Max, priority: Priority.High, ticker: 'ticker');
var iOSPlatformChannelSpecifics = IOSNotificationDetails();
var platformChannelSpecifics = NotificationDetails(
androidPlatformChannelSpecifics, iOSPlatformChannelSpecifics);
await flutterLocalNotificationsPlugin.show(
0, 'plain title', 'plain body', platformChannelSpecifics,
payload: 'item x');
}
Future<void> onSelectNotification(String payload) async {
if (payload != null) {
debugPrint('notification payload: ' + payload);
}
}
There is problem in your plugin initialization. I see in your code, you created the instance flutterLocalNotificationsPlugin but used FlutterLocalNotificationsPlugin().initialize() instead. And then you tried to show notification with the created instance which has not been initialized.
I got this error for the same reason - my FlutterLocalNotificationsPlugin was not initialized properly. To check if it is, I tried the below code:
void main() {
runApp(MyApp());
initializeNotification(); //Its Important to place this line after runApp() otherwise FlutterLocalNotificationsPlugin will not be initialize and you will get the error as mentioned in the question.
}
void initializeNotification() async {
try {
flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
var initializationSettingsAndroid = AndroidInitializationSettings('app_icon');
var initializationSettingsIOS = IOSInitializationSettings();
var initializationSettings = InitializationSettings(initializationSettingsAndroid, initializationSettingsIOS);
await flutterLocalNotificationsPlugin.initialize(initializationSettings, onSelectNotification: didSelectNotification);
} catch(e) {
print(e.toString());
}
}
If it catch any exception, your flutterLocalNotificationsPlugin has not been initialized, and you will get an error.
Also try to wrap initialization code in separate async-await function.
In my case, I added app_icon.png to the android drawables, in this path : MY_PROJECT\android\app\src\main\res\drawable
Take a look at the source code here
https://github.com/MaikuB/flutter_local_notifications/tree/master/flutter_local_notifications/example/android/app/src/main/res/drawable
Copy Paste all drawables to your project, it will work.
And Don't Forget to add these receivers to Manifest
<receiver android:name="com.dexterous.flutterlocalnotifications.ScheduledNotificationReceiver" />
<receiver android:name="com.dexterous.flutterlocalnotifications.ScheduledNotificationBootReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<action android:name="android.intent.action.MY_PACKAGE_REPLACED"/>
</intent-filter>
</receiver>
for me adding WidgetsFlutterBinding.ensureInitialized(); to main.dart before creating AndroidInitializationSettings helps.
uture _requestPermissions() async {
const AndroidInitializationSettings initializationSettingsAndroid =
AndroidInitializationSettings('app_icon');
/// Note: permissions aren't requested here just to demonstrate that can be
/// done later
final DarwinInitializationSettings initializationSettingsIOS =
DarwinInitializationSettings(
requestAlertPermission: false,
requestBadgePermission: false,
requestSoundPermission: false,
onDidReceiveLocalNotification: (
int id,
String? title,
String? body,
String? payload,
) async {
didReceiveLocalNotificationSubject.add(
ReceivedNotification(
id: id,
title: title,
body: body,
payload: payload,
),
);
});