20110525[Taipei GTUG] titanium mobile簡介
-
Upload
justin-lee -
Category
Technology
-
view
111 -
download
0
description
Transcript of 20110525[Taipei GTUG] titanium mobile簡介
Titanium Mobile簡介
阿修用Javascript打造原生行動應用程式
李易修 Justin Lee赫迅互動科技 使用者經驗架構師
現場調查
誰想開發Mobile App?
會JAVA和Objective-C的請舉手
會做網頁的請舉手
進軍手機、平板有哪些選擇?
在瀏覽器內執行Web App
HTML5+CSS+JS
強
尚可
低
無
弱
沒辦法
把網站包進全螢幕瀏覽器Hybrid App
HTML5+CSS+JS+JS API
強
尚可
低
有
有
可
完全為裝置打造Native App
Java, Obj-C+Native API
低
最佳
高
有
最佳
可
技術
跨平台能力
使用者經驗
學習門檻
離線能力
整合性與功能
上架賣錢
網路應用程式沒辦法上架賣錢
原生應用程式門檻太高,找不到人
混合式應用程式好像不錯!
但是...
要做混合式應用程式很簡單,要做好混合式應用程式不簡單。
要有好的使用體驗,必須看起來像原生應用程式
必須自己刻UI
系統整合有限
效能是個問號
混合式應用程式
混合式應用程式快不起來
hello world!
建立window建立webview載入DOM parser載入JavaScript interpreter載入CSS parser載入HTML renderer載入SVG renderer載入Canvas renderer載入history manager載入SQLLite engine載入index.html等待載入完成render頁面打開windowlabel顯示在螢幕上
建立window建立label打開windowlabel顯示在螢幕上
網路應用程式 原生應用程式
用熟悉的web技術開發原生應用程式?
讓網站開發人員能夠快速上手的跨平台原生應用程式開發框架
Titanium Mobile
簡易的語法使用JavaScript語言,便能開發原生行動應用程式
var win = Titanium.UI.createWindow({ backgroundColor:'#fff'});
var label = Titanium.UI.createLabel({ text: 'Hello World!'});
win.add(label);win.open();
Javascript原始碼+素材
原生應用程式
Titanium API
Native API
Titanium高效能的祕密
JS to Native Bridge
一套原始碼跨多平台iPhone, iPad, Android與BlackBerry
與作業系統高度整合透過UI API與Phone API,取用原生的使用者介面與系統功能
更少的程式碼更高的生產力50%的程式碼長度,同時支援多平台
高度擴充性可經由Java或Objective-C擴充Titanium API功能
開發環境
要開發Titanium行動應用程式你需要:
SDK•Titanium Mobile SDK (1.6.2)•iOS SDK or Android SDK
Developer Tool•Titanium Developer (1.2.2)•Titanium Studio (RC1)
文字編輯器•textmate, vim...
開發iOS應用程式仍然需要Mac
{
Titanium Developer
Titanium StudioBreakpoint+Debugger
Titanium的javascript環境
沒有DOM,不用JQuery
所有的UI由Javascript建立window相當於瀏覽器視窗view相當於div事件處理同樣是用AddEventListener
維持一個execution context
牛刀小試Hello World! Titanium
HowIsTheWeather/ build/ android/ ... iphone/ ... CHANGELOG.txt LICENSE LICENSE.txt manifest README Resources/ android/ ... app.js iphone/ ... KS_nav_ui.png KS_nav_views.png tiapp.xml
檔案及目錄結構原生專案
起始檔
設定檔
android專用檔案
iphone專用檔案
原始碼和其他資料檔
var win = Titanium.UI.createWindow({ backgroundColor:'#fff'});
var label = Titanium.UI.createLabel({ text: 'Hello World!', textAlign: 'center'});
label.addEventListener('click', function(e){ Titanium.API.info('label clicked!');});
win.add(label);win.open();
Hello World!
http://goo.gl/0be5C
Titanium開發實戰現在天氣怎麼樣?
功能:顯示這裡現在的天氣
你可以學到:建立UI取得GPS資訊讀取遠端XML儲存資訊顯示網頁使用各平台特有功能
現在天氣怎麼樣?
原始碼:http://goo.gl/Fj3pl
var win = Titanium.UI.createWindow({ backgroundColor:'#fff'});
var locationLabel = Titanium.UI.createLabel({ color:'#000', text:'內湖區', font:{fontSize: 30, fontFamily:'Helvetica Neue'}, textAlign:'center', width:'auto', height: 'auto', left: 15, top: 75});
var weatherIcon = Titanium.UI.createImageView({ image: 'images/mostly_cloudy.gif', width: 80, height: 80, left: 15, top: 120});
建立UI
75px
15px絕對定位
var temperatureLabel = Titanium.UI.createLabel({ color:'#000', text:'28°C', font:{fontSize: 90, fontFamily:'Helvetica Neue'}, textAlign:'center', width:'auto', height: 'auto', right: 15, top: 100});
var detailLabel = Titanium.UI.createLabel({ color:'#000', text: '多雲時陰\n濕度: 62%\n風向: 西北\n風速:10 公里/小時', font:{fontSize: 24, fontFamily:'Helvetica Neue'}, textAlign:'left', width:'auto', height: 'auto', left: 20, top: 220});
win.add(locationLabel);win.add(weatherIcon);win.add(temperatureLabel);win.add(detailLabel);win.open();
建立UI (續)
if (Titanium.Geolocation.locationServicesEnabled === false){ Titanium.UI.createAlertDialog({title:'無法使用定位服務',
message:'請開啓定位服務,這樣才能取得現在位置的天氣。'}).show();}else{ Ti.Geolocation.purpose = "get current position"; Titanium.Geolocation.accuracy = Titanium.Geolocation.ACCURACY_THREE_KILOMETERS; Titanium.Geolocation.distanceFilter = 1000; Titanium.Geolocation.getCurrentPosition(function(e) { if (e.error) { Titanium.API.info("error: " + JSON.stringify(e.error)); return; } var latitude = e.coords.latitude; var longitude = e.coords.longitude; Ti.API.info(longitude+','+latitude); }); ...}
取得經緯度座標
iOS 3.2以上需要這行。
取座標
function updateLocationName(lat, lng){ Titanium.Geolocation.reverseGeocoder(lat, lng, function(e) { if (e.success) { var places = e.places; if (places && places.length) { locationLabel.text = places[0].city; } else { locationLabel.text = ""; } Ti.API.debug("reverse geolocation result = "+JSON.stringify(e)); } else { Ti.UI.createAlertDialog({ title:'Reverse geo error', message:evt.error }).show(); Ti.API.info("Code translation: "+translateErrorCode(e.code)); } });}
更新地名利用座標查詢地址
http://www.google.com/ig/api?hl={locale}&weather=,,,{lat},{lng}
Google’s secret Weather API
http://www.google.com/ig/api?hl=zh-tw&weather=,,,25060808,121485606
<?xml version="1.0"?><xml_api_reply version="1"><weather module_id="0" tab_id="0" mobile_row="0" mobile_zipped="1" row="0" section="0" > <forecast_information> <city data=""/> <postal_code data=""/> <latitude_e6 data="25060808"/> <longitude_e6 data="121485606"/> <forecast_date data="2010-09-15"/> <current_date_time data="2010-09-14 23:00:00 +0000"/> <unit_system data="SI"/> </forecast_information> <current_conditions> <condition data="多雲"/> <temp_f data="79"/> <temp_c data="26"/> <humidity data="濕度: 87%"/> <icon data="/ig/images/weather/cloudy.gif"/> <wind_condition data="風向: 公里/小時"/> </current_conditions> <forecast_conditions> <day_of_week data="週三"/> <low data="26"/> <high data="35"/> <icon data="/ig/images/weather/thunderstorm.gif"/> <condition data="晴午後短暫雷陣雨"/> </forecast_conditions> ...</weather></xml_api_reply>
http://img0.gmodules.com/前面要加上
更新天氣function updateWeather(lat, lng){ var xhr = Titanium.Network.createHTTPClient();
xhr.onload = function() { Ti.API.info('weather xml ' + this.responseXML + ' text ' + this.responseText); //var doc = this.responseXML.documentElement; encoding bug on Android var doc = Titanium.XML.parseString(this.responseText).documentElement;
var condition = doc.evaluate("//weather/current_conditions/condition").item(0).getAttribute('data'); Ti.API.info(condition);
...
temperatureLabel.text = temp_c + '°C'; weatherIcon.image = icon; detailLabel.text = condition + '\n';
detailLabel.text += humidity + '\n'; detailLabel.text += wind_condition.split('、')[0] + '\n'; detailLabel.text += wind_condition.split('、')[1] + '\n'; }; var url = 'http://www.google.com/ig/api?hl=zh-tw&weather=,,,'+parseInt(lat*1000000, 10)+','+parseInt(lng*1000000, 10); Ti.API.info(url); xhr.open('GET', url); xhr.send();}
包裝一下function getCurrentWeather()
{
if (Titanium.Geolocation.locationServicesEnabled === false)
{
Titanium.UI.createAlertDialog({title:'無法使用定位服務', message:'請開啓定位服務,這樣才能取得現在位置的天氣。'}).show();
}
else
{
Ti.Geolocation.purpose = "取得目前位置的天氣資訊";
Titanium.Geolocation.accuracy = Titanium.Geolocation.ACCURACY_BEST;
Titanium.Geolocation.distanceFilter = 1000;
Titanium.Geolocation.getCurrentPosition(function(e)
{
if (e.error)
{
Titanium.API.info("error: " + JSON.stringify(e.error));
Titanium.UI.createAlertDialog({title:'無法取得位置資訊', message: e.error.message}).show();
detailLabel.text = '無法取得目前位置的天氣資訊,請稍候再試。';
return;
}
var latitude = e.coords.latitude;
var longitude = e.coords.longitude;
Ti.API.info(longitude+','+latitude);
updateLocationName(latitude, longitude);
updateWeather(latitude, longitude);
});
}
}
getCurrentWeather();updateInterval = setInterval(getCurrentWeather, 300000);
每五分鐘更新一次
別忘了第一次
建立設定頁面—相同的部份var settingWin = Titanium.UI.createWindow({ backgroundColor: '#999'});
var aboutWebview = Titanium.UI.createWebView({ url: 'about.html', ... });settingWin.add(aboutWebview);
var doneButton = Titanium.UI.createButton({ title: '完成', ...});settingWin.add(doneButton);
doneButton.addEventListener('click', function(e){ if(Titanium.Platform.osname === 'iphone') { settingWin.close({transition: Ti.UI.iPhone.AnimationStyle.FLIP_FROM_RIGHT}); mainWin.open(); }else if(Titanium.Platform.osname === 'android') { mainWin.open(); settingWin.close(); } getCurrentWeather();});
iOS內建特效
依平台不同調整轉場效果
<!doctype html><html lang="zh-tw"><head> <meta charset="utf-8"> <title>About</title> <meta name="description" content="About the app"> <meta name="viewport" content="width=320"/> <meta name="author" content="lis186"> <link rel="stylesheet" href="screen.css"></head>
<body><h1>現在天氣怎麼樣</h1><img src='appicon.png'><p>版本 1.0</p><p>Powered by Titanium Mobile.</p></body></html>
about.js
用WebView來簡化文字段落編排
建立設定頁面—iPhone部份if(Titanium.Platform.osname === 'iphone'){ var unitTabbedBar = Titanium.UI.createTabbedBar({ labels:['°C', '°F'], style:Titanium.UI.iPhone.SystemButtonStyle.BAR, ... }); unitTabbedBar.addEventListener('click', function(e){ if(e.index === 0) { Titanium.App.Properties.setString('tempUnit', 'c'); }else if (e.index === 1){ Titanium.App.Properties.setString('tempUnit', 'f'); } }); settingWin.add(unitTabbedBar); var settingButton = Titanium.UI.createButton({ ... style: Titanium.UI.iPhone.SystemButton.INFO_DARK }); mainWin.add(settingButton);}
iOS系統按鈕
建立設定頁面—Android部份if(Titanium.Platform.osname === 'android'){ var cButton = Titanium.UI.createButton({ title: '°C', ... }); var fButton = Titanium.UI.createButton({ title: '°F', ... });
cButton.addEventListener('click', function(e){ Titanium.App.Properties.setString('tempUnit', 'c'); cButton.enabled = false; fButton.enabled = true; }); fButton.addEventListener('click', function(e){ Titanium.App.Properties.setString('tempUnit', 'f'); cButton.enabled = true; fButton.enabled = false; });
settingWin.add(cButton); settingWin.add(fButton);}
依照平台UI慣例切換頁面—iPhone部份
if(Titanium.Platform.osname === 'iphone'){ mainWin.add(settingButton); settingButton.addEventListener('click', function(e){ settingWin.open({ transition: Ti.UI.iPhone.AnimationStyle.FLIP_FROM_LEFT
}); var tempUnit = Titanium.App.Properties.getString('tempUnit', 'c'); if(tempUnit === 'c') { unitTabbedBar.index = 0; }else if(tempUnit === 'f') { unitTabbedBar.index = 1; } mainWin.close(); });}
iOS內建特效
利用Property儲存溫度單位
依照平台UI慣例切換頁面—Android部份if(Titanium.Platform.osname === 'android'){ Titanium.Android.currentActivity.onCreateOptionsMenu = function(e) { Titanium.API.info("create menu"); var menu = e.menu; var refreshMenuItem = menu.add({ title: '更新天氣' }); var settingMenuItem = menu.add({ title: '設定' }); refreshMenuItem.addEventListener("click", function(e) { getCurrentWeather(); }); settingMenuItem.addEventListener("click", function(e) { indicator.hide(); settingWin.open(); var tempUnit = Titanium.App.Properties.getString('tempUnit', 'c'); if(tempUnit === 'c') { cButton.enabled = false; fButton.enabled = true; }else if(tempUnit === 'f') { cButton.enabled = true; fButton.enabled = false; } mainWin.close(); }); };}
if(Titanium.Platform.osname === 'iphone'){ var service; Titanium.App.addEventListener('pause',function(e) { Ti.API.info('pause'); service = Titanium.App.iOS.registerBackgroundService({ url: 'bgjob.js', tempUnit: Titanium.App.Properties.getString('tempUnit', 'c') }); Titanium.API.info("registered background service = "+service); });
Titanium.App.addEventListener('resumed',function(e) { Ti.API.info('resumed'); if(service != null){ getCurrentWeather(); service.stop(); service.unregister(); Ti.API.info('Stop background service'); } });}
利用iOS background service更新badge
custom property
function updateWeather(lat, lng){ var xhr = Titanium.Network.createHTTPClient(); xhr.onload = function() {
var tempUnit = Titanium.App.currentService.tempUnit;
...
if(tempUnit === 'c') { Titanium.UI.iPhone.appBadge = temp_c; Ti.API.info('Update badge:' + temp_c); }else if(tempUnit === 'f') { Titanium.UI.iPhone.appBadge = temp_f; Ti.API.info('Update badge:' + temp_f); } }; var url = 'http://www.google.com/ig/api?hl=zh-tw&weather=,,,'+
parseInt(lat*1000000, 10)+','+parseInt(lng*1000000, 10); Ti.API.info(url); xhr.open('GET', url); xhr.send();}
function getCurrentWeather(){
...}...Ti.API.info('starting background service');var updateInterval = setInterval(getCurrentWeather, 300000);...
bgjob.js
custom property
if(Titanium.Platform.osname === 'android'){ Titanium.Android.currentActivity.addEventListener('resume', function(e) { Ti.API.info("resumed"); getCurrentWeather(); });}
Android從背景resume後更新天氣
結論
跨平台 !== “Write Once, Run Everywhere”別忘了為各平台最佳化
有了好工具,仍然需要好點子
http://www.cultofmac.com/self-evidently-bad-app-idea-scale-for-ipad
http://goo.gl/Se1dF
http://goo.gl/Fj3pl範例:現在天氣怎麼樣
Titanium Mobile SDK
Kitchen Sink
http://goo.gl/5v6dJ
Titanium Mobile說明會(加映場)
6/9晚上 邀請制http://www.lis186.com/?p=2140
We’re Hiring!
Titanium SDK Developer
Titanium Evangelist
http://ti.herxun.co/?page_id=66
謝謝!