在行動裝置作業系統進入戰國時代的今日,許多的 App 開發商經常都需要為同一個 App 產品開發多個平台上的版本,至少主流的 iOS (iPhone)、Android、Windows 8 三大行動作業系統就各自有各自的開發生態,iOS 使用 Objective-C 或 2014 年發表的 Swift,建立在 Apple 公司的作業系統執行環境;Windows 8 主要使用 C#,執行在Microsoft 公司的 .NET Framework 環境;Android 更是百家爭鳴,開放式的作業系統在各家手機廠商的各自針對裝置效能優化下,Android 碎片化(fragmentation) 已經是 Android App 開發商很頭痛的一個問題,在同一個 layout 外,必須提供不同尺寸螢幕適用的圖檔,增加了開發時的麻煩,螢幕越變越大的 iPhone 也逐漸有這樣的困擾出現。
為了解決這個問題,出現了 PhoneGap 這樣的開發框架,它提供了 App 開發者可以透過 HTML、CSS 與 JavaScript 編寫單一網頁程式,接著再透過 PhoneGap 的工具將 PhoneGap 專案打包成 iOS、Android、Window 8、Firefox OS ...等多種行動作業系統的手機應用程式,達到跨平台的目的,也做到了銜接 Web 與桌面應用程式的目標。
PhoneGap 的成長快速,許多網上或是坊間書籍的教學方式已經不符合現行發佈的 PhoneGap 框架使用方式與檔案結構,以下是我們實作時的安裝、建置等實驗記錄:
Platform:
* OS: OS X Marverick 10.9.5
* Xcode: 6.0.1
* Android Debug Bridge version 1.0.31
* PhoneGap: 3.5.0-0.21.17
Install:
如果是直接用:$ npm install -g phonegap,這樣是直接用 phonegap 來建立專案,舊版 phonegap 是要在 Android 或 iOS 中加入 Library 的方式建構 App,在 3.x 版以後已經不適用,可以用 phonegap create my-app 或 cordova create my-app 來建立,還在研究怎麼用,而且使用 phonegap run android 或 cordova build 會出現 execvp() Permission Denied. 不過,用 chmod -R 777 還是無解。
目前成功的建立專案方法是:
cordova platforms ls
or ls platforms
)cordova platform remove wp8
)Build:
到這裡本來應該要用 cordova build (遞迴編譯全部),我只建立了兩個平台:Android 和 iOS,但是在 build android 時就一直發生 execvp() Permission Denied,但是單獨 cordova build ios 是成功的
cordova build android 的錯誤如下:
~/Desktop/demo/hello -->cordova build android
Running command: /Users/veck/Desktop/demo/hello/platforms/android/cordova/build
execvp(): Permission denied
events.js:72
throw er; // Unhandled 'error' event
^
Error: spawn EACCES
at errnoException (child_process.js:980:11)
at Process.ChildProcess._handle.onexit (child_process.js:771:34)
Error: /Users/veck/Desktop/demo/hello/platforms/android/cordova/build: Command failed with exit code 8
at ChildProcess.whenDone (/opt/local/lib/node_modules/cordova/node_modules/cordova-lib/src/cordova/superspawn.js:135:23)
at ChildProcess.EventEmitter.emit (events.js:98:17)
at maybeClose (child_process.js:735:16)
at Process.ChildProcess._handle.onexit (child_process.js:802:5)
因為沒有過,所以 cordova run android 和 cordova emulator android 也就沒有試了。
而 cordova build ios 成功訊息如下:
~/Desktop/demo/hello -->cordova build ios
Running command: /Users/veck/Desktop/demo/hello/platforms/ios/cordova/build
Build settings from command line:
ARCHS = i386
CONFIGURATION_BUILD_DIR = /Users/veck/Desktop/demo/hello/platforms/ios/build/emulator
SDKROOT = iphonesimulator8.0
VALID_ARCHS = i386
=== BUILD TARGET CordovaLib OF PROJECT CordovaLib WITH CONFIGURATION Debug ===
Check dependencies
=== BUILD TARGET HelloWorld OF PROJECT HelloWorld WITH CONFIGURATION Debug ===
Check dependencies
PhaseScriptExecution Copy\ www\ directory build/HelloWorld.build/Debug-iphonesimulator/HelloWorld.build/Script-304B58A110DAC018002A0835.sh
cd /Users/veck/Desktop/demo/hello/platforms/ios
/bin/sh -c /Users/veck/Desktop/demo/hello/platforms/ios/build/HelloWorld.build/Debug-iphonesimulator/HelloWorld.build/Script-304B58A110DAC018002A0835.sh
real 0m0.049s
user 0m0.018s
sys 0m0.027s
ProcessInfoPlistFile build/emulator/HelloWorld.app/Info.plist HelloWorld/HelloWorld-Info.plist
cd /Users/veck/Desktop/demo/hello/platforms/ios
export PATH="/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin:/Applications/Xcode.app/Contents/Developer/usr/bin:/Library/Frameworks/Python.framework/Versions/3.4/bin:/Library/Frameworks/Python.framework/Versions/3.4/bin:/Users/veck/anaconda/bin:/usr/local/Cellar/ruby/1.9.3-p327/bin:/opt/local/bin:/opt/local/sbin:/Users/veck/adt-mac/sdk/tools:/Users/veck/adt-mac/sdk/platform-tools/:~/apache-ant-1.9.3/bin:/Applications/Racket v5.93/bin:/Users/veck/adt-mac/sdk/platform-tools:/Users/veck/adt-mac/sdk/tools:User/veck/Desktop/SMTB:/usr/local/heroku/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/usr/local/git/bin:/Users/veck/.rvm/bin"
builtin-infoPlistUtility /Users/veck/Desktop/demo/hello/platforms/ios/HelloWorld/HelloWorld-Info.plist -genpkginfo /Users/veck/Desktop/demo/hello/platforms/ios/build/emulator/HelloWorld.app/PkgInfo -expandbuildsettings -format binary -platform iphonesimulator -additionalcontentfile /Users/veck/Desktop/demo/hello/platforms/ios/build/HelloWorld.build/Debug-iphonesimulator/HelloWorld.build/MainViewController-PartialInfo.plist -o /Users/veck/Desktop/demo/hello/platforms/ios/build/emulator/HelloWorld.app/Info.plist
GenerateDSYMFile build/emulator/HelloWorld.app.dSYM build/emulator/HelloWorld.app/HelloWorld
cd /Users/veck/Desktop/demo/hello/platforms/ios
export PATH="/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin:/Applications/Xcode.app/Contents/Developer/usr/bin:/Library/Frameworks/Python.framework/Versions/3.4/bin:/Library/Frameworks/Python.framework/Versions/3.4/bin:/Users/veck/anaconda/bin:/usr/local/Cellar/ruby/1.9.3-p327/bin:/opt/local/bin:/opt/local/sbin:/Users/veck/adt-mac/sdk/tools:/Users/veck/adt-mac/sdk/platform-tools/:~/apache-ant-1.9.3/bin:/Applications/Racket v5.93/bin:/Users/veck/adt-mac/sdk/platform-tools:/Users/veck/adt-mac/sdk/tools:User/veck/Desktop/SMTB:/usr/local/heroku/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/usr/local/git/bin:/Users/veck/.rvm/bin"
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/dsymutil /Users/veck/Desktop/demo/hello/platforms/ios/build/emulator/HelloWorld.app/HelloWorld -o /Users/veck/Desktop/demo/hello/platforms/ios/build/emulator/HelloWorld.app.dSYM
Touch build/emulator/HelloWorld.app
cd /Users/veck/Desktop/demo/hello/platforms/ios
export PATH="/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin:/Applications/Xcode.app/Contents/Developer/usr/bin:/Library/Frameworks/Python.framework/Versions/3.4/bin:/Library/Frameworks/Python.framework/Versions/3.4/bin:/Users/veck/anaconda/bin:/usr/local/Cellar/ruby/1.9.3-p327/bin:/opt/local/bin:/opt/local/sbin:/Users/veck/adt-mac/sdk/tools:/Users/veck/adt-mac/sdk/platform-tools/:~/apache-ant-1.9.3/bin:/Applications/Racket v5.93/bin:/Users/veck/adt-mac/sdk/platform-tools:/Users/veck/adt-mac/sdk/tools:User/veck/Desktop/SMTB:/usr/local/heroku/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/usr/local/git/bin:/Users/veck/.rvm/bin"
/usr/bin/touch -c /Users/veck/Desktop/demo/hello/platforms/ios/build/emulator/HelloWorld.app
** BUILD SUCCEEDED **
更多 CLI 操作請參考這篇
Use IDE:
我後來直接點選 hello/platforms/ios/HelloWorld.xcodeproj 來啟動 Xcode 載入這個專案和用 Eclipse ADT Bundle 載入 hello/platforms/android 的 HelloWorld 和 hello/HelloWorld-CordovaLib (前者主要,後者是相依),用模擬器和裝置跑測試就可以動了
後來在 Platform Guide/Android[1]中的 "Open a New Project in the SDK",有講到建立好並加入 platforms 後,就可以用 Eclipse 做進一步的編輯動作和跑測試
Develop Flows for Android:
1 $ cordova create hello com.example.hello HelloWorld
2 $ cd hello
3 $ cordova platform add android
4 $ cordova build android #不過我沒有這一步就直接進入 Eclipse 跑模擬器和手機也是可以
5 Load project in Eclipse ADT Bundle
6 Run as Android Application
7 Modified www/index.html for fundamental UI or other files for customization
而在 iOS 的話:
1 $ cordova create hello com.example.hello HelloWorld
2 $ cd hello
3 $ cordova platform add ios
4 $ cordova build ios #不過我沒有這一步就直接進入 Eclipse 跑模擬器和手機也是可以
5 Click "HelloWorld.xcodeproj" to open project in Xcode
6 ⌘ + R 來跑模擬器測試
7 Modified www/index.html for fundamental UI or other files for customization
How PhoneGap Work:
PhoneGap 好像只是在原本的 Android 和 iOS 程式中載入 Web (index.html),並所以跨平台只是說你可以只寫一次程式 (Web App),然後用 PhoneGap 包裝成不同平台的 App
因此,PhoneGap 不是說建立好 Web App 然後可以用它來轉成 android, ios 的 Code
NOTE:
* Phonegap 應該是 corvoda 的後來包裝,就像 hadoop 在 2.x 後的核心是 yarn,所以主要指令類似,也就是 phonegap create app
== cordova create app
, phonegap run android
== cordova run android
* 上一點中,沒有執行 build 還是可以在 IDE 中用模擬器執行,好像是因為 IDE 在 Run 的時候,就會先 Build 一次了
[1] http://docs.phonegap.com/en/3.5.0/guide_platforms_android_index.md.html#Android%20Platform%20Guide