2022年7月21日星期四

Local Notification with Sound

Caution: 

1. Android in Debug Mode has no sound!!! in build mode has sound

2. For Android 8.0+, sounds and vibrations are associated with notification channels and can only be configured when they are first created. Showing/scheduling a notification will create a channel with the specified id if it doesn't exist already. If another notification specifies the same channel id but tries to specify another sound or vibration pattern then nothing occurs.

Custom sound path:

flutter_app_name > android > app > src > res > raw > slow_spring_board.mp3

 // Method 1

Future _showNotificationWithSound() async {
var androidPlatformChannelSpecifics = new AndroidNotificationDetails(
'your channel id', 'your channel name', 'your channel description',
sound: 'slow_spring_board',
importance: Importance.Max,
priority: Priority.High);
var iOSPlatformChannelSpecifics =
new IOSNotificationDetails(sound: "slow_spring_board.aiff");
var platformChannelSpecifics = new NotificationDetails(
androidPlatformChannelSpecifics, iOSPlatformChannelSpecifics);
await flutterLocalNotificationsPlugin.show(
0,
'New Post',
'How to Show Notification in Flutter',
platformChannelSpecifics,
payload: 'Custom_Sound',
);
}
// Method 2
Future _showNotificationWithDefaultSound() 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(
androidPlatformChannelSpecifics, iOSPlatformChannelSpecifics);
await flutterLocalNotificationsPlugin.show(
0,
'New Post',
'How to Show Notification in Flutter',
platformChannelSpecifics,
payload: 'Default_Sound',
);
}

flutter_launcher_icons

pubspec.yaml


dependencies:

  flutter:

    sdk: flutter

  flutter_launcher_icons: ^0.9.3


flutter_icons:

 image_path: "assets/icon.png"

 android: true

 ios: true


Perfect. Now you can run flutter pub get to get and update all mentioned dependencies in pubspec.yaml. The next step is to run the command.

flutter pub run flutter_launcher_icons:main 


======================

if have error:

Adding
flutter.minSdkVersion=21
to android/local.properties solved the issue for me.

See

https://github.com/fluttercommunity/flutter_launcher_icons/blob/master/lib/android.dart

which calls
getMinSdkFromFile(androidGradleFile)

[iOS] Sound not working in iPhone Simulator?

 On your Mac, go to System Preferences > Sound > Sound Effects and then uncheck and recheck "Play user interface sound effects".

You need to re-activate your system sounds, see the end of this page.

DateTime to TZDateTime

import 'package:timezone/data/latest.dart' as tz;

import 'package:timezone/timezone.dart' as tz;


tz.TZDateTime.from(

          DateTime(2022, 7, 21, 17, 41),

          tz.local,

        ) 

Local Notification with Schedule (specific datetime)

//Even if you kill the app will work at Android & iOS

 import 'dart:async';

import 'package:flutter/material.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:timezone/data/latest.dart' as tz;
import 'package:timezone/timezone.dart' as tz;

void main() {
runApp(
new MaterialApp(home: MyApp()),
);
}

class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
late FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin;

@override
initState() {
super.initState();
// initialise the plugin. app_icon needs to be a added as a drawable resource to the Android head project
// If you have skipped STEP 3 then change app_icon to @mipmap/ic_launcher
var initializationSettingsAndroid =
const AndroidInitializationSettings('icon');
var initializationSettingsIOS = IOSInitializationSettings();
var initializationSettings = InitializationSettings(
android: initializationSettingsAndroid, iOS: initializationSettingsIOS);
flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
flutterLocalNotificationsPlugin.initialize(initializationSettings,
onSelectNotification: onSelectNotification);
//initialize timezone package here
tz.initializeTimeZones(); // <----
}

Future _showNotificationWithoutSound() async {
var androidPlatformChannelSpecifics = const AndroidNotificationDetails(
'channel id', 'channel name',
playSound: false, importance: Importance.max, priority: Priority.high);
var iOSPlatformChannelSpecifics =
IOSNotificationDetails(presentSound: false);
var platformChannelSpecifics = NotificationDetails(
android: androidPlatformChannelSpecifics,
iOS: iOSPlatformChannelSpecifics);
await flutterLocalNotificationsPlugin.show(
0,
'Title',
'Content',
platformChannelSpecifics,
payload: 'No_Sound',
);
}

Future setSchedule() async {
var androidPlatformChannelSpecifics = const AndroidNotificationDetails(
'channel id', 'channel name',
playSound: false, importance: Importance.max, priority: Priority.high);
var iOSPlatformChannelSpecifics =
IOSNotificationDetails(presentSound: false);
var platformChannelSpecifics = NotificationDetails(
android: androidPlatformChannelSpecifics,
iOS: iOSPlatformChannelSpecifics);
await flutterLocalNotificationsPlugin.zonedSchedule(
1,
"Notification Title",
"zonedSchedule",
//tz.TZDateTime.now(tz.local).add(const Duration(seconds: 5)),
tz.TZDateTime.from(
DateTime(2022, 7, 21, 17, 41),
tz.local,
),
platformChannelSpecifics,
androidAllowWhileIdle: true,
uiLocalNotificationDateInterpretation:
UILocalNotificationDateInterpretation.absoluteTime);
}

@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Plugin example app'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
RaisedButton(
onPressed: _showNotificationWithoutSound,
child: Text('Show Notification Without Sound'),
),
RaisedButton(
onPressed: setSchedule,
child: Text('set Schedule'),
),
],
),
),
),
);
}

void onSelectNotification(String? payload) async {
// when pressed the notification
showDialog(
context: context,
builder: (_) {
return new AlertDialog(
title: Text("PayLoad"),
content: Text("Payload : $payload"),
);
},
);
}
}

Local Notification with Schedule (5 seconds)

//Even if you kill the app will work at Android & iOS

 import 'dart:async';

import 'package:flutter/material.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:timezone/data/latest.dart' as tz;
import 'package:timezone/timezone.dart' as tz;

void main() {
runApp(
new MaterialApp(home: MyApp()),
);
}

class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
late FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin;

@override
initState() {
super.initState();
// initialise the plugin. app_icon needs to be a added as a drawable resource to the Android head project
// If you have skipped STEP 3 then change app_icon to @mipmap/ic_launcher
var initializationSettingsAndroid =
const AndroidInitializationSettings('icon');
var initializationSettingsIOS = IOSInitializationSettings();
var initializationSettings = InitializationSettings(
android: initializationSettingsAndroid, iOS: initializationSettingsIOS);
flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
flutterLocalNotificationsPlugin.initialize(initializationSettings,
onSelectNotification: onSelectNotification);
//initialize timezone package here
tz.initializeTimeZones(); // <----
}

Future _showNotificationWithoutSound() async {
var androidPlatformChannelSpecifics = const AndroidNotificationDetails(
'channel id', 'channel name',
playSound: false, importance: Importance.max, priority: Priority.high);
var iOSPlatformChannelSpecifics =
IOSNotificationDetails(presentSound: false);
var platformChannelSpecifics = NotificationDetails(
android: androidPlatformChannelSpecifics,
iOS: iOSPlatformChannelSpecifics);
await flutterLocalNotificationsPlugin.show(
0,
'Title',
'Content',
platformChannelSpecifics,
payload: 'No_Sound',
);
}

Future setSchedule() async {
var androidPlatformChannelSpecifics = const AndroidNotificationDetails(
'channel id', 'channel name',
playSound: false, importance: Importance.max, priority: Priority.high);
var iOSPlatformChannelSpecifics =
IOSNotificationDetails(presentSound: false);
var platformChannelSpecifics = NotificationDetails(
android: androidPlatformChannelSpecifics,
iOS: iOSPlatformChannelSpecifics);
await flutterLocalNotificationsPlugin.zonedSchedule(
1,
"Notification Title",
"zonedSchedule",
tz.TZDateTime.now(tz.local).add(const Duration(seconds: 5)),
platformChannelSpecifics,
androidAllowWhileIdle: true,
uiLocalNotificationDateInterpretation:
UILocalNotificationDateInterpretation.absoluteTime);
}

@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Plugin example app'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
RaisedButton(
onPressed: _showNotificationWithoutSound,
child: Text('Show Notification Without Sound'),
),
RaisedButton(
onPressed: setSchedule,
child: Text('set Schedule'),
),
],
),
),
),
);
}

void onSelectNotification(String? payload) async {
// when pressed the notification
showDialog(
context: context,
builder: (_) {
return new AlertDialog(
title: Text("PayLoad"),
content: Text("Payload : $payload"),
);
},
);
}
}

Local Notification Code

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';

void main() {
runApp(
new MaterialApp(home: MyApp()),
);
}

class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
late FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin;

@override
initState() {
super.initState();
// initialise the plugin. app_icon needs to be a added as a drawable resource to the Android head project
// If you have skipped STEP 3 then change app_icon to @mipmap/ic_launcher
var initializationSettingsAndroid =
const AndroidInitializationSettings('icon');
var initializationSettingsIOS = IOSInitializationSettings();
var initializationSettings = InitializationSettings(
android: initializationSettingsAndroid, iOS: initializationSettingsIOS);
flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
//flutterLocalNotificationsPlugin.initialize(initializationSettings, onSelectNotification);
flutterLocalNotificationsPlugin.initialize(initializationSettings,
onSelectNotification: onSelectNotification);
}

Future _showNotificationWithoutSound() async {
var androidPlatformChannelSpecifics = const AndroidNotificationDetails(
'channel id', 'channel name',
playSound: false, importance: Importance.max, priority: Priority.high);
var iOSPlatformChannelSpecifics =
IOSNotificationDetails(presentSound: false);
var platformChannelSpecifics = NotificationDetails(
android: androidPlatformChannelSpecifics,
iOS: iOSPlatformChannelSpecifics);
await flutterLocalNotificationsPlugin.show(
0,
'Title',
'Content',
platformChannelSpecifics,
payload: 'No_Sound',
);
}

@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Plugin example app'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
RaisedButton(
onPressed: _showNotificationWithoutSound,
child: Text('Show Notification Without Sound'),
),
],
),
),
),
);
}

void onSelectNotification(String? payload) async { // when pressed the notification
showDialog(
context: context,
builder: (_) {
return new AlertDialog(
title: Text("PayLoad"),
content: Text("Payload : $payload"),
);
},
);
}
}

2022年7月20日星期三

Check flutter version 3up? or not

enum AuthException {

  invalidEmail('Invalid email'),

  emailAlreadyInUse('Email already in use'),

  weakPassword('Password is too weak'),

  wrongPassword('Wrong password');


  const AuthException(this.message);

  final String message;

}


//dart 2.17 only

//lower than dart 2.17 cannot compile and error

Center the children in Row with Spacer() with wrap prevent overflow


Row(

children: [
Spacer(flex: 1),
Container(width: 15,),
FaIcon(
FontAwesomeIcons.solidCheckCircle,
color: FlutterFlowTheme.of(context).primaryColor,
size: 23,
),
Container(width: 10,),
Expanded(
flex: 4,
child: Text(
'tfjftjftgjftgjfgj',
textAlign: TextAlign.left,

style: FlutterFlowTheme.of(context).bodyText1,
),
),
Spacer(flex: 1)
],
),


with wrap 
prevent overflow
flex

Container background Colors colour

 

Container(
color: Colors.blue,

2022年7月19日星期二

Container padding EdgeInsets fromLTRB

 Container(                         

padding: EdgeInsets.fromLTRB(20, 0, 20, 0),


===================

class PaddingTestRoute extends StatelessWidget {

  const PaddingTestRoute({Key? key}) : super(key: key);


  @override

  Widget build(BuildContext context) {

    return Padding(

      //上下左右各添加16像素補白

      padding: const EdgeInsets.all(16),

      child: Column(

        //顯式指定對齊方式為左對齊,排除對齊干擾

        crossAxisAlignment: CrossAxisAlignment.start,

        mainAxisSize: MainAxisSize.min,

        children: const <Widget>[

          Padding(

            //左邊添加8像素補白

            padding: EdgeInsets.only(left: 8),

            child: Text("Hello world"),

          ),

          Padding(

            //上下各添加8像素補白

            padding: EdgeInsets.symmetric(vertical: 8),

            child: Text("I am Jack"),

          ),

          Padding(

            // 分別指定四個方向的補白

            padding: EdgeInsets.fromLTRB(20, 0, 20, 20),

            child: Text("Your friend"),

          )

        ],

      ),

    );

  }

}

2022年7月3日星期日

Flutter image loading builder example

 Image.network(

/* Other code */ loadingBuilder: (context, child, loadingProgress) { if (loadingProgress == null) return child; return const Center(child: Text('Loading...')); // You can use LinearProgressIndicator, CircularProgressIndicator, or a GIF instead }, ),

2022年7月1日星期五

loop & list [ ] , map, where, reduce, every, any, for in

Create a list with loop in 1 line

 [   for ( var i in text ) Text(i.toString())  ]

----------------------------------------------------------------------------

Mapping a list

myList.map((item){

    return item * item;

  }).toList()

----------------------------------------------------------------------------

Where

List myList = ['apple','banana','cat','dog','egg','face','good'];

var result = myList.where((item){

  return item.contains('o');

});

print(result.toList());  //[dog, good]

----------------------------------------------------------------------------

Reduce example 1 - accumulate

List myList = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

int result = myList.reduce((accumulator, currentElement){

return accumulator + currentElement;

});

print(result);   // 55

----------------------------------------------------------------------------

Reduce example 2 - find max

List myList = [2,9,4,6,1,3,9,4,0,2];

int result = myList.reduce((max, currentElement){

return currentElement>max?currentElement:max;

});

print(result);   // 9

----------------------------------------------------------------------------

Every - every item < 5 ?

List myList = [3,2,1,3,2,3];

bool result = myList.every((item){

  return item < 5;

});

print(result); //true

----------------------------------------------------------------------------

Any - Is any number less than zero?

List myList = [-1, 0, 1, 2, 3, 4, 5];

bool result = myList.any((item){

  return item < 0;

});

print(result);   // true

----------------------------------------------------------------------------

for…in loop

List myList = [1, 2, 3, 4, 5];

for(int i in myList){

  print(i); //1 2 3 4 5

}