highlight.js

顯示具有 android 標籤的文章。 顯示所有文章
顯示具有 android 標籤的文章。 顯示所有文章

星期日, 12月 28, 2014

製作 local 本機版的 App Inventor

App Inventor 相信是許多人入門 Android 程式設計的工具,只要有瀏覽器就可以開發程式, 而且透過滑鼠拖拉的方式就可以完成,不過因為整個開發環境必須連上 App Inventor的網站, 只要網路中斷, 或是網站掛點, 就什麼事也做不了了。事實上, App Inventor 是開放原始碼的服務, 只要你需要, 可以自行下載原始檔案, 建置一份在本機上執行的 App Inventor 網站,就不用擔心意外狀況了。

要建置本機版的 App Inventor, 需要以下幾個元件 (以下均以 Windows 平台為依據):
  1. Git 版本控制工具:你可在 Git 的 Windows 專頁下載 Windows 版本的安裝程式。記得要把 git.exe 所在的資料夾路徑加入 PATH 環境變數中。
  2. App Inventor 原始檔:可在 MIT App Inventor Public Open Source 網站下載, 下載回來解壓縮等候建置。不過建議用 git 工具 clone 回來, 因為下一步驟還需要補上所需的程式庫, 指令為:

    git clone https://github.com/mit-cml/appinventor-sources.git

  3. 補充下載所需的程式庫, 否則編譯會因為缺少必要的檔案而出錯 (可參考這一篇討論串):

    git submodule update --init

  4. Apache Ant 建置工具:你可在 Apache Ant 的下載專頁下載 zip 格式的壓縮檔, 下載回來後只要解壓縮, 並且將其中的 bin 資料夾路徑加入 PATH 環境變數中。
  5. Python 程式開發環境:你可在 Python 的下載專頁下載 Python 2.7 版 安裝程式, 你也必須把 python 的路徑加入 PATH 環境變數中。
  6. JDK:你可在 Oracle JDK 專頁下載安裝程式, 並設定環境變數 JAVA_HOME 為安裝的資料夾路徑 (是 JDK 而不是上層的 JAVA 資料夾路徑喔), 再把 java.exe 所在資料夾的路徑加入 PATH 中。請特別注意, 官方文件是使用 JDK7, 如果使用太新版本的 JDK, 可能會在執行時發生問題, 目前我使用 JDK8U66 的版本是可以執行的, 可參考這一篇討論
  7. Google App Engine Java SDK:可在 Google App Engine SDK 專頁下載壓縮檔, 下載後解開即可。

在 Windows 下, 為了讓建置過程順利, 你可能得建立 _JAVA_OPTIONS 環境變數:

set _JAVA_OPTIONS=-Xmx1024M

否則可能會遇到建置過程中, Java 回報在建立虛擬機器時無法配置足夠的記憶體。

完成上述的準備工作後, 就可以開始建置 App Inventor 了, 請進到解壓的原始檔中, appinventor 資料夾中, 執行以下指令:

ant clean

上述指令會清除之前建置的內容, 之後再執行

ant

即可開始一連串的建置動作, 建置時間有好幾分鐘, 你會看到一大堆的訊息, 成功時會看到以下訊息:



建置好後就可以開始執行,  App Inventor網站其實有兩個伺服器, 一個是提供 App Inventor 開發環境的網站,一個是實際進行打包 APK服務的伺服器。首先執行開發網站, 以下是以 App Engine Java SDK 資料夾在 C:\appengine-java-sdk-1.9.17 為例, 下達指令:

D:\temp\mit-cml-appinventor-sources-5455be9\appinventor>c:\appengine-java-sdk-1.9.17\bin\dev_appserver.cmd --port=8888 --address=0.0.0.0 appengine\build\war



最後看到以下訊息, 就表示開發環境網站已經啟動:



你可以使用瀏覽器連上 http://localhost:8888/ 測試:



local 版的 App Inventor 一樣需要登入, 不過登入機制和雲端版本不同。如果沒有顯示上面登入頁面, 而是顯示錯誤訊息 "org.apache.jasper.JasperException: Unable to compile class for JSP:", 就表示使用的 JDK 版本太新, 可換成 JDK7 或是 JDK8U66 之前的版本試看看 (可參考這一篇討論)。這裡請點選 "Click Here to use your Google Account to login", 切換成只要填入 email 就可以登入的模式:

 

此種模式並不具有安全性, 任何人用同樣的 email 登入就可以存取同一使用者的專案。登入後同意授權條款之後就可以看到熟悉的 App Inventor 環境了:



你可以在網址列清楚的看到這是本機位址, 之後就可以如同操作雲端 App Inventor 服務一樣開發程式。不過在你按下打包 APK 功能之前,記得要先啟動後端打包 APK 的服務,這個服務稱為 buildsever, 啟動方法請先開啟新的命令提示字元, 切換到 App Inventor 下的 buildserver 資料夾, 再執行 ant RunLocalBuildServer 指令:



等看到以下訊息時, buildserver 服務就已經啟動了:



這樣你就可以在 App Inventor 中按功能表的『打包 APK』 建立可安裝的 APK 檔了。

星期三, 2月 19, 2014

Android 4.2 以上開啟『開發人員選項』

Google 真是一間充滿技客 (Geek) 風格的公司, Android 4.2 版以上在『設定』中把『開發人員選項』給隱藏了, 但是除非你查網路, 或者是剛好跟Google 心有靈犀一點通, 否則大概永遠猜不出來要怎麼把它秀出來。

答案其實很簡單, 進到『設定/關於手機』, 找到『軟體版本』項目 (或是者『建置編號』、『版本號碼』之類的), 在這個項目上連續按幾次, 就會看到『恭喜你已經成為開發人員』這樣的訊息, 接著在『設定』下就會看到熟悉的『開發人員選項』。

PS:如果你按錯項目, 在『Android 版本』上連按, 則是會看到可愛的 Jelly Bean 彩蛋畫面!

星期二, 12月 03, 2013

Google Play Service 版本更新

今天收到一封信詢問 Google Map API V2 的問題,由於 API 改版頻繁,一個月前寫的程式在另外一台機器上竟然無法執行, 一跑就當掉。經過一番搜尋之後, 發現 Google Map API V2是屬於 Google Play Service,而 Google Play Service 之前改版到 13, 在這一版中必須在專案的 AndroidManifset.xml 中為 application 元素加上以下的 meta 屬性:
<meta-data
android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version" />
google-play-services_lib 程式庫才能正常運作, 否則就會當掉, Android 程式設計之路真是步步驚心啊!

星期六, 9月 14, 2013

Linux 下 Eclipse 的 Java 原始碼編碼設定

由於 Eclipse 的 Java 原始碼預設採用 OS 的編碼, 這在中文 Windows 上是 big-5, 但是在 Linux 上卻是 UTF-8, 所以如果在 Linux 上匯入一個原本是在 Windows 上開發的專案, 就可能會遇到 Java 原始碼中的中文顯示亂碼的情況, 這時可以在 Linux 的 Eclipse 上選取『Window/Preferences』開啟 Preferences 交談窗, 接著切換到『General/Appearance/Content Types』後, 在右側點開『Text/Java Source File』, 並在下方的『Default encoding』填入『BIG5』即可, 詳細畫面如下圖:

星期四, 1月 03, 2013

讓 Android 模擬器顯示虛擬按鈕

Android 的模擬器在小尺寸的設定時, 預設都是假設裝置是有 home、menu、back 這些硬體按鈕, 如果你要測試一些 Android 3.0 之後的功能, 像是在 action bar 顯示功能選單, 就會因為預設的設定而不會出現在 action bar 中, 仍然是從螢幕下方滑出來。如果要設定成沒有這些硬體按鈕的裝置, 就必須手動更改模擬器的設定檔。

首先啟動 Android Virtual Device Manager, 會在上方看到模擬器的資料存放的資料夾:


在該資料夾中, 每個模擬器都會以模擬器的名字建立專屬的資料夾。在個別模擬器的資料夾中, 有個 config.ini 檔, 就是有關該模擬器的基本設定:


開啟 config.ini 檔, 找到以下這行:
hw.mainKeys=yes
把設定值改為 no, 存檔後再重新啟動模擬器, 就可以看到模擬器顯示虛擬的按鈕了:




星期二, 11月 27, 2012

Android 模擬器 Skin 設成 WXGA720 就跑不起來?

Android 模擬器一直是大家詬病的工具, 除了跑得很慢以外, 還回到一些奇奇怪怪的問題, 像是網路上許多人都發生過, 只要把 Android 模擬器設定為 Skin 使用 WXGA720, 像是這樣:

結果一起動模擬器就會出現配置記憶體錯誤, 終止執行。看了各路人馬的補救方案後, 我自己最後要這樣才能跑來, 一是改為自訂解析度 720X1280, 另外則是要很無俚頭的把 Hardware 中 Device ram size 的 1024 加上 mb 字尾, 像是這樣:
就可以執行了。至於原因嘛, 我真的不懂, 但至少這樣可以測試程式了。

星期二, 9月 25, 2012

Eclipse 中文化後變回英文介面

大部分的人都知道可以到 Eclipse 的 Babel 專案頁面中下載中文化的語言包, 讓 Eclipse 變成中文介面。不過 Eclipse 預設會根據作業系統目前的語系設定, 使用對應的語言包。也就是說, 一旦你安裝了繁體中文的語言包, 那麼預設就是中文的介面, 而這在 Eclipse 中並設定畫面可以更改。

如果想將 Eclipse 改回英文介面, 網路上大部分人的作法都是建議在執行 Eclipse 時, 加上參數指定語系為英文, 例如:
eclipse.exe -vmargs   -Duser.language=en” 
為了方便起見, 你可以建立不同的捷徑, 在不同語系之間轉換。不過實際上會想換回英文, 大概也都不需要在不同語系間切換了, 這時可以把上述的參數加到在 Eclipse 資料夾下的 eclipse.ini 檔案中, 例如:
-startup
plugins/org.eclipse.equinox.launcher_1.3.0.v20120522-1813.jar

...............................
-vmargs
-Dosgi.requiredJavaVersion=1.5
-Dhelp.lucene.tokenizer=standard
-Xms40m
-Xmx384m
-Duser.language=en”
這樣執行 eclipse 時就會強制改用英文語系了。

星期六, 9月 22, 2012

錯誤訊息:Missing styles. Is the correct theme chosen for this layout?

Android 開發採用 Eclipse 作為整合開發環境, 不過這 Eclipse 真的是有許多狀況, 今天同事給我一個很簡單的專案檔案, 說怎麼跑都會出錯, 程式當掉。我看了之後, 雖然發現了程式撰寫上的問題, 但還看到一個怪怪的畫面, 我打開 layout 檔案後看到的是這樣:


首先注意到的是怎麼不管是 TextView 或是 Button 的樣子都很怪, 有些字還疊在一起。然後看到下方顯示了 "Missing styles. Is the correct theme chosen for this layout?" 的錯誤訊息, 但明明使用的就是建立專案後預設的 AppTheme 啊?檢查了 styles.xml、AndroidManifest.xml 的內容, 都沒有改過, AppTheme 的定義都沒有錯誤。如果從上方選取 theme 的功能表拉下來看, 會發現原來根本就誤以為專案中沒有定義 AppTheme 這個主題:


顯然一定是資源的相關資料亂掉了, 只好死馬當活馬醫, 先隨便換個現在系統認得的主題:


果然改個主題之後, 畫面看起來就正常多了:


但是下方還有個錯誤訊息, 這次變成找不到 @string/app_name 這個字串資源了, 所以畫面的標題無法顯示 App 的名稱。明明剛剛都沒問題, 也沒去動過 strings.xml 檔, 根據經驗, 當 Eclipse 頭腦不清時, 最有用的作法就是重新啟動 Eclipse, 重新啟動之後果然一切正常, 而且也認得專案中有定義 AppTheme 主題, 就算再選回 AppTheme 也沒有問題:


之後專案就完全正常了, 接著將之前提到有問題的程式碼改正後, 執行起來也都正確無誤。Eclipse, 我真是被你打敗了! (可以來個 Visual Studio for Android 嗎?)

Android Virtual Device 模擬器的儲存位置

我自己的習慣都是把資料單獨儲存在一個分割區中, 與作業系統分開, 不過因為 Windows 預設的使用者資料夾就是在 C, 所以在建立 Android 模擬器時, 預設也都會儲存到 C 下, 經過 Google 一下, 只要設定一個環境變數 ANDROID_SDK_HOME, 指定希望儲存的目的資料夾, 就可以讓 Android Virtual Device Manager 把新建立的模擬器儲存到指定位置了。


這同時也可以解決當使用者名稱有中文時, 無法從包含名稱有中文的資料夾啟動模擬器的問題。

星期六, 9月 08, 2012

Android 的 process、activity、task 與 back 鈕的關係

在 Android 系統中, 一個 App 主要是以畫面為單位來切分程式單元, 每個程式單元就稱為一個「活動 (Activity)」, 負責處理單一畫面的工作, 包含畫面本身的構成、顯示以及該畫面與使用者的互動。以 Gmail 內建 App 為例, 就具有信件清單、信件內容、編寫新郵件等不同的畫面, 每一個畫面就由一個活動來處理。活動一開始的工作, 就是將畫面顯示出來, 例如 Gmail 的信件清單畫面, 就要擺個能夠切換不同標籤信件的按鈕, 並且放置一個列表元件顯示信件清單。畫面顯示出來之後, 活動也必須負責像是使用者按了清單中的某一封信件時要跳轉到信件內容畫面的動作。在同一個 App 的所有活動之中, 必須指定其中一個為「主活動 (main activity)」, 也就是 App 一開始時要最先執行的活動。

由上可知, 當我們使用 Android 系統時, 畫面的跳轉實際上就是從一個活動跳到另一個活動, 系統會幫我們把活動跳轉的過程記錄下來, 當我們按了 Back 按鈕時, 系統就會依照跳轉的歷程, 結束目前的活動, 返回到前一個活動。舉例來說, 如果你在 Gmail 的信件清單中按了某一封信件, 這時處理信件清單畫面的活動就會跳轉到顯示信件內容的活動, 由該活動將信件內容顯示出來, 此時如果按了 Back 鈕, 就會結束顯示信件內容的活動, 回到前一個活動, 也就是顯示信件清單的活動。活動跳轉的歷程是紀錄在一個堆疊中, 稱為「返回堆疊 (back stack)」, 而返回堆疊裡的這一串活動, 就統稱為是一個「任務 (task)」, 任務中第一個推入到返回堆疊中的活動稱為「根活動 (root activity)」。

一個任務是由使用者在 Home 畫面或是應用程式列表中點選了某個 App 的圖示開始, 假設此 App 名稱為 A1, 此時 A1 的主活動就會推入返回堆疊中成為根活動, 隨著使用者的操作切換畫面, 並將對應的活動堆入返回堆疊。如果使用者按了 Back 鈕回到根活動, 並再次按下 Back 鈕從根活動回到 Home 畫面, 那麼整個任務就結束了。如果在任務尚未結束的情況下, 使用者按了 Home 鈕回到 Home 畫面, 並點選執行了另外一個 App, 假設名稱為 A2, 此時系統就會建立一個新的任務, 配置一個新的返回堆疊, 並以 A2 的主活動為根活動。這個時候, 系統中同時存在兩個任務, 如果長按 Home 鈕, 就可以在兩個任務之間切換。

要特別注意的是長按 Home 鈕時會看到的 App 圖示是以任務為單位, 而不是以活動為單位。舉例來說, 如果你執行了瀏覽器, 接著在瀏覽器的網頁瀏覽畫面中使用分享的功能進入 Gmail 編寫新郵件的畫面, 此時的任務是由瀏覽器開始, 因此若是長按 Home 鈕, 只會看到瀏覽器的圖示, 而不會看到 Gmail 的圖示。另外, 如果已經有以某個 App 開始的任務在執行, 那麼在 Home 畫面點選該 App 圖示時會直接切換到該任務, 而不會建立新的任務。


在 Android 系統中, 編譯好的 App 經過安裝後就存在檔案系統中, 當使用者點觸某個 App 的圖示執行時, 系統就會將 App 相關的程式碼載入到記憶體中執行, 在系統中執行的 App 就稱為是「行程 (Process)」, 系統會紀錄相關的資訊。當行程執行, 完成初始動作後, 就會執行主活動, 開始與使用者互動。


星期三, 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 連線才行吧!

星期四, 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 版本低的系統中以其他的方式提供相同的功能, 或是甚至禁用該功能, 才不會讓舊版系統的使用者因為執行到系統不具備的功能而出錯。