Android 2.3.x 的 JavaScript Interface

星期天利用Google reader看文的時候,看到Fred大的這篇:Android 問題百出之 2.3.x 的 JavaScript Interface,我就心想,完了,我踩到雷。因為最近正好在實驗WebView Javascript與Java部份,回家一試,果真如此,真的頭很大。

再上網找了一下,發現很早以前就有人回報這個問題,喂,我說Google啊,那為什麼不修?!(怒),這個討論串很長,連PhoneGap開發小組也都有回。結果沒辦法,只能參考Fred大的文去改了。可是改了以後,卻怎麼樣都不能動,連原來的會導向到LogCat的部份都失效了,試了好久,又去StackOverflow找,找了幾篇,像:Uncaught TypeError when using a JavascriptInterface…等等,但還是不行,真的讓人摸不著頭緒。

後來是發現 onConsoleMessage 應該是要加 @Override 的,現在卻不用了,上網去Android reference找,才發現我搞錯類別名稱了。一個是WebChromeClient,而Fred大文章裡用的是WebViewClient,搞清楚,修改程式以後,這才讓我有了log利器,能用這個來去找到Javascript修補程式的錯誤,並修正。

為了要可以自動化為類別產生javascript修補程式的步驟,我運用了Annotation去標記需要產生Javascript代碼的函式,這樣就可以運用reflection的方式去找到這些函式,並產生程式,以注入到WebView裡面去。為了避免老是改程式,我也利用了Google瀏覽器,直接把產出的Javascript程式,放到Google瀏覽器的網址列去執行,這樣很快就知道哪裡有錯誤,並且修正。

總之,大概就是這樣子,解決了。

電影流水帳(2011/11/21~2011/12/2)

  • Johnny English(IMDB, Wikipedia),中譯:凸槌特派員。相當爆笑的故事啊,英國第一號情報員因為Johnny的失誤而掛掉,接著,一堆情報員又因為要幫第一號情報員送終而死光光,那就只剩下Johnny跟他的跟班了。過沒多久,他們接到保護英國王冠跟權杖的任務,不幸的是,保護不力,王冠跟權杖失蹤了,幸運的是認識了漂亮的女主角。於是他們展開調查,調查的過程裡,很顯然的,Johnny的跟班比Johnny本人更適合當情報員,後來搞了一堆烏龍,Johnny被首相開除,很失意的回家。女主角找到他,重燃起他的信心,讓他深信沒有他就無法阻止壞蛋登上王位,在阻止壞蛋登上王位的過程,又搞了一個超大的烏龍,但也讓壞蛋在公開的場合忍受不了,說出了不好的話,因此揭穿了陰謀。最後當然是皆大歡喜的解決了這個事件,和平落幕。
  • The Green Hornet(IMDB, Wikipedia),中譯:青蜂俠。我個人覺得不好看,劇情普普。特效的部份,在當年的科技或許那樣子是相當先進的,可是在今天看起來,卻顯得很拙,不合時宜,而且沒有交代年代,有種奇妙的時空背離感。唯一令人驚奇的是那個煮咖啡機,竟然可以瞬間加熱,炒好咖啡豆,然後研磨並立即有熱水去濾泡,這一台如果能量產,應該會有不少玩家買才是。
  • Fast Five(IMDB, Wikipedia),中譯:玩命關頭5。搞了四集之後,Dom、Brian、Mia聚在一起,再次偷車,卻發現了巴西最大犯罪公司的秘密,再加上美國中情局派出Luke來追捕他們,於是他們開始逃竄。但在逃的同時,決定用他們得到的秘密來幹一票,把最大犯罪公司的錢都偷光光。然後據說是前面幾集的人又再次聚在一次,開始演練計畫,並且施計讓犯罪公司的首腦把錢集中到警局,準備去偷。在正要下手的當天,Luke帶人衝了進來,抓住了Dom、Brian、Mia,並準備把他們移交到美國,移交的半路被犯罪公司襲擊,Luke的小組死光光,Dom、Brian、Mia被女警察鬆開,出手幫了Luke。Dom超火大,決定無論如何都要幹這票,Luke也加入了,說是要報仇。Luke首先衝到警局,把地下停車場清空,Dom跟Brian兩台車跟著進去把大大的保險櫃拖了出來,開始在街上跑,一狗票警車就在街上展開追逐,看著他們兩台車拖著大保險櫃跑來跑去真的很過癮。兩台車後來把保險櫃拖到了橋上,沒路跑了,Dom讓Brian先走,自己跟一堆警車對幹,然後利用慣性讓保險櫃撞到犯罪公司首腦開的車,犯罪首腦僥倖從車裡逃了出來,但卻沒逃過緊追而來的Luke的子彈。Luke最後還是以中情局的立場跟Dom與Brian說,錢你們不能拿走,兩人很瀟灑的離去。離去之後,Luke打開保險櫃一看,發現保險櫃早在跟警方追逐戰時就被調包了。一個皆大歡喜的結局,最後的最後,有埋了梗,看起來是Luke要挑起Fast 6大樑的樣子。相當好看的一部動作片,前面有點悶,雖然有些情節不是很合理,但後面相當精彩。

emulator無法啟動

這蠻奇怪的,但只要每次我在 AVD Manager 要啟動時,勾選 Wipe user data 以後,就都可以啟動。可是因為要手動指定 proxy 的關係,我必須用指令列的方式,但加上 -wipe-data 卻沒有用,上網搜了一下發現 Android Emulator can’t start, ’cause of wrong folder裡面有提到要設定 ANDROID_SDK_HOME,於是在命令提示字元裡先設置 set “ANDROID_SDK_HOME=c:\Documents and Settings\your_name” 之後,就可以順利啟動 emulator 了。
以後要省這麻煩的話,可以在”我的電腦”/”內容”/”進階”/”環境變數”裡去新增,就可以一勞永逸了。

Android MapView – Failed to find provider info

這篇Failed to find provider info for com.google.settings in MapView Example講得很仔細,該說的都說了。
我個人的經驗:

  • 有這個錯誤訊息,未必會看不到地圖。
  • 當apiKey是對的時候,沒有網路,仍然會看不到地圖,會讓人懷疑apiKey有誤。
  • 請務必讓網路暢通,如果公司裡面有proxy,可以試試在命令提示字元去啟動emulator:emulator -avd your_avd -http-proxy your_proxy_server:your_proxy_server_port -debug-proxy,這樣應該就可以了。(這指令是在Android 2.0, 2.0.1 proxy problems撈到的)。

關於網路的部份,還可以參考:

WebView裡$.parseJSON() fail

查了好久。我是先用setWebChromeClient()去處理WebView的onConsoleMessage() callback,將console.log()的輸出導向到Android的LogCat以便於觀察。先懷疑jQuery是不是有問題,就先拿另外一個變數放確定可以的JSON字串丟進去parse,沒問題。那我就懷疑從addJavascriptInterface()那兒來的物件的傳回值了,直接複製傳回結果,放到JavaScript裡當作一個字串,parse的結果,是沒問題的。那?會是型態的問題嗎?用typeof()檢查了一下,發現是object,而非字串,真相大白。我先試著把一個空字串加到傳回值裡,然後就可以得到字串,也就可以正常parse了。再查了一下,JavaScript是有轉換函式的,叫String(),試了一下,也可以把型態是object的傳回值轉為字串。至此,就解決了parseJSON()的問題。

WebView

畫面如果用Android裡的xml,光想,就讓我頭痛。還是用HTML來的方便,而且現在有HTML5,Android也有WebView,再加上之前敗了這本建構Android應用程式,我想這樣應該會方便很多。可是用HTML,就得用JavaScript,也需要從Android程式那邊溝通,就研究了一下。

Using WebViews裡提供的範例,就有講其中的關鍵了,就是使用WebView提供的addJavascriptInterface(),這可以把Java的物件加到JavaScript runtime裡去,這樣JavaScript就可以使用這個物件。可以呼叫之後,那麼資料該怎麼傳遞呢??這牽涉到轉換的問題,而且Android只允許傳遞int、String等一些基礎類別,而不允許使用自訂類別,這就糟了。還好,這篇Working with Android addJavascriptInterface就有討論到這個問題,他的結論是使用JSON字串,這看來是最簡便的方法。JavaScript可以使用jQuery提供的parseJSON()與toJSON()來從字串轉成物件,或從物件轉為字串,而Java則可以用jackson來轉換。Build a Contacts Application With jQuery Mobile & the Android SDK這篇是更完整的使用範例。

Using WebViews裡另外有提到WebView的setWebViewClient,這個其實是WebView的callback,讓你可以在WebView遇到一些特定狀況的時候,作一些處理。詳細的說明要參照WebViewClient這邊。

如果嫌麻煩的話,是參考書裡的PhoneGap就好,書上介紹的步驟就只要寫HTML+CSS+JavaScript就好,不用特別再寫Java的部份,也不用裝eclipse,最後就用ant,就可以build出apk。

電影流水帳(2011/11/9~2011/11/20)

  • Rat Race(IMDB,Wikipedia),中譯:瘋狂世界。這在網樂通上面看的,蠻有趣的片子。就一堆人玩了角子老虎,然後拿到特別的珠子,說有特別的禮物,然後就到樓上去。到了樓上,賭場主人出來宣佈說,現在開始比賽,誰先到Silver鎮,就可以拿到兩百萬美金。一開始大家都用不可置信的心情,以為是騙人的。豈料到了門外,大部份人就開始衝了,有的人不屑一顧,有的人在樓下睡著。不過到了中間的時候,大家都卯起來往Silver鎮前進。中間就發生很多很妙的事情,也交代了為什麼賭場主人要辦這比賽,原來是他們賭到沒什麼可以賭,就亂找花樣來賭,這個比賽就是其中之一。到了最後,大家都趕到小鎮,結果在爭奪的過程裡,鈔票被掛到熱氣球上,開始飄啊飄,飄到了募款晚會會場。一群人從舞台後面衝了進去,大家手上都抓了幾把鈔票。到了台上,主持人跑了出來,陰錯陽差的對話之下,變成了捐款,這群人後來也大器地把錢捐了出去。然後律師看到了賭場主人也出現在舞台邊,就接過麥克風,開始說,我們會來到這裡捐款,都要謝謝這個賭場主人,然後就宣佈,賭場主人會捐出在大會募得金額的兩倍,片子就在賭場主人哭喪臉,眾人歡呼的情況下結束了。
  • 劍雨(IMDB, Wikipedia)。挺不錯的武俠片。片頭的動畫蠻精緻的,我很喜歡,把前因都交代挺清楚的。黑石是個暗殺組織,細雨是裏面頂尖的殺手,殺了張海瑞全家,奪得了羅磨遺體。後來她就帶著遺體逃走,途中遇到陸竹,這場相遇,陸竹死了,而她決定易容隱居。隱居的時候就遇到了阿生,並且被感動,結了婚。可是後來還是被發現了,黑石要脅她,幫忙從崆桐派手中搶回另一半遺體,沒辦法,為了阿生,只好幹了。後來搶到,黑石發生內鬨,細雨不想惹事,就把遺體留下,說今後再沒瓜葛,可是還是被轉輪王打傷。細雨勉勉強強逃了回去,叫阿生快逃,然後就昏了。阿生把細雨扶到床上以後,並沒有逃走,反而開始在地上挖洞。黑石的追兵雷彬跟綻青來了,準備要動手。阿生說,請等我一下,說完把劍拔了出來,開始磨劍。黑石的追兵從劍認出了阿生的真正身份,原來是張海瑞的兒子,他的心臟異位,所以並沒有被細雨殺死,還被神醫給救了,並易了容。黑石追兵在錯愕之下,佔了劣勢,後來雷彬受了重傷,綻青逃走。阿生把細雨帶去神醫那邊,然後跑去約轉輪王出來決戰。細雨沒多久就醒了,也跟著趕去,趕去前,神醫意味深長的說,這真是天意啊。最後就是阿生揭露了自己的身份,細雨知道了以後,很難過,但仍然決意由自己承擔一切,她先故意把阿生給刺傷,並讓他服下龜息散。跟轉輪王的決戰,靠著陸竹之前的指點,血戰之下贏的僥倖,自己也傷得很重。看似死亡但仍聽得到聲音的阿生也知道了一切,醒來以後,意想不到的抱著重傷的細雨離去。整個故事我還蠻喜歡的,特別是阿生跟細雨從相戀到背叛的那幾段,很讓人唏噓啊。看完才發現林熙蕾跟楊紫瓊還蠻像的,然後就是大S跟幻術師的那兩個角色不知道是戲份被抽掉了還是剪接的關係,感覺上挺雞肋的。

學校教材的下載

有些科目的教材好多,用滑鼠可能會按到死。本想用 curl 來硬幹的,可是從登入頁面一路解析到教材下載頁面的時候,發現 ASP.NET 的頁面還真是難搞,後來選擇放棄。

於是想了一下看Firefox有沒有現成的AddOn可用,有,的確是有,那是DownthemAll,可是,教材下載頁面的”下載”是用javascript埋起來,所以必須解析div的onclick屬性,把真正的連結拿出來。這時候GreaseMonkey又再次派上用場,就是你啦!!於是就弄了這個userscript,他會在原來的下載圖形下方增加一個download連結,這樣DownthemAll就可以抓到。要用的話,可以直接到userscripts.org這邊安裝,下面是原始碼:

wordpress以SSH自動更新

考量到以後wordpress的更新問題,可是又不想開FTP的洞,所以研究了一下不使用FTP的方式,大致上就是照這一篇WordPress Automatic Update with SSH來操課即可。第一次更新失敗,在調整 wp-content/plugins 與 wp-content/themes 以後,就解決了。我把這兩個目錄的owner調整為apache:groupname,然後permission調整為0775。

Canon BJC-240+cups+SAMBA+CentOS

Canon BJC-240 以Parallel 轉 USB 接到電腦上,接上以後是在/dev/usb/lp0。

先設置一下跟cups相關的部份,你要先確定自己在sys群組裡,因為cups會需要權限來寫入設定檔。

cups,我是以web介面去安裝印表機,打開瀏覽器,在網址列輸入localhost:631,然後選新增印表機,首先會要求你輸入名稱以及描述,名稱裡不可以有空白。下一步之後,會要你選介面,這時候就選有偵測到的USB介面。接著會要選驅動程式,我試過raw了,不行,我改用了generic postscript。接著會要你選queue的部份,只有一個可以讓你選,就選吧。至此,cups會要你輸入帳號跟密碼,請輸入你的帳號跟密碼即可。

接著是SAMBA。SAMBA的部份比較簡單,打開 /etc/samba/smb.conf,確定 printcap name = /etc/printcap 、 printing = cups,然後將 [printers] 下的 guest ok、writable、public、use client driver 都設為 yes 即可,如果沒看到就自己補上。接著重新啟動SAMBA。

至此,Windows就可以連上,並且去新增印表機了。

p.s. 這邊不多贅述SAMBA的權限控管,就看是用user或share或其他什麼的,總之要有權限可以存取server就是了。