Related
I am trying to send local notification in android using flutter_local_notifications and it's working nicely. But the problem is I can not show the app custom icon in notification bar. So, could anyone please help me sharing a solution. Thanks in advance!
Here you go with code and image-
const notificationChannelId = 'fit_jerk';
const notificationId = 1;
final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();
const AndroidNotificationChannel channel = AndroidNotificationChannel(
notificationChannelId, // id
'MY FOREGROUND SERVICE', // title
description:
'This channel is used for sending daily quotation.', // description
importance: Importance.low, // importance must be at low or higher level
);
await flutterLocalNotificationsPlugin
.resolvePlatformSpecificImplementation<
AndroidFlutterLocalNotificationsPlugin>()
?.createNotificationChannel(channel);
await service.configure(
androidConfiguration: AndroidConfiguration(
onStart: onStart,
autoStart: true,
isForegroundMode: true,
notificationChannelId: notificationChannelId, // this must match with notification channel you created above.
initialNotificationTitle: 'FitJerk',
initialNotificationContent: 'Welcome to FitJerk',
foregroundServiceNotificationId: notificationId,
), iosConfiguration: IosConfiguration(),);}
await flutterLocalNotificationsPlugin.show(
notificationId,
'FitJerk',
todayQuote,
const NotificationDetails(
android: AndroidNotificationDetails(
notificationChannelId,
'MY FOREGROUND SERVICE',
icon: 'mipmap/ic_launcher',
ongoing: false,
),
),
);
I am building a Flutter app with Firebase Messaging. I am using AwesomeNotifications plugin to display the notifications.
My notifications contain the notification property, because sending data only message does not trigger the iOS if the device is rebooted.
The issue with the notification property is that it triggers flutter SDK and auto display the default notification alone with the custom notification I configured with AwesomeNotifications .
Below is my JSON code.
"message": {
"notification": {
"title": senderName,
"body": "Image Sent"
},
"token": recieverFcm,
"data": {
"name": senderName,
"body": "Image Sent",
"chatRoomId": chatRoomId,
"sender_profile_pic": senderProfilePic,
"senderUid": senderUid,
"data_type": messageType,
"image_link": message,
"click_action": "OPEN_CHAT_ROOM"
},
"android": {
"priority": "high"
},
"apns": {
"payload": {
"aps": {
"category": "OPEN_CHAT_ROOM",
"sound": "enable",
"content-available": 1,
}
}
}
}
main.dart
void main() async {
WidgetsFlutterBinding.ensureInitialized();
NotificationController _notificationController = NotificationController();
//Initialize firebase
await Firebase.initializeApp();
await _notificationController.startNotificationService();
//Listen for the Token change
FirebaseMessaging.instance.onTokenRefresh.listen((String token) {
print("New token: $token");
});
//Apply MultiProvider
runApp(MultiProvider(
providers: [
//provider lists
],
child: MyApp(),
));
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
NotificationController _notificationController = NotificationController();
_notificationController.startAwesomeNotificationlistener();
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(
textTheme: GoogleFonts.poppinsTextTheme(),
primaryColor: primaryColor,
backgroundColor: Colors.white,
scaffoldBackgroundColor: Colors.white,
accentColor: darkColor,
appBarTheme: AppBarTheme(
backgroundColor: Colors.white,
elevation: 0,
iconTheme: IconThemeData(color: Colors.black),
titleTextStyle: GoogleFonts.poppins(
fontSize: 16, color: darkColor, fontWeight: FontWeight.w500)),
textSelectionTheme: TextSelectionThemeData(cursorColor: darkColor),
outlinedButtonTheme: OutlinedButtonThemeData(style: outlineButtonStyle),
elevatedButtonTheme:
ElevatedButtonThemeData(style: elevatedButtonStyle),
),
routes: {
//Routes go here
},
home: LoadingScreen3(),
);
}
}
notification_controller.dart
class NotificationController {
///Start notification service
Future<void> startNotificationService() async {
NotificationService _notificationService = NotificationService();
await _notificationService.initializFirebaseeNotifications();
}
///Display a new notification in foreground
Future<void> displayNotification({
required String groupKey,
required String channelKey,
required String title,
required String body,
required String summary,
required NotificationLayout layout,
required bool displayOnBackground,
required bool displayOnForeground,
required String messageType,
String? clickAction,
String? chatRoomId,
String? chatMessageFrom,
}) async {
NotificationService _notificationService = NotificationService();
await _notificationService.createAwesomeNotification(
groupKey: groupKey,
channelKey: channelKey,
title: title,
body: body,
summary: summary,
layout: layout,
displayOnBackground: displayOnBackground,
displayOnForeground: displayOnForeground,
messageType: messageType,
clickAction: clickAction,
chatRoomId: chatRoomId,
chatMessageFrom: chatMessageFrom);
}
//Start awesome notification listener
void startAwesomeNotificationlistener() {
NotificationService _notificationService = NotificationService();
_notificationService.startAwesomeNotificationListener();
}
}
notification_service.dart
class NotificationService with ChangeNotifier {
FirebaseMessaging _messaging = FirebaseMessaging.instance;
///Start initializing the notification service
Future<void> initializFirebaseeNotifications() async {
FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
//Request permission for firebase messaging
NotificationSettings settings = await _messaging.requestPermission(
alert: true,
announcement: false,
badge: true,
carPlay: false,
criticalAlert: false,
provisional: false,
sound: true,
);
if (settings.authorizationStatus == AuthorizationStatus.authorized) {
print('User granted permission');
FirebaseMessaging.onMessage.listen((RemoteMessage message) async {
RemoteNotification? notification = message.notification;
AndroidNotification? android = message.notification?.android;
developer.log("REMOTE MESSAGE LISTENER");
print("REMOTE MESSAGE LISTENER");
if (message.data["data_type"] == "TEXT") {
await createAwesomeNotification(
groupKey: message.data["senderUid"],
channelKey: 'basic_channel',
title: message.data["name"],
body: message.data["body"],
summary: message.data["body"],
layout: NotificationLayout.Messaging,
displayOnBackground: true,
displayOnForeground: true,
messageType: message.data["data_type"],
clickAction: message.data["click_action"],
chatRoomId: message.data["chatRoomId"],
chatMessageFrom: message.data["senderUid"]);
} else if (message.data["data_type"] == "IMAGE") {
await createAwesomeNotification(
groupKey: message.data["senderUid"],
channelKey: 'basic_channel',
title: message.data["name"],
body: Emojis.art_framed_picture + " " + message.data["body"],
summary: message.data["body"],
layout: NotificationLayout.Messaging,
displayOnBackground: true,
displayOnForeground: true,
messageType: message.data["data_type"],
clickAction: message.data["click_action"],
chatRoomId: message.data["chatRoomId"],
chatMessageFrom: message.data["senderUid"],
);
}
});
} else {
print('User declined or has not accepted permission');
}
/// Update the iOS foreground notification presentation options to allow
/// heads up notifications.
await FirebaseMessaging.instance
.setForegroundNotificationPresentationOptions(
alert: true,
badge: true,
sound: true,
);
FirebaseMessaging.instance
.getInitialMessage()
.then((RemoteMessage? message) {
developer.log("REMOTE MESSAGE");
if (message != null) {
developer.log(message.data.toString());
}
});
// For handling notification when the app is in background
// but not terminated
FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) {
print("onMessageOpenedApp executed");
});
await initializeAwesomeNotifications();
}
//Initialize the notification display plugin
Future<void> initializeAwesomeNotifications() async {
AwesomeNotifications().initialize('resource://drawable/logo', [
NotificationChannel(
channelGroupKey: 'basic_tests',
channelKey: 'basic_channel',
channelName: 'Basic notifications',
channelDescription: 'Notification channel for basic tests',
defaultColor: Color(0xFF9D50DD),
ledColor: Colors.white,
importance: NotificationImportance.High),
]);
}
//Create and display notification
Future createAwesomeNotification({
required String groupKey,
required String channelKey,
required String title,
required String body,
required String summary,
required NotificationLayout layout,
required bool displayOnBackground,
required bool displayOnForeground,
required String messageType,
String? clickAction,
String? chatRoomId,
String? chatMessageFrom,
}) async {
await AwesomeNotifications().createNotification(
content: NotificationContent(
id: UniqueKey().hashCode,
groupKey: groupKey,
channelKey: channelKey,
title: title,
body: body,
summary: summary,
notificationLayout: layout,
displayOnBackground: displayOnBackground,
displayOnForeground: displayOnForeground,
payload: {
"messageType": messageType,
"clickAction": clickAction ?? "",
"chatRoomId": chatRoomId ?? "",
"chatMessageFrom": chatMessageFrom ?? ""
}),
);
}
//Start Awesome notification listener
void startAwesomeNotificationListener() {
AwesomeNotifications()
.actionStream
.listen((ReceivedNotification receivedNotification) {
developer.log("Notification clicked");
developer.log(receivedNotification.body ?? "no data");
});
}
}
// Declared as global, outside of any class
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
// If you're going to use other Firebase services in the background, such as Firestore,
// make sure you call `initializeApp` before using other Firebase services.
await Firebase.initializeApp();
NotificationController _notificationController = NotificationController();
developer.log("background listener called");
print("Handling a background message: ${message.data}");
RemoteNotification? notification = message.notification;
AndroidNotification? android = message.notification?.android;
// Use this method to automatically convert the push data, in case you gonna use our data standard
//AwesomeNotifications().createNotificationFromJsonData(message.data);
if (message.data['data_type'].toString().toUpperCase() == "TEXT") {
print("Handling a background message: ${message.data['data_type']}");
await _notificationController.displayNotification(
groupKey: message.data["senderUid"],
channelKey: 'basic_channel',
title: message.data["name"],
body: message.data["body"],
summary: message.data["body"], // Anything you want here
layout: NotificationLayout.Messaging,
displayOnForeground: true,
displayOnBackground: true,
messageType: message.data["data_type"],
clickAction: message.data["click_action"],
chatRoomId: message.data["chatRoomId"],
chatMessageFrom: message.data["senderUid"]);
} else if (message.data['data_type'].toString().toUpperCase() == "IMAGE") {
Future.delayed(Duration(seconds: 2));
await _notificationController.displayNotification(
groupKey: message.data["senderUid"],
channelKey: 'basic_channel',
title: message.data["name"],
body: Emojis.art_framed_picture + " " + message.data["body"],
summary: message.data["body"], // Anything you want here
layout: NotificationLayout.Messaging,
displayOnBackground: true,
displayOnForeground: true,
messageType: message.data["data_type"],
clickAction: message.data["click_action"],
chatRoomId: message.data["chatRoomId"],
chatMessageFrom: message.data["senderUid"]);
}
}
How can I fix this issue and stop showing the custom created AwesomeNotifications only?
I started Flutter exactly today.
I want to use HTML code within Android notifications.
It seems that by setting the DefaultStyleInformation argument to true, HTML can be used, but I don't know how to write the actual code.
//This is the interface provided.
/// The default Android notification style.
class DefaultStyleInformation implements StyleInformation {
/// Constructs an instance of [DefaultStyleInformation].
const DefaultStyleInformation(
this.htmlFormatContent,
this.htmlFormatTitle,
);
/// Specifies if formatting should be applied to the content through HTML
/// markup.
final bool htmlFormatContent;
/// Specifies if formatting should be applied to the title through HTML
/// markup.
final bool htmlFormatTitle;
}
The following is the code I am writing.
I feel I need help with the "//here" part.
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'dart:io';
Future<void> showBigTextNotification() async {
const styleInformation=DefaultStyleInformation(true,true);
const NotificationDetails notificationDetails =
NotificationDetails(
android: AndroidNotificationDetails(
'channel_id',
'Channel Name',
importance: Importance.max,
priority: Priority.high,
styleInformation: styleInformation
),
iOS: IOSNotificationDetails());
await flutterLocalNotificationsPlugin.show(
id,
Platform.isAndroid? '<b>'${title}'</b>': title, // here???
Platform.isAndroid? '<b>'${content}'</b>': content, // here???
payload: 'Destination Screen(Big Text Notification)');
}
thanks.
you problem is in the bigTextInformation style and some more thing are missing please use the below code which will now convert html text into regular text
Future<void> showBigTextNotification() async {
BigTextStyleInformation bigTextStyleInformation = BigTextStyleInformation(
body, htmlFormatBigText: true,
htmlFormatTitle:true ,
htmlFormatContent:true ,
contentTitle: 'overridden <b>big</b> content title',
htmlFormatContentTitle: true,
summaryText: 'summary <i>text</i>',
htmlFormatSummaryText: true
);
final androidChannelSpecifics = AndroidNotificationDetails(
'your channel id',
'your channel name',
importance: Importance.max,
styleInformation: bigTextStyleInformation,
priority: Priority.high,
ongoing: true,
autoCancel: true,
);
final iOSChannelSpecifics = IOSNotificationDetails();
NotificationDetails platformChannelSpecifics = NotificationDetails(android: androidChannelSpecifics, iOS: iOSChannelSpecifics);
await flutterLocalNotificationsPlugin.show(
id,
Platform.isAndroid? '<b>'${title}'</b>': title, // here???
Platform.isAndroid? '<b>'${content}'</b>': content, // here???
type: platformChannelSpecifics,
payload: 'Destination Screen(Big Text Notification)');
}
Simply use BigTextStyleInformation to show html content in notifications
flutterLocalNotificationsPlugin.show(
notification.hashCode,
notification.title,
'',
NotificationDetails(
android: AndroidNotificationDetails(
channel.id,
channel.name,
channelDescription: channel.description,
importance: Importance.high,
styleInformation: BigTextStyleInformation(
'<b>Your</b> notification',
htmlFormatBigText: true,
),
),
),
payload: jsonEncode(message.data),
);
I'm stuck. My notification in the background show twice. But in the foreground only one notification. This is my code
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
// If you're going to use other Firebase services in the background, such as Firestore,
// make sure you call `initializeApp` before using other Firebase services.
await Firebase.initializeApp();
if(
!AwesomeStringUtils.isNullOrEmpty(message.notification?.title, considerWhiteSpaceAsEmpty: true) ||
!AwesomeStringUtils.isNullOrEmpty(message.notification?.body, considerWhiteSpaceAsEmpty: true)
){
// print('message also contained a notification: ${message.notification.body}');
String imageUrl;
imageUrl ??= message.notification.android?.imageUrl;
imageUrl ??= message.notification.apple?.imageUrl;
print(imageUrl);
if(imageUrl == null){
var id = Random().nextInt(2147483647);
await AwesomeNotifications().createNotification(
content: NotificationContent(
id: id,
title: message.notification.title,
body: message.notification.body,
color: Colors.orange,
customSound: 'resource://raw/alert',
notificationLayout: NotificationLayout.BigText,
channelKey: 'basic_channel_background',
payload: {'data':message.data['payload']}
),
actionButtons: [
NotificationActionButton(
label: 'Lihat Selengkapnya',
enabled: true,
buttonType: ActionButtonType.Default,
key: 'background',
)
]
);
}else{
await AwesomeNotifications().createNotification(
content: NotificationContent(
id: Random().nextInt(2147483647),
title: message.notification.title,
body: message.notification.body,
bigPicture: imageUrl,
color: Colors.orange,
customSound: 'resource://raw/alert',
notificationLayout: NotificationLayout.BigPicture,
channelKey: 'basic_channel_background',
payload: {'data':message.data['payload']}
),
actionButtons: [
NotificationActionButton(
label: 'Lihat Selengkapnya',
enabled: true,
buttonType: ActionButtonType.Default,
key: 'background',
)
]
);
}
}
}
// End Background Message
and this is my foreground code
// Foreground Apps
Future<void> main() async{
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
if (!kIsWeb) {
await FirebaseMessaging.instance
.setForegroundNotificationPresentationOptions(
alert: true,
badge: true,
sound: true,
);
await AwesomeNotifications().initialize(
'resource://mipmap/launcher_icon',
[
NotificationChannel(
channelGroupKey: 'basic_tests',
channelKey: 'basic_channel',
channelName: 'My Cahaya Notification',
channelDescription: 'Notification channel for basic tests',
icon: 'resource://mipmap/launcher_icon',
importance: NotificationImportance.High,
playSound: true,
soundSource: 'resource://raw/alert'
),
NotificationChannel(
channelGroupKey: 'basic_background',
channelKey: 'basic_channel_background',
channelName: 'My Cahaya Notification Background',
channelDescription: 'Notification channel for basic tests',
icon: 'resource://mipmap/launcher_icon',
importance: NotificationImportance.High,
playSound: true,
soundSource: 'resource://raw/alert'
),
], debug: true);
AwesomeNotifications().actionStream.listen((event) async{
print('event received!');
var data = event.toMap();
if(data['buttonKeyPressed'] == "background"){
SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.setString("Navigate", data['payload']['data']);
}else{
_navigateToItemForeground(data['payload']['data']);
}
// do something based on event...
// AwesomeNotifications().actionSink.close();
});
}
FirebaseMessaging.onMessage.listen((RemoteMessage message) async{
RemoteNotification notification = message.notification;
AndroidNotification android = message.notification?.android;
if (notification != null && android != null && !kIsWeb) {
if(!AwesomeStringUtils.isNullOrEmpty(message.notification?.title, considerWhiteSpaceAsEmpty: true) ||
!AwesomeStringUtils.isNullOrEmpty(message.notification?.body, considerWhiteSpaceAsEmpty: true)){
print("something");
String imageUrl;
imageUrl ??= notification.android?.imageUrl;
imageUrl ??= notification.apple?.imageUrl;
if(imageUrl == null){
await AwesomeNotifications().createNotification(
content: NotificationContent(
id: Random().nextInt(2147483647),
title: notification.title,
body: notification.body,
color: Colors.orange,
customSound: 'resource://raw/alert',
notificationLayout: NotificationLayout.BigText,
channelKey: 'basic_channel',
payload: {'data':message.data['payload']}
),
actionButtons: [
NotificationActionButton(
label: 'Lihat Selengkapnya',
enabled: true,
buttonType: ActionButtonType.Default,
key: 'test',
)
]
);
}else{
await AwesomeNotifications().createNotification(
content: NotificationContent(
id: Random().nextInt(2147483647),
title: notification.title,
body: notification.body,
bigPicture: imageUrl,
color: Colors.orange,
customSound: 'resource://raw/alert',
notificationLayout: NotificationLayout.BigPicture,
channelKey: 'basic_channel',
payload: {'data':message.data['payload']}
),
actionButtons: [
NotificationActionButton(
label: 'Lihat Selengkapnya',
enabled: true,
buttonType: ActionButtonType.Default,
key: 'test',
)
]
);
}
}
}
});
runApp(MyApp());
}
// End Foreground Apps
and this is my screenshot
screenshot
I've tried changing the awesome notification but the result is the same. Could you help me to solve that? I hope you can help me. Thank you very much
FCM payload
{
"to":"_some_fcm_token_",
//remove this
"notification": {
"title": "this is title",
"body": "this is subtitle"
},
"type": "post_like",
"data": {
"model":{"id":"dsaflkdskfklgdkgjdksakdk"},
"body": "this is subtitle",
"title": "this is title",
"click_action": "FLUTTER_NOTIFICATION_CLICK"
},
"priority": "normal"
}
The first one is manually created (locally), and the other one is automatic by Firebase.
When sending a message to your device, make sure it is a notification rather than data. The documentation mentions that if you send data it will likely be ignored as a push notification. Only use it to send packets of data to the app instead.
If your Notification is sent while the App is in background, Firebase
automatically sends a Push-Notification, so you don't need to call the show Notification manually in the App.
I solved the problem like this:
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
if (message.notification != null) {
//No need for showing Notification manually.
//For BackgroundMessages: Firebase automatically sends a Notification.
//If you call the flutterLocalNotificationsPlugin.show()-Methode for
//example the Notification will be displayed twice.
}
return;
}
Solved)
**{
"to":"_some_fcm_token_",
//remove this
//"notification": {
// "title": "this is title",
// "body": "this is subtitle"
},
"type": "post_like",
"data": {
"model":{"id":"dsaflkdskfklgdkgjdksakdk"},
"body": "this is subtitle",
"title": "this is title",
"click_action": "FLUTTER_NOTIFICATION_CLICK"
},
"priority": "normal"
}**
payload: Platform.isAndroid?
json.encode(message.data):json.encode(message.notification)
set payload data like this
I am trying to download an attachment for a mailing system.
To do that I am using Flutter downloader but I need to pass my token with my http client.
I think this plugin doesn't take care of it.
I have tried to do this using dio.
I can download files but I don't know how I can display the Android download indicator (cf. image)
Does somebody have any idea of a plug-in or something to display this Android indicator ?
EDIT: I finally have found a solution.
Actually, there are nothing to display the download indicator but Flutter_downloader. So I have kept this plugin and I have passed my token in headers.
Like this :
Map<String, String> requestHeaders = {
'Authorization': 'Bearer ' + http.cookie,
};
final assetsDir = documentsDirectory.path + '/';
final taskId = await FlutterDownloader.enqueue(
url: url,
savedDir: assetsDir,
fileName: attachment.name,
headers: requestHeaders,
showNotification: true, // show download progress in status bar (for Android)
openFileFromNotification: true, // click on notification to open downloaded file (for Android)
);
Sorry for my english and thanks to Ryan for the correction
One way to display download progress notification on Android with Flutter is by using flutter_local_notifications plugin. Here's a sample that you can try out.
import 'package:flutter/material.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
final flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
String selectedNotificationPayload;
class ReceivedNotification {
ReceivedNotification({
#required this.id,
#required this.title,
#required this.body,
#required this.payload,
});
final int id;
final String title;
final String body;
final String payload;
}
void main() async {
WidgetsFlutterBinding.ensureInitialized();
const AndroidInitializationSettings initializationSettingsAndroid =
AndroidInitializationSettings('#mipmap/ic_launcher');
final InitializationSettings initializationSettings = InitializationSettings(
android: initializationSettingsAndroid);
await flutterLocalNotificationsPlugin.initialize(initializationSettings,
onSelectNotification: (String payload) async {
if (payload != null) {
debugPrint('notification payload: $payload');
}
});
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Text(
'Download Progress Notification',
),
),
floatingActionButton: FloatingActionButton(
onPressed: () async {
await _showProgressNotification();
},
tooltip: 'Download Notification',
child: Icon(Icons.download_sharp),
),
);
}
Future<void> _showProgressNotification() async {
const int maxProgress = 5;
for (int i = 0; i <= maxProgress; i++) {
await Future<void>.delayed(const Duration(seconds: 1), () async {
final AndroidNotificationDetails androidPlatformChannelSpecifics =
AndroidNotificationDetails('progress channel', 'progress channel',
'progress channel description',
channelShowBadge: false,
importance: Importance.max,
priority: Priority.high,
onlyAlertOnce: true,
showProgress: true,
maxProgress: maxProgress,
progress: i);
final NotificationDetails platformChannelSpecifics =
NotificationDetails(android: androidPlatformChannelSpecifics);
await flutterLocalNotificationsPlugin.show(
0,
'progress notification title',
'progress notification body',
platformChannelSpecifics,
payload: 'item x');
});
}
}
}
Here's how the app looks like running
For Flutter_Downloader
If you are using API 29+(ANDROID 10 and Above) add the below code in AndriodManifest.xml
android:requestLegacyExternalStorage="true"
Like this
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
...........
<application
..............
<!-- Add This line -->
tools:replace="android:label"
android:requestLegacyExternalStorage="true"> <!-- Add This line if you are targeting android API 29+-->
<activity>
...............
</activity>
</application>