20110525[Taipei GTUG] titanium mobile簡介

Post on 28-Jan-2015

111 views 0 download

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!

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

謝謝!