[教學] 小米路由器 mini 刷機紀實 (PandoraBox / Padavan / OpenWRT / LEDE)

xiaomiroutermi42.jpg

圖片來源:https://blog.jks.coffee/wp-content/uploads/2017/11/xiaomiroutermi42.jpg

其實 小米路由器 mini 這台已經出一陣子了,

官方的韌體也是不錯用但小弟有一些更進階的需求,
所以嘗試使用刷第三方韌體的想法,
網路上教學很多,多方參考才能降低失敗率
以下是我參考多方文件所得出的筆記

刷機有風險,刷機前請參考各方教學文 
步驟弄錯,變磚不要找我 😛

打開 SSH 介面

瀏覽官方 SSH 解鎖工具
前提要先把機器綁定到小米帳號底下,這網址才會有作用 (注意,該動作也會直接註銷喪失保固!

https://d.miwifi.com/rom/ssh

這裡會提供 root 密碼, SSH 工具 (miwifi_ssh.bin)

大略步驟如下:

  1. 刷入開發版 Rom
  2. USB隨身碟放入SSH工具 miwifi_ssh.bin
  3. 斷電,按住reset按鈕之後重新接上電源,長按約3-5秒 LED 變為黃燈閃爍,安裝後會自動重啟
  4. 連入 ssh 進行刷機

screencapture-d-miwifi-rom-ssh-1512040175668.png

打開 SSH 刷入 Breed 工具

Breed 是一款類似於 u-boot 的不死固件,類似手機的 Recovery
它放在 Bootloader 中,當 Firmware 有問題的時候,還可以經由進入 Breed 來做刷機

另外因為小米路由器的韌體架構的關係,韌體上面會有小米序號,
必須要先做備份,以免事後無法回復到原廠韌體。

  1. 查看 rom 資料
$ cat /proc/mtd
dev:    size   erasesize  name
mtd0: 01000000 00010000 "ALL"
mtd1: 00030000 00010000 "Bootloader"
mtd2: 00010000 00010000 "Config"
mtd3: 00010000 00010000 "Factory"
mtd4: 00c80000 00010000 "OS1"
mtd5: 00b11e68 00010000 "rootfs"
mtd6: 00200000 00010000 "OS2"
mtd7: 00100000 00010000 "overlay"
mtd8: 00010000 00010000 "crash"
mtd9: 00010000 00010000 "reserved"
mtd10: 00010000 00010000 "Bdata"
  1. 備份成檔案
cd /tmp
mkdir rom
dd if=/dev/mtd0 of=/tmp/rom/ALL.bin
dd if=/dev/mtd1 of=/tmp/rom/Bootloader.bin
dd if=/dev/mtd2 of=/tmp/rom/Config.bin
dd if=/dev/mtd3 of=/tmp/rom/Factory.bin
dd if=/dev/mtd4 of=/tmp/rom/OS1.bin
dd if=/dev/mtd5 of=/tmp/rom/rootfs.bin
dd if=/dev/mtd6 of=/tmp/rom/OS2.bin
dd if=/dev/mtd7 of=/tmp/rom/overlay.bin
dd if=/dev/mtd8 of=/tmp/rom/crash.bin
dd if=/dev/mtd9 of=/tmp/rom/reserved.bin
dd if=/dev/mtd10 of=/tmp/rom/Bdata.bin
  1. 複製備份到電腦上

用 scp 把備份檔案抓出來 $ scp -r [email protected]:/tmp/rom .

(註:scp 指令適用於 Mac / Linux 環境,
如果是 Windows 的使用者,請改用 pscp 或 WinSCP 來做資料傳輸)

恢覆指令 (以後備用)

mtd write /tmp/rom/Bootloader.bin Bootloader
mtd write /tmp/rom/Config.bin Config
mtd write /tmp/rom/Factory.bin Factory
mtd write /tmp/rom/OS1.bin OS1
mtd write /tmp/rom/rootfs.bin rootfs
mtd write /tmp/rom/OS2.bin OS2
mtd write /tmp/rom/overlay.bin overlay
mtd write /tmp/rom/crash.bin crash
mtd write /tmp/rom/reserved.bin reserved
mtd write /tmp/rom/Bdata.bin Bdata
  1. 刷入 Breed

用 scp 把 breed-mt7620-xiaomi-mini.bin 檔案複製進去

$ scp breed-mt7620-xiaomi-mini.bin [email protected]:/tmp
  1. 執行刷機
cd /tmp
mtd -r write breed-mt7620-xiaomi-mini.bin Bootloader

進入 Breed 介面

斷電,按住reset按鈕之後重新接上電源,長按3-5秒,LED 變為藍燈閃爍 插網路線,瀏覽 192.168.1.1 進入 Breed 介面

screencapture-192-168-1-1-1512040517285.png

選固件更新,在固件這欄刷入你要的 Rom

screencapture-192-168-1-1-upgrade-html-1512040580563.png

[PandoraBox]

檔名:PandoraBox-ralink-mt7620-xiaomi-mini-squashfs-sysupgrade-r1024-20150608.bin

下載位置

[Padavan (老毛子華碩第三方固件)]

檔名:RT-AC54U-GPIO-30-xiaomimini-128M_3.4.3.9-099.trx

下載位置

[OpenWRT]

檔名:openwrt-15.05.1-ramips-mt7620-xiaomi-miwifi-mini-squashfs-sysupgrade.bin

15.05.1下載位置

snapshots(開發版)下載位置

[LEDE]

檔名:lede-17.01.4-ramips-mt7620-miwifi-mini-squashfs-sysupgrade.bin

17.01.4下載位置

(下載連結均由網路搜尋而得,可能會失效,如有缺檔,請自行搜尋,小弟亦不補檔)

刷完手動重新整理,進入新韌體介面

這裡就留給大家動手玩玩各種韌體了

要注意,Breed 適用刷第三方 Rom,雖然也可以刷回小米官方韌體
但是 序號(SN) 會被洗掉不見,沒有序號就不能綁定小米帳號,也不能重新開啟 SSH 權限
如果要刷回原本官方韌體,要把原本備份下來的資料 (包含 Bootloader) 整個倒回去才行
如果成功的話,這時候應該會回到官方的開發版韌體

總結一下,小米路由器mini 這台其實沒有想像中的難刷機,刷了之後能用的功能就更多了,能調整的地方更細緻 第三方韌體穩定度蠻不錯的,適合中重度的玩家使用

參考資料

http://www.jianshu.com/p/111b6c1cbccf
http://eric0703.pentaxfans.net/2934
http://kyoko7384.blogspot.com/2017/03/mini-mod-iptv-rom-mod-padavan-rt-ac54u.html
https://leamtrop.com/2017/05/11/flash-openwrt-squashfs/
https://kirkhsutw.blogspot.tw/2017/06/mini.html
https://kknews.cc/tech/oyb2j3m.html
https://jingyan.baidu.com/article/c45ad29c24ee27051653e264.html
https://jingyan.baidu.com/article/3f16e003faa67e2591c10300.html
https://jingyan.baidu.com/article/215817f790b3ca1eda142333.html

[教學] Tomato 設定 OpenVPN 伺服器步驟 (以 RT-N16 為例)

有鑒於 OpenVPN 的 Server 設定官方文件又臭又長,常常望之卻步
小弟就自己的經驗做一個小小的分享,還有寫了一些方便自己的 Scripts
小弟使用的機器與資訊如下

硬體:Asus RT-N16
韌體:Advanced Tomato
Version 3.4-138    
K26USB-1.28.AT-RT-N5x-MIPSR2-3.4-138-AIO.trx
(OpenVPN version: v2.3.11)
設定使用的電腦:Mac

設定步驟

1. 下載檔案

首先先下載 easy-rsa

https://github.com/OpenVPN/easy-rsa/releases/tag/2.2.2

和小弟寫的 Scripts

https://github.com/j796160836/tomato-openvpn-setup

因為這版的 Tomato 使用的是 OpenVPN v2.3.11
所以搭配 easy-rsa  v2 做設定

然後解壓縮跟我的 Script 放在一起

2. 修改 vars 變數檔案

$ vi vars

把設些改成你要的內容

export KEY_SIZE=2048
export KEY_COUNTRY="US"
export KEY_PROVINCE="CA"
export KEY_CITY="SanFrancisco"
export KEY_ORG="Fort-Funston"
export KEY_EMAIL="[email protected]"
export KEY_OU="MyOrganizationalUnit"
export KEY_NAME="EasyRSA"
export KEY_CN="CommonName"

3. 產生伺服器金鑰

generate-keys-server.sh  指令

$ ./generate-keys-server.sh

他會把剛剛的環境變數設定好,並清掉之前有產生的金鑰

產生一個預設名字的伺服器金鑰,最後印出來

如果你之前有跑過這個指令,就不要再跑第二次了

(如果要跑第二次,就要重新設定用戶端金鑰)

執行成功會出現類似這樣的東西

================================================================
Please paste it at Tomato's OpenVPN key config page
================================================================
[Certificate Authority]
-----BEGIN CERTIFICATE-----
MIIDhDCCAu2gAwIBAgIJAJ9a8dYhq73TMA0GCSqGSIb3DQEBCwUAMIGJMQswCQYD
Q6Xp2vd6068LHC7b9qTs1nWHfYbpdOv1GmzKONIGd3FDiuRFJu4J/g==
-----END CERTIFICATE-----
[Server Certificate]
-----BEGIN CERTIFICATE-----
MIID5jCCA0+gAwIBAgIBATANBgkqhkiG9w0BAQsFADCBiTELMAkGA1UEBhMCVFcx
TRmjwzCO84lz2LOYFDVlETjb6Mb76SysoHVb4zNPX7Bkrr2u3c8+vzaV
-----END CERTIFICATE-----
[Server Key]
-----BEGIN RSA PRIVATE KEY-----
MIICXAIBAAKBgQCy1Pwvi8bE0dTpNddzNBluQoKHdHQpa7mBuH7T0+fWLhs3HoEd
POvdTEVwh+G/2kce8xtOwJAkvyppXMWjY2WmSqimVP8=
-----END RSA PRIVATE KEY-----
[Diffie Hellman parameters]
-----BEGIN DH PARAMETERS-----
MIGHAoGBAN8PIYvlZy1rDghoF+K9wmMrCaN5DBi+3HPFemJEZK4wlyeXHLDOGYx+
5vtwBR2tPYXwTwdeMZItmqVMsVuIN4d0vEzDrbNihAU7OaaWzP+bAgEC
-----END DH PARAMETERS-----

(請你自己跑一次,不要直接照樣 copy,這裏的金鑰只是示意而已)

你就打開 Tomato 的 VPN > OpenVPN Sever > Keys 進入金鑰設定頁面

把金鑰對應地複製貼上到對的地方

1

如果它跑太快或者你不小心把結果清掉了,你可以再跑一次 print-server.sh 指令查看

$ ./print-server.sh

4. 抓取 Tomato 上的設定值

這裡有點 Tricky,我是直接讀取它的設定檔指令來做的

請使用 Tools > System Commands (System Shell) 來執行 fetch-server-config.txt 檔案裡面的指令

2

這個是 fetch-server-config.txt 檔案裡面的內容

#!/bin/bash
server_config="/etc/openvpn/server1/config.ovpn"
if [ ! -e $server_config ]; then
echo "File not found!: $server_config"
exit 1
fi
port=cat $server_config | grep "port" | awk '{print $2}'
public_ip=curl -s ipinfo.io/ip
#public_ip=curl -s checkip.dyndns.org | sed -e 's/.*Current IP Address: //' -e 's/<.*$//'
config_data="remote "$public_ip" "$port"n"$(cat $server_config | grep "proto|dev|cipher" | awk '{printf "%s\n", $0}')
echo "=================================================="
echo "Please paste this command in your easy-rsa folder"
echo "=================================================="
echo
echo "echo -e ""$config_data"" > server-config" 

執行之後會得到類似這樣的指令

3

==================================================
Please paste this command in your easy-rsa folder
==================================================
echo -e "remote 1.2.3.4 1194nproto udpndev tun21ncipher DES-CBCn" > server-config 

一樣,把剛剛產生出來的指令,貼回 Mac 的 Terminal 上,產生 server-config 這個檔案

5. 產生用戶端金鑰

這裡執行 generate-keys-client.sh 這個指令,並打入你要的名稱

$ ./generate-keys-client.sh Client01

這裡我打的是 Client01 做為名稱,你可以換成你要的,但不能重複

執行成功會得到類似這個訊息

Write out database with 1 new entries
Data Base Updated

就完成產生了

6. 產生用戶端OpenVPN設定檔

使用 print-client-config.sh  這個指令,帶入剛剛打的名稱,並寫入進一個 ovpn 檔案之中

$ ./print-client-config.sh Client01 > Client01.ovpn

他就會抓取金鑰跟剛剛 server-config  裡面的內容產生一個設定檔

接下來你只要把 OpenVPN 的用戶端安裝好,使用剛剛的 ovpn 設定檔就可以了

以 Mac 為例,

Mac 的 OpenVPN 用戶端使用 Tunnelblick

https://tunnelblick.net/

安裝完成,雙點 ovpn 檔案,再輸入電腦使用者的密碼就可以使用了

IOS 的話有 OpenVPN Connect 可以使用

https://itunes.apple.com/us/app/openvpn-connect/id590379981?mt=8

把 ovpn 檔案放在 iCloud drive 然後載入它,就可以了

 

祝設定成功!

 

 

 

 

 

 

 

 

 

[Mac OS X] 為你的舊 Macbook iMac 升級藍牙 Bluetooth 4.0 BLE

IMG_8415

最近因為需要,所以研究藍芽Mac OS X 上的 藍牙傳輸

才赫然發現,手邊的 Macbook 所搭載的是舊版藍牙模組是舊的,所以出現此文

 

確認你的 Macbook 型號是否支援

CompatibilityChart-13.12.2014  

(資料來源:Continuity Activation Tool)

請去對照一下你的 Mac 型號,點左上角的蘋果 > About this Mac 就可以看到資訊

主要是落在 亮綠色 (Works) / 草綠色 (Works with Bluetooth 4.0 USB dongle OR new AirPort Extreme Card) / 藍色 (Works with Bluetooth 4.0 USB dongle)

就可以使用

小弟的電腦是 Macbook Pro 13" (Late 2011) 所以落在草綠色上

所以可以使用

Screen Shot 2015-02-27 at 8.36.27 PM  

 

選購藍牙接收器

所需使用的必需要是 Broadcom BCM20702 的晶片(這也是Apple所使用的藍芽晶片)

市面上買的到的,小弟這裏列出幾個可供挑選

  • WellWhole WED-210 V4 藍芽迷你接收器 V4.0+EDR
  • IOGEAR GBU521 迷你型藍牙4.0 傳輸器藍芽接收器
  • KBTalking 藍芽接收器

 

當然還有其他的 Broadcom 晶片的,如果有看到歡迎不吝告知

採用 CSR (Cambridge Silicon Radio) 的晶片目前是不支援,選購時可要注意

 

安裝藍牙接收器

小弟是使用 WellWhole WED-210 V4 藍芽迷你接收器

就直接插進去就好了

IMG_8415  

 

然後會在 系統資訊 USB 頁籤看到二個藍牙裝置

一個會寫 Broadcom Corp. 一個會寫 Apple Inc.

Screen Shot 2015-02-27 at 8.35.08 PM  

 

使用工具Patch

主要是使用 Continuity Activation Tool 這個工具幫我們調整

主要位置在這

https://github.com/dokterdok/Continuity-Activation-Tool

下載位置在此

https://github.com/dokterdok/Continuity-Activation-Tool/archive/master.zip

 

解壓縮之後,開啟 Continuity Activation Tool

中間會要你輸入您的使用者密碼

Screen Shot 2015-02-27 at 8.14.02 PM  

會有

1) Activate Continuity

2) System Diagnostic

3) Uninstall

4) Quit

四個選項讓您選擇

填入數字1 按下Enter 開始Patch

安裝完成之後會提示你重開機

以下是小弟的安裝時的Log

 

— OS X Continuity Activation Tool 2.0.0 —
by dokterdok

— Initiating system compatibility check —

Verifying Mac model reference… OK
Verifying Mac board-id… OK
Verifying OS X version… OK
Verifying Wi-Fi hardware… OK
Verifying Bluetooth version… OK
Verifying Bluetooth features… OK
Verifying kexts readability… OK
Verifying Bluetooth blacklist status… OK
Verifying Wi-Fi whitelist status… OK
Verifying legacy Wi-Fi card patch… OK
Verifying old Wi-Fi kext presence… OK

— Initiating Continuity mod —

Disabling OS kext protection… OK
Fixing disk permissions… OK
Backing up original drivers… OK. Wi-Fi and Bluetooth kexts were backed up in ‘…’
Skipping blacklist patch… OK
Patching whitelist……………. OK
Cleaning up old Wi-Fi kext… OK
Applying legacy Wi-Fi card patch… OK
Verifying BT4 dongle patch status… OK
Setting HCI switch behavior… OK
Patching Bluetooth feature flags… OK
Skipping legacy Wi-Fi cards patch… OK
Applying correct permissions… OK
Updating kext caches… OK
Updating system caches… OK
Backing up patched drivers… OK. Wi-Fi and Bluetooth kexts were backed up in ‘…’

ALMOST DONE! After rebooting:
1) Make sure that both your Mac and iOS device have Bluetooth turned on, and are on the same Wi-Fi network.
2) On OS X go to SYSTEM PREFERENCES> GENERAL> and ENABLE HANDOFF.
3) On iOS go to SETTINGS> GENERAL> HANDOFF & SUGGESTED APPS> and ENABLE HANDOFF.
4) On OS X, sign out and then sign in again to your iCloud account.
Troubleshooting: support.apple.com/kb/TS5458

Thanks to Lem3ssie, UncleSchnitty, Skvo, toleda, TealShark, Manic Harmonic, rob3r7o and the many beta testers for their support.

 

完成測試

可以使用 Mac 版的 LightBlue 做測試

icon128-2x  

請自 Mac App Store 下載

https://itunes.apple.com/tw/app/lightblue/id639944780?mt=12

下載完成看看能不能成功打開,而沒有收到需要開啟藍芽的提示
這樣就成功了

Screen Shot 2015-02-27 at 8.26.59 PM  

也可以在系統資訊看到

Bluetooth Low Energy Supported: Yes
Handoff Supported: Yes
Manufacturer: Broadcom
Transport: USB

這些字樣

Screen Shot 2015-02-27 at 8.40.35 PM  

 

參考資料:

https://github.com/dokterdok/Continuity-Activation-Tool

https://justhackme.wordpress.com/2014/05/21/adding-a-ble-bluetooth-4-0-dongle-to-mac-os-x-mavericks/&nbsp;

 

 

 

 

解決 Windows 10 安裝 Parallels desktop tools 字體空白的問題

 

 

 Screen Shot 2015-02-23 at 2.18.55 PM  

如果您有遇到 Windows 10 安裝完 Parallels desktop tools 的時候

原有的字體空白就突然間全變成的空白

不要緊張

因為 Windows  10 preview 與 Parallels desktop 有一些相容性的問題

目前的解法:

Screen Shot 2015-02-23 at 2.10.49 PM

將虛擬機關閉,在 Action > Configure 的地方

在 Hardware > Video 頁籤,的 3D Acceleration 選項

請選擇 DirectX9

然後開啓虛擬機即可

Screen Shot 2015-02-23 at 2.25.08 PM  

 

參考資料

https://forum.parallels.com/threads/win10-tp-build-9860.327352/#post-766243

 

 

 

 

[Android] 全自動覆蓋安裝APK

好吧,連自己都覺得這個Script很方便
簡單來說這可以
1. 如果機器有曾經有安裝過,會自動執行解除安裝
2. 自動安裝新版APK
3. 自動打開剛裝好的APK (如果有需要)

使用方式很簡單

./ReInstallAPK.sh myApp.apk

如果需要自動打開,就加上 start 字樣

./ReInstallAPK.sh myApp.apk start

就這樣

需要設定 ANDROID_HOME 環境變數,目前只能用USB接一台Android devices
有空可以把它改成一次發佈多台的

https://gist.github.com/j796160836/df2dbf05d9f408739c06

[Android] 如何做到多重螢幕支援 (Multi Screen Support) (1/2)

這個主題不是很好寫,也不是很好解釋
我儘量把我所知道的解釋出來,如果有誤請糾正

在Android的世界裡,螢幕非常多

4" 5" 6" 7" 8" 9" ….各種寸數都有
其中也有各種解析度

 

但在使用者的眼中,只有 手機、平板 這二種類別

至少在iOS的世界是這樣子分的沒錯(只分iPhone / iPad二種版)

(正確應該說是三種版,因為iPhone5之後它變長了)


有些名詞要先懂

Density

到時候一定會圍繞這個單字,字面意思是 密度

這裡要表示螢幕上的密度

 

PPI (Pixel per inch)

字面翻譯爲 一英寸多少像素

算數公式如下:

tumblr_lxiqrxwFxp1qjgx8i  

實際算法可以從畢氏定理求得知

螢幕寬平方 與 螢幕高平方 相加後 開根號  得到一個值
然後將這個值除以螢幕對角線實際尺寸的值

跟我們常聽到的DPI (Dot per inch)想法很像

 

都是螢幕對角線的 虛擬尺寸(px)實際尺寸(inch) 的 比值
表示一種密度

 

小螢幕畫質很精密,這代表著他的密度很高

iPhone的Retina螢幕也是在表示這件事 


再來你需要知道Android對於像素的處理

Density-independent pixel (dp)

也簡稱為 dip 或 dp

Android他就發明了這個詞,這代表一個單位 (可以度量的單位,可以將它當做是layout使用的px)

這個單位的發明,只為了解決一件事情

不管螢幕密度多少,都要在實際畫面 (可以直接拿皮尺量螢幕的尺寸,例如:公分)  呈現一樣大的大小

在正確一點來說

不管螢幕密度為何,都以160dpi所看到螢幕的看到的差不多大(這句看不懂沒有關係)

 

 

放張大家有印象的圖

density-test-bad  

若是在螢幕尺寸不變(假設爲4"手機螢幕),由左至右 爲 低畫質 至 高畫質
螢幕就像640×480 演變成 1024×768 再演變成 1920×1080的感覺一樣

以前字很大,隨著解析度條高,字也就越小(畫面也就更細緻了)

因為密度變大了

density-test-good  

若使用了dp這個單位的話,就算是螢幕再細緻,畫面實際尺寸也不會有太大的差異

這就是Android想要達成的目的,就算是比較差的手機(畫質差),至比較高檔的手機(高畫質)

畫面也不要差太多

 

dp 轉 px 的公式如下

px = dp * (dpi / 160)

公式搬移一下變成

dp = px / dpi * 160

 

這時候就出現了ldpi、mdpi、hdpi、xhpi 這幾個詞,這個跟圖有關係,晚點再解釋


螢幕的分類

這個就是重點了

Android對於螢幕的分類有以下:

Small、Normal、Large、XLarge

這幾種

就跟你穿衣服一樣
不是有S號、M號、L號、XL號嗎?

這就是螢幕的大小

Android官方這裡有一張一般螢幕尺寸與密度的對照圖

screens-ranges  

這張對於螢幕尺寸(第一行)的部分,只有給區間而已

你不需要去拘泥與這張圖的分類  到底是幾吋到幾吋,也不需要急著要知道你手上的這支手機的型號 是 屬於哪個分類

這張圖的重點只有 一個

也就是

平板 都常都落在 large 以上


重點是你需要知道

螢幕分類dp 之間的關係

因為各家螢幕大小不一樣,這裡有列一個參考值

xlarge screens are at least 960dp x 720dp
large screens are at least 640dp x 480dp
normal screens are at least 470dp x 320dp
small screens are at least 426dp x 320dp

它幫我們算出,每個分類 至少 會有多少dp

當然參考值畢竟是參考值,多少會有例外
例外的部分就依照個別機種去調整版面

 

就我的經驗是

你必須要先考慮各種螢幕大小的版型是否會跑版,
再來考慮圖的畫質問題

 

怎麼測各種螢幕大小、機種?有幾種方法

  1.  儘可能的拿實機測

  2.  拿模擬器,指定特定的密度與螢幕大小來模擬

 

剛建立版型的時候,先固定一種螢幕大小去測試 (例如手上測試機)

然後先利用GenyMotion等模擬器,把所有螢幕大小分類都跑一遍
有問題的話先做修正

再來就是看各機種的問題做測試了


密度的分類

再來是畫質密度的問題,就是文章開頭很頭痛 Density

密度的分類剛剛看過了

ldpi、mdpi、hdpi、xhpi

screens-densities  

一樣有low、medium、high、extra high等分別

以mdpi為基準點

3:4:6:8比例做縮放

 

以48px x 48px的圖示來說

ldpi 為 36×36

mdpi 為 48×48 (因為它是基準點嘛) 

hdpi 為 72×72

xdpi 為 96×96

 

以Desire HD來說

device-2014-02-18-014336  

(不要再問我為何Desire HD有4.0.3了,因為我有刷機嘛)

以Desire HD來說,像素尺寸為 480×800

分類屬於 normal / hdpi 的螢幕

所以是換算成mdpi的話,將px全部除上1.5倍

480 / 1.5 = 320
800 / 1.5 = 533.33

再回頭查看原有程式的比例

在dp這一欄,剛好就是320×533

 

 

官方文件可以清楚看到

ldpi Resources for low-density (ldpi) screens (~120dpi).
mdpi Resources for medium-density (mdpi) screens (~160dpi). (This is the baseline density.)
hdpi Resources for high-density (hdpi) screens (~240dpi).
xhdpi Resources for extra high-density (xhdpi) screens (~320dpi).
tvdpi Resources for screens somewhere between mdpi and hdpi; approximately 213dpi. This is not considered a “primary” density group. It is mostly intended for televisions and most apps shouldn’t need it—providing mdpi and hdpi resources is sufficient for most apps and the system will scale them as appropriate. If you find it necessary to provide tvdpi resources, you should size them at a factor of 1.33*mdpi. For example, a 100px x 100px image for mdpi screens should be 133px x 133px for tvdpi.

ldpi 約爲 120dpi,mdpi 約為 160,hdpi 約為 240,xhdpi 約為 320

dpi的數字你不知道是多少也沒關係,可以直接記住 3:4:6:8 的比例(或是圖片上的 0.75x、1x、1.5x、2x 也行)


tvdpi

比較特別的是tvdpi,約為213dpi,這個專為電視所設計,因為電視現今螢幕不管多大尺寸通常都是 1920×1080

而且不管上述螢幕尺寸一致的問題,就是固定是倍率大小為1.33x

這跟使用體驗有關,畢竟電視不是像手機一樣般的操控

 

 


 

大部份的資料,參考自這份很難懂的原文資料

http://developer.android.com/guide/practices/screens_support.html

我很少把參考資料的字放大(代表它很重要),多看幾次才會知道它在寫什麼 

 


 

參考資料:

http://en.wikipedia.org/wiki/Pixel_density

http://shareandopen.tumblr.com/post/15559202965/android-support-multiple-screens

http://developer.android.com/training/multiscreen/screensizes.html

[.Net / C#] 撰寫在背景執行的服務 (Windows Service)

最近在研究Windows Service

網路資料有些片段,寫個文章整理一下

 

主要目標很簡單,就是寫一個排程器

每隔幾秒做事情

放在伺服器上

—–

以下用visual studio 2012做示範

 

建立專案

一樣老樣子從開新專案開始

File -> New -> Project…

Screen Shot 2014-02-03 at 7.09.57 PM  

選Visual C# -> Windows -> Windows Service   (中文叫做Windows服務)

然後打上專案名稱 (這裡用MyService1)

按下OK後建立

Screen Shot 2014-02-03 at 7.10.18 PM  

然後就建立專案

Screen Shot 2014-02-03 at 7.51.03 PM  

這裡可以發現這個Service的專案跟一般視窗專案有些不同

除了一樣有Program.cs

多了Service1.cs

點選Service1.cs在Design模式時,什麼都沒有(因為只有元件沒有畫面)

點選Click here to switch to code view直接看程式碼

Screen Shot 2014-02-03 at 7.11.28 PM  

這裡就有原始碼

Screen Shot 2014-02-03 at 7.55.37 PM    

只有很簡單的OnStart跟OnStop

因為它是服務,所以無法直接執行

直接按Start按鈕執行的話會看到這個視窗

Screen Shot 2014-02-03 at 7.12.25 PM  

意思是說,這服務需要被安裝才可以執行

需要用到 installutil.exe 這程式來安裝(等下再介紹)
然後還要用NET START指令啟動服務(這可以不用理會沒關係,我們可以用圖形介面)

———

到這裡還沒有開始寫排程器,還要爲這個服務做一些設定

回到Service1.cs的Design模式(就是剛剛什麼都沒有地方)

按右鍵 -> Add Installer (加入安裝程式)

Screen Shot 2014-02-03 at 8.01.11 PM  

這時會多一個ProjectInstaller.cs檔案,在設計模式底下會有這二個東西

Screen Shot 2014-02-03 at 8.05.49 PM  

點選 serviceInstaller1

Screen Shot 2014-02-03 at 8.08.00 PM  

這裡需要做一些設定

DisplayName 就是服務要顯示的名稱

Description 服務描述

ServiceName 服務的唯一名稱

StartType 啓動方式,初始值爲Manual (手動)
當然要設定Automatic (自動) 呀

DelayedAutoStart 爲開機之後是否延遲啓動

 

點選 serviceProcessInstaller1

Screen Shot 2014-02-03 at 8.13.38 PM  

設定只要改一個

Account 這裡決定服務的帳號與權限

我們可以設定爲LocalSystem (就是最大權限)

———

 

撰寫相關程式碼

先撰寫定時器

這裡用到 System.Timers 所以要先引用

using System.Timers;

 

然後寫一個定時器

private Timer MyTimer;

public Service1()

{

    InitializeComponent();

}

 

protected override void OnStart(string[] args)

{

    MyTimer = new Timer();

    MyTimer.Elapsed += new ElapsedEventHandler(MyTimer_Elapsed);

    MyTimer.Interval = 10 * 1000;

    MyTimer.Start();

}

 

private void MyTimer_Elapsed(object sender, ElapsedEventArgs e)

{

    // Do SomeThing…

}

 

這裡設定 定時器為每10秒 執行一次

 

日誌輸出

在設計模式拉一個EventLog

Screen Shot 2014-02-03 at 8.55.57 PM  

然後增加一些程式碼變成如下

private Timer MyTimer;

 

public Service1()

{

    InitializeComponent();

    this.AutoLog = false;

    if (!System.Diagnostics.EventLog.SourceExists(“MySource”))

    {

        System.Diagnostics.EventLog.CreateEventSource(

            “MySource”, “MyLog”);

    }

    eventLog1.Source = “MySource”;

}

 

protected override void OnStart(string[] args)

{

    eventLog1.WriteEntry(“Start Timer.”);

    MyTimer = new Timer();

    MyTimer.Elapsed += new ElapsedEventHandler(MyTimer_Elapsed);

    MyTimer.Interval = 10 * 1000;

    MyTimer.Start();

}

 

private void MyTimer_Elapsed(object sender, ElapsedEventArgs e)

{

    eventLog1.WriteEntry(“Timer Ticked.”);

}

 

protected override void OnStop()

{

    eventLog1.WriteEntry(“Stop Timer.”);

    MyTimer.Stop();

    MyTimer = null;

}

 

 

剩下就讓大家自由發揮了

——————————

安裝 / 解除安裝 服務

 

剛剛不是有提到 installutil.exe 嗎?

官方文件是寫

安裝服務的時候執行指令

InstallUtil MyService1.exe

解除安裝的時候執行指令

InstallUtil /u MyService1.exe

但事情沒有這麼簡單

 

installutil.exe 它其實是在

C:WindowsMicrosoft.NETFramework<版本號>   底下

Screen Shot 2014-02-03 at 7.13.05 PM  

版本號會有很多個

因為我這個專案是用.Net Framework 4.5

所以就用v4.0.30319

有安裝.Net Framework 4.5都會有這個資料夾,也會有這個程式

但還有一個問題

因為我執行時是用LocalSystem

這個需要額外的管理員權限

——-

在這裡我寫了二個Bat檔案,做安裝服務與解除安裝的服務

這裡只列安裝服務,反正把指令加上 /u 就是 解除安裝就不列出了

Install-MyService1.bat

內容為 

@ECHO OFF

net session >nul 2>&1
IF NOT %ERRORLEVEL% EQU 0 (
   ECHO ERROR: Please run Bat as Administrator.
   PAUSE
   EXIT /B 1
)

@SETLOCAL enableextensions
@CD /d “%~dp0”

REM The following directory is for .NET 4
SET DOTNETFX4=%SystemRoot%Microsoft.NETFrameworkv4.0.30319
SET PATH=%PATH%;%DOTNETFX4%

ECHO Installing MyService1…
ECHO —————————————————
InstallUtil /i .MyService1.exe
ECHO —————————————————
ECHO Done.
PAUSE

 

藍色字自行修改所需要的.Net版本號
還有服務程式的exe名稱

橘色字是檢查管理員權限用的
若Account不是選LocalSystem的話

可以刪掉它

——————————

執行測試

完成之後可以做安裝,然後做測試

在Install-MyService1.bat按右鍵 -> Run as administrator

Screen Shot 2014-02-03 at 9.16.09 PM   

打開控制台 -> 系統管理工具 -> 服務

這個列表裡面就會多了一個你的服務

Screen Shot 2014-02-03 at 9.24.25 PM

裡面的名稱都跟剛剛打的一樣

 Screen Shot 2014-02-03 at 9.24.41 PM  

 

那我們剛剛寫的日誌呢?

控制台 -> 系統管理工具 -> 事件檢視器

找到Applications and Services (應用程式及服務記錄檔)

就會多出一個MyLog

裡面就是我們寫的日誌檔

Screen Shot 2014-02-03 at 9.29.35 PM  

 

除錯

之前在重複若干次的 安裝服務/解除安裝服務 的時候

有遇到EventLog的問題

可以嘗試去登錄編輯器(regedit)刪除以下機碼

HKEY_LOCAL_MACHINESYSTEMControlSet001serviceseventlogMySource
HKEY_LOCAL_MACHINESYSTEMControlSet001servicesMySource
HKEY_LOCAL_MACHINESYSTEMCurrentControlSetserviceseventlogMySource
HKEY_LOCAL_MACHINESYSTEMCurrentControlSetservicesMySource

在執行 解除安裝服務 的程式

 

參考資料:

http://blog.wahahajk.com/2008/06/cservice.html
http://msdn.microsoft.com/en-us/library/y817hyb6(v=vs.110).aspx
http://gogo1119.pixnet.net/blog/post/27575780-%5Bc%23%5D-windows-service%E5%BB%BA%E7%AB%8B%E7%AF%84%E4%BE%8B
http://www.cnblogs.com/xianspace/archive/2009/04/05/1429835.html

http://stackoverflow.com/questions/3307151/receiving-has-already-been-registered-from-eventlog-createeventsource-ev
http://stackoverflow.com/questions/4824051/problem-installing-windows-service

 

[MySQL] 增加phpmyadmin的登入過期時間

有時候需要因為測試用途,需要把phpmyadmin的Token過期時間加長
省得要一直反覆登入的麻煩

在phpmyadmin資料夾底下的config.inc.php

增加或修改這行

$cfg[‘LoginCookieValidity’] = 3600 * 9; // 9 小時

 

在Mac底下的XAMPP可以用這指令修改

sudo vi /Applications/XAMPP/xamppfiles/phpmyadmin/config.inc.php

 

參考資料:

http://stackoverflow.com/questions/4361416/phpmyadmin-configuration

[PHP] PHP 5.4 (for Windows)之後版本連接Microsoft SQL Server

Screen Shot 2013-08-26 at 12.50.45 PM  

PHP要怎麼連Microsoft SQL Server?網路上教學很多

但很多是舊版,這是新版的做法
只有Windows平台受影響

 

敝人愛用XAMPP所以就用這套講起

它好像自從其中一個版號之後…
XAMPP for Windows把原本mssql的連接方式抽掉了

只能用Native Client的連接方式

 

而其它平台則不受影響


簡單講一下差異…

Screen Shot 2013-08-26 at 8.28.07 PM  

這裡有三個流程圖…

Mac / Linux 是看最右邊的方式,底層採用FreeTDS連接SQL Server

Windows則有二種方式連接,中間的是舊版做法,左邊的是新版做法

 

簡單來說…就是換Library了啦!

SQLSRV的話,是微軟提供&維護的Driver,

 

在Microsoft官網有完整的API Reference
http://msdn.microsoft.com/en-us/library/cc296152.aspx

當然,php官方也Mirror了一份

http://php.net/manual/en/book.sqlsrv.php

 

所以這篇,主要教怎做這個更換Library的動作

 

 


剛開始,你在Configure Command裡面看到類似 "–without-mssql" "–without-pdo-mssql"的字眼就不要太緊張

因為它換模組名稱

 


敝人愛用XAMPP所以就用這套講起

首先你需要裝一個Native Client

依照這個網址指示
http://msdn.microsoft.com/en-us/library/cc296170.aspx

Screen Shot 2013-08-26 at 1.08.39 PM  

這就看你的SQL Server版本不同平台不同裝不一樣的

 

我的話,用Microsoft SQL Server 2008,系統是64位元的
所以裝這個

http://go.microsoft.com/fwlink/?LinkID=188401&clcid=0x409

(它有特別提到,系統如果是64位元的SQL Server就一定要裝64位元的)


到這網址

http://www.microsoft.com/en-us/download/details.aspx?id=20098

抓檔案 

 

但這也要看PHP版本,以我的版本XAMPP 1.8.2 for Windows來說

Screen Shot 2013-08-26 at 1.16.48 PM  

我的圖面上很清楚看到的是php 5.4

然後比照php資料夾裡的dll是Thread Safe 還是 non-Thread Safe的版本

 

Screen Shot 2013-08-26 at 1.11.14 PM  

 

 

以我的版本XAMPP 1.8.2 for Windows來說

我在C:xamppphp裡面

找不到php5.dll但有php5ts.dll

所以我知道我的版本是Thread Safe版本

SQLSRV30.EXE檔案,用7-zip等程式直接解壓縮(本身執行檔是壞的,不用在雙點了)

就會得到

php_sqlsrv_54_ts.dll

php_pdo_sqlsrv_54_ts.dll

這二個檔案

 

把它複製到C:xamppphpext 裡面

然後手動在php.ini裡面加上

extension=php_sqlsrv_54_ts.dll

extension=php_pdo_sqlsrv_54_ts.dll

然後重開Apache

—————–

看phpinfo(),找sqlsrv就會看到類似以下畫面

Screen Shot 2013-08-26 at 12.49.33 PM  

就完成了

 

因為模組有變更,程式碼也變更

所以以下這段在Windows底下就棄用了喔(Mac / Linux的話不受影響,還是用這一段)

<?php
$conn = mssql_connect($serverName, $DBUsername, $DBPassword)
or die("Couldn’t connect to SQL Server on $myServer");
if (!$conn) {
die(‘Something went wrong while connecting to MSSQL’);
}
?>

 

改成新版的寫法 

<?php
$serverName = "localhost"; //serverNameinstanceName
$connectionInfo = array( "Database"=>"dbName", "UID"=>"userName", "PWD"=>"password");
$conn = sqlsrv_connect( $serverName, $connectionInfo);

if( $conn ) {
echo "Connection established.<br />";
}else{
echo "Connection could not be established.<br />";
die( print_r( sqlsrv_errors(), true));
}
?>


網路找了個半天,終於解出來問題了

之後來測試一下連線

 

至於更詳細sqlsrv和mssql使用上的差異

可以參考這一篇

http://blogs.msdn.com/b/brian_swan/archive/2010/03/10/mssql-vs-sqlsrv-what-s-the-difference-part-2.aspx

 


參考資料:

整個模組Reference

http://php.net/manual/en/book.sqlsrv.php
http://msdn.microsoft.com/en-us/library/cc296152.aspx

安裝準備

http://msdn.microsoft.com/en-us/library/cc296170.aspx

官方的範例

http://msdn.microsoft.com/en-us/library/cc296196(v=sql.105).aspx

 

http://blogs.msdn.com/b/brian_swan/archive/2010/03/08/mssql-vs-sqlsrv-what-s-the-difference-part-1.aspx
http://blogs.msdn.com/b/brian_swan/archive/2010/03/10/mssql-vs-sqlsrv-what-s-the-difference-part-2.as

http://www.apachefriends.org/f/viewtopic.php?f=16&t=49670&p=191610&hilit=SQLSRV#p191610