發現這篇從08年年底到現在一直在草稿狀態,雖然只有一點點,不過還是貼上來好了,因為接下來不知道什麼時候才有時間更新...
偶爾嘗試點不同的寫作風格,就先用這篇開刀好了。本來想用敘事的方式來說明一下這個blog的排版原因和某些小細節,不過寫一寫發現有點難閱讀,所以改用Q&A的方式看看會不會有所改善。以下是左腦跟右腦的訪談:
Q:感謝你接受我的訪問,能不能請你大概聊一下整個版面的設計理念?
A:我希望我的讀者能在第一眼就很清楚文章的位置在哪裡,尤其是使用手持式裝置(PDA、SmartPhone甚至PSP)的讀者,這樣的讀者已經愈來愈多了。當然我也想提供行動裝置版的版面,不過在Blogger現有的template下是蠻難實現的。除此之外,在右側我放了一些Gadget,主要是希望能多些人交流。
Q:那配色呢,有什麼特別的原因嗎?
A:我想藍色是很貼近科技本質的一種顏色,所以我就用它當標題的顏色了。我曾經在白底黑字跟深底淺字兩種方式做徘徊,深底淺字的好處包括對行動裝置來說比較省電、對眼睛來說比較溫和,但是白底黑字才是大多數習慣閱讀的方式,另一方面由於blog可能會出現大量的貼圖,我不太喜歡貼圖跟背景色的反差太大(我想很多人都有在深色投影片貼過圖的經驗),所以最後選擇的是白底黑字。
8.20.2010
在Framework中加入自己開發的API
By
Michael
大家好久不見,今天要分享的是如何將自有API跟系統一起build並且能將build出來的SDK放在Eclipse裡面用,不過這招不適合要放到android market上的程式,如果是這種情況,你需要的是git並且做好管理(包括把Eclipse的sync選項打開,好像越扯越遠...)
我想很多人應該也跟我一樣,開發程式時會寫出很多共用的API(通常是utility API),或是很多程式都會去bind同一樣一個service,而這些code(包括AIDL檔)通常會有很多份copy在各個Eclipse的project內,造成sync上的問題。這還不是主要的問題,更主要的問題在於,如果你的程式用到了hidden API,那可是連在Eclipse中build都build不過,更別想直接跑在emulator或是透過新版adb install到target上(因為Eclipse有error就無法產生apk檔)。
為了解決這兩個問題,我想最好的方式就是把code放在frameworks中一起build,而build出來的SDK正好可以給Eclipse用。
假設今天com.blogspot.dejob這個package有a.java及b.aidl要放進framework,那麼請試著這麼做:
1. 把這兩個檔案放在frameworks/base/core/dejob/java/com/blogspot/dejob/底下
2. 更改build/core/pathmap.mk,在FRAMEWORKS_BASE_SUBDIRS最後面加上"dejob \"
3. 更改frameworks/base/Android.mk:
如果你的code沒寫錯,應該就可以看到SDK已經build完並且壓成zip檔了,接下來只要將這個zip檔解開,然後在Eclipse中指定SDK的位置到這個目錄就可以了。另外也建議在Eclipse的project中選clean將project重新build一次才能知道有沒有成功。
講一些題外話,最近一直在想要不要去應徵聯發科的android工程師,不過應該會被打槍吧,不知道還有沒有其他android相關的工作...
我想很多人應該也跟我一樣,開發程式時會寫出很多共用的API(通常是utility API),或是很多程式都會去bind同一樣一個service,而這些code(包括AIDL檔)通常會有很多份copy在各個Eclipse的project內,造成sync上的問題。這還不是主要的問題,更主要的問題在於,如果你的程式用到了hidden API,那可是連在Eclipse中build都build不過,更別想直接跑在emulator或是透過新版adb install到target上(因為Eclipse有error就無法產生apk檔)。
為了解決這兩個問題,我想最好的方式就是把code放在frameworks中一起build,而build出來的SDK正好可以給Eclipse用。
假設今天com.blogspot.dejob這個package有a.java及b.aidl要放進framework,那麼請試著這麼做:
1. 把這兩個檔案放在frameworks/base/core/dejob/java/com/blogspot/dejob/底下
2. 更改build/core/pathmap.mk,在FRAMEWORKS_BASE_SUBDIRS最後面加上"dejob \"
3. 更改frameworks/base/Android.mk:
在LOCAL_SRC_FILES這一段的最後加入dejob/java/com/blogspot/dejob/b.aidl,這樣就可以讓AIDL檔build到framework中,但是這樣還不夠,你還需要下一步才能將AIDL檔內的javadoc build到SDK的document內。 在aidl_files這一段的最後加入frameworks/base/dejob/java/com/blogspot/dejob/b.aidl - 在packages_to_document這一段的最後加入com/blogspot,意思是說com.blogspot底下的所有package都build進document。
- 先確認你不是用root權限來build code!
- 裝好所有toolchain及下載android source code(騙一點篇幅,雖然沒稿費...)
- 切換到android目錄下打". build/envsetup.sh",請注意最前面那個"點"
- lunch sdk-eng
- make sdk
如果你的code沒寫錯,應該就可以看到SDK已經build完並且壓成zip檔了,接下來只要將這個zip檔解開,然後在Eclipse中指定SDK的位置到這個目錄就可以了。另外也建議在Eclipse的project中選clean將project重新build一次才能知道有沒有成功。
講一些題外話,最近一直在想要不要去應徵聯發科的android工程師,
6.15.2009
在Eclipse下看framework的source code
By
Michael
參考: View Android Source Code in Eclipse
簡單來說,trace ADT的code會發現ADT會去android.jar同個目錄下的sources這個目錄找source code,
所以我們只要將android的java source code撿一撿,照package放到sources這個目錄就可以了。
所以參考link中的python script就是在幹這件事,不過我有兩點建議:
1. 在沒有make過的source code目錄下執行這個script:因為out這個目錄下有重複的java code
(而且out這個目錄有夠肥)
2. 把zippath = match.group(1).replace('.', '/') + '/' + file改成
zippath = 'sources/' + match.group(1).replace('.', '/') + '/' + file
這樣解出來的檔案和目錄就會放在sources目錄裡面了.
最近還在研究怎麼debug native code,之前make的gdb不能debug multi-thread的程式 = ="
看看android-ndk有沒有進展好了
簡單來說,trace ADT的code會發現ADT會去android.jar同個目錄下的sources這個目錄找source code,
所以我們只要將android的java source code撿一撿,照package放到sources這個目錄就可以了。
所以參考link中的python script就是在幹這件事,不過我有兩點建議:
1. 在沒有make過的source code目錄下執行這個script:因為out這個目錄下有重複的java code
(而且out這個目錄有夠肥)
2. 把zippath = match.group(1).replace('.', '/') + '/' + file改成
zippath = 'sources/' + match.group(1).replace('.', '/') + '/' + file
這樣解出來的檔案和目錄就會放在sources目錄裡面了.
最近還在研究怎麼debug native code,之前make的gdb不能debug multi-thread的程式 = ="
看看android-ndk有沒有進展好了
6.14.2009
Eclipse JEE vs Java 6 Update 14
By
Michael
如果你更新到Java 1.6 Update 14, 而且原本能跑的Eclipse突然不能跑的話,
將eclipse.ini中的-Xmx512m改成--launcher.XXMaxPermSize所指定的size試看看,
我是改成-Xmx256m就能跑了
將eclipse.ini中的-Xmx512m改成--launcher.XXMaxPermSize所指定的size試看看,
我是改成-Xmx256m就能跑了
3.28.2009
不知不覺都變月刊了
By
Michael
這個月的頭條就是筆者找到工作了,從事Android UI的設計。最近發現API Demo的sample已經不夠參考了,因為不同的device跟輸入方式所需要的UI是大大不同,而API demo基本上是以手機的應用為主,今天如果我是要設計成Nettop或是TV用的UI,絕不是把畫面放大就能草草交差的事。雖然筆者滿懷雄心壯志,但是在業界打滾幾年後也知道公司根本不會有那個耐心等我好好設計架構、做user survey甚至是發好幾版的demo template;"time to market" kills designs,難怪路上滿滿都是山寨UI。
大家也都知道現在工作難找,筆者也被凹了。對我來說,這也就只是一份工作罷了,如果可以,我還寧願自己寫程式去賣。
大家也都知道現在工作難找,筆者也被凹了。對我來說,這也就只是一份工作罷了,如果可以,我還寧願自己寫程式去賣。
2.18.2009
癮科技也有Android專屬子頻道了
By
Michael
網址是 http://android.cool3c.com/
這是比較偏向user端的site,開發者也可以藉此觀察使用者的需求。
順便更新一下近況,歷經過年,最近的工作機會“似乎”有那麼多了一些,所以最近忙著更新自傳履歷還有K書,不管未來是做什麼工作,基本功是一直要練的。明天又要去面試了,先這樣。
這是比較偏向user端的site,開發者也可以藉此觀察使用者的需求。
順便更新一下近況,歷經過年,最近的工作機會“似乎”有那麼多了一些,所以最近忙著更新自傳履歷還有K書,不管未來是做什麼工作,基本功是一直要練的。明天又要去面試了,先這樣。
1.04.2009
[C語言] Rounding 四捨五入
By
Michael
前陣子有公司找我去面談,結果被打槍了,心情低落了一陣子,所以一段時間沒文章。最近在實驗室BBS有學弟妹分享如何在Matlab呼叫C寫的code(因為Matlab實在跑太慢了,更不用說Mac版的),不過這不是重點,因為我的畢業論文就用過這招了,那段程式是用inline assembly做四捨五入,所以我想就來分享一點使用C語言實作Rounding(四捨五入)的各種方法與經驗。
一般人想到用C實作四捨五入,會有幾種方法?就我所知,至少有將近10種或是更多(不好意思,學藝不精),以下分享最簡單到稍難的方法,除此以外大概還有C++專屬的用法、CPU限定的用法(跟32/64-bit有關)以及使用magic number的用法,這些我就不多著墨了,有興趣的讀者可以用我前面提供的線索去找找。
1. 利用C語言中浮點數轉整數會把小數點去掉的特性,這是ANSI C裡頭制定的規格,所以大部份的平台都可以使用(沒有浮點數的就別來亂了),程式大概長這樣:
inline int myIntRound(double dInput)
{
if(dInput >= 0.0f)
{
return ((int)(dInput + 0.5f));
}
return ((int)(dInput - 0.5f));
}
2. 使用math.h中的round()函式,唯一要特別注意的是接回傳值是用double或int,永遠別忽略type casting所帶來的effort,使用方法很簡單,把值丟進去就行了:
double dResult = round(dInput);
3. GCC的math.h中可以找到nearbyint()這個函式,用法跟round()一樣:
double dResult = nearbyint(dInput);
4. 接下來這個方法其實有點脫褲子放屁,如果你的math.h沒有提供round()可以派上用場。一樣include math.h,我們改用floor()及ceil()來實作,程式碼如下:
inline double myFloorRound(double dInput)
{
if(dInput >= 0.0f)
{
return floor(dInput + 0.5f);
}
return ceil(dInput - 0.5f);
}
5. 接下來要介紹的方法就比較不那麼跨平台了,我們要使用frndint這個FPU指令,並且以inline assembly實作,在使用x86 CPU的Win32上的實作上大概長得像這樣:
inline double myDoubleRound(double dInput)
{
double dResult;
__asm__ (
"frndint;": "=t" (dResult) : "0" (dInput)
);
return dResult;
}
順道一提的是,某些math.h中的round就是這樣寫的。
6. 一樣用inline assembly,我們用到了fld及fistp這兩個指令,程式碼如下:
inline int double2int(double dInput)
{
int nResult = 0;
__asm {
fld dInput
fistp nResult
}
return nResult;
}
其實在使用fistp之前應該要先用fldcw設定rounding的方式,可以設定為最近的int,或是floor/ceil等。
=========== 我是分隔線 ===========
現在讓我們來測試一下各種方法的效能如何,筆者使用的環境是Mac OS X 10.5.6(Intel)、GCC 4.0.1,compile參數為-O2 -fasm-blocks,每個方法呼叫100000000次,以-3.5做為input,測試結果如下:
Math.round: 0.048509 sec, result = -4
Math.nearbyint: 0.045757 sec, result = -4
myIntRound: 0.045828 sec, result = -4
myDoubleRound: 0.045824 sec, result = -4
myFloorRound: 0.045940 sec, result = -4
double2int: 0.222163 sec, result = -4
前面的5種方法速度都在誤差範圍內,只有double2int的速度特別慢,這件事告訴我們:拔獅子的鬃毛不一定會長出頭髮,就算用inline assembly也不一定會比較快!另外不知道是不是筆者的compiler特別愛作怪,inline assembly加上volatile甚至還會拖慢,以myDoubleRound來說好了,我在__asm__後面加上__volatile__,測試結果竟然要0.457702 sec,足足慢了10倍!
小小做個總結好了,其實C語言有很多不起眼卻可以探討的主題,翻一翻GCC的code也可以挖到不少寶。以四捨五入來說,每種方法都各有優缺點,使用math.h的方法最容易實作,卻也會讓program image變大;使用myIntRound的方法如果回傳後是塞到double就需要cast的effort;採用myDoubleRound的方法需要FPU指令。要使用何種方法就見人見智囉。
一般人想到用C實作四捨五入,會有幾種方法?就我所知,至少有將近10種或是更多(不好意思,學藝不精),以下分享最簡單到稍難的方法,除此以外大概還有C++專屬的用法、CPU限定的用法(跟32/64-bit有關)以及使用magic number的用法,這些我就不多著墨了,有興趣的讀者可以用我前面提供的線索去找找。
1. 利用C語言中浮點數轉整數會把小數點去掉的特性,這是ANSI C裡頭制定的規格,所以大部份的平台都可以使用(沒有浮點數的就別來亂了),程式大概長這樣:
inline int myIntRound(double dInput)
{
if(dInput >= 0.0f)
{
return ((int)(dInput + 0.5f));
}
return ((int)(dInput - 0.5f));
}
2. 使用math.h中的round()函式,唯一要特別注意的是接回傳值是用double或int,永遠別忽略type casting所帶來的effort,使用方法很簡單,把值丟進去就行了:
double dResult = round(dInput);
3. GCC的math.h中可以找到nearbyint()這個函式,用法跟round()一樣:
double dResult = nearbyint(dInput);
4. 接下來這個方法其實有點脫褲子放屁,如果你的math.h沒有提供round()可以派上用場。一樣include math.h,我們改用floor()及ceil()來實作,程式碼如下:
inline double myFloorRound(double dInput)
{
if(dInput >= 0.0f)
{
return floor(dInput + 0.5f);
}
return ceil(dInput - 0.5f);
}
5. 接下來要介紹的方法就比較不那麼跨平台了,我們要使用frndint這個FPU指令,並且以inline assembly實作,在使用x86 CPU的Win32上的實作上大概長得像這樣:
inline double myDoubleRound(double dInput)
{
double dResult;
__asm__ (
"frndint;": "=t" (dResult) : "0" (dInput)
);
return dResult;
}
順道一提的是,某些math.h中的round就是這樣寫的。
6. 一樣用inline assembly,我們用到了fld及fistp這兩個指令,程式碼如下:
inline int double2int(double dInput)
{
int nResult = 0;
__asm {
fld dInput
fistp nResult
}
return nResult;
}
其實在使用fistp之前應該要先用fldcw設定rounding的方式,可以設定為最近的int,或是floor/ceil等。
=========== 我是分隔線 ===========
現在讓我們來測試一下各種方法的效能如何,筆者使用的環境是Mac OS X 10.5.6(Intel)、GCC 4.0.1,compile參數為-O2 -fasm-blocks,每個方法呼叫100000000次,以-3.5做為input,測試結果如下:
Math.round: 0.048509 sec, result = -4
Math.nearbyint: 0.045757 sec, result = -4
myIntRound: 0.045828 sec, result = -4
myDoubleRound: 0.045824 sec, result = -4
myFloorRound: 0.045940 sec, result = -4
double2int: 0.222163 sec, result = -4
前面的5種方法速度都在誤差範圍內,只有double2int的速度特別慢,這件事告訴我們:拔獅子的鬃毛不一定會長出頭髮,就算用inline assembly也不一定會比較快!另外不知道是不是筆者的compiler特別愛作怪,inline assembly加上volatile甚至還會拖慢,以myDoubleRound來說好了,我在__asm__後面加上__volatile__,測試結果竟然要0.457702 sec,足足慢了10倍!
小小做個總結好了,其實C語言有很多不起眼卻可以探討的主題,翻一翻GCC的code也可以挖到不少寶。以四捨五入來說,每種方法都各有優缺點,使用math.h的方法最容易實作,卻也會讓program image變大;使用myIntRound的方法如果回傳後是塞到double就需要cast的effort;採用myDoubleRound的方法需要FPU指令。要使用何種方法就見人見智囉。
訂閱:
文章 (Atom)