Flutter 二三事

這兩天試驗 flutter 時,查找到的一些東西,大致上還蠻順利的。

安裝 flutter

照官方文件 (Linux install) 來進行安裝,大致沒什麼問題。

我碰到的問題是,執行 flutter doctor 以後有 Android license status unknown. 的問題。可是 Android SDK 也裝了,應該是要可以才對。

後來自行去執行 Android SDK 裡的 sdkmanager 以後,才知道是因為無法執行 sdkmanager 而導致 flutter doctor 檢查失敗。我檢查了一下 java 的版本,目前使用的是 java 11,而 Android 還不支援 java 11,所以改安裝 openjdk-8-jdk 以後,再執行 flutter doctor –android-licenses 就可以了。

RenderFlex overflowed

這個是因為 Layout 固定 (StackOverflow),鍵盤出現,會蓋住輸入框,flutter 很貼心的出現這個 warning ,提醒要改用可以 Scroll 的 View我是改用 SingleChildScrollView:https://api.flutter.dev/flutter/widgets/SingleChildScrollView-class.html

退出 app

有查到這個退出 app ,說可以用 exit(0),也可以用

import 'package:flutter/services.dart';
// ...
SystemChannels.platform.invokeMethod('SystemNavigator.pop');

但有人說 SystemNavigator.pop 只適用於 Android。

講 Layout 的

其他

Django jsonfield

Django 有提供 jsonfield,但只能用在 postgresql 上,有另外一個專案 django-mysql 提供了可以用在 MySQL 上的 jsonfield。是的,就目前來說,並沒有一個通用的 jsonfield。惟一能找到的,就這個 django-jsonfielddjango-jsonfield 的網站上也有特別提到這件事情,並且說 django-jsonfield 只繼續維護,不再開發,因此不建議使用這個專案。但是就跨資料庫來說,目前好像也就這個專案可用。

我有想過要依照 DATABASE 設定來區分要使用哪個 jsonfield,但仔細想想,這最大的問題可能會出在 Migration,因為 Migration 裡會直接引用 jsonfield 。migration 裡沒辦法讀取到 django settings ,也就沒辦法做到動態的處理。不過,可能還是要試試看才知道行不行。

MySQL 到底有沒有 case sensitive ?

公司的程式有人回報說,在搜尋電子郵件時,沒有區分大小寫 (case insensitive),我心裡想,雖然電子郵件並沒有嚴格區分大小寫,但我應該沒有特別做這件事,照理說,是要有區分大小寫才是,於是我開始看程式碼去找是不是 Django 等框架/函式庫自動加上了。

不過我找了好一陣子都沒找到,看來應該不是程式的問題。既然不是程式問題,那就可能是資料庫問題了,我在開發環境的 SQLite 裡用 SELECT SQL 查詢,有區分大小寫;生產環境是用 MySQL,我改在 MySQL shell 用 SELECT SQL 來查詢。結果,真的是資料庫設定問題,上網搜尋,才確定真的是 MySQL 問題:

簡單的說,是 collation 問題,所以解決方法也算是簡單,一個方法是改變 collation,看是要資料庫整個改,還是個別 table/column 去改;一個方法則是改 column data type。

MySQL 手冊對 collation 的說明是這樣的 (連結),只要後綴是 _cs 的或是 _bin 的,都是 case-sensitive 的。改 collation ,可以先使用 SHOW COLLATION WHERE COLLATION LIKE “%_cs” 來找,但 utf8 是沒有後綴名為 _cs 的 collation,只能使用 utf8_bin 。找到合適的 collation 後,要改指定 column data type ,可以使用 ALTER TABLE documents__document CONVERT TO CHARACTER SET utf8 COLLATE utf8_bin;

以 Django 來說,當然最好是一開始在建立資料庫時,就指定好 charset 跟 collation,之後的作法就是自己寫 Migration 執行自訂的 SQL 來變更指定欄位的 data type 了。

電影流水帳(2019/04/01~2019/04/14)

Embed from Getty Images
  • The Bourne Identity (IMDB, Wikipedia),台譯:神鬼認證。
  • The Bourne Supremacy (IMDB, Wikipedia),台譯:神鬼認證-神鬼疑雲。
  • The Bourne Ultimatum (IMDB, Wikipedia),台譯:神鬼認證:最後通牒。

這篇放在草稿裡,放了很久,劇情差不多都快忘光了,靠著維基百科才回想起來。

The Bourne Identity

讓 Matt Damon 成為動作明星的代表作,故事緊湊,動作也寫實,場景都在歐洲取景,很好看。

Jason 哥被漁船從海上撈起來,醒了以後,發現自己什麼都不記得。靠著藏在身上的訊息,去瑞士銀行取出保險箱裡的東西,發現自己的身份…很多,暫時就先用了 Jason Bourne 當作自己的名字。值此同時,CIA 在銀行安插的人也通報了 CIA,CIA 高層相當的驚訝,懷疑 Jason 回來的動機,決定展開追殺。Jason 以前的訓練讓他感覺到危機,開始逃跑。在路上遇到了 Marie,請她幫忙。兩人開始逃跑,Jason 也在一連串的追殺中,慢慢回憶起自己的過去,並且知道了自己為什麼被追殺。最後,Jason 幹掉了之前負責自己這個任務,也是想幹掉自己的長官,然後去找了 Marie。

The Bourne Supremacy

這一集裡,Marie 被賜死了。線索還是指向上集的絆腳石計劃,絆腳石計劃裡有個事件跟俄羅斯政客有關係,CIA 高層也在調查 Jason 的事情,這些事情導致了 Marie 死去。Jason 不開心,決定回去搞清楚狀況。經過一番交手,Jason 跟 CIA 的 Pamela 算是達成某種程度的默契,Pamela 解決了 CIA 內部的問題,而 Jason 也暫時得以脫身,不被追殺。

The Bourne Ultimatum

這一集是一個結尾,Jason 找回自己的過去。

雖然 Jason 沒有惡意,但 CIA 仍然認為 Jason 是個威脅,持續的追蹤著他。而 Jason 在報紙上看到一篇關於自己的報導,認為這個記者可能有內線,才能進行有這樣深度的報導。於是 Jason 去找了記者,並且知道了這個內線是誰。這個內線是 CIA 裡的高層,並且經手過 Jason 的黑薔薇計劃。Jason 動身去找他,在過程裡遇到之前的熟人 Nicky 。不過 CIA 相當的心狠手辣,炸死了這個內線,Jason 在爆炸現場的碎片中找到 CIA。Jason 決定前往 CIA 大樓,這邊的故事接到前集最後的場景,Jason 利用 Pamela 將要追殺自己的人都引誘到別的地方,自己進去取得黑薔薇計劃的文件。在文件上提到了特別行動訓練中心的位置,Jason 前往那兒,並得知了自己所有的過去。在這同時,Pamela 也取得黑薔薇計劃的文件,送交給記者,揭發 CIA 的黑暗面。最後,Jason 從訓練中心頂樓跳入紐約東河,生死未卜。

Serveo.net

網址:https://serveo.net/
找 ngrok alternative 時,找到這個用 ssh 指令就可以破牆,挺方便的。

例子1

Port forwarding

在 A 電腦裡輸入

ssh -R 80:localhost:3000 serveo.net

按下 yes,會拿到一個類似 https://talis.serveo.net 的網址,當從另外一台電腦連到此網址時,會連接到 A 電腦的 port 3000

P.S. 

  1. 要拿到不一樣的網址,就帶 username,例如:ssh -R 80:localhost:8888 foo@serveo.net
  2. localhost 可以替換為其他電腦,例如 192.168.1.1

例子2

ssh port forwarding

在 A 電腦裡有 SSH server,然後輸入

ssh -R myalias:22:localhost:22 serveo.net

接著在其他電腦有 ssh client 的電腦裡輸入

ssh -o ProxyCommand="ssh -W myalias:22 serveo.net" user@myalias

就可以連接到 A 電腦的 SSH server

P.S.

  1. OpenSSH client 7.3 以後可以用 -J 參數:ssh -J serveo.net user@myalias

用 autossh 自動重連

事前預備

  1. sudo adduser –system –group –disabled-password autossh
  2. sudo chsh –shell /bin/false autossh
  3. 預先使用 autossh ,執行過一次 autossh 指令

autossh + upstart

# /etc/init/autossh.conf
# http://logan.tw/posts/2014/12/15/autossh-and-ubuntu-upstart-daemon/
description "autossh daemon for ssh tunnel"
start on net-device-up IFACE=br0 # 此處需因應網路裝置來調整為 eth0, eth1 ...
stop on runlevel [01S6]

setuid autossh
respawn
respawn limit 5 60
script
#export AUTOSSH_FIRST_POLL=30
#export AUTOSSH_GATETIME=0
#export AUTOSSH_POLL=60
autossh -M 0 -R pokemon22:22:localhost:22 serveo.net
end script

autossh + systemd

# /etc/systemd/system/autossh.service
# https://gist.github.com/thomasfr/9707568
[Unit]Description=Keeps a tunnel to 'serveo.net' open
After=network-online.target

[Service]
User=autossh
# -p [PORT]
# -l [user]
# -M 0 --> no monitoring
# -N Just open the connection and do nothing (not interactive)
# LOCALPORT:IP_ON_EXAMPLE_COM:PORT_ON_EXAMPLE_COM
# ExecStart=/usr/bin/autossh -M 0 -N -q -o "ServerAliveInterval 60" -o "ServerAliveCountMax 3" -p 22 -l autossh remote.example.com -L 7474:127.0.0.1:7474 -i /home/autossh/.ssh/id_rsa
ExecStart=/usr/bin/autossh -M 0 -R pokemon22:22:localhost:22 serveo.net

[Install]
WantedBy=multi-user.target