Build App & Upload to store
กำลังหาข้อมูลเกี่ยวกับการ build app with signed เพื่อส่งขึ้น Play Store
ทำตามขั้นตอนในเว็บ flutter.dev
สร้าง key
keytool -genkey -v -keystore /Users/name/appname.jks -keyalg RSA -keysize 2048 -validity 10000 -alias release
Build
flutter build appbundle
ผลลัพท์ของการ build จะอยู่ที่
build/app/outputs/bundle/release/app-release.aab
ติดขั้นตอนอัพโหลดขึ้น play store
"Your Android App Bundle is signed with the wrong key. Ensure that your App Bundle is signed with the correct signing key and try again. Your App Bundle is expected to be signed with the certificate with fingerprint"
ลองหาทางแก้ไข ก็ไม่หาย แต่พอลองอัพหลายครั้ง ก็ยังขึ้น error แต่ปุ่มให้ SAVE สามารถใช้งานได้ ก็เลยผ่าน
ลองอัพ version ใหม่ ปรากฎว่า ไม่ขึ้น error
ที่มา:
เทคนิคการพ่วงแบต
1.ให้ความสำคัญที่สายพ่วงแบตฯ ต้องเส้นใหญ่ (โดยเฉพาะไส้ในต้องเป็นทองแดงเส้นใหญ่ หรือ มีจำนวนเส้นมากๆ) สายเส้นเล็กๆ ที่ขายตามห้าง หรือ ที่อื่นๆ ใช้งานจริงไม่ได้
2.เมื่อพ่วงแบตฯ ควรสตารท์ รถคันที่มาช่วย (เรียก ก) แล้วคีบสายไปรถที่ไฟหมด (เรียก ข) เริ่มที่ ขั้วบวก ก ไป ขั้วบวก ข ต่อมาที่ ลบ ก ไป ลบ ข หรือ คีบตรงเครื่องยนต์ (ส่วนที่มีขอเกี่ยวไว้ยกเครื่อง) เร่งเครื่องยนต์ รถ ก ที่ประมาณ 2000 รอบ ซักพัก (ให้ไฟเข้า) แล้วสตาร์ทรถ ข เมื่อเครื่องยนต์ติดแล้ว ให้ถอดสายพ่วงออกโดยย้อนกลับ เริ่มที่ ลบ ข ไป ลบ ก บวก ข ไป บวก ก เป็นอันจบ
หมายเหตุ 1.สีของสายพ่วงจะแบ่งเป็น แดง (ขั้วบวก) ดำ (ขั้วลบ) ห้ามต่อสลับกันเด็ดขาด ทำให้เกิดไฟช๊อต อาจทำให้ระบบ ไฟฟ้า และ ECU ในรถพังได้
2.เวลาพ่วงรถให้ใครต้องสตาร์ทรถ ก่อนพ่วงทุกครั้ง (ให้ไดร์ชาร์ทจ่ายกระแสไฟแทนหม้อแบตฯ) ป้องกันไฟกระชาก
ปล. copy เขามา
Flutter :: Package Info for About us
import 'dart:developer'; import 'package:flutter/material.dart'; import 'package:package_info/package_info.dart'; class AboutScreen extends StatefulWidget { static String routeName = "/about"; @override _AboutScreenState createState() => _AboutScreenState(); } class _AboutScreenState extends State<AboutScreen> { PackageInfo _packageInfo = PackageInfo( appName: 'Unknown', packageName: 'Unknown', version: 'Unknown', buildNumber: 'Unknown', ); //SharedPreferences.setMockInitialValues({}); @override initState() { super.initState(); _initPackageInfo(); } Future<void> _initPackageInfo() async { final PackageInfo info = await PackageInfo.fromPlatform(); log(info.toString()); setState(() { _packageInfo = info; }); } Widget _infoTile(String title, String subtitle) { return ListTile( title: Text(title), subtitle: Text(subtitle.isNotEmpty ? subtitle : 'Not set'), ); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( // title: Text(widget.title), title: Text('About us'), ), body: Column( // mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ _infoTile('App name', _packageInfo.appName), _infoTile('Package name', _packageInfo.packageName), _infoTile('App version', _packageInfo.version), _infoTile('Build number', _packageInfo.buildNumber), ], ), ); } }
ที่มา
Alumni Med Server Installation
ติดตั้ง Server ใหม่ของ Alumni Med เขียนบันทึกคำสั่งไว้สักหน่อย
sudo nano /etc/php/7.4/fpm/php.ini sudo systemctl restart apache2 sudo nano /etc/mysql/conf.d/mysqld.cnf sudo systemctl restart mysql mkdir alumni sshfs -p 22 username@example.com:/home/folder/ folder umount folder sudo apt update<br /> sudo apt upgrade sudo apt install apache2 -y systemctl status apache2 sudo a2dismod ssl sudo a2enmod ssl apt install php7.4 php7.4-mysql php-common php7.4-cli php7.4-json php7.4-common php7.4-opcache libapache2-mod-php7.4 apt install mariadb-server mariadb-client systemctl status mariadb mysql> CREATE USER 'newuser'@'localhost' IDENTIFIED BY 'password'; mysql> GRANT ALL PRIVILEGES ON * . * TO 'newuser'@'localhost'; sudo systemctl restart apache2<br /> sudo systemctl restart mysql wget -r --ask-password ftp://user:example.com/
ที่มา
Flutter Permission
iOS: in ios/Runner/Info.plist
ขอสิทธิ์ Location
<key>NSAppTransportSecurity</key> <dict> <key>NSAllowsArbitraryLoads</key><true/> </dict>
ขอสิทธิ์ใช้กล้อง
<key>NSCameraUsageDescription</key> <string>Explanation on why the camera access is needed.</string>
ขอสิทธิ์ไมโครโฟน
<key>NSMicrophoneUsageDescription</key> <string>Flutter requires acess to microphone.</string>
Android: android/app/build.gradle
defaultConfig { minSdkVersion 21
Android: android/app/src/main/AndroidManifest.xml
<application> <provider android:name="com.pichillilorenzo.flutterinappwebview.InAppWebViewFileProvider" android:authorities="${applicationId}.flutterinappwebview.fileprovider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILEPROVIDERPATHS" android:resource="@xml/provider_paths" /> </provider> </application>
Create file res/values/provider_paths.xml
<?xml version="1.0" encoding="utf-8"?> <paths> </paths>
main.dart
import 'package:permission_handler/permission_handler.dart'; Future main() async { WidgetsFlutterBinding.ensureInitialized(); await Permission.camera.request(); runApp(MyApp()); }
สิทธิ์อื่นดูได้จาก Enable camera for HTML inputs
ที่มา
Flutter App Lifecycle
Step 1. Create a new application. The main screen in which will be StatefulWidget. Which should implement the WidgetsBindingObserver interface. Next, we get the instance of WidgetBinding and add an observer to it.
class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', theme: ThemeData( primarySwatch: Colors.blue, ), home: MyHomePage(), ); } } class MyHomePage extends StatefulWidget { @override _MyHomePageState createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> with WidgetsBindingObserver { @override void initState() { WidgetsBinding.instance.addObserver(this); super.initState(); } @override void dispose() { WidgetsBinding.instance.removeObserver(this); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Flutter Tutorial Lifecycle'), ), body: Center(), ); } }
Step 2. Now we have the didChangeAppLifecycleState method available. In this example, we simply print a state change to the thermal.
@override void didChangeAppLifecycleState(AppLifecycleState state) { print('state = $state'); }
ที่มา Flutter App Lifecycle
My First Flutter App
เขียน Flutter App
Create new app
flutter create --org com.yourdomain appname
Set App signing team to your email
Open app using VSCode and run
Then build iodopen ios/Runner.xcworkspace
flutter build ios
In Runner / Targets/Runner -> select Team
If have already created a project: Change package name by add dependencies changeapppackagename: and run
apppackagename:main com.package.appnameflutter pub run change
Run in release mode
flutter run --release
Settings
- เปลี่ยนชื่อ App Icon
- Add permission: กำหนด Permission ด้วยนะ ไม่อย่างนั้นจะเปิด WebView เข้าเน็ตไม่ได้
iOS: แก้ไขไฟล์ ios/Runner/info.plist
<key>CFBundleName</key> <string>APP NAME</string> <key>io.flutter.embeddedviewspreview</key> <string>YES</string>
Android manifest: แก้ไขไฟล์ android/app/src/main/AndroidManifest.xml
<uses-permission android:name="android.permission.INTERNET" /> <application android:label="APP NAME" >
macOS: in macos/Runner/DebugProfile.entitlements and macos/Runner/Release.entitlements
<key>com.apple.security.network.client</key> <true/>
App Icon:
File : pubspec.yaml
dependencies: ... flutter_launcher_icons: ^0.9.0
flutter_icons:<br /> image_path: "assets/icon/logo_192.png"<br /> android: true ios: true remove_alpha_ios: true
# flutter pub run flutter_launcher_icons:main
เอาคำว่า "DEBUG" ของเธอคืนไป
ใส่ไว้ใน MaterialApp
debugShowCheckedModeBanner: false
Add dependencies แล้ว แต่ import package ไม่ได้
close project and re-open projectflutter packages get
Upgrade version iOS แล้วมองไม่เห็น device
ให้ดาวน์โหลดไฟล์จาก GitHub แล้วนำไฟล์มาวางไว้ที่ (~/Application/) Xcode app ใน path Contents/Developer/Platform/iPhoneOS.platform/DeviceSupport
แล้วก็ Flutter Clean
flutter clean
App Permission
หัวข้ออื่น
ที่มา
- มาลองสร้าง Flutter App กันเถอะ
- ประสบการณ์ Build flutter on iOS ครั้งแรก
- webview_flutter 2.0.2
- Different ways to change the status bar and navigation bar color (iOS and Android) in Flutter
- Flutter Launcher Icons
- How to use user-agent in webview-flutter Flutter?
- Flutter webview intercept and add headers to all requests
- Webview in flutter not working getting a platform error
- Flutter BottomNavigationBar not working with more than three items
Server Down : Mysql error 28 no space left on the device
เกิดอาการนี้มาเป็นวันที่ 2 แล้ว เมื่อวานสั่ง reboot แล้วหาย แต่วันนี้ reboot แล้วยังคงมีอาการอยู่
ที่เคยเจออาการนี้ คือ harddisk เต็ม ซึ่งปกติจะตรวจพื้นที่เหลือใน harddisk ก่อน ด้วย df -h ผลออกมาว่ายังมีพื้นที่เหลืออีกเพียบ จนในที่สุดก็พบว่าที่เต็มนั้นไม่ใช่พื้นที่ แต่เป็น inode ลองตรวจดูด้วยคำสั่ง df -i พบว่า / เต็ม 100%
สาเหตุของครั้งนี้คือ inode ที่มีไว้สำหรับเก็บตำแหน่ง folder/file เต็ม เท่าที่อ่านดู ยังไม่สามารถขยายเพิ่มได้ (ต้องทำตอน format harddisk) จึงต้องค้นหาว่า folder ไหนที่มีไฟล์เป็นจำนวนมาก แล้วก็ลบ/ย้ายไปไว้ที่อื่นที่ใช้คนละ inode กัน
# df -i
Filesystem Inodes IUsed IFree IUse% Mounted on udev 1275949 357 1275592 1% /dev tmpfs 1278745 553 1278192 1% /run /dev/sda1 1831424 1831424 0 100% / tmpfs 1278745 1 1278744 1% /dev/shm tmpfs 1278745 3 1278742 1% /run/lock tmpfs 1278745 15 1278730 1% /sys/fs/cgroup /dev/sdb1 122093568 8699755 113393813 8% /backup /dev/sda4 119996416 4748787 115247629 4% /home /dev/sda2 122400 337 122063 1% /boot tmpfs 1278745 10 1278735 1% /run/user/1004
คำสั่ง ls เพื่อดูว่าแต่ละ file มี inode หมายเลขอะไร
# ls -lai
คำสั่งสำหรับนับจำนวนไฟล์ในแต่ละ folder
# for i in /*; do echo $i; find $i |wc -l; done
# echo "Detailed Inodes usage for: $(pwd)" ; for d in `find -maxdepth 1 -type d |cut -d/ -f2 |grep -xv . |sort`; do c=$(find $d |wc -l) ; printf "$c - $d " ; done ; printf "Total: $(find $(pwd) | wc -l) "
พบว่า folder usr/local/directadmin/data/tickets มี folder/file จำนวนมาก ซึ่งสะสมมาจาก ticket ที่ระบบอัตโนมัตของ directadmin สร้างขึ้นมา จึงทำการลบไฟล์ทิ้งทั้งหมด
# rm -rm /usr/local/directadmin/data/tickets[code] แล้วย้าย folder tickets ไปไว้ใน /backup (ซึ่งอยู่คนละ harddisk ก็จะไม่มีผลต่อ inode ของ /) [code] # mkdir /backup/usr # mkdir /backup/usr/local # mkdir /backup/usr/local/directadmin # mkdir /backup/usr/local/directadmin/data # mkdir /backup/usr/local/directadmin/data/tickets [code] เปลี่ยน owner/group ให้เป็นของ DirectAdmin [code] # chown diradmin:diradmin /backup/usr/local/directadmin # chown diradmin:diradmin /backup/usr/local/directadmin/data # chown diradmin:diradmin /backup/usr/local/directadmin/data/template # chown diradmin:diradmin /backup/usr/local/directadmin/data/tickets
สร้างลิงก์ tickets ไปที่ใหม่
# cd /usr/local/directadmin/data # mv tickets tickets.old # ln -s /backup/usr/local/directadmin/data/tickets tickets # chown -h diradmin:diradmin tickets
ปล. เขาบอกว่าให้ลบไฟล์ session ทิ้งด้วย
# find . -type f -name sess_\* -delete
ที่มา
Xcode on Mac App Store can't install , show disk space not enough
ตอนจะติดตั้ง Xcode มัน error "Not enough storage disk space, you can't install the product".
สาเหตุเกิดจาก App Store คำนวณพื้นที่ว่างผิด ได้ไม่เท่ากับพื้นที่ว่างจริง
สำรวจพื้นที่ว่างในฮาร์ดดิสกันก่อน
About this Mac > Storage
Trick คือ ให้ macOS ทำการ clean up APFS โดยสร้าง a huge garbage file หลังจากนั้นก็ลบมันทิ้งไป
สร้างไฟล์โดยคำสั่ง:
dd if=/dev/zero of=/Users/<username>/hugefile bs=100m
ปล่อยให้มันทำงานไปสัก 30 วินาที แล้วก็ kill มันทิ้งด้วย ctrl+c หลังจากนั้นก็ลบไฟล์นั้นทิ้งไป:
rm ~/hugefile
ลบ Snapshots
tmutil thinlocalsnapshots / 21474836480 4