2010年12月29日 星期三

[Android] Screen capture for Android

雖然Android可以透過ddms抓screen shot, 不過這樣畢竟沒iOS方便, iOS只要按個熱鍵就可以抓了, 不用接著電腦

要在Android上實現這功能其實也不難(不過,應該只能跑在rooted device吧?本文介紹的是直接跟AOSP一起build用platform certificate)

第一個直覺想到的是直接access framebuffer, 不過這樣實在太醜了, 我想要做的是直接利用Android既有的framework

想到framebuffer在往上一層就是surfaceflinger了, 稍微掃一下code果然發現有captureScreen這種東西, 所以下一步就是grep一下找看看範例囉!!沒想到, 運氣真好, 一下子就在 frameworks/base/services/surfaceflinger/tests/screencap 這邊找到範例, 還是一個standalone的程式

不過我想做的是直接收一個Intent就可以把screen capture到SD卡, 所以這個東西還要做進一步包裝, 於是動手把它包裝成JNI, 並寫了一個簡單的BroadcastReceiver去呼叫他.....花不到一個小時...搞定!!! XD

Source在這邊

不過, 這不是我原本想做的東西....繼續改... :P

社群問答網站 Quora

講到問答網站, 可能會想到的是Yahoo奇摩知識家, 如果是developer可能會想到StackOverflow

不過今年有另一個新型態的問答網站崛起, 就是以社群(Social network)為基礎的

這之中有一個由前Facebook CTO所創辦的Quora最近還蠻受注目的(至少是吸引到我的目光 :P)

最近看起來TechCrunch就很喜歡上Quora挖資料挖訊息:

詳見: Q: What Does Quora Mean For The Future Of Blogging? A: Business As Usual

 

Quora跟傳統問答網站不同的是, 它會依據你的興趣來列出關於你感興趣的主題的問題, 這樣一個好處是, 你會感興趣的東西通常會是你也會想知道答案, 或是你會知道答案, 這樣一來, 問出問題被有效回答的機率也會比較高

而他靠什麼來判斷呢?當你把你的Facebook帳號跟Quora帳號連結一起時, 它就會去Facebook找出所有你喜歡的, 建議相關的主題給你Follow, 還會自動Follow你Facebook上你也follow的朋友, 並且會根據朋友follow的主題來建議你, 這樣一來, 對於你喜好的精準度的掌握還算蠻高的, 你問的問題也有更大的機會讓真正對這主題專精的人回答

此外, 我最喜歡的功能是, 不但人, 主題可以follow, 你也可以去追蹤某個問題, 隨時可以得知有沒人對這個問題給一個不同的或是新的答案

有時候令人驚奇是, 出來回答你問題的人可能會跟這問題直接相關的人, 比如說你可能問一家公司的狀況或是相關問題, 搞不好這家公司的相關人士(甚至CXO)都跑出來回答你....

2010年12月28日 星期二

人體真是奇妙

最近老爸常喊胸悶,可能天氣的原因讓他心臟比較負荷不來,但醫生做了幾個檢查又查不到原因,只好安排入院再做一次心導管檢查
昨天東元的張醫師在檢查完之後很詳細的跟我解釋觀察到的
之前裝上支架的前端一點的血管後來也有阻塞,但他說不至於有太大影響,最讓我覺得奇妙的事,右邊的血管長新分支到左邊已經損壞的血管支援
生命真是神奇,就像株羅記公園臺詞一樣

2010年12月27日 星期一

[Android] Building Gingerbread for Nexus One

抓到Gingerbread之後本來要build一份給Nexus one的, 後來Build break後就懶得管它, 昨天稍微研究一下解法, 果然跟我想的差不多

Builde break的點在於libcameraservice, 主要是某H公司的camera driver並沒open source, 要build必須先從Nexus One取出binary來build, 但偏偏Gingerbread的libcameraservice跟camera driver的interface有變, 像是HAL_getNumberOfCameras, HAL_getCameraInfo在舊版的driver並不存在

解決的方法有兩種:

  1. 用dummy driver
  2. 加個wrapper給它

目前實驗出來的結果很...殘念..還是沒能讓它的camera可以正常使用... orz

第一個方法比較簡單, 只要改makefile: frameworks/base/services/camera/libcameraservice/Android.mk

把USE_CAMERA_STUB:=true變成always的true (就是把一些判斷都mark掉就好)

這樣build出來的就會是用camera stub

第二個方法可以參考這邊

這方法只是加個wrapper把需要的幾個function加上去, 並包裝舊的call

一樣要改frameworks/base/services/camera/libcameraservice/Android.mk, 只是多個目錄放wrapper

Cyanogenmod也是用同一招解決的, 不同的是, 它並沒多生出一個lib來放這warpper, 它是直接改在CameraService.cpp

其實是同一個方法, 由於它多生一個define : BOARD_USE_FROYO_LIBCAMERA來enable/disable這段code(畢竟Cyanogenmod不是只有for N1), 所以要在 device/htc/passion-common/BoardConfigCommon.mk 裡面加上 BOARD_USE_FROYO_LIBCAMERA := true 來把它打開

基本上, 兩種方法N1的Camera都等於廢了, 所以用哪一種都一樣 

 

 

 

2010年12月24日 星期五

聖誕活動

Download now or watch on posterous
p450.mov (2000 KB)

[Android] Getting package signature in runtime

如果使用過Google MapView你會發現G社會叫你用你的package signature去申請map key(參考這邊)

那MapView本身又是如何取得你的package signature的呢? 

其實很簡單, 可以透過目前的Context用Context.getPackageName()取得package name, 然後再利用package name去PackageManager.getPackageInfo()去查詢package的資訊(PackageInfo), 裡面有項資訊"signatures"就是我們所要的(一個package是可以被sign多次的)

Facebook Android SDK所提供的Single sign on (SSO)也是得先在server端註冊你的package signature, 這樣它可以避免別人偷用你的API key去做single sign on的動作(因為別人的AP可能不會跟你sign同一個signature)

但Facebook的SSO是透過Facebook for Android來做login的動作的, 你的application是透過startActivityForResult去叫Facebook for Android, 這牽涉到兩個不同的package, 如果依上面的例子的話, MapView其實是鑲嵌在你的UI上, 跟你的application是同一個package, 所以可以拿context來取得這資訊

Facebook for Android是如何取得call他的人的signature呢?

其實也是用PackageManager.getPackageInfo() 來取得, 但它如何知道呼叫他的人是哪個package的?

這只要組合兩個API就可以辦到了

第一個是Binder.getCallingUid() , 這可以讓你取得你的Calling process的UID

第二個是PackageManager.getPackagesForUid() , 這可以讓你取得屬於這UID的所有package

或許這邊你可能會有點疑問, 不是不同的package可以share UID嗎? 這樣取出來的package可能有很多個, 我怎知道用哪個? 我們目的只是要取得signature, 所以用哪個都一樣, 因為share UID的必要條件就是這些相同UID的package都是要sign同一把key, 所以只要找出所有package共通的signature就大功告成了 

 

[Android][筆記] Single Sign on with Facebook SDK

透過Facebook Android SDK去sign in Facebook其實很單純, 只需要這樣幾行code:

if (!facebook.isSessionValid()) {

    facebook.authorize(this, new String[] { "publish_stream" }, new AuthDialogListener());

}

 

其中AuthDialogListener是繼承自Facebook.DialogListener, 因為Authentication dialog是由Facebook SDK處理的, 應用程式只要負責處理onComplete, onError等等callback

但單純這樣的code會在手機內有安裝Facebook for Android時發生問題

因為後來Facebook導入所謂Single sign on的機制, 讓Application跟Facebook for Android是可以用同一使用者的

Single sign on的原理很簡單, 只是透過Facebook for Android去做proxy login的動作而已, Application只消去Facebook註冊一個自己的package signature就可以了

但由於原本舊的Login視窗是包在SDK內一起被build進applciation package, 但在SSO機制內, Dialog是由Facebook for Android出的, 因此如果沒有加下面的code, AuthDialogListener的callback都不會被call到

p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco} span.s1 {color: #9a1867} span.s2 {color: #0023c7} span.Apple-tab-span {white-space:pre}

protected void onActivityResult(int requestCode, int resultCode, Intent data) {

super.onActivityResult(requestCode, resultCode, data);

facebook.authorizeCallback(requestCode, resultCode, data);

}

這是由於Facebook SDK是用startActivityForResult去call Facebook for Android, 因此application必須加上這行自己接它的callback再轉送給原本的listener

2010年12月23日 星期四

最後一顆阿花合體

買GF-1之前本來是用Sony Alpha-100, 本來是Minolta 50mm F1.7, Sigma 17-70mm, Sony 105mm三鏡, 為了買GF-1, 賣掉105mm的, 而50mm F1.7懶的賣, 而且Sigma 17-70mm在之前變焦環壞了, 這兩顆就留了下來了

後來買了M42的老鏡加轉接環後發現手動拍攝也蠻好玩的, 所以就去買了Alpha to M4/3轉接環(有光圈播桿, 可調手動光圈), 接了50mm F1.7後, 覺得還蠻不錯的, 就想說壞掉的西格馬也拿去送修拿來用好了

送到恆伸修的經驗還蠻好的, 不得不說服務不錯, 星期一我用黑貓寄到台中的維修部, 星期二他們一收到就打來問我壞掉原因, 下午就跟我報價問我要不要修, 然後請我匯維修費, 費用匯完隔天馬上就說修好要寄回給我了, 今天(12/23)回到家, 包裹已經在等著我了

當然不用說, 馬上合體, 雖然不能自動對焦, 所有都得手動來, 但這還是一顆不折不扣到Marco, 對焦距離短, 以後有多一顆鏡頭可以應用了

這顆算是我第一顆單眼鏡頭, 當初買A-100沒買Kit, 買這隻當Kit, 雖然不是我最喜歡那顆(最喜歡的賣掉了), 不過也算蠻常用的(被我轉到對焦環壞了)

[筆記] Touch Draw with in HTML5

-- 前言 --

Safari2Phone做兩天就膩了(天呀, 我無可救藥), 昨天想到玩點別的

第一階段目標, 用"<canvas>" tag + JQMobile (其實非必要) 做了一個Tocuh Draw, 就是手指在Canvas上畫圖, 像這樣(這是測試結果):

----

測試平台: Nexus One (Android) + WebView

碰到的問題:

Canvas可以很正常的在Android上跑沒問題, 但主要是event的問題, 本來用addEventListener('mousemove', draw)的方式, 沒想到在mobile環境全部怪怪的

手機上的event應該是touchstart, touchend, touchmove, 其中touchmove跟mousemove有點不同, mousemove不用mousedown就會被觸發, 但touchmove卻是在有touch的狀況下才會發生

touch event的點也不一定只有一點, 所以有event.touches, 而這是一個array, 裡面放每一點座標, 像是clientX, clientY之類的

Canvas的部份, 用moveTo->lineTo來畫這些經過點就可以達成了(筆記: 下一步做一個queue來儲存)

Simple, Creative, Fun?

好久沒po個幾篇胡言亂語了

這陣子聽了不少觀念, 也想了不少東西, 也開始抽時間做一些自己想study的, 很久沒去做這類的事了

昨天去了Trend Micro, 也趁機跟老弟聊了一下, 交換經驗

又開始想, 自己到底想要做些什麼? 又是想以什麼樣的態度來處事?

一天過去, 其實也還沒啥結論, 不過有幾個字一直在腦海繞來繞去.... Simple, Creative, Fun

或許, 如果做事可以just for fun應該可以快樂很多, 如果做事情可以用更creative的方式來做, 也應該會快樂很多, 至於生活, 簡單, 或許才可以多活幾年吧....

2010年12月22日 星期三

[Safari Extension] Safari2Phone

其實這是我自己無聊寫的啦, 這是我第一隻Safari Extension, 不過我不打算publish到Safari extension網站, 放這邊就好, 請點此下載

這是從Chrome2Phone porting來的, 如果不知道Chrome2Phone是啥東西, 可以先看一下這段影片:

要玩這個東西, 首先你必須要有隻Android手機....

然後Android手機上必須裝Chrome2Phone:

裝完後, 你會發現有個烏七媽黑的button 在你的tool bar上(抱歉, 沒做美工... orz)

當你想把正在看的網頁送到手機上, 就按下這個button, 如果沒有登入, 會有一條新的bar上面有顯示訊息叫你登入, 點選連結即可登入

 

Chrome extension跟Safari extension本質上蠻像的, 所以要po蠻容易的, 基本上花了我一晚上的時間, 從開始看Safari extension的文件開始, 到這個可以正常工作, 今晚回來後又稍微小修點bug再release

Chrome2Phone本身原理也蠻簡單的, 加上也open source, server端跟Chrome extension端都有source可看, extension端其實只是透過XMLHttpRequest把資料傳送過去, 這部份甚至可以原封不動reuse

讓我花比較多時間才發現的是, redirect url居然hard code在server端, 導致我的extension最後登入完只能被導到醜醜的圖, 本來想透過injected script讓他碰到那張圖的url就導到我的page, 但似乎好像沒辦法在tab內開啟extension package裡的一個HTML

總之, 先這樣, 有空再修好了, 繼續找看看有沒其他好玩的來玩..

2010年12月21日 星期二

開發Safari Extension (之一)

現在的Browser好像不開放給人家掛一些外掛就落伍了, 大部分的Desktop Browser也都有提供這樣的功能, Apple的Safari也不例外

開發Safari Extension其實不難, 如果有開發過Google Chrome browser extension的話, 可能還更好上手, 架構差不多類似, 文件也沒很多, 大概花個半小時看一下文件就應該可以上手了 

不過, 前置作業的門檻可能就大了一點了!

首先....你必須要有台.... Mac ... 光聽到這需求感覺就很鳥, 我沒在Windows底下的Safari開發, 所以我不確定有沒方法解決, 不過我相信, 至少要能找到Keychain的替代方案才可以! 所以, 用Mac是最保險的!

然後你必須上蘋果的開發者網站去申請一個Safari developer的帳號, 好消息是, 這不像iOS developer方案是要錢的, 它是...完全免費

有了帳號後就要申請憑證, 申請憑證先要透過keychain這隻MacOS內建的程式去產生certificate request (CSR)檔, 如下(中文是憑證授權要求憑證...好爛的翻譯):

把CSR檔上傳後就可以產生憑證, 記得下載回來安裝, 不過這邊有點要注意一點, 用Chrome browser上傳總是會失敗, 用Safari就沒問題了, 光這部份搞了我一個晚上... orz

要開發Safari Extension的起始點是Extension Builder(延伸功能建構器), 打開你的Safari然後從"開發人員"->"顯示延伸功能建構器"

打開後從"+"的地方新增新的Extension, 它會讓你指定你Extension要存放的目錄, 之後只要把你的程式還有資源(圖檔等等)都copy到這目錄即可

先設定一下你的Extension的基本資料:

此外別忘了設定存取權限, 如果你的Extension要存取比預設多的資訊

接著設定一下幾個主要的元件, 以及資料庫所需要的容量大小(如果你會需要儲存資料的話)

這邊稍微簡單介紹幾個基本的元件, 以後有空再細寫

基本上一個Safari extension可以由以下的幾種東西構成

  1. Global page : 不會被顯示出來的一個背景頁面, html檔案, 通常用來提供function而非顯示
  2. Tool button : 工具列上的一個按鈕 (由新增工具列項目那邊新增)
  3. Context menu item : 按滑鼠右鍵叫出的選單(中翻譯成特色選單)
  4. Extension bar(中文翻譯成"列") : 一整列工具列, 可以由一個Html檔案來構成
  5. Injected script : 像是Chrome Browser的content script, 嵌入到網頁的java script
  6. Injected style : 嵌入到網頁的style sheet

基本上這些都可以在extension builder這邊設定, 不過看API, 也應該可以由程式動態控制去設定, 大概組合這六樣就可以簡單寫出一個Safari extension了

2010年12月19日 星期日

^$%$%!*..... Safari Developer certificate申請記

之前申請iOS的certificate, 因為是用XCode直接產生完的, 並沒注意到這問題, 昨天想到要申請一下Safari的, 沒想到搞半天, 用keychain產生好幾個不同的csr檔都沒過.....快氣死了!!

沒想到後來改用Safrai連developer網站申請, 一次就過...

用來問題在於:

我用Chrome Browser呀!!!

真是OOXX....

君遠, 凱依和凱呱

小遠有許多的玩偶, 每個他都取個名字, 連杯子都有名字, 而且都是"凱"字開頭的, 他最喜歡的就是凱依

今天早上一起床, 小遠抱著凱依跟他的妹妹凱呱來跟我說:"把拔, 來幫凱依跟凱呱拍照吧!"

然後凱依跟凱呱就拍下這一張合照:

P1020062

小遠: "怎麼辦!怎麼辦!凱依不會站!!!"

P1020063

於是....小遠就抱來他的乖乖桶...."這樣凱依就能站了!!", 小遠說

P1020064

我說: "你要不要跟凱依跟凱呱一起照一張呀??"

小遠說: "好呀!"

P1020065

我說: "你都沒笑, 不好看, 再一張!"

"要笑開心點喔! 1....2.....3!"

P1020066

 

呃~~~~我說呀~~~~ 這表情是大吃一驚吧.... = ="

很久之前無聊寫的Chrome Extension

Chrome Extension其實還蠻簡單的, 之前無聊試寫了一個, 其實也不是啥大東西, 就只是去氣象局抓張最新的衛星雲圖回來

沒啥code, 隨便把它開放出來好了:  https://bitbucket.org/fishuman/taiwansatimage/src

2010年12月16日 星期四

"When you hit a certain point, enough is enough." - Cliff Lee

今天早上看到Cliff Lee這段話:

"It's plenty of money," he said. "When you hit a certain point, enough is enough."

最近他的新聞實在不少, 也算大條:

Phillies introduce their newest ace in Lee

Big deal: Cliff Lee says $120 million was enough

說實在的, 捨洋基就費城, 並不能說是啥不對的, 只是錢比較起來較少而已, 費城給的也是一大筆錢, 並不能說少

但我實在蠻佩服他的不貪心, 持續追求挑戰, 追求成就感的那種心態

"The intensity that you can feel when you get in the game, you can feel the volume every game," Lee said. "Every game has got an elevated feel to it compared to everywhere else."

這世上, 要能夠講出"enough is enough"的人實在不多了

[iPhone] GyroCompass

很炫的指南針,其實也沒啥太特別的,會隨手機方向轉動,以及實景

早餐 楓糖唱片

這在台北火車站二樓的米哥麵包買的

名字叫楓糖唱片...正面就跟一般黑膠唱片長相很像, 然後大到比臉還要大

昨晚買來當早餐吃的

還蠻好吃的.. ^^

Angry birds版iPhone4後蓋 非常隨便 開箱

從Gear4說要出這款iPhone4外殼後, 我就注意他很久了, 一來我的iPhone4也沒有殼, 二來, 我也蠻喜歡Angry Birds的, 這的確是很適合發洩的好遊戲

上次去逛街, 在新光三越的蘋果店有看到, 但那時候看到的是iPod touch版本, 還沒有iPhone版, 有點小失望

後來回來到拍賣網站上也只看到從香港代購的

前天一時興起跑到PCHome上搜尋Angry birds, 居然被我找到了!!!馬上二話不說下訂, 今天終於拿到了(為啥不是24HR到貨!!!)

至於為啥買豬呢?因為......怕我自己太狂熱了, 看到鳥就想拿起來丟!!!!

[iPad] FlipBoard有新版囉!

Flipboard是iPad上相當有名的軟體, 它相當的創新, 把你在Social network上的資訊編排的像雜誌一樣讓你閱讀, 後來也有很多軟體仿效

今天終於出了新版了, 而且是一個相當棒的大改版, 不只加了很棒的功能, 而且這些功能還是來自於user的feedback, 表示這一家公司一直有在聆聽使用者的心聲

新的功能最重要的是加入了Google Reader的支援, 雖然RSS Reader不算Social network, 但Flipboard把它當做另一個social stream的來源, 其實也算蠻合理的啦

而且還可以在Google reader上筆記

另外也支援把新聞Post/Share到另一個Social network的功能

Facebook的部份不只支援自己的新聞更新, 還可以看自己的wall, 也可以看自己Favorite的page的新聞更新, 還可以單獨看你設定的某個群組(list),我想搞不好不久後就有可能支援Facebook Group了

我最喜歡的就是, 終於...支援Flickr了!! Contacts, Photostream, Favorites一個都不少, 更棒的是還有Interestingness和Group, 對一般輕度Flickr使用者來說, Group或許沒那麼重要, 不過很多重度用戶, 常常會去看一些Group pool裡面的照片, 這功能就相當實用了!

Interestingness是我個人最喜歡Flickr的一個功能, 我常常會去這邊瀏覽一些別人的照片, 有新奇的, 有有趣的, 也有賞心悅目的, 但除了網頁外的大多數應用程式都沒支援, 這提供我除了網頁以外另一個可以看Interestingness的地方

 

2010年12月12日 星期日

花博便當

P1010925P1010927P1010931P1010940

這雖然不是傳說中的陶瓷便當, 但也是相當特別的便當, 在吃飯的時候, 工作人員還特別跑來跟我們說, 這便當盒是環保便當盒, 吃完別丟掉, 可以帶回家洗一洗再利用, 可以微波 (不過這一個多少錢, 我是不知道, 老弟去買的)

除了便當盒特殊外, 裡面的內容也不含糊, 日式的菜色, 主菜有炸豬排, 配上黑豆, 海帶芽, 牛蒡, 筍乾, 花椰菜, 還算蠻健康的, 還蠻好吃的, 不過對於食量大的人, 份量可能不夠就是了

台北花博遊

Taipei International Flora Expo

第一次到台北花博...第一個印象是....人應該比花還多!!!

這麼兇猛的人潮還真是恐怖呀!!!

園內的花其實算相當多樣化了, 有些我還是第一次看到, 比如說這個玫瑰聖誕紅

P1010900

雖然沒有原本大品種的聖誕紅來得大來的喜氣, 但這樣一整片還蠻漂亮的呀!

缺點是所有的館, 一大早預約券被拿光光, 沒有一個館有去的(加上老爸身體不好, 又帶小遠隨行, 實在不好去排長長的隊伍), 不過, 反正這邊有的是花, 拍拍照也很好, 當然不能免俗的多拍些照片囉!

P1010994P1020020P1010976P1020052

 

不過也發生一件令人很生氣的事

排隊等遊園車時, 一群阿桑就這樣很順的從我們後面往前面插隊, 一開始雖然不爽, 但想說他們年紀大, 不好跟他們大小聲, 就沒計較了, 沒想到後面還有兩個, 因為正好穿不過去, 被我們擋到了, 然後就跟我們說, 他們跟前面的是一夥的, 可不可以讓他們過去, 我本來還很客氣的說他們插隊已經很不對了, 還要求我們讓路, 這樣有點過分, 然後他們居然開始怪起我們說如果讓他們跟同伴走散了怎麼辦, 我就沒好氣的說, 我爸爸也在前面, 就剛好在他們同伴前面, 我也被他們分散了, 我都沒說話了, 更何況這樣惡劣的插隊本來就很不對, 我就沒讓他們, 然後他們就在那邊一直唸唸唸的

看他們是長輩, 不想跟他們太計較, 不過, 說實在的,  這樣的行為真是沒水準

後來我媽說, 她上次來的時候更誇張, 人都坐下來了, 居然有人指著她說"這我的位置"然後趕她起來, 她一開始原本以為坐到啥對號座, 但後來想到這根本沒啥對號座呀, 她先來, 而且坐下來了....

真不知道現在的社會是生了什麼怪病呀!

2010年12月11日 星期六

原夜市鴨肉麵

今天去新竹空軍基地後, 跑到"原夜市鴨肉麵"去吃炒麵

很久之前, 工作的公司就在新竹武陵路那 (再過去就是空軍基地), 下班回到租屋的地方的路線會經過這裡, 偶爾會去這邊吃, 不過那已經是好多年前的事了, 今天順便去回味一下

點了炒麵, 跟炒大腸:

P1010824P1010823

這炒麵看起來好像不怎起眼, 也沒看到鴨肉, 其實鴨肉都在底下啦! 只是現在鴨肉越給越少, 好像就跟單炒麵差不多, 不過這家還算不差

地點在新竹中正路跟經國路交叉口那邊, 旁邊有家7-11, 對面有停車場

2010年12月8日 星期三

[筆記] 產生 Web page thumbnail (續前篇)

前篇提到利用CutyCapt來產生Web page thumbnail, 不過畢竟CutyCapt是C++寫的, build出來也是一個執行檔, 寫完上一篇就有股衝動想用PyQt來做, 反正一樣可以利用Qt/WebKit, 原理應該相同的

沒想到, 真的那麼簡單, 只用了二十幾行code就可以辦到了

這邊主要利用到的一個class就是 QWebPage , 透過這個class我們就可以很簡單的達成這任務

為了程式的重複利用性, 我把它包裝成一個class PageRender:

class PageRender(QObject):

    def __init__(self, url, outfile, scale):

       QObject.__init__(self)

       self.outfile = outfile

       self.scale = scale

       self.web = QWebPage()

       self.web.mainFrame().load(QUrl(url))

       self.connect(self.web, SIGNAL("loadFinished(bool)") ,self.loadFinished)

 

    def loadFinished(self, b):

        print "load finished"

        self.web.setViewportSize(self.web.mainFrame().contentsSize())

        image = QImage(self.web.viewportSize(), QImage.Format_ARGB32);

        painter = QPainter(image)

        self.web.mainFrame().render(painter)

        painter.end()

        thumbnail = image.scaledToWidth(self.scale)

        thumbnail.save(self.outfile)

        app.exit(0)

 在Constructor那邊做的就是把loadFinished跟我們實際處理save to thumbnail的function connect在一起

而在loadFinished那邊就是實際render到image的部份, 這邊要注意的是:

self.web.setViewportSize(self.web.mainFrame().contentsSize())

這是把QWebPage的View port size設成跟實際content一樣大, 後面接著我們就可以建立QImage跟其相對映的painter, 然後用QWebFrame的"render()"把它實際輸出到image

最後scale到我們想要的大小(pixels)

這邊是一個實際call它的範例:

p = PageRender("http://www.yahoo.com.tw", "sssss.png", 200)

結果:

實際的程式可以在此下載

2010年12月7日 星期二

Social networking with mobility

本來想寫一篇這主題的, 後來想想, 跟自己工作太過接近, 寫了也不好, 所以這篇單純來推薦一篇好文:

Social Networking: The Future

其中的"Social Graph will become portable", 其實我想的稍微多了點, 不過還是先推薦這篇就好

[筆記] 產生 Web page thumbnail

剛突然想弄一個可以產生Web page thumbnail的service

第一個想到的是能不能用Webkit做一個, 不過, 自己寫, 有點太麻煩了, 想說應該有人做過, 後來就找到這個: CutyCapt 

這軟體是用qt寫的, 也不會很複雜, 只有六百多行 (有點想用PyQt仿一個 :P), 也很容易就可以build起來了(只要qmake; make), 但記得要裝libqt4-dev就是了

使用方式很簡單:

CutyCapt -url=http://julianshen.posterous.com -out=julian.png

但產生的檔案, 是一整個頁很大一張, 像這樣(點開可以看大圖) :

這樣就不能算是thumbnail了吧?

所以只好拿ImageMagick來剪成200x200的Thumbnail

我用的command是這樣:

convert -resize 200 -shave 0x200 julian.png julian_small.png

出來的結果:

再找時間包裝成一個web app吧~~

[Android] Access remote data on another process using ContentProvider and Cursor

這篇要示範的是, 如何寫一個ContentProvider讓其他的應用程式透過這個Provider去存取網路上的資料

這不是正統用法, 不過的確可以這樣用, 那為啥要這樣呢? 只是好玩, 還沒想到特別的應用

這邊用的範例是Twitter search (search keyword): MLB

首先要建立一個放Provider的Package, 不過這個Provider不是拿來存取DB的, 傳統的Android ContentProvider通常是用來存取資料庫, 但那並不代表那就是它的全部, "Content"Provider不就是拿來提供"Content"的嘛?管他Content哪來

建立一個Provider, 姑且叫它做TwitterSearchProvider, Authorities定為twitter.my.search好了, 裡面, 先只實作一個"query" 

p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco} span.s1 {color: #9a1867} span.Apple-tab-span {white-space:pre}

public Cursor query(Uri uri, String[] projection, String selection,

String[] selectionArgs, String sortOrder) {

return new TwitterSearchCursor();

}

這Query啥事都不用作, 回傳個TwitterSearchCursor就好了

從這看出玄機了嘛? 我們就是要利用Cursor, 在Cursor裡面實作連接網路取得資料的動作

後面我懶得寫解釋了, MBP快沒電了, 以下就是TwitterSearchCursor的Source:

個人雲端數位圖書館

昨天一直很想來寫這一篇, 沒想到今天凌晨, Google eBooks就發表了, 某方面來看, 概念跟我原本想講的差不多, 先看一下它的介紹

最近常在iPad/iPhone上看電子書(老實說, 手機並不適合看書), 就一直在想, 紙本書存在的必要性?什麼樣的書比較適合電子化?

首先第一個問題, 我聽過很多人說, 電子書很方便, 但還是無法取代閱讀紙本書的樂趣, 的確, 我個人也是會這樣認為, 至少"翻書", 夾上特別圖案的書籤, 這類的事在電子書上就沒辦法做到了, 不過, 玩傳統單眼的攝影師也常說無法接受數位, 但隨著數位攝影的進步, 這些人也漸漸投降了, 我覺得, 同樣的道理也可以套在這上面, 隨著數位內容的進步, 很快的, 人們也可以接受很多書都是電子化的

那什麼樣的書適合電子化呢?應該所有都適合吧, 不管是文字內容電子化, 或是以掃描的方式, 其實都可以任何型態存在, 但最適合電子化的, 我個人是認為是雜誌, 而且我覺得甚至它以後可以不用以紙本存在, 雜誌與一般書籍不同, 它可以提供最新的消息內容, 並且可以是一種娛樂, 其實, 漸漸的它的角色很容易被web給取代, 因為網際網路可以提供更快速更豐富的消息, 如果藉由現在行動平台的優勢, 可以提供內容更新, 更加豐富互動的內容, 那應該很多人也蠻喜歡的, 最大的一個好處是, 不會製造垃圾, 以往雜誌通常就看過就算, 但實體的雜誌常常堆積在那邊造成一堆垃圾, 搬家時更麻煩, 這種東西全面電子化應該也可以減少不少垃圾

對於電子書來說, 最重要的應該不是閱讀器, 很快的, 不, 就是現在, 閱讀器人人可做, 不管是硬體(Kindle)也好, 軟體也好(iBook), 甚至Web化(Google eBook), 使用者對閱讀器的選擇可以有很多種, 閱讀器的優劣差異也會越來越小, 因此這不會成為一個電子書發行的成敗關鍵, 最重要的, 反而是 -- 平台

這也就是Google進來了, Amazon就要趕快反擊, 平台就如同是實體書店一樣, 任何出版商都可以鋪到任一種平台上, 就如同到金石堂或誠品上架一樣, 當然, 任何一個人都可以踩進來做平台, Google, Amazon可以, 出版商亦可以, 但出版商自己來, 流通性不高, 小型出版商也負擔不起, 因此到別人的平台上上架變成是一個比較經濟的方式

目前電子書平台的優勢在哪? 個人覺得是Cloud, 電子書平台不能夠單單的提供使用者購買並下載電子書而已, 還要有完善的管理功能, 這就像是有人蓋了一間很大很大的移動圖書館, 任何人都可以在這間圖書館裡面有一整排的書架, 買來的書直接擺在這書架上, 隨時想看的時候, 這間圖書館隨時都找的到(當然要有電子裝置在手), 而且要不管任何的裝置都要能夠取得你自己的書(這點就像是Amazon做的一樣, Google也做了)

除了這樣以外, 未來還能怎樣延伸呢? 其實不只傳統定義下的"書", 任何個人相關的知識內容應該要都可以存到這書架上, 比如說某年某月在某網站看到的一篇文章, 或是哪份電子報看到的一小篇剪輯, 甚至隨手寫下的小記, 應該都要能夠存到這座個人的圖書館去, 這樣的圖書館, 可以成為一個知識的累加基地, 甚至可以透過這樣的一個平台發表並販售自己的創作, 可以找到志同道合的人聯合創作並販賣, 以後出書可以不用找出版社, 也不用看出版社臉色, 只要有讀者, 到處都可以販售

Wikipedia目的是要建立一套百科全書, 但百科全書的內容來自於事實來自於歷史, 來自於前人的創作, 但知識的累積, 除了這些以外還仰賴了接連不斷的創作跟創新, 這些應該就是建立一個好的電子書平台的一個任務吧....

[iPhone] RSS Reader for iPhone : Reeder and FLUD

常常在看一些文章, 但share給朋友始終不是很方便, 大部分的軟體都會做透過e-mail share的功能, 但現在其實用Social network會比用e-mail來的頻繁(e-mail應該快恐龍化了吧), 如果先點share到e-mail再把link copy下來貼其實也很不方便, 後來找到Reeder和FLUD這兩個軟體, 前者是收費的, 後者目前還是免費

先來說Reeder這套付費的軟體, 介面相當的簡單直覺, 但這並不表示它的功能不好, 可以同步Google reader而且還蠻好操作的

最重要的是Share功能, 它提供相當多, 按下按鈕後就可以出現一個Panel裡面有很多支援的服務

對我來說有Twitter, Facebook就很足夠了, 可惜沒支援Plurk, 不過國外沒那麼流行Plurk倒是情有可原, 不過這麼多也很容易眼花撩亂, 所幸在設定裡面其實是可以開關每個服務的

Reeder還算不錯用, 價錢還算OK, 只是缺點是雖然支援Google reader但我有些跟的站, 內容似乎會抓不下來, 這是一大敗筆

再來說到FLUD, 它最大的好處是不用錢, 介面也新穎, 可惜的就是不支援Google Reader (不過iPad版居然是支援的, 不知道為啥iPhone版沒有)

這樣的介面自從Flipboard, Pulse流行後, 好像蠻多人採用的, 好處是可以直接看圖略過, 看到圖就沒興趣的就略過不看, 這樣感覺上還是蠻有效率的, 一樣可以share到Twitter, Facebook, 不過不支援Google Reader還有不是很穩定是致命傷, 希望在iPhone上很快就可以支援Google Reader

目前我會比較推薦Reeder (iPhone上), iPad上我就會推薦FLUD了(Pulse我是覺得很雜亂)

2010年12月5日 星期日

A pattern learned from memcached

晚上快速翻了一變 memcached , 想了一些想法, 趁還沒忘之前先寫下來再去睡好了

memcahced的設計概念說實在的簡單到不行, 說簡單不是說他不好或是沒什麼, 反而這麼一個簡單的設計, 幫助真的會不小

memcached簡單說了就是一個分散式key-value based data cache, 資料是分散放在很多台電腦的RAM裡面, 因為是key-value based, 所以說起來就是一個大的hash table, 並不需要複雜的query, 只需要O(1)就可以取得資料, 而且資料就在RAM中, 可以是相當的快

我們都知道一個事實: "IO costs", 如果每次都需要從database query資料, 那所花的時間, 包含SQL處理的時間, 以及IO的時間會是相當長的, 這點不管是Web application或是在mobile上(尤其現在SQLite被大量使用)都通用

因此使用RAM來cache query result as long as possible會是tuning這類的performance的其中一步, 這觀念應該是很多人都想的到

不過這樣得pattern可能得考慮的:

  1. 怎樣把一個常用且複雜的query對應到一個key-value pair
  2. cache的存續時間
  3. How to efficiently invalidate or update cache after data set changed

或許在Android的ContentProvider中可以引入memory caching的機制來減少IO的量

[筆記][Three20] 設定launcherView item的字型

有關Style sheet的用法參考前篇

Three20的document跟Android比起來不遑多讓, 實在也少的可憐, 當然啦, 這樣也有另一種樂趣, 就是上網找跟追code囉!

剛嫌我的code在Launcher View上面的字型實在太醜, 很想把它改掉, 第一個想到的當然是Style sheet, 但遍尋TTStyleSheet, TTDefaultStyleSheet的document, 找不到類似的東西

後來在TTLauncherButton.m發現這一行:

[self setStylesWithSelector:@"launcherButton:"];

難不成就是"launcherButton"?

所以就試著在style sheet的class中加入:

- (TTStyle*)launcherButton:(UIControlState)state { 

UIColor *color = RGBCOLOR(30, 30, 30);

return [TTTextStyle styleWithFont:[UIFont systemFontOfSize:12

color: color

minimumFontSize:12 shadowColor:nil 

shadowOffset:CGSizeZero next:nil];

 

直覺想說是字型, 所以用了TTTextStyle, 不過這樣的code下場是....圖不見了!!

由於剛剛是在TTLauncherButton發現的, TTLauncherButton繼承自TTButton, 所以看了一下TTButton, label的字型是TTTextStyle沒錯, 而圖是TTPartStyle, 所以兩者都要給, 缺一不可, 而以TTButton.m的這行code來看:

TTPartStyle* imageStyle = [style styleForPart:@"image"];

圖的名字是"image"

(TTPartStyle *)  styleWithName:style:next:

TTPartStyle的constructor除了name以外還需要style和next, TTStyle是個linked list, 所以沒有下一個style, next就指定成nil就好, 但style這參數卻不可, 試過給nil, 圖還是不見, 所以還是得繼續找怎回事

這時侯只好到Three20Style裡把TTDefaultStyleSheet.m的source挖出來看囉....(一挖出來發現, 我一開始就看這隻就好了嘛... = =")

看了一下TTDefaultStyleSheet的launcherButton是這樣寫的:

- (TTStyle*)launcherButton:(UIControlState)state {

  return

    [TTPartStyle styleWithName:@"image" style:TTSTYLESTATE(launcherButtonImage:, state) next:

    [TTTextStyle styleWithFont:[UIFont boldSystemFontOfSize:11] color:RGBCOLOR(180, 180, 180)

                 minimumFontSize:11 shadowColor:nil

                 shadowOffset:CGSizeZero next:nil]];

}

Ok, 看來整段只要照抄再改就好, 所以上面那段就改成這樣:

return [TTTextStyle styleWithFont:[UIFont boldSystemFontOfSize:12

color: color

  minimumFontSize:12 shadowColor:nil 

shadowOffset:CGSizeZero next:[TTPartStyle styleWithName:@"image" 

  style:TTSTYLESTATE(launcherButtonImage:, state) next:nil]];

 

 

(跟TTDefaultStyleSheet.m裡面那段有點小不同是, 一來是我是直接接在剛剛那段Text style後面, 二來只是驗證一下順序有沒差, 不過當然是沒關係的)

 

交大竹湖 12/05

今天帶小遠到交大看寰宇家庭安排的表演(這次演的還真的很無聊, 上次在桃園的比較好看)

好幾年沒回交大了, 雖說看起來好像沒啥變化, 但似乎是太久沒回去了, 總是有一種既熟悉又陌生的感覺

順手到竹湖拍了幾張照, 看著湖中的動物似乎無憂無慮, 還真的是好羨慕

P1010648

2010年12月4日 星期六

BBS and Social Networking

早上看到這篇文章, 興起了寫這篇的念頭, 雖然說自己也應該大約十多年沒玩BBS了

現在在台灣所說的BBS跟早期流行的BBS其實是不同的, 早期流行的BBS是撥接式的, 還記得我在高中的時候, 因為看到國小同學在玩, 也去買了台modem玩起了撥接的BBS, 早期由於Internet尚未興起, 因此訊息的交換就是透過這種方式, 一般的使用者利用數據機撥接到BBS站台下載訊息回來, 然後利用像是藍波快信(Blue wave)這類的軟體離線閱讀和回覆, 然後下次撥接的時候在把內容上傳, 除了討論區外, 還可以分享檔案, 而BBS站台的主持人通常會申請的一到多線電話讓人撥接進來, 利用半夜的時間與其他站台交換信件跟資料, 以現在的觀點來看雖然是很落伍, 不過當時其實還蠻多人玩的不亦樂乎的

現在台灣流行的BBS像是PTT, 並不是這種形式, 而是一種架構於Internet上的telnet型態的BBS, 在台灣, 早期也是在學術網路(TANET)上崛起, 這一點跟Facebook的起源有點像

記得大一剛搬進宿舍時, 我也把電腦跟Modem帶了去, 學長一看到我有Modem就很高興的問: "學弟, 你也玩BBS呀? 要不要玩學校的BBS", 那時候我認識的BBS也只有舊式的BBS, 並非telnet型態的BBS, 但由於此時並沒所謂的宿網, 要連接到TANET上也是要透過撥接的, 所以玩telnet型態的BBS也是得需要有台modem (當時我擁有的是一台19200 bps的modem) , 也就這樣, 我就栽進了這個BBS的世界, 我還記得我的第一個ID是DOTT是以一個當時蠻喜歡的電腦遊戲: Manioc Mansion: Day of the tentacle命名, 後來又改名叫bCat (babycat)

後來學長kaoc架設了系上第一個BBS, 我因為有興趣, 也就跟著一起維護, 後來也就接下了所謂的sysop的職務, 當時的時間幾乎都奉獻給BBS, 不是在上面打屁聊天, 就是想盡辦法改進它的程式, 增加新功能, 一路上從Phoenix BBS, Firebird BBS, Secret lover BBS, 玩到Maple BBS(以上都是BBS版本) , 還試著去做出Web BBS(當時用C + CGI + NCSA Httpd), 一直到被二一 :P , 我資料結構的觀念可以說是BBS程式教我的, 不是後來念資訊系才懂的.. :P

講了堆廢話, 不過那不是我要說的重點

可能有人會認為, 如果台灣之前出現像是Facebook這東西, 那就會是PTT

這是無可否認的, Facebook上出現過的東西, 在以前BBS上其實都已經出現/實現過了, BBS不只是一堆討論區的集合而已, 如果要討論區, 當時已經有俗稱news的usenet, 而且其實跨站的BBS文章的交換基本上也是透過usenet去實現的

除了討論區之外, Facebook上現有的功能, 像是chat (BBS上的talk, 一對一), ping, 在BBS上也老早就有, social games, 很早在BBS上也流行過QK麻將, 還有像是個版, 也可以看成像是另一種型態的personal "wall", 此外還有些現在看似先進, 但其實BBS以前都已經流行過了, 比如說public/private chat room (Facebook一直到Group發表後才有類似的功能), 還有一些Facebook並沒有的東西, 像是看板等等...

用過Facebook group的人可能會發現, 使用者也可以透過e-mail來發表文章到Group wall上面去, 這種mail post的方式, 其實也是已經在BBS上出現快有20年了, 並不是很新鮮的idea

近幾年, Facebook等新型態的Social network 服務改變了很多人與人之間互動及溝通的方式, 但很多這些東西, 其實很早點時候在台灣的學術網路上就已經很盛行了, BBS可以說是一個早期Social network典型的代表, 雖然以telnet的方式來連接, 在現在的觀點看來或許已經不合時宜, 但很多觀念, 還是可以值得去吸取, 並且拿來應用在現在新型態的Social network服務上的...

 

Splashtop Remote

這是可以從你的iPad上控制你的PC或Mac的軟體

雖然覺得不見得很實用, 但只要1.99, 還是買下去了, 一個便當的價位, 其他很多類似的軟體其實是很高價的, 甚至上百元, 當然也有很多lite版, 但看起來lite版多是缺東缺西的,這邊有Demo影片

在iPad上, 長得是這樣:

居然是繁體中文的, 真感動, 這家公司還真有心呀~~

似乎不是跟一般VNC一樣, 所以在Mac/PC上, 還需要裝一個Host, 像這樣:

可能是iPad解析度的關係, 當一turn on時, 我Macbook pro的桌面解析度自動被調低, 不過反正在iPad上使用, 其實也還好啦

整體上速度感覺還好, 不過畢竟是touch based的操作對應到滑鼠, 其實不是很好操作, 鍵盤則是使用iPad上的

如果不想帶自己的電腦到處跑, 這或許是不錯的選擇