剛剛從Chrome要列印一份文件時, 發現一件有趣的事, 在選擇印表機時, 發現我的手機也在清單當中


這怎一回事? 難道可以從電腦"列印"文件到手機?

測了一下果然是如此, 在我的手機上會多了一份pdf, 內容就是由我的電腦列印過去的, 而且是透過Google Cloud Print, 打開Cloud Print的設定, 可以看到Print Jobs的確有我剛列印過去的


這功能需要有登入Cloud Print, 並且手機也要安裝Chrome才可以

不知道實不實用, 還蠻有趣的就是了




via Blogger http://bit.ly/17aurqN

原本在Android下解析JSON內容,  大多用JSONObjectJSONArray, 這兩個是很簡單的JSON parser, 只要將字串(String)傳入即可

不過, 這跟在用DOM解析XML是有類似的問題, 解析文件是一氣呵成, 必須要把所有內容先走過一遍, 也需要更多的記憶體來儲存, 這對於解析較大的文件是一個大問題, 必須要花費更多時間和空間, 而且如果所需要的資料就算只是整份文件中間的一小部分, 還是得先把整份文件走完, 在XML, 可以用SAX來解決這問題, 但Android要到API level 11(Honeycomb) 才新增了JsonReader這個算是JSON界的SAX的解決方案

 JsonReader類似SAX, 也是一種streaming parser, 並不用一次讀出所有字串內容, 它要的只是個Reader, 但不太像SAX屬於事件驅動(event driven)的方式, 它應該比較像token consuming, 它定義了幾類基本的JsonToken,  它也有BEGIN(END)_OBJECT, BEGIN(END)_ARRAY這種類似SAX中startElement, endElement, 但卻沒類似SAX的startDocument

解析一個JSON物件的程式碼如下:

     {username:"Bob", age: 14, sex: "m"} 
     reader.beginObject();
while (reader.hasNext()) {
String name = reader.nextName();
if (name.equals("username")) {
username = reader.nextString();
} else if (name.equals("age")) {
followersCount = reader.nextInt();
} else {
reader.skipValue();
}

}
reader.endObject();
解析一個物件, 要從beginObject開始(陣列則是beginArray), endObject結束, 接著透過一個while loop一個個走過這物件內所有的token, 說實在的, 不是很好debug,  你必須要先知道下一個要處理的token是啥類別, 以上面的例子為例, 物件內第一個token是"username", 這是一個JsonToken.NAME, 因此要用nextName來處理, 搞錯了就會出錯, 還不容易知道錯哪,  而上面那例子裡的"else"也是必須的, 拿掉的話, 在endObject就會出錯, 因為這段程式並沒去處理"sex", 因此處理完sex這個名字後, 並未消化掉"m"這個值(JsonToken.STRING), 而是直接endObject, 這會產生一個IllegalStateException

為了避免用了錯誤的方式處理下一個token, 可以先用peek()來看一下下一個要處理的種類

在可讀性上, 用JsonReader寫出的並不是很好, 但它卻適合來處理大的JSON文件, 或是像Twitter Streaming API這種幾乎無止盡的

這當然也不是只有在Android上有, Google也早把這也包含到GSON去了

via Blogger http://bit.ly/16rSFLZ

最近科技界比較流行的戲碼是: Google要把Google Reader給送上斷頭台了

這齣戲有點輕肥皂劇的感覺, 先是Google公布要把Reader給喀嚓了, 再來就是一堆重度使用者叫苦連天, 一堆原本吃Google reader豆腐的服務跳出來說要接手實作替代方案, 緊接著是Google reader的Product manager 在Quora上爆料Google都把人抽去做Google+, 再來就是有重量級的部落格重炮轟擊Google關掉受歡迎的東西卻拿人力去開發沒用的東西(Google+), 對於這樣的評論, 個人是認為"言重了", 我自己本身的觀點跟這些是有點相反的, 不過我的觀點不主流, 這篇也不是為了談這個, 只是先行加點小小囉嗦… :P

Google Reader停了, 對原本的重度使用者以及使用到他的服務比如說feedly, 應該是重傷不少, 對我個人而言, 影響不大, 我在幾年前早把我消耗資訊的習慣, 從Reader轉到Twitter了, 個人認為Twitter也是一個很好的消化資訊的管道

不過, 先不管Reader和Twitter…你聽過Google有一個跟Reader同質性相當高的服務叫Google Currents嗎? 這是一個在這一年內(應該是吧)的新服務(中文譯名是有點矬):


目前除了有Android版本外, iOS上也是可以找的到

跟Google Reader不同的是, 它比較像Flipboard, 事先把新聞網站分類整理好讓使用者訂閱, 乍看之下是跟Google Reader不一樣的概念, 但是, 其實Google Reader訂閱的東西也是可以轉移到這邊來的

首先, 從"新增訂閱項目"開始

拉到最下面, 可以找到你原本就在Google Reader已訂閱的項目, 這時候你就可以把他們一個個加進來了


那可不可以加自定的RSS呢? 也不難, 這邊示範了怎樣加我自己Flickr的RSS, 搜尋"flickr julianshen", 馬上就找到它了, 我甚至還不用跑到Flickr網頁去找到那個RSS

再做另一個實驗, 搜尋我的名字"julianshen", 不但我的Flickr, 我的blog, 甚至是我的GitHub, Youtube, 都跑出來可以讓你去訂閱, 而且搜尋速度, 還蠻快的

當然也不是沒有缺點:

  1. 目前只有Android, iOS 版本並無PC或Web版本, 當然更無其他3rd party軟體
  2. 加進去的RSS都會被自動歸類, 大多被歸類在"資訊提供", 有些會被歸類的其他類別(比如說某些科技公司的新聞的RSS可能會被自動歸類到科技類), 沒辦法像Google Reader一樣自定目錄來分類, 也不能修改分類
  3. 沒辦法直接跟瀏覽器配合
不過這些好像對Google來說也不是啥複雜難做的吧

有兩個同質性那麼高的服務, 關掉其中一個也還蠻合理的啦, 賴到Google+頭上, 好像也有點無辜 XD






via Blogger http://bit.ly/WXnszx

以往Twitter的search API是不需要任何認證, 也不需要設定啥App ID或啥consumer key的, 不過, 在API 1.1之後, 這就改了

因為1.1, search也列入rate limit的追蹤囉, 所以使用search API也要做認證(Authentication), 但由於search api的使用情境, 不見得一定需要使用者登入, 有些做資料分析的應用也有可能會用到, 所以強制用OAuth就有點不是很合理, 所幸, 除了用OAuth以外, 這類的API也可以使用Application-only authentication:


  1. 首先必須要用Basic Auth的方式取得token, 用consumer key當user name, consumer secret當password去呼叫/oauth2/token的API
    1. 使用POST
    2. 必須要有grant_type=client_credentials
  2. 成功的話就會得到access_token (注意token type為bearer)
  3. 使用這個token去呼叫API (search或其他不需要user login的API)
    1. 把token加在HTTP的Authentication header (像是: Authorization: Bearer AAAAAAAAAAAAAAAA )
    2. 一定要走SSL (https), 如果是非SSL會碰到"Bad Authentication data"的錯誤
以下是Sample code (使用Go):






via Blogger http://bit.ly/X79jKT

iOS和Mac OS的應用程式裡都有個info.plist放置著應用程式相關的設置, 用Qt開發Mac應用程式時, 這個檔是在編譯時自動產生, 因此幾乎是固定內容

但還是有需要在info.plist內加入額外的內容, 比如說Retina display的支援(NSHighResolutionCapable), 預設並沒有, 因此還是有需要做自訂的info.plist

作法並不難, 在專案檔(通常是 xxxx.pro)內加入下面的內容:

mac {
QMAKE_INFO_PLIST = XXXX.plist
}

mac {}內指得是, 這些內容只有針對mac os才有效, 而XXXX.plist則是你的Info.plist的範本檔名, 這個檔跟專案檔放在同一個目錄

XXXX.plist的內容則像這樣:

跟一般的Info.plist其實是一樣的, 我在這範例裡面加上了"NSHighResolutionCapable", 其餘都跟原先自動產生的內容是差不多的, 除了幾個關鍵內容用變數取代, 這邊變數都是以"@“包起來的, 比如說”@ICON@“就是應用程式的圖示

重新做一次qmake後, 下次編譯的Info.plist便會以這個檔案為範本產生了



via Blogger http://bit.ly/VYVRbw