Titanium中Android模塊開發(fā)指南
- @Kroll.proxy
- public class MyProxy extends KrollProxy {
- @Kroll.method(runOnUiThread=true)
- public int doSomething() {
- return 100;
- }
- }
官方地址:Android Module Development Guide
摘要
本指南教你如何在Titanium中開發(fā)Android模塊從而擴(kuò)展Titanium的功能. 在本指南中,你將會學(xué)習(xí)到以下幾點:
- 設(shè)置你的環(huán)境能夠構(gòu)建Android模塊
- 構(gòu)建一個Android模塊
- 打包一個Android模塊
- 理解Android模塊API
Titanium Android模塊開發(fā)指南
為了使用Android模塊SDK, 你必須具有Android SDK相關(guān)的知識. 本指南將假定你知道如何使用原生的Android SDK進(jìn)行開發(fā).
前提條件
- Titanium Mobile SDK 1.5 及以上版本
- 最新版的Python( >= 2.5), 必須在PATH路徑中, 或定義PYTHONHOME常量 在Windows中, Titanium Developer / Desktop綁定了Python2.5,因此不需要額外配置
- Oracle JDK
- Android SDK
- Ant 1.7.1 或以上版本,必須包含在PATH中. 如果你不想單獨安裝Ant,你可以使用Eclipse
環(huán)境設(shè)置
參照 Titanium命令行工具 完成環(huán)境設(shè)置.
創(chuàng)建一個模塊
要創(chuàng)建一個模塊,我們需要傳遞一些參數(shù)給titanium命令行工具.
- 模塊的名字 ($MODULE_NAME) 和ID ($MODULE_ID)
- 模塊的目標(biāo)運行平臺 (android)
- Android SDK的安裝目錄 ($ANDROID_SDK) 例如 /opt/android-sdk
對于一個Android, 我們以如下參數(shù)創(chuàng)建一個模塊:
titanium create --platform=android --type=module --name=$MODULE_NAME --id=$MODULE_ID --android=$ANDROID_SDK |
作為一個示例,我們創(chuàng)建了一個運行簡單的加減操作的模塊,命名為“calc”,給定其ID為“org.appcelerator.calc”,并把Android SDK的路徑指向/path/to/android-sdk
引用
titanium create --platform=android --type=module --name=calc --id=org.appcelerator.calc --android=/path/to/android-sdk |
如果運行成功,應(yīng)該能在當(dāng)前目錄下看到新創(chuàng)建的 calc 子目錄了.
模塊項目目錄布局
在模塊目錄中, 你可以看到剛生產(chǎn)的文件和目錄樹:
- LICENSE – 模塊的版權(quán)說明
- build.properties – Ant的properties文件,包含Titanium SDK和Android SDK的路徑
- build.xml – Ant 構(gòu)建腳本 – 用于構(gòu)建, 分發(fā)和測試模塊
- manifest – 包含模塊的版本,作者,許可,版權(quán),名稱,ID,GUID和平臺信息的清單文件
- timodule.xml – 放置自定義的activities和想插入到AndroidManifest.xml文件的配置
- hooks – 腳本目錄,在模塊被添加/安裝/刪除/卸載的時候調(diào)用
- documentation – 生成的Markdown文件,包含了你的模塊的例子文檔
- assets – 模塊所需的其他資源比如圖像等放這里(詳看README)
- lib – 放置需要的第三方JAR文件,他們將會被自動的追加到你的工程和模塊zip中[*]src – 模塊源代碼目錄
- example – 模塊例子工程
Eclipse集成
TItanium 會創(chuàng)建導(dǎo)入為Eclipse項目所需要的文件, 在Eclipse 執(zhí)行如下操作導(dǎo)入calc項目:
- 在頂部菜單中單擊 “File > Import…”
- 打開General文件夾后,雙擊“Existing Project into Workspace”
- 點擊“Select root directory”之后的“Browse…”
- 選擇模塊項目目錄
- 在 Projects 列表中可以看到你的模塊了:
- 按下“Finish”后,就應(yīng)該能夠在Eclipse的”Package Explorer “下看到你的模塊工程了.
構(gòu)建模塊zip
dist目錄下的zip包是模塊的可分發(fā)形式, 它通常遵循的命名模式為$MODULE_ID-android-$MODULE_VERSION.zip
其中包含:
- 編譯的包含類,生成的綁定,以及資源文件的JAR包
- lib目錄中的第三方JAR包
- 模塊清單, 包括作者,版本,許可,版權(quán)等部署需要的元數(shù)據(jù)
- 模塊的timodule.xml文件
通過Ant從命令行構(gòu)建
如果ant已經(jīng)在PATH中, 你可以簡單地在模塊頂層目錄執(zhí)行, 你會看到如下輸出:
$ ant Buildfile: /Users/marshall/Code/test/test_modules/calc/build.xml init: [mkdir] Created dir: /Users/marshall/Code/test/test_modules/calc/build/classes [mkdir] Created dir: /Users/marshall/Code/test/test_modules/calc/dist process.annotations: [javac] Compiling 2 source files to /Users/marshall/Code/test/test_modules/calc/build/classes [javac] Note: [KrollBindingGen] Running Kroll binding generator. [javac] Note: [KrollBindingGen] No binding data found, creating new data file. [javac] Note: [KrollBindingGen] Found binding for module Calc [javac] Note: [KrollBindingGen] Found binding for proxy Example compile: [javac] Compiling 2 source files to /Users/marshall/Code/test/test_modules/calc/build/classes [copy] Copying 1 file to /Users/marshall/Code/test/test_modules/calc/build/classes dist: [jar] Building jar: /Users/marshall/Code/test/test_modules/calc/dist/calc.jar [zip] Building zip: /Users/marshall/Code/test/test_modules/calc/dist/org.appcelerator.calc-android-0.1.zip BUILD SUCCESSFUL Total time: 1 second |
從Eclipse構(gòu)建
如果你米有安裝Ant,或者你更愿意使用Eclipse,參照下面的步驟:
- 在模塊目錄中右擊build.xml文件
- 點擊RunAs>AntBuild
- 你將看到類似的輸出
模塊分發(fā)
要再TitaniumMobile應(yīng)用程序中使用模塊,參照下面的步驟:
[list]
- 復(fù)制模塊的zip文件到Titanium應(yīng)用程序的根目錄,或TitaniumSDK的根目錄
- 在應(yīng)用程序的tiapp.xml文件的標(biāo)簽內(nèi)添加如下XML:
Xml代碼
- <!-- $MODULE_VERSION should be the same as "version" in the module manifest -->
- [*]<modules>
- [*] <module version="$MODULE_VERSION">$MODULE_ID</module>
- [*] <!-- For example, if we were adding the calc module: -->
- [*] <module version="0.1">org.appcelerator.calc</module>
- [*]</modules>
- 在應(yīng)用程序代碼中使用require函數(shù)包含模塊代碼到應(yīng)用程序中,例如:
- var Module = require('$MODULE_ID');
- [*]// For example, to load the calc module:
- [*]var Calc = require('org.appcelerator.calc');
用嵌入的Example項目進(jìn)行測試
使你的模塊能夠工作,最簡單的方法是在example/app.js文件中編寫代碼,并使用ant運行和測試模塊代碼.example目錄等同于應(yīng)用程序的Resources目錄.
運行示例項目的過程非常簡單:
運行Android模擬器
從命令行在模塊項目木下運行:
引用
ant run.emulator |
你應(yīng)該會在控制臺中看到模擬器的輸出!
在Eclipse中配置調(diào)用信息:
- 右擊build.xml, 點擊Run As > Ant Build… (第二個選項)
- 為了一個新的啟動配置將會打開一個配置設(shè)置的窗口
- 然后選擇execute對象,去掉**dist對象,選擇run.emulator對象
- 重命名啟動配置,然他跟明顯的看的出來含義,比如“run emulator”
- 窗口長啥樣的一個例子,calc module:
- 點擊Apply然后運行
- 這樣你就可以通過外部工具菜單(或者工具欄)的run運行這個啟動配置
- 你應(yīng)該能看到在Eclipse的控制臺窗口,emulator有輸出信息
運行Example項目
Once the emulator is up and running, you just need to wait for the unlock screen to appear, and you can start running your project. Make sure to unlock the screen so you’ll see the example project when it launches.
From command line, run this inside your module project:
ant run |
在Eclipse中設(shè)置啟動配置:
Follow the same steps from the Launch configuration setup above, but use the run target instead of the run.emulator target. You should also name the configuration something different, for example run calc project
疑難排除技巧:
如果你運行對象是超時,試著找到emulator,然后通過以下命令重啟ADB服務(wù):
$ $ANDROID_SDK/tools/adb kill-server $ $ANDROID_SDK/tools/adb start-server |
到這里,如果你成功的運行了模塊例子工程的話,你將在模擬器中看到默認(rèn)的”hello world“應(yīng)用:
生成模塊和Example代理
作為初始創(chuàng)建項目的一部分,Titanium產(chǎn)生兩個示例項目中使用的類:
- module類, 如: src/org/appcelerator/calc/CalcModule.java
- proxy類, 如: src/org/appcelerator/calc/ExampleProxy.java
產(chǎn)看這些代碼來了解一下Modules和Proxies是怎么樣跟Javascript通信的,在下一節(jié)將簡要介紹了Titanium 和Kroll的API。
Android Titanium API
模塊和代理(Kroll part 1)
- 一個模塊是一個靜態(tài)的、可選的頂級接口點,總是可以通過相同的名字訪問.Titanium.UI 和 Titanium.App 就是兩個在頂級API TItanium對象下的兩個Module例子.
- 代理是能夠被用于通過一個模塊或其他代理創(chuàng)建和查詢的動態(tài)對象.當(dāng)你使用 “Titanium.UI.createView”:http://developer.appcelerator.com/apidoc/mobile/latest/Titanium.UI.createView-method.html 創(chuàng)建一個原生視圖時, 視圖對象本身就是一個代理
- 模塊和代理都能夠向Javascript API導(dǎo)出方法,屬性,常量以及getters/setters方法.
模塊
- 必須使用 @Kroll.module 符號標(biāo)注,并繼承 KrollModule 類
- 模塊可以有父模塊, 比如 “Titanium.App.Properties“http://developer.appcelerator.com/apidoc/mobile/latest/Titanium.App.Properties-module 模塊就存在于 Titanium.App 下
- 可以給定一個唯一的ID用于require()
- 可以導(dǎo)出為頂級對象(與Titanium同級)
代理
- 必須使用 @Kroll.proxy 符號標(biāo)注, 并繼承 KrollProxy 類
- 當(dāng)使用 @Kroll.proxy#creatableInModule() 時, 有一個生成的 “create” 方法.
- 有內(nèi)置的事件管理
導(dǎo)出方法和屬性(Kroll part 2)
方法
代理和模塊的方法通過 @Kroll.method 符號標(biāo)注進(jìn)行導(dǎo)出. 下面是一個簡單的例子:
Java代碼
- @Kroll.method
- public String getMessage() {
- return "Hello World";
- }
如果你導(dǎo)出的方法要求當(dāng)前Activity, 你可以添加 KrollInvocation 作為第一個參數(shù):
Java代碼
- @Kroll.method
- public String getMessage(KrollInvocation invocation) {
- Activity activity = invocation.getTiContext().getActivity();
- }
方法還有許多其他的選項,詳細(xì)信息可查看@Kroll.methodJavadoc
屬性
屬性可以以兩種不同的形式導(dǎo)出:
1,getter/setter方法通過@Kroll.getProperty和@Kroll.setProperty符號導(dǎo)出,Getter/setter方法還可以被導(dǎo)出為Kroll方法(這是在Titanium中常用的模式)
2,使用Kroll.property符號導(dǎo)出為一個對象字段(使用反射,速度稍慢)
該示例為message屬性導(dǎo)出了一個getter和setter,以及同名的方法:
Java代碼
- @Kroll.getProperty @Kroll.method
- public String getMessage() {
- return "Hello World";
- }
- @Kroll.setProperty @Kroll.method
- public void setMessage(String message) {
- Log.d(TAG, "Tried setting message to: " + message);
- }
在Javascript中可以這樣使用:
Js代碼
- var object = //..
- object.message = "hi"; // or
- object.setMessage("hi");
常量
常量是 @Kroll.module 中的以及靜態(tài)屬性, 該字段以 “@Kroll.constant” 符號標(biāo)注, 必須是static和final, 這兒有一個例子:
Java代碼
- @Kroll.module
- public class MyModule extends KrollModule {
- @Kroll.constant
- public static final int CONSTANT = 100;
- }
常量可以直接使用: Ti.My.CONSTANT == 100
視圖
在Titanium中視圖必須要有2個class::
視圖代理: TiViewProxy的子類
- 負(fù)責(zé)視圖屬性和方法暴露給JavaScript(和一般代理做的一樣).
- 實現(xiàn)TiUIView的createView(Activity activity)方法來返回一個TiUIView的實例
- 很多時候,你想在UI線程中調(diào)用你的UIView,參考 @Kroll.method#runOnUiThread
視圖實現(xiàn): TiUIView的子類
- 必須用視圖的一個實例來調(diào)用setNativeView,無論是在構(gòu)造函數(shù)中,或在processProperties
- 視圖實現(xiàn)負(fù)責(zé)從視圖代理的獲取數(shù)據(jù),并直接應(yīng)用到本地View
- 這個類可以選擇性的實現(xiàn)propertyChanged 和 processProperties,當(dāng)用戶在proxy中設(shè)置了屬性的話會的得到通知。
作為了一個簡單的例子,參考Button 的實現(xiàn)方法ButtonProxy 和TiUIButton
重量級和輕量級窗口
當(dāng)用戶使用Titanium.UI.createWindow API 創(chuàng)建一個窗口時, 運行一些檢查來告知是否創(chuàng)建應(yīng)該是 heavy weight:
- 如果一個窗口被設(shè)置了以下任何一個屬性的話,他就是”heavyweight“: fullscreen, navBarHidden, modal, windowSoftInputMode, 或者tabOpen:true
- 相反的話, 他就是”lightweight“
- Heavyweight窗口會在棧中生成一個新的Activity,而且也一直為窗口創(chuàng)建新的Javascript Context
- Lightweight窗口創(chuàng)建的時候一個全屏的View(調(diào)用代碼是相同的Activity) ,如果設(shè)置了url屬性的話,也會為每個窗口創(chuàng)建新的Javascript Context
線程安全
從Javascript的Context(潛在的任何Activity或Thread)調(diào)用一個方法或者屬性的話,在設(shè)計你的API的時候,很重要的一點是保證線程安全。
為了確保一個方法是在UI線程上執(zhí)行, 可以參考 @Kroll.method#runOnUiThread(). 以下是例子:
Java代碼