2014/12/25

Android Studio 筆記

最近Google releases正式版的Android Studio,並宣稱此工具將成為official IDE for Android。那Android未來還會繼續維護與發展ADT嗎?從Android用official IDE這字眼,並在官網上鼓勵大家轉到Android Studio的態度,個人覺得以Eclipse為基礎的ADT可能會走向尾聲了(參考這一篇)。

因為Android Studio的專案結構與觀念與ADT有蠻大的差別,所以一定要來瞭解一下

讀了一些網頁,把一些重要的記錄下來

Android Studio Overview
官方的資料一定是不可或缺的
我覺得這裡的workflow章節很重要,可讓我們可以瞭解一下這工具的使用概念
這裡稍作紀錄一下,Android Studio開啟是以專案(project)為單位(Eclipse則是workspace)
每個project可以包含一至多個modules(至少要有一個application module)。Module是個容器,用來存放與組織所需要的source codes與resources。Module又分為四種:
  • Application Module:可用來產出.apk檔來安裝至Android設備
  • Library Module:如其名稱,用來存放可被其他projects或modules共用的source codes與resources,以達到reuse之目的
  • Test Module:用來包含可對application projects進行測試的codes。其中講到"are built into test applications that run on a device",這等有時間可以來多瞭解一下
  • App Engine Module:可以與Google App Engine(GAE)結合,來整合device與雲端成為一體。這一塊對應該是做IoT的朋友可以多留意的

Android Studio vs. Eclipse: What You Need To Know
如果已經用慣Eclipse的朋友,可以先看看這篇,瞭解這兩者的異同
另外這一篇也可以參考一下

Android Tutorial for Beginners: Part 1
Android Tutorial for Beginners: Part 2
Android Tutorial for Beginners: Part 3
就如標題,這是針對正式版(v.1.0)所修改過的入門文,不是用之前beta版,有正確的畫面截圖,在學習時應該會減少很多混淆與誤解

Gardle
Android Studio並未採用Ant做為其build tool,而是選用了Gardle。因此若想把Android Studio玩好,把Gardle讀通也是必要的。
也可以參考Android官網上的Gradle Plugin User Guide


2014/12/12

GCMRegistrar置換為GoogleCloudMessaging的問題

GCMRegistrar已經宣告為deprecated,官方建議大家應改用GoogleCloudMessaging,並提供範例供大家參考


不過依照這份文件來實作時,當執行到 GooglePlayServicesUtil.isGooglePlayServicesAvailable (context); 時,會遇到  "The Google Play services resources were not found. Check your project configuration to ensure that the resources are included." 的錯誤訊息。

主要的問題在文件中沒有提到要在AndroidManifest.xml的application宣告中,加上
<meta-data android:name="com.google.android.gms.version" android:value="@integer/google_play_services_version"></meta-data>
然後在 /res/values/versions.xml 裡,加上
<integer name="google_play_services_version">6111000</integer>
至於這個version number應該填入什麼值?可以從 <sdk>/extras/google/google_play_services/libproject/google-play-services_lib/res/values/version.xml 中獲得。

另外一種說法,不應該把version number寫死,不過這個方法我還沒有試成功 (Eclipse)

參考文件

2014/11/26

真的不應該依賴software stack嗎?

在這篇文章中The full stack developer is dead, long live the un-stack developer,提出了un-stack developer的理念

不過現在的開發環境與應用平台,以及software reuse的概念下
不用software stack,什麼都自己動手做,在講求效率的今天,已經是接近天方夜譚了

也有許多開發者並沒有身處於start from zero的機會
不過開發者應該知道,一位好的開發者
必須要有從零開始的能力,必須要有設計架構的能力
並且努力為自己培養這樣的能力
因為有這樣的能力,才能讓自己有start-up的技能、觀念與胸懷

2014/11/17

Activity與Fragment間的轉場效果(transition animation)

為了要做Activity與Fragment間的轉場效果(transition animation),找了些資料來瞭解,覺得這些資料挺寶貴的,所以在這裡留下來。

贴一个定义android animation的应用实例
這一篇是簡體中文,針對四種特效(Alpha, Scale, Translate, Rotate)及相關參數有蠻詳細的說明

Various effect of interpolator in Android Animation
透過影片解釋不同的interpolator對於數量變化的影響

Android Animations Tutorial 5: More on Interpolators
用詳細的公式與圖表解釋不同的interpolator對於數量變化的影響

切換 ACTIVITY 的簡單轉場動畫
利用overridePendingTransition來進行activities間的轉場

android學習筆記之Fragment
用setCustomAnimations來達到fragments間的轉場

2014/11/12

ListView自我更新多次

剛剛開發一個有ListView的Activity,從SQLite資料庫取出資料,透過adapter將資料顯示在ListView上
資料庫中的測試資料總共有20筆
當畫面進入到這個Activity時,發現得花超過三四秒,才能將這些items顯示出來 (ASUS Nexus 7)

一開始以為是SQLite的效能太差,所以要花這麼長的時間,可是才20筆資料就花這麼多時間,效能也未免太差了
(select * from XXX order by YYY desc)
進入debug模式,發現其實從資料庫撈資料的速度很快,顯然不是SQLite的問題

經過一番追蹤,發現adapter裡的getView被呼叫了80次
才20筆資料,getView被叫了80次,也就是做了4次refresh
為什麼?

經過一番折騰與閱讀,總算知道主要原因是那個ListView的height設定為wrap_content,Android為了要將高度調整能wrap content,可能就必須不斷做載入與調整,也因此才會refresh了多次。
當把height改成match_parent時,果然這個現象就不會發生了。

2014/11/03

有時,工程師做的事是一種ART!

今天一整天,就只改了一行程式。

對,就只有一行!

我很偷懶嗎?才不,今天可是超級「精實」。
那為什麼只改一行而已?改一行要那麼久嗎?
如果你是主管,你會怎麼評斷這位工程師?

如果你是位注重量化,把「人月」、「line of code」「function point」掛在嘴上,透過一些指標,這位工程師的一天簡直是災難吧!

先聽聽我今天做了什麼事
一早被指派這個工作後,先瞭解問題是什麼,可能的因素又有那些,接著就開始設計如何測試來確定是什麼原因造成的。等確定成因,大概就過了半天。半天,真的很快了。

接下來,就是修正這個錯誤。對,就是改那一行!真的不是我偷懶,有問題的就只有那一行,所以也只能改那一行。(我也很盡責的加上註解喔)。這大概花了幾分鐘。

這樣不就解決了嗎?你還有半天可以做別的事呀。這半天被你摸掉了喔。

才不是啦。公司的機器有十幾種models,而這個程式會被用在所有的models中,所以,除了出錯的那個機種外,我還必須一個一個機種去做regression test,以確定這樣的改法在別的機種上也可以正確運作。等這些機種都測完,一天也結束了。

所以,別再用那些奇怪的指標來衡量工程師了。有時,工程師做的事是一種ART!
就好像,你不該跟梵谷計較,在那幅星空中應該多畫幾顆星星才比較有價值!

2014/11/02

大法官


大法官,看這片名,一開始以為是部精采的法律攻防片。不過,如果是被這樣題材吸引進入戲院,恐怕會失望了。這部片片中沒有著墨於太多的法律攻防,而是滿滿的父子間之關愛與衝突。在這裡就不破梗,有興趣可以看看火行者精采的影評

在片中,法律,對於擔任法官的父親,是正義;對於擔任律師的兒子,是工具。

兩位演員勞勃杜瓦(Robert Duvall)與小勞勃道尼(Robert Downey Jr.),真的演活了劇中的角色。另外,韋娜法米加(Vera Farmiga)在劇中很有戲的眼神,讓薩曼莎一角的浪漫不羈都活了起來,真的擄獲了我的心。
還有,Carla與Lauren都有咬頭髮習慣的動作與神情,真的是有趣的梗。

好了,談談我的感受,對於大部份的人子,父親,從小就像是大樹、就像是無所不能的超人。但隨著日子飛逝,人子逐漸長成大人,而人父也逐漸衰老。電影中最觸動我一幕是,法官父親在浴室狼狽的那一幕。
如果,你曾經看過父親年邁而脆弱的那一刻,你一定會警醒,那棵從小就庇護著你的大樹,已不再如你想像的巨大與堅強。那種警醒,會讓人很心痛,也會在你的心中烙下一個印痕,提醒著你有個時間終將到來,當那一刻到來,你不再有人可以依靠,可以幫你,可以再庇廕你。那種感覺,應該是為人子女的你我在心中會隱隱作痛的疤。

而在電影的最後一幕,律師走進父親的法庭,走上法官席,觸摸著父親坐了數十年的座椅,看著座椅旋轉。當座椅停下來,面對著他停下來時,我覺得在人子的心中,應該萌生出了一個決定!

2014/10/30

GCM推播訊息(notification)延遲問題

最近在開發Android APP,使用到GCM(Google Cloud Message),發現一個問題:
我們的server已經送出notification,可是Android phone/table有時很快(兩三秒)就收到推播訊息,有時則等超過10分鐘才收到。

雖然Google宣稱notification不保證即時送達,也不保證可以送達,不過我們還是希望在免費的服務下,能夠儘可能的即時送達
對有些應用而言,超過5分鐘就真的很久了

工程師個性使然,總是想找出是我們的server+APP有問題,還是其他因素造成。因為有時是即時就能收到,照理說應該不是server或APP的問題
找了andQlimax的po文,覺得他的測試與推論是合理的,也符合我所觀察到的狀況

手機/平板與GCM server間是透過TCP connection來進行通訊。當手機/平板連上網路時,Android就與GCM server建立連線。為了維持連線,手機/平板會定期送出heartbeat訊號到GCM server。andQlimax觀察到如果是使用3G/4G連線,則每28分鐘會送一次heartbeat;若是用WiFi則是15分鐘。(為什麼間距那麼大?這除了要考慮手機平板的耗電外,還有GCM server的負擔等等)

andQlimax認為一般電信服務商(3G/4G)或WiFi router(無線分享器...),就資源分配與使用效率等考量,通常不會無限維持這麼多的TCP connection(因為可以建立的connection數是有限的),因此這些設備(3G/4G:基地台; WiFi:無線分享器/HotSpot)會定期(例如每5分鐘)檢視那些connection是idle的(沒有傳送資料),就將這個connection關掉。

因為Android的heartbeat間距很長,所以手機平板與GCM server間的TCP connection會被關掉,因此當有訊息時,GCM server便無法透過原來建立的connection將訊息送到手機平板,必須等到手機端時間到要發heartbeat時,才會重新建立連線。
所以當connection還沒有被關掉,或是heartbeat週期很快又到了,手機平板就能很快的接收到推播訊息;若是connection被關了,那就得等到下一次送heartbeat時才能收到notification了。

andQlimax在很多論壇與管道都呼籲Google/Android應該修改heartbeat的傳送週期。不過看來到目前Google都尚未採納。

如果,真的有mission critical的應用,也許應考慮是不是用long-polling request等機制來作,而不依賴GCM。

2014/09/17

書摘:托爾斯泰藝術論


托爾斯泰藝術論(What is Art?)

促使人類進步的兩大重要因素:語言文字、藝術。

  • 語言文字;傳達人們的思想與經驗
  • 藝術:傳達感覺與情感

藝術是一種人類的活動,藉此將自己的感受有意識地傳達給他人

藝術感染力的強度取決於三條件:

  • 所傳達之情感的特別度
  • 所傳達之情感的清晰度
  • 藝術家的真誠度


2014/09/15

Android APP無法取得GCM notification token

維護一支具有GCM notification功能的Android APP,因應客戶customization需要,必須更改package name以及修改manifest裡的root package定義,這會影響generated出來的R.java的package定義,因此,須再針對受影響的各程式更改import路徑

這樣的改法應該是最簡單的,比用refactor功能變更各package的name快多了 (之前也遇到一樣的需求,這樣改就OK了,也不會大幅改變svn裡的架構) 

不過卻遇到了一個問題,當device送資料到server時,GCM register ID(token)竟是空的! trace一下程式,我有一個GCMIntentService class是繼承GCMBaseIntentService,原來override上層的onRegistered是會被呼叫的,現在程式一執行,這個callback function竟然一直沒有被叫用,難怪token會是空的。 可是,這又是那裡出錯了?改的東西好像也沒幾個,而且那些應該都不會影響到這部份的功能呀。

找了許多資料,也做了一些嘗試,找到了一個因素,就是這個GCMIntentService必須要在menifest所定義的root package,例如說,menifest定義的package是com.abc.app,則這個service也要在com.abc.app,不可以在com.abc.app.service等其他的package中,即使manifest對service的宣告是指向com.abc.app.service也不行! 所以,只好再用refactor功能,把這個GCMIntentService移到它該在的package中,這樣執行起來就OK了!

2014/08/20

Android開發,appcompat_v7需要進版本管控嗎?

用Eclipse或Android Studio開發Android APP的朋友會發現,在ADT 22.6以後,當建立新的專案時,都會多一個appcompat_v7(或appcompat_v7_xx)的專案。
這專案是什麼?有什麼用途?網路上已有不少文章,大家找一下就可以找到一堆了 (參考)

那當專案要進版本管控(SVN, CVS, etc.)時,這個自動生成的support library project也需要跟著進去嗎?
找了一些文章,似乎沒有找到有較明確的說法。
當然,一起納管一定沒問題,可是納管這個自動生成的project似乎很沒道理。

換個角度來思考,如果我們在沒有這個project的workspace中,可以讓工具自動再生成這個project,讓我們的porject可以正常運作,那這個appcompat_v7就可以不用放進版本管控了。

做一個實驗,模擬一下當從SVN or CVS check-out一個專案時,是否能把整個開發環境建立回來。
開一個新的workspace,把一個之前做好的project給import進來,當然如預期的,會有一大堆的錯誤。錯誤當然都是跟support library有關。

接下來就要把support library project建立起來。相信大家的環境一定會有Android SDK。接著我們就要從下面的目錄把support library給import進來
<android_sdk>\extras\android\support\v7\appcompat  (註:<android_sdk>是指你SDK的安裝目錄)
不過還是一堆error


看一下原專案的properties,其library的名稱是appcompat_v7,但我們import進來的名稱是android-support-v7-appcompat,兩者名稱不同,必須修改一下讓兩者一致。那要修改那一個?我比較偏好改support library project的名稱。因為改properties裡的library名稱,再commit回版本管控時,可能會影響到別的同仁。

在project上right-click,用refactoring的功能來改project name為appcompat_v7 (如果在上一步驟所看到的project name不是這一個,以properties裡的設定為主)

修改完後,Eclipse就開始重新build workspace,這時errors就消失了

試跑了一下,原project的功能都正常。因此整個開發環境都回來了。
透過這個實驗可以得知,我們可以不用把support library project放進版本管控系統中,之後也能把開發環境重建起來。

補註:想瞭解Android support library有那些及分別有那些功能,<android_sdk>\extras\android\support\README.txt這份文件是個好起點

2014/08/15

在Android中周期性更新ListView的內容

在一個Activity裡有一個ListView,需要每10秒鐘更新ListView的資料
用寫Java的傳統想法,寫出了這樣的程式
其中ListItemProducer.getInstance().getList()會傳回ArrayList<string>

ArrayAdapter adapter = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
  ...
  list = (ListView) findViewById(R.id.listView1);
adapter = new ArrayAdapter(ListActivity.this, android.R.layout.simple_list_item_1, ListItemProducer.getInstance().getList());
list.setAdapter(adapter);

timer = new Timer();
timer.schedule(new MyTask(), 5000, 10000);
}

class MyTask extends TimerTask {

@Override
public void run() {
adapter.notifyDataSetChanged();
}
}

一執行,當掉了,怎麼可能!?
這樣的Java程式我寫了無數次了,不應有錯呀
 靜下心仔細看了一下,原來出現"Only the original thread that created a view hierarchy can touch its views."的exception
Android只允許原始的thread去變動views,上面的MyTask是在另一個thread跑,不被允許去碰views
找找資料,Handler倒是個解決問題的好方向
於是加了這段

private Handler updateHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
adapter.notifyDataSetChanged();
}
};

然後把 MyTask改成

class MyTask extends TimerTask {
@Override
public void run() {
try {
updateHandler.sendEmptyMessage(0);
} catch (Exception e) {
e.printStackTrace();
}
}
}

讓MyTask在每次時間到時,透過handler來送message回原來的thread,讓原來的thread去做update views的工作

如何讓Android的WebView不會跳出browser來呈現網頁

在開發一個Android APP時,有一個需求是必須將網頁開在APP裡。

嗯...這不難,Android SDK有提供WebView元件可以用。用這段code就搞定了

WebView web = (WebView) findViewById(R.id.webView1);
web.getSettings().setJavaScriptEnabled(true);
web.loadUrl(url);

如果有這樣簡單,就不會寫這一篇了。
這樣的寫法當然可以將網頁開在WebView裡。不過,一遇到post form, redirect或其他的情況,就發現會跳出APP,用browser去顯現後面的網頁了。

做一下功課,瞭解了幾件事
  1. WebView如果沒有設定WebViewClient,那預設WebView會要Activity Manager來提供適當程式來處理這個URL。這也就是為什麼會跳出browser來顯現網頁
  2. 如果WebView有設定WebViewClient,這時會執行這WevViewClient的shouldOverrideUrlLoading method。這方法如果傳回true則表示APP會自行處理這個URL,否則WebView會接著出面來接手處理這個URL
瞭解了這段後,我們就須把剛剛的code改一下

WebView web = (WebView) findViewById(R.id.webView1);
web.getSettings().setJavaScriptEnabled(true);
web.setWebViewClient(new InsideWebViewClient());
web.loadUrl(url);

然後也要加個class
class InsideWebViewClient extends WebViewClient {
    @Override
    public boolean shouldOverrideUrlLoading(WebView view, String url) {
        view.loadUrl(url);
        return true;
    }
}

這樣,就可以達到需求了


2014/07/27

[讀書筆記]慢的力量

慢的力量

最近很多人在推動「慢」,「慢」學在快步調的現代社會,也引起大家的省思。

這本書個人覺得有點雜,除了講「慢」以外,也講了習慣、拒絕、拖延等等。感覺針對的不只是慢,而是在現今社會的人們常見的問題或毛病。每一個章節都提出了10個原則,來破除那些問題與毛病。

其實這本書要靜得下心才容易讀進去,也就是心要「慢」,才有辦法讀得進去。作者提出的問題與解決方案都很有道理,但是,也許要讀者自己覺醒,才能讓這本書發揮功能吧。

[讀書筆記] 創新拼圖下一步

創新拼圖下一步


這本書提到了世上有很多很棒的創新,卻是以失敗落場。雖然創新是許多企業與個人追求卓越的手段,但是為什麼有執行成果的創新,卻無法受到市場與產業的青睞?

書中提到了除了創新的執行力外,產業的生態系統也是不能乎視的重要因素。

Stackholders之角色與關係
一個創新的生態系統,會有許多的stackholders:
  • 合作創新者: 許多創新會與其他的創新有依存關係,若有這樣的關係,合作者的態度與意願就會左右創新事業的成敗
  • 垂直產業鏈:上游供應鏈是否成熟,下游的採用鏈的利益關係與採用意願也將會是成功的重大因素 [這點讓我想起五力分析]
時機
很多人有先發先贏的觀念,不過書中提出許多案例,當產品推出時,整個生態系統仍未完備時,反而會造成產品的失敗

書中也提到了幾個分析工具:

  • 價值藍圖:讓我們瞭解生態系統中有那些stackholders,他們所處的位置以及之間的關係
  • 領導棱鏡:用以瞭解stackholders的成本與獲益,藉以瞭解採用鏈中各環節的採用意願 [個人覺得這可以與價值藍圖結合,可以在一張圖中看到所有的資訊]
  • 先發者矩陣
若是無法使價值藍圖的採用鏈一路順暢,那就有重組價值藍圖的必要。重組可以透過下列方式來進行:
  • 什麼可以分離
  • 什麼可以結合
  • 什麼可以重新安排 (位置、角色)
  • 什麼可以減少
  • 什麼可以增加
[心得]
這本書提供了創新以外必須正視的問題,也提供了一些工具來協助我們分析產業的生態系統。不過也許是篇幅的關係,感覺內容稍薄弱了些。不過若能配合「競爭論」來思考,也能激盪出很棒的想法

2014/06/28

一份對我很有意義的公報,留做紀念


2014/06/27

一個在Chrome裡不斷觸發onload的問題

昨天接獲回報,原來一個Chrome瀏覽正常的網頁(內含SVG),不知為何在Chrome(35.0)中會一直閃爍。

看了一下,這閃爍是因為onload event一直被觸發,而且不僅是Chrome,連Opera(22.0)也有此狀況。這對難兄難弟同時發難,讓我想起了這則新聞 (Google將捨棄WebKit改用新的Blink瀏覽器引擎),很有可能是Blink這個JavaScript engine的onload event handler行為與其他engine不同,造成onload一直被觸發。

修改就不在svg tag中加onload=""了,改用JavaScript的方式,在程式的最後加上
<script type="text/ecmascript">
 window.onload = function(evt) {
   load(evt); } 
</script>


寫網頁應用的朋友可以注意一下這個問題,看看你的應用在這兩個browsers會不會有問題。

2014/06/11

OpenSSL CCS Injection Vulnerability

OpenSSL新公布一項針對CCS Injection Vulnerability的安全建議

此次漏洞是由KIKUCHI Masashi發現(lepidum.co.jp),影響的範圍有OpenSSL SSL/TLS 0.9.8, 1.0.0, 1.0.1。根據KIKUCHI Masashi指出,這個bug已存在達16年

KIKUCHI Masashi在下列網頁有對此弱點做詳細說明:網頁1網頁2


此次弱點是發生在SSL handshaking phase 4的CCS。要瞭解SSL的handshaking,可以參考這些文件
文件1 ,文件2 ,文件3

2014/05/28

加jQuery進使用MooTools的頁面

手邊有一些網頁用到了MooTools,不過為了一些需求,需要加進jQuery
看過一些網頁資料,MooTools與jQuery有某種程度的相沖
實際在使用時,jQuery不管加在MooTools前面或後面,原來使用MooTools的功能就出問題
後來經過一些嘗試,把下列這段加在MooTools之前
<script type="text/javascript" src="lib/jquery.js"></script>
<script type="text/javascript">
var $j = jQuery.noConflict();
</script>


這樣$保留給原來MooTools用,而$j供jQuery使用

怪,IE8顯示的資料少了

今天遇到一件怪事,面對同樣的資料來源,IE8的呈現出來的資料筆數竟然與IE11, Firefox, Chrome不同

環境
這是個web-based的系統,browser以AJAX,透過XMLHttpRequest向server取得資料後,再以JavaScript呈現在頁面

問題
以現有的設定應該會顯示出3筆資料,在Firefox, Chrome與IE11都正確顯示,唯有IE8只顯示出一筆資料。

解決過程
用Chrome的development tool來看,responseText拿到的資料是
192.168.10.120/1/1##192.168.10.57/2/1##192.168.10.63/1/5
(我們是用"##"來做分隔號)
但在IE8中,responseText卻是
192.168.10.120/1/1## 
所以,問題就不是在javascript把資料呈現在頁面這段,而是資料來源了。而這就有點詭異了,因為在同一個時間點,這設定是不會變動的,IE8理應拿到的是跟其他browser相同的資料才對。難道IE8有問題?
直接用IE8連結資料源的網址,咦~~,拿到的資料是3筆呀。所以IE8從server拿的資料應該是正確的。那問題是在IE8的XMLHttpRequest把我的資料暗槓了嗎?應該不會才對,其他相同作法的頁面都沒事呀。

在百思不得其解時,突然想起用Wireshark來抓抓兩端間的封包看看,果然有了重大發現。server傳回來的responseText在Wireshark看到的是
192.168.10.120/1/1##\000192.168.10.57/2/1##\000192.168.10.63/1/5

在每個## (分隔號)的後面,都多了\000,也許就是因為這個,IE8的javascript engine解譯為octal null character,對null-terminated string來說,這就是字串的結束,所以把後面的都忽略了;而其他browser的javascript engine則是忽略掉這個null character,所以才有這樣的差別。

看來問題是在server-side的程式了。
查找了一下server程式,果然發現該程式(C language)在把分隔號##寫入response chunk,給的length竟然是3,難怪會多出那個null character。改正後就沒問題了。

結案!

2014/05/19

datalist在Chrome跟Firefox的表現

HTML5的datalist在Chrome跟Firefox的表現還真是差別不小
以下面這個例自來看
<input list="states" />
<datalist id="states">
<option value="Kansas">
<option value="Missouri">
<option value="Colorado">
<option value="Nebraska">
<option value="Oklahoma">
</datalist>
a

如果在input field中輸入 "o",在Chrome與Opera中看到的是以o開頭的選項,而且有像select/option的下拉式操作


而在Firefox中所看到的,是選項中含有o這個字母的選項,且沒有下拉的三角形 (不過在input field中用mouse click,還是會有選項出現)






2014/04/18

10 Reasons why Java Rocks More Than Ever

我喜歡Java,從2000年開始使用Java到今天已經有14年了。對我而言,用Java來開發各種系統,都是很美好的經驗。

Java,對有些人來說,是種語言。但對我來說,Java不只單單是種語言,她還是個執行平台(JVM),更是個很漂亮的API。

今天看到這篇文章10 Reasons why Java Rocks More Than Ever,裡面提到的十點,真的點出了我也認同的Java十大優點:

Part 1: The Java Compiler
Java的結構讓Java程式在compile時可以快速且簡易,也沒有複雜的linking問題

Part 2: The Core API
經過十多年來的演進與累積,JDK core API無論在功能與效能上,都有明顯的進步。一般的程式,只要用core API幾乎就足夠了

Part 3: Open Source
這一點對我來說真的是獲益良多。Internet上充滿了一大堆好用的Java open source,你想得到或想不到的功能都有,讓我可以在很短的時間,就能做出符合需求的系統。不過對我也有些困擾,就是有太多類似功能的libraries/frameworks,讓我得花不少時間去評比與測試,來決定用那一個

Part 4: The Java Memory Model
Java在memory的規劃上完全支援了concurrency computing。這個只要用Java寫過threading就能體會它的好,連C++11與C11都加入了這樣的memory model了

Part 5: High-Performance JVM
JVM加上了JIT,讓這個雖然是虛擬機器(VM),但跑起來卻不笨重。有不少benchmark的評比,Java跑起來的速度不會差C/C++太多,尤其是在server environment,雖然有不少C/C++的忠實者不太同意,不過它的效能在一般用途上真的是夠好了

Part 6: Bytecode
bytecode對JVM來說,其實就是這個VM的machine code。所有的Java程式都要先compile成.class的file,裡面就是可以在JVM上執行的bytecode。現在也有其他語言(http://c2.com/cgi/wiki?OtherLanguagesForTheJavaVm)可以compile成bytecode了,所以不一定只能用Java語言才能寫出能在JVM上執行的程式了

Part 7: Intelligent IDEs
對Java programmers來說,這一點真的很幸福,像Eclipse, Netbeans這些IDE,功能強大,而且不用錢

Part 8: Profiling Tools
由於JVM的結構容易與外界溝通,所以Java的開發者有不少profiling工具,可以來量測CPU, memory等等的使用狀況,幫助做performance的調校

Part 9: Backwards Compatibility
當你寫了十幾二十年的程式,看到好久以前寫的程式,不用修改就能在新平台上執行,你就會知道那是何等值得感動的事
Java就是這麼可愛,不像某家公司,換個版就夠你改得要死

Part 10: Maturity With Innovation
Java從1995誕生至今也快20年了,它的成熟度如何,看看金融界使用的情況就知道了,連在火星上都有它的足跡。Java仍在演進,與時俱進地不斷創新功能,這也是為何有這麼多Java的死忠者願意跟著它走。

你喜歡Java嗎?Java還有很多我都還未接觸過的面,值得大家一起來學習與分享。

2014/04/15

OpenSSL的HeartBleed漏洞

最近OpenSSL的HeartBleed漏洞鬧得沸沸揚揚,讓很多使用者與開發者都心存恐懼。那到底什麼是HeartBleed漏洞?

從SSL/TLS的heartbeat機制講起
OpenSSL是SSL/TLS protocol的實作之一。目前這個漏洞也要從這個通信協定談起。詳細的內容大家可以參考wiki的文章,這裡不多做贅述。一般使用者最常使用到的應該就是其上層的https協定了。

當通訊的兩端建立起安全通道(secure channel)後,為保持此通道不會被結束,client端可以送heartbeat信號給server,而server則會回應給client。
如下圖,client會先送任意的內容及此內容的長度給server,server會再將此內容與長度回覆給client。這個內容的最大長度是64K bytes。



這種heartbeat機制是很常用的機制,很多協定或應用都會使用這樣的機制。但為什麼OpenSSL出了問題?

首先,OpenSSL只有1.0.1 ~ 1.0.1f這幾個版本有問題,之前的版本並沒有問題,之後的版本也修復了這問題。

其次,出問題是因為OpenSSL在實作上的問題,不是SSL/TLS通信協定的問題。
OpenSSL在實作上會開一個64K bytes的buffer space,供來自所有clients的通訊共用。當有來自client的heartbeat時,OpenSSL會將送來的內容寫到此buffer,再將符合長度的內容由此buffer回傳給client。
於是,這就產生了問題。如下圖,當有心的client送的內容只有5 bytes長,卻宣稱有25 bytes;OpenSSL server並沒有去查真正的內容是多少,完全信任client所宣稱的長度,所以會老老實實的送回25 bytes的資料給client。



我們可想想,如果client只送1-byte的內容,卻宣稱長度有64K bytes,則等於獲得了整個buffer的內容。再從這裡去過濾所得到的內容,或許就可以得到其他clients與server間的對話內容。(想想網路銀行、購物網站等等,他們不都是用https來傳送你的銀行帳號、信用卡號、識別碼...等等的機密或隱私資料嗎)

雖然對有心人來說,很難預測可以從這64K bytes中取得什麼資料,不過不斷地送heartbeat,再透過程式來自動過濾擷取到的資料,還是可以撈到不少有用的資料。

既然事情發生了,怎麼解決?
對server side的管理者來說,先看看有沒有使用OpenSSL,而且是1.0.1~1.0.1f這幾個版本。如果是,那就儘快換掉。
對client使用者來說,你也不知道那些server是用OpenSSL 1.0.1~1.0.1f這些版本。最好是跟相關網站確認他們有沒有這樣的漏洞以及該如何處理。如果資料已被拿走了,最好的方法可能就是把密碼、信用卡等等的趕快換了。

參考1
參考2


2014/04/13

安藤忠雄的建築http://www.benesse-artsite.jp/chichu/images/page_photo2.jpg

日前參加了由李清志教授主講的安藤忠雄作品導覽演講,雖然只有一個多小時,但讓我對他的作品有更多的瞭解

李教授一開始先介紹了安藤的生平,如何形成了日後他的風格與作風。接著介紹了清水混凝土的施工方式,以及安藤與他的工班間的磨合

李教授提到了很重要的一點,為何安藤的作品都是由清水混凝土構成,沒有太多的裝飾,因為安藤希望「讓光影在牆上表演」。
Yes! 建築的牆面是硬的,而光影則是軟的;建築物是靜的,而光影是動的,會隨著一天的時間與四季的變化而更動。有硬有軟,有靜有動,這樣就夠精采了。太多的贅飾反而模糊了重點。就用光影,讓建築物也有大自然的脈動。

李教授首先介紹了住吉的長屋,一棟佔地僅14坪的兩層樓矩形混擬建築,從外觀完全看不見窗,只有一個黑洞般的門,安藤留下了透空的中庭,讓屋子與四季互動

接著介紹大阪茨木市光之教堂,這個作品應該很多人都不陌生

還有北海道水之教堂,這是個很知名的婚禮教堂,李教授一直推崇這裡的美,並建議未婚的朋友如果想結婚,可以考慮這個教堂

李教授也播放了一段寶兒在這教堂所拍的MV,讓大家感受一下這教堂的美


介紹完西式教堂,李教授接著介紹了佛教的本福寺水御堂,這是蠻顛覆傳統的佛教寺廟建築,但若是從佛教的哲觀來說,也不會違背佛教的理念


接著稍微帶了一下淡路夢舞台
高瀨川邊的Time's商場

最後花了不少時間,介紹了瀨戶內海的直島,這裡有美麗的Benesse House旅店與收藏著莫內睡蓮的地中美術館(其實整個島都是美術館了),當然在這裡還有草間彌生的南瓜,這應該很多人都看過了

還有明石大橋旁的4x4


一個多小時的演講,雖然短短的,可是卻很充實。讓大家體會到安藤的作品不是只有硬梆梆的靜態建築,還有的是柔美的動態光影。讓我更知道要用怎樣的角度來瞭解與欣賞這位大師所追求的融入環境的作品。



2014/04/10

到Open Catalog挖寶


DARPA的Open Catalog將逐步公開許多軟體與文件,有空可以來挖挖寶

2014/03/21

FileDropJS 的 Java servier-side

最近要做drop file upload的系統,經過挑選,選擇了一個較light-weight的FileDrop (filedropjs.org)
不過它只有提供PHP server-side程式可參考,找了老半天,沒有看到Java的solution,於是只好自己來研究一下了
還好花一天的工就完成,在這裡做個記錄

protected void process(HttpServletRequest request, HttpServletResponse response) throws IOException {
PrintWriter writer = response.getWriter();
JSONObject obj = new JSONObject();

try {
saveRawDataToFile(request); // file upload by raw request

    obj.put(AbstractCommand.R_SUCCESS, true);
    obj.put(AbstractCommand.R_MSG, "upload completed");
} catch (IOException e) {
    obj.put(AbstractCommand.R_SUCCESS, false);
    obj.put(AbstractCommand.R_MSG, e.getMessage());
} finally {
    writer.println(obj.toString());
writer.flush();
}
}

protected void saveRawDataToFile(HttpServletRequest request) throws IOException {
String filename = request.getParameter("img") + ".png";
String outputFile = uploadPath + File.separator + filename;

InputStream in=request.getInputStream();
int size=request.getContentLength();

try {
OutputStream out=new FileOutputStream(outputFile);
byte[] chunk= new byte[size];
in.read(chunk);
out.write(chunk,0,size);
out.close();
} catch (Exception e) {
e.printStackTrace(System.out);
} finally {
in.close();
}
}

2014/02/17

發牢騷

早上看新聞,好多主題都繞在「xxx明星穿價值xxx萬的名牌服飾」,「xxx女星要嫁入身價xxx億的豪門」...

為什麼不提提這品質有什麼特色,有什麼故事,這個人有怎樣的奮鬥,怎樣的成就?
還是,我們窮的只剩下錢了?

而小孩在這種以金錢為主要刻度的環境成長,又會習得以什麼角度來看世界與人生?

2014/02/10

crontab的怪問題

上週總公司的PM告訴我,過年後回來開工,發現CVS server掛點,經過一天的搶救,才把CVS給救回來。

台中辦公室也有Subversion server,想說也該趁這機會建立自動備份機制,尤其這server是架在有點老舊的機器(應該快十年了吧,Ubuntu 8.10)上,哪天鬧脾氣,真的會欲哭無累。

SVN上總共有三十多個repositories。寫了幾個shell scripts,讓這備份機制可以一一將每個repository備份出來,經壓縮後,以ftp上傳到另一部主機。執行一下,OK,順利備份到ftp server了。接下來,只要設定一下crontab,這shell script可以定時執行就完成了。

不過,莫非定律果然無所不在--"Anything that can go wrong will go wrong.",想說老天怎麼會這麼善待我。用cron跑的,就只有備份出七個repositories而已。

怪了,怎麼會有問題,手動執行不是好好的嗎?
一個一個來查查...
權限有問題...應該不是,不然不會還完成七個
先把ftp上傳的功能關掉...還是一樣
會不會是備份出來檔案佔太多空間,改成dump一個就上傳一個,上傳完就砍掉local的檔案...還是一樣
...

黔驢技窮,不過這樣盲目亂猜太不科學了,應該要想辦法看一下執行過程的輸出,再對症下藥
把crontab裡的command由 xxxxx.sh 改成 xxxxx.sh > /home/yy/cron.out 2>&1
這樣執行時,就可以看到stdout與stderr的內容,才能避免瞎子摸象,用較有效率的方式解決問題

設定的時間一到,script開始執行,svn repository開始備份上傳了
一個、兩個、三個...六個、七個
嗯,準備看看cron.out能不能給我點靈感了
八個、九個、十個...
咦,這次怎麼沒有停下來
三十、三十一、三十二... 竟然全部備份並上傳完了

這是怎麼回事?
再把crontab的command改回原來的樣子,還是完成七個備份就停掉了
再把stdout, stderr的output加上去,備份功能又正常了

完全不解這是怎麼一回事!找了老半天,也沒看到有這方面的討論或敘述。有人遇過這樣的情形嗎?
不過至少auto-backup機制是能正常工作了。至於為什麼會這樣?再來慢慢找解答了。

2014/02/01

一段美麗的邂逅

在嘉義回台中的火車上,一位十歲的小妹妹就站在我旁邊。她不怯生地看著我,對著我笑。她的笑好可愛。我試著跟她聊天,她也很自然的與我分享她的生活趣事。

我們就這樣東聊西聊,也拿我在讀的書給她看,試著用最淺顯的方式說這本說講些什麼,就這樣一直聊到她在彰化下車。

雖然在車上要看的進度沒有讀完,不過能與這位活潑的小美女有這段美麗的邂逅,也是這個新年一個收穫。(也要感謝她的家人沒把我當怪叔叔,若我可以和她一路聊下去)

2014/01/07

JavaMail 遇到 MessagingException

使用JavaMail送信時,在開發的機器(WinXP)以及staging server(Ubuntu 11.04)上,都可以正常送出。但在正式server(CentOS 6.3)上,卻無法送出。檢視log file,發現有exception
javax.mail.MessagingException: 501 5.0.0 HELO requires domain address

關於這個exception,Oracle在官網上倒是有一些解說

回頭來瞭解SMTP protocol一下,參考了這一篇,猜測可能是OS沒有設domain name,用指令查了一下,果然是如此。所以問題不
在於OS,而應是安裝時有沒有去設domain name吧。
$ domainname
(none)


因為之後會deploy出去的環境,也不知道作業系統的管理者是不是會去設domain name,所以先從加property的方向來解決,看能不能work。


用這樣的方式,就可以正常送出mail了。
留個紀錄,以後如果再遇到,就不用找太久了。