[筆記] Android 使用httpclient對self-signed certificate網站進行SSL連線
Android SDK 在進行 https 連線時,對於自簽署的憑證是會拒絕連線的,會得到 Not trusted server certificate 的例外。如果使用 HttpsURLConnection 來連線,網路上可以找到一些破解方法,在此不多談。使用 apache httpclient 其實執行效率比較差一點,但是他最大的好處就是有內建的機制儲存cookie,並且也可以跟隨 server 作自動轉址。網路上資料比較多的是 httpclient 3.x版,Android 使用 httpclient 4 (而且還有些實作被拿掉) 唯一找到比較可信的來源是 apache httpclient 官方的 example。節錄重點段落如下:
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
FileInputStream instream = new FileInputStream(new File("my.keystore"));
try {
trustStore.load(instream, "nopassword".toCharArray());
} finally {
instream.close();
}
SSLSocketFactory socketFactory = new SSLSocketFactory(trustStore);
Scheme sch = new Scheme("https", socketFactory, 443);
httpclient.getConnectionManager().getSchemeRegistry().register(sch);
直接把這段拿去用當然只有一個死字。本來看討論以為是要製造一個假的空憑證騙過 httpclient,從 Android 檔案系統有點微妙開始改來改去,一連串不同的例外或直接crash就不多談了。解決了檔案路徑,到底有沒有建立等等方面的問題之後才終於發現,假憑證是不行的…
1. 所以首先,開啟你PC或Mac上的瀏覽器連上目標網站,從憑證管理的地方把該網站的憑證匯出。每個瀏覽器做法都不同,請各位發揮正常工程師的水準做完這件事。以Firefox為例,找到site名後選匯出,多半是會得到一個檔名為 your_site_name.crt 的 X509(PEM) 憑證檔。為了之後使用方便,先把這檔案複製一份並把檔名改為 your_site_name.pem。
2. 將這個憑證格式從 PEM 轉為 BKS 格式。 這是關鍵性的一步啊。
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
這行中的 getDefaultType 到底會 get到什麼 type 呢?答案:在 Android 中是 BKS。有 J2ME 經驗的人會想說,我看多半是跟 J2ME 一樣的 Sun JKS 格式吧,而且,我不要用 getDefaultType 就好了,我可以自己指定為 PEM, JKS格式啊。是的,你可以。只是你會得到錯誤訊息說 KeyStore JKS implementation not found。測了半天,看起來 Android 的 httpclient 只吃 BKS 就對了,其他都沒實作。
3. 那格式要怎麼轉?根據網路上找到的資料,可以使用 KeyTool IUI 這個Java工具。打開後從介面選 create → KeyStore,格式選 BKS,自己命名一下,要不要設密碼都可。接著選 import → Keystore’s entry → Trusted certificate → Regular certificate。 Source 的部分選 PEM 並選到剛剛瀏覽器得到的那個檔,Target 當然選 BKS 和剛 create 出來的檔。順利的話你應該就會有一個 your_keystore.bks 之類的檔案了。
4. 要把憑證檔放在 Android app 能讀到的地方,做法有兩種,放在 SD card 中,或直接放在 resources 中。
[方案一] 放在 SD card 的情形:首先模擬器要掛上SD card,這在 Eclipse 用 AVD 工具產生 avd 時就可以順便指定SD了。如果習慣用指令的話,也可以用如下指令產生 image 並 mount 上:
$ mksdcard 512M my_sdcard.so $ emulator -sdcard ./my_sdcard.so
再來要把憑證檔 copy 到 SD card 中,目前只知道指令的做法:
$ adb push file_path/your_keystore.bks /sdcard
如果有顯示類似 ftp 傳輸速度之類的訊息應該就是成功了。
接著把 android 程式碼中檔案部分改一改
FileInputStream instream = new FileInputStream(new File("/sdcard/your_keystore.bks"));
...
trustStore.load(instream, null);
如果沒設密碼,可以把 keystore load 的第二個密碼參數改成 null,有設的話當然就把 “nopassword” 改成你的密碼。
基本上這樣應該就大功告成了。
[方案二] 再講講憑證放在 resources 的方法。首先把檔案複製到專案下的 res/raw/your_keystore.bks 。Eclipse 沒有錯誤的話就 ok,否則多半是你檔名不合規格,稍微改改。接著取用方法是把 android 程式碼改成:
InputStream instream = getResources().openRawResource(R.raw.your_keystore);
其它同SD card。
5. 還有一個地方要注意,就是 SSL port。
Scheme sch = new Scheme("https", socketFactory, 443);
如果你要連的網站不是用 port 443,這邊請記得改掉。
6. 另外如果要使用檔案放在 resources 的做法,getResources() 應該只能在 Activity class 中執行,如果另外包裝連線類別的話請不要直接服用上面的程式碼,要自行從 context 抓到資源再傳過去。
看起來不太複雜的事情我其實還鬼打牆了滿久才解決,希望對各位有點幫助。
[筆記]Android 的 Activity Lifecycle
Activity Lifecycle實驗:1 = Root Activity, 2 = Sub Activity started by 1
Scenario A
- 先測單一Activity時,程式啟動,進入主畫面
onCreate 1
onStart 1
onResume 1 - 按 BACK,螢幕跑回桌面
onPause 1
onStop 1
onDestroy 1 - 選程式icon再進入主畫面
onCreate 1
onStart 1
onResume 1
結論:在 Root 按 BACK 等於結束程式。
Scenario B
- 程式啟動進入主畫面
onCreate 1
onStart 1
onResume 1 - 按 HOME,螢幕跑回桌面
onSaveInstanceState 1
onPause 1
onStop 1 - 選程式icon再進入主畫面
onRestart 1
onStart 1
onResume 1
結論:在 Root 按 HOME 只是把程式放到背景,重新進入後不會執行 onCreate。
Scenario C
- 程式啟動進入主畫面
onCreate 1
onStart 1
onResume 1 - 按下按鈕,進入畫面2
onSaveInstanceState 1
onPause 1
onCreate 2
onStart 2
onResume 2
onStop 1 - 按BACK 返回主畫面
onPause 2
onRestart 1
onStart 1
onResume 1
onStop 2
onDestroy 2
結論:在 Sub 按 BACK,Sub活動會消滅,另外看起來Android滿仔細的,停掉2重開1的流程是有巧妙的安排。
Scenario D
- 程式啟動進入主畫面
onCreate 1
onStart 1
onResume 1 - 按下按鈕,進入畫面2
onSaveInstanceState 1
onPause 1
onCreate 2
onStart 2
onResume 2
onStop 1 - 在畫面2,按HOME 返回桌面
onSaveInstanceState 2
onPause 2
onStop 2 - 選程式icon,會直接進入畫面2
onRestart 2
onStart 2
onResume 2
結論:在 Sub活動按 HOME 會暫停Sub (Root早就暫停了),再回到程式是直接 Reactivate Sub畫面
Scenario E
- 補充:在 textbox 打字到一半,按POWER鎖住螢幕
onSaveInstanceState x
onPause x - 解除鎖定,會直接回app畫面,並且之前的輸入到一半的文字不會消失
onResume x
Scenario F
- 補充:打字到一半,有電話進來
onSaveInstanceState x
onPause x
onStop x - 掛斷電話,畫面及游標回到原來的 textbox,輸入的文字還在
onRestart x
onStart x
onResume x
這裡面有個更讓我在意的事情,就是我在兩個Activity都有overwrite onRestoreInstanceState,並加入message,但是從來都沒有被呼叫過。官方手冊在提到 onSaveInstance 的時候,也是說明這儲存的bundle是讓你在下次onCreate時使用,並沒有提到 onRestoreInstanceState。不論如何,這兩個method並不是在 Lifecycle 中必定會呼叫的程序,不要依賴它們來儲存使用者輸入到一半的資料,照設計目的看來比較像是記住上一次是看到第二頁之類的功能。之後如果有讀到相關說明再補充上來。
上面的實驗雖然 onPause 和 onStop 總是在一起,但根據手冊,Pause 狀態跟 Stop狀態確實是不同。Pause狀態下,使用者不能與這個活動互動,但是仍然看的見它。也就是說如果你產生了一個透明的或不占到全螢幕的子活動,則主活動有可能只會 Pause,而不會 Stop。而Pause狀態對系統來說仍然是alive,只有系統資源真的太低時才會kill它,而Stop的活動相對來說很有機會被殺掉。(不知道 Alert Dialog 與 Parent是不是這種關係)
關於保存狀態或傳遞資料方面,官方SDK手冊強調,如果需要回傳結果給主活動,不要在 onDestroy 加入 setResult function! ,之前被 google 到的某論壇文章騙了,說可以在 onDestroy setResult,怒。根據手冊說,想要做保存資料,例如 user 輸入之類的事情應該放在 onPause,onDestroy 應該只做釋放資源之類的動作,因為 oPause是唯一一個保證會在系統 kill process 之前呼叫並且等待其return的function。實際上測試的結果,確實在 onDestroy 試圖 setResult 是沒有用的,intent 應該是會隨著此sub Activity 被消滅,onActivityResult 的地方會得到 null intent。一般來說返回鍵表示要放棄現在的動作返回,不保留狀態還算合理,但看了一下Android的通訊錄app,按下返回鍵時,其實還是當作 submit 立刻儲存了打到一半的資料,這可能是為了防止編輯到一半電話進來,資料全被清空的滿腔怒火。另外已經在背景的Activity是有機會被kill process的。萬一發生了這事情,在kill process之前會先 onSaveInstanceState(Bundle),下次再 onCreate(Budle) 時就可以使用這 bundle 的動態暫存資料。
總之,儲存永久性資料的動作可以在 onPause做,onDestroy只能做資源回收,比如 connection close,之後有其他心得會再補充資料。
[筆記]Android 多國語言
官網的Hello, L10N,還有 ADT plug-in 都叫大家使用兩個字母的語言代碼,例如 zh, en, ja 來分字串語系檔。圖片則規定要使用語系+地區,例如 zh-rTW。這時候最大的疑惑立刻浮上心頭,那簡體跟繁體字串要怎麼辦(〃*`Д´)。網路上沒有搜到甚麼資料,乾脆自己惡搞看看,直接把/res/values-zh/strings.xml 複製修改成兩份,變成 /res/values-zh-rTW/strings.xml 跟 /res/values-zh-rTW/strings.xml 內容當然分別是簡體跟繁體的。喔! 沒有編譯錯誤,很好。接著開始切換模擬器語系…おおお!還真的會分簡體跟繁體啊!教學幹嘛不寫啊!(`・ω・´)總之姊妹們,有需要的話語系分下去就對了(*´∀`*)
ps. 版本的話,SDK 1.1的模擬器只有德文和英文懶的測,SDK 1.5 和 SDK 2.01 是測試OK的,推論應該是只要手機有支援相關語系都可以。
[筆記]Android的返回鍵
從Main Activity 使用 startActivity 或 startActivityForResult 產生並切換到 sub Activity之後,如果按下返回鍵,會發生甚麼事? 本來很擔心整個sub Activity只是看不見,但仍然蹲在角落畫圈圈,隨著Main Activity一次一次的再度 startActivity 而產生撿不完的屍體。Google之後再測試一下發現好家在,按下返回鍵系統就會呼叫 onDestroy(),結束掉這個 sub Activity。上以前被寫得很爛的J2ME Midlet 嚇過,真的是很害怕屍體山啊,為了愛護大自然大家一定要做好資源回收喔。∑(´д`*)
關於 BACK key,HOME key,官方Dev Guide 的 Application Fundamentals 的 Activities and Tasks 這個 session 講得滿清楚的。你的整個 App 是一個TASK,root Activity 和 sub Activity,包括中間呼叫系統地圖在內,跑在同一個 TASK process,一個 TASK 就是一個 STACK。主活動也就是程式載入的第一個活動一定是在堆疊底端,它產生子活動時,子活動就被加入堆疊。按下BACK key 時,子活動就從堆疊中被拿出來(丟掉)。子活動的子活動當然也是相同。所以BACK key做的事情就是把現在這個活動拿去丟:P (各位兄弟姊妹們應該沒有忘記STACK是LIFO吧) 而HOME key又會做甚麼? 他不丟東西,他會把這整個TASK / STACK 放到背景。等你在別人家玩一圈,再度按下app icon,背景的那整包 STACK / TASK 就被放回前景。如果剛在是從某個子活動按下HOME,現在應該還是看到剛才的那個子活動才對。BACK key則還是負責殺掉目前的子活動,並不會回到你剛玩過的其他app。謎之聲:不知道為什麼忽然開始覺得好險沒有Forward Key。另外補充一點,就是如果離開去外面玩太久,系統會把TASK中的子活動都殺光,只剩下主活動,下次切回來時看起來就好像新開的應用程式一樣。
上面說的是系統預設行為,TASK 和 Activity 的行為是可以由一些參數設定加以改變的,這邊就不深入討論了。有興趣可以繼續看完上面給的連結。
私にとって、シャントット帝国最大の陰謀は…
クローン・タルタル部隊はフォモルだヽ(`Д´)ノ
這次更新之後先去解了超壯闊超感人的塔魯史詩完全召喚篇,接著看山多軍又一次學不乖沒帶解毒藥死掉,再勉為其難的拿了一下巴斯D3棍,之後當然就是衝S斯拉S女王的劇情了。解到萬歲牌塔魯部隊時,時間有些晚應該沒有野團shout了,就先去收集星屑順便開希望看有沒有現地團。這種時間…好吧雖然是米人勸誘就打看看吧。組到最後只有隊長是米人( ´Д`)=3 還是很沒耐性的米人(話說有幾個米人有耐性了) 我說看這編成沒黑,要回去換黑他不想等,當然沒兩下就全滅出來了。沒想到隊長居然畏罪潛逃,剩下五個『日人』,反正就先收星屑吧。後來T塔魯找了Y大來一起打,總之最後打贏了,跟日人也聊的滿愉快的,恩,這其實是前言。
其實因為上班後比較懶神兵勳章都被拔了兩階了,本來打算打完黑白香拖拖就再度封印,不過既然換了からくり士穿的加速褲子總要去感受一下。就這麼吃了一堆自主海老,升了好幾點沒力波後某一天,忽然想到詩跟召都40了還沒去拿AF1。就開著赤掛忍去震動的迴廊秒了一隻眼怪,想說沒練習過solo召喚獸,就又打了個土召換。開赤忍沒有D1也沒teleport可回家,就直接掏出了塔布戒。既然都飛到地下壕了,就去禮拜堂拜拜一下吧。跟fomor無冤無仇的我進了禮拜堂的fomor區當然是不會補消音,正在對書架上下其手找料理書的時候消音掉了。一瞬間忽然聽到fomor唱忍術的唱忍術,轟魔法的轟魔法,完全不知道發生甚麼事就看到本塔魯屁屁朝天了,而且周圍都是fomor,雖然掛了RR也不敢爬起來只好D4。゚(゚´Д`゚)゚。 我…我沒有殺fomor阿哪來的怨み…震驚之餘努力回想了一兩分鐘,忽然腦中浮出一整排黑黑的塔魯高唱香脫脫萬歲的場景(´・ω・`)
『ドルチェ.シャントット!』
『ドルチェ.シャントット!』

cyberduck for snow leopard
剛剛想要傳東西到 web hosting才驚覺我的太空鴨溺水了…直接連去官網又沒仔細看說明笨笨的抓了3.2.1版當然還是不work。原來for 64bit snow leopard要抓beta版的 orz,目前是3.3b4,提供給跟我一樣瞎的蘋果人….・゚・(ノд`)゚・.
Windows每次開機都檢查硬碟(chkdsk)的解決方法
前一陣子因為工作需要添購了Sony VAIO Z45的筆記型電腦。沒辦法,我的15吋蘋果書普羅2.5公斤,再之前曾經有一陣子會每天背出門,捷運沒幾站而且下捷運也走不到十分鐘就已經覺得很重。加上很久以前Toshiba SS電池的經驗,認為Notebook電池最好經常用光再接變壓器,沒想到才沒放掉十幾次,電池容量就忽然變成不到原本的一半。雖然我很愛我的蘋果但竟然沒買三年保,既然平常根本不帶出門就繼續當桌機了。好我承認很敗家,但是我桌上放不下一臺蘋果桌機,另外還有一台pc跟螢幕要負責FFXI(等XIV出來應該會升級吧)。總之綜合所有因素就買了1.5公斤的VAIO,而且當時想說Win 7快出了,也不用忍受vista太久。上週拿到Sony從日本快遞過來的7之後馬上升級,升級過程有不少讓人圈圈叉叉的抱怨就先不談,穩定使用了幾天後,某天開始忽然每次開機都會chkdsk..。我的天,這可是新到不行的電腦又很小心的使用,應該是軟體出問題。雖然如此解除了不少回憶中那幾天安裝的東西還是沒用,最後從事件檢視器發現最可疑的殺手竟然是最近VAIO自己更新的VAIO Edit Components。同時也Google到單純解決開機檢查硬碟的方法:
1. 執行 Regedit.exe
2. 找到機碼 HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager
3. 該機碼右邊應該有字串 BootExecute 它的值應該不是空白,而是autochk autochk*一類,將值清空!
完成,下次開機應該不會再檢查磁碟。而且不用擔心,真的硬碟出問題還是會檢查的,這個值只是暫存值,照理說磁碟檢查完就會清掉了。而因為某些軟體造成不正確關機時,系統會自動加入值引發下次開機的檢查。這次很可能就是VAIO這個軟體關機時無法正確停止造成的吧。總之目前我的狀況解決了,有類似情形的網友可以試試看。
星の神子で星間飛行
http://www.nicovideo.jp/watch/sm8683104
好久沒看到製作的這麼精美的塔魯動畫了ヽ(`▽´)/
タルの神子さまかわいいすぎる〜〜〜
鏡頭拉近時請注意神子手上是拿莫古麥克風…
旁邊還有溫國最偉大召喚士觀眾一名(受到某FF11 nico配音版影響總覺得大召喚士是石田..長得有像!)
續上篇:Nokia S60模擬器的小Issue
Nokia S60 模擬器預設是英語, 用它內建的瀏覽器看不到中文(當然也看不到日文), 當然也不能輸入。開始工作列的Nokia套件中有切換模擬器語系變成中文的程式捷徑,但經過 32 bit java安裝風波後這捷徑是沒有作用的。(應該說 Java SE SDK安裝之後, JRE的路徑已經換掉了) 請把捷徑內容叫出來,把 javaw.exe的路徑換成安裝 32bit jre的路徑, 就可以切換中文了。換成中文後,殘念是簡體中文介面,但顯示UTF8沒有問題,還有拼音輸入法可用。另外試著用模擬器中的Browser瀏覽網站,登入很容易錯誤,推測是模擬器在鍵盤對應上出了問題,尤其是按數字會錯很大,叫出軟體鍵盤用點的會改善,但還是很可能有錯,要自己邊點邊注意..總之只有一個慘字。順便再抱怨一下這S60模擬器真的好慢…loading霹靂久, BUG又滿多的,但感覺Nokia本身UI的設計還是好的,可以感覺到手機本身操作動線設計的精良和符合直覺。不過個人如果真的要買智慧型手機自用的話…應該還是iPhone吧ヽ(´ー`)ノ
另外試著寫了一下Nokia的widget, 玩玩看WRTKit,發現文件編碼如果是UTF-8 no BOM,模擬器就會顯示亂碼。改成 UTF-8 BOM 中文就會正常顯示,但部分日文顏文字會爛掉,不確定是模擬器支援問題或者是S60系列手機真的會這樣。用firefox看則當然是沒問題。另外如果要使用Nokia Web Runtime Plug-in for Aptana, 配合他的 Firefox預覽引擎的話則有一些特殊注意事項,如果有用到 Ajax, 會有一些安全性相關的細節, firefox會檔掉script, 必須手動改設定。詳情請自行參考Aptana Help中的 Nokia Web Runtime Plug-in Release Note。
Java ME SDK 3.0 and Sony Ericsson SDK 2.5 on Vista 64bit
最近在新買的VAIO上裝Eclispe Pulsar,當然也把Moto, Nokia, Sony Ericsson 的 SDK 一起裝上。不過試圖啟動 Sony Ericsson 的模擬器時出現找不到某個32bit檔案的錯誤。仔細去它的官網看才發現果然它的SDK只支援32bit,接著發現 WTK 3.0 也有同樣情形。本來還不覺得是什麼大事,反正暫時也沒有真的要進入開發階段,不如先移除好了。此時天地異變…移除程式出現一樣的錯誤,WTK拒絕讓我移除!!!我雖然不算有潔癖,但新買的電腦就給我出現有東西移除不了的該死的問題真是不能忍受阿阿阿阿。努力google之後在Sun本家的論壇找到解決辦法,就是系統要灌兩套JDK, 32bit跟64bit。然後讓這兩套知道要使用32bit的版本。雖然說不久後vista就會變成光,但win 7一樣是會裝64bit,應該是會遇到同樣的問題。以下就是解法:
- 先去抓 32bit 的 JDK 來安裝到跟 64bit JDK不同目錄下。
- Sony Ericsson的比較好解決,直接重新run installer他就會問你要不要重裝,選是之後會再問一次JDK路徑,而且還會自己去抓到32bit的路徑當預設值,裝完就會動了。
- WTK的話,據說有兩個解決法,但我傾向改文字檔法。要修改兩個檔案:
- <WTK家目錄>/ bin 下的java這個檔 (沒改名稱的話應該是 Java_ME_platform_SDK_3.0/bin/java ),文字編輯器打開看裡面就只有一行就是JDK路徑,改成你新裝的32bit的那個路徑。
- <WTK家目錄>/toolbar/bin 下的 java,同上。
- 把 <user home>/javame-sdk 這個目錄砍掉。
完成!
WTK應該會正常工作,當然uninstaller也是,不過或許就不一定要移除他了:p