highlight.js

星期三, 9月 05, 2012

PhoneGap 問題又一樁:index.html 檔載入太慢

今天同事在測試 PhoneGap 做出來的 Android App 時, 又遇到了一個靈異現象, 他使用 Samsung SIII 測試可以正常執行的 App, 到了我的 LG P970 上一執行就出現以下的錯誤訊息:
Application Error - The connection to the server was unsuccessful.
(file:///android_asset/www/index.html) 
 查了 Google 之後才發現, 這個問題可能是因為手機速度或是連網速度太慢, 超過 20 秒還無法將 index .html 載入 (連同 index.html 中所連結的外部檔案, 此例就是用了外部的 jQuery 與 jQueryMobile 檔案), 就會出現這個訊息。馬上測試一下, 把我的手機改成用 WiFi 連網, 果然就成功了, 後來發現原來同事用的 Samsing SIII 一直都是用 WiFi, 所以都沒有遇到過同樣的問題。

為了解決這個問題, 網路上有聰明的人把 index.html 改名字成 main.html, 另外加了一個 index.html, 這個 index.html 其實只是個空殼子, 用來轉址到 main.html, 也就是真正包含 App 內容的網頁:
<!doctype html>
<html>
 <head>
  <title>tittle</title>
  <script>
   window.location='./main.html';
  </script>
 <body>  
 </body>
</html>
這樣問題就解決了, 提供給大家參考, 不然總不能叫用你 App 的使用者都要改成 WiFi 連線才行吧!

星期一, 9月 03, 2012

Dreamweaver CS6 的 PhoneGap Build 服務與中文路徑名稱水土不服?

因為同事在測試 Dreamweaver CS6 的 PhoneGap Build Service, 之前用英文版都很正常, 可是一改成中文版的 Dreamweaver CS6 之後, PhoneGap Build 服務就沒成功過, 一直看到錯誤。但如果自己打包上 PhoneGap Build 網站上又都正常無誤, 感覺一整個奇怪, 沒道理到了中文版同樣的功能就不能用!

為了測試, 我也裝了 Dreamweaver CS6, 也是先試看看英文版, 果然沒問題。換到中文版, 把剛剛在英文版建好的網站拿來測試, 用 PhoneGap Build 服務重新建置, 沒問題啊!但是念頭一想, 那我用中文版建個新的網站來試試, 一試之下果然出現錯誤!

我想了一下, 看看建好的網站, 發現英文版與中文版唯一的差別是預設的網站儲存路徑一個是「Unnamed Site XX」, 一個是「未命名網站 XX」(XX 是序號), 這下我想不會是因為中文資料夾的原因吧?趕緊試一下, 果然, 只要路徑沒有中文,PhoneGap Build 服務馬上又恢復正常了。

我自己推測, 應該是 PhoneGap Build 服務會把整個網站的內容壓成 Zip 檔之類的, 再上傳到 PhoneGap Build 網站進行建置的工作, 但是路徑有中文的時候可能這個幕後的 Zip 檔檔名會因為編碼的關係變成莫名其妙的檔名, 導致後續的動作出錯吧?

如果你也在測試 Dreamweaver CS6 PhoneGap Build 服務的功能, 可以參考一下!

星期四, 8月 16, 2012

OOXX, Eclipse 中 R.java 就是不更新!

根據我估狗的結果, 顯然許多人都遇過這個問題, 比方說你在 res/layout 中加個新的 layout 檔, 或是改了某個資源的 Id, 可是 R.java 中這個新的 layout 檔就是不出現, 更改的 Id 名稱也不會更改變數名稱, 真的是不知道背後發生什麼事!

遇到這種狀況, 可以試試看使用 Project/Clean 功能表指令清理一下專案, 或者是更暴力一點, 把 R.java 刪除, 這兩個舉動都會重新產生 R.java 檔, 一般來說, 這樣就會根據目前的資源內容產生正確的 R.java 了。

星期三, 8月 15, 2012

android:minSdkVersion、android:targetSdkVersion、Project Build Target 的區別

初學 Android 的人在 Eclipse 裡建專案時, 看到這個建立新專案的精靈視窗, 常常會搞不懂中間 Build SDK 與 Minimum Required SDK 這兩個欄位的意義:

簡單來說, Minimum Required SDK 是宣稱此專案至少要在哪一個版本的 Android 系統上才能跑, 這裡選擇的值會出現在專案中 AndroidManifest.xml 檔中的 uses-sdk  元素中:
<uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="15" />
其中 android:minSdkVersion 屬性值就是上圖中 Minimum Required SDK 欄位的設定值。要特別注意的是, 這裡 SDK 版本都是以所謂的 API Level 值來指定, 而不是版本號碼, 例如圖中 Android 2.2 的 API Level 就是 8, 所以設定的值是 8, 而不是 2.2。

要特別說明的是, 這個設定值會影響 Google Play 是否將此程式顯示在商店中, 如果使用者裝置的 Android 版本比程式中這一項設定值指定的版本低, 此程式就不會出現在  Google Play 商店中。實際在執行程式時, 系統也會檢查此項設定值, 若是系統版本比程式的設定值低, 也會禁止執行這個程式。不過要注意的是, 這個設定值是開發者所「宣稱」, 至於這個程式是不是真的可以在該版本的 Android 裝置上正確執行, 就是開發者要負責的事情。

那麼在上面精靈視窗中的 Build SDK 設定的又是什麼值呢?這指的是實際在編譯程式時要用那一個版本的程式庫。這就與你實際要使用的功能有關, 有些功能只有在特定版本才提供, 若程式要使用, 就必須指定 Build SDK 欄位值為該版本。這個設定值會記錄在專案中 project.properties檔案中:
# Project target.
target=android-10
 或者也可以透過專案的 Properties 視窗檢視:


前面提到 AndroidManifest.xml 檔時, 您可能有注意到在 uses-sdk 元素中除了 android:minSdkVersion 外還有一個屬性叫做 android:targetSdkVersion, 請特別留意, 這個 android:targetSdkVersion屬性值和 Build SDK 欄位值是兩個不同的值。android:targetSdkVersion 屬性值是開發者『宣稱』在特定版本平台上已測試過程式可以正確無誤的執行。你可能會覺得很疑惑, 那這個值和 android:minSdkVersion 屬性值有什麼差異?

這就要講到 Android 平台的演進了, 在 Android 的新版本中, 當遇到以舊版程式庫編譯的程式時, 可能會嘗試啟動某些相容性的處理, 以便在新系統的平台上不會因為版本的差異而讓程式出錯。舉例來說, 新版的 Android 因為支援大畫面的平板, 所以遇到舊版程式時, 有可能會自動做某些調整, 讓理論上是為小尺寸螢幕設計的程式顯示起來不會與大螢幕格格不入。當然這額外的處理有可能會影響到執行的效能, 如果開發者確認不用系統幫忙程式也不會有問題, 就可以設定 android:targetSdkVersion 屬性值, 強制系統就不要啟動相容性的處理。

綜合上述, 一般來說, android:targetSdkVersion >= Build SDK >= android:minSdkVersion, 這是因為既然宣稱至少要使用 android:minSdkVersion 設定的版本才能執行此程式, 那麼編譯時就會透過 Build SDK 使用 android:minSdkVersion設定版本或是更新版本的程式庫, 才能包含所需的功能;而這個程式有可能在往後新版的 Android 版本上正確執行, 所以 android:targetSdkVersion 設定的版本至少會是 Build SDK 指定的版本。

舉例來說, 若是 android:minSdkVersion 為 7、Build SDK 為 8、android:targetSdkVersion 為 10, 就表示這個程式至少要在 Android 2.1 的裝置上才能執行, 但程式編譯時是使用了 Android 2.2 的程式庫, 而且程式已經在 Android 2.3.3 上測試過顯示、執行皆正常。

android:targetSdkVersion 屬性值在建立新專案時並沒有欄位可以設定, 我自己測試的結果似乎預設值為最新版本的前一版, 例如目前是 Android 4.1, API Level 為 16, 所以預設值就會自動設為 15, 請務必依照實際測試狀況修改此屬性值。

從上述說明就衍生了一個重要的問題, 因為 Build SDK 設定值可能會大於 android:minSdkVersion 設定的版本, 因此開發者必需自行處理相容性的問題, 如果使用了較新版本的功能, 就必須在程式中檢查執行時的系統版本, 在比 Build SDK 版本低的系統中以其他的方式提供相同的功能, 或是甚至禁用該功能, 才不會讓舊版系統的使用者因為執行到系統不具備的功能而出錯。