Sencha Touch + Phone Gap Loiane Groner Encontro 21 Maio 2013 IBM São Paulo
May 24, 2015
Sencha Touch +Phone Gap
Loiane Groner
Encontro 21 Maio 2013IBM São Paulo
Loiane GronerJava JUG LeaderSencha Community Leader
7+ XP Java4+ XP Sencha
Software Developer Manager @ Citibank
http://loiane.com@loiane
Autora Técnica Internacional
Nativo x Web
1
Nativo
Web
Acesso Device
Sim
Parcial
Nativo
Web
Acesso Device
Velocidade
Sim Sim
?Parcial
Nativo
Web
Acesso Device
Velocidade Tempo Desenvolvimento
Sim Sim
?
Caro
Parcial Sussa
Nativo
Web
Acesso Device
Velocidade Tempo Desenvolvimento
App Store
Sim Sim
?
Caro
Parcial Sussa
Sim
Não
Nativo
Web
Acesso Device
Velocidade Tempo Desenvolvimento
App Store
Cross Platform
Sim Sim
?
Caro
Parcial Sussa
Sim
Não Sim
Não
Nativo
Web
Acesso Device
Velocidade Tempo Desenvolvimento
App Store
Cross Platform
Sim Sim
?
Caro
Parcial Sussa
Sim
Não Sim
Não
Híbrido Sim ? Sussa* Sim Sim
?
Sussa*
Já vamos discutir
Já vamos discutir
App Híbrida?
Desenvolva Desenvolva
Desenvolva
Teste
Desenvolva
Teste
Desenvolva
Teste
Build
Desenvolva
Teste
Build
Desenvolva
Teste
Build
Desenvolva
Teste
Build
Desenvolva
Teste
Build Build
{Híbrido
?
Our biggest mistake was betting too much
on HTML5
In your face!
“So, when Mark Zuckerberg said HTML5 wasn't ready, we took a little offense to the comment.”
Pq Mobile?Pq
Multiplataforma?
2
Aplicações
WORA:Write Once
Run Anywhere
Mobile
Android Java
BackBerry Java
iOS Objective-C
Palm OS C, C++, Pascal
Symbian C++
Windows Phone C#
Sencha Touch
3
Primeiro framework Javascript para desenvolvimento de apps mobile ricas
usando padrões web - HTML 5
O que tem no Sencha Touch?
Componentes e LayoutsThemas e ÍconesOrientação e AnimaçãoEventos Touch e ScrollerPacote de DadosMVC
ComponentesLists- Nested, Grouped, SortableCarouselPickerOverlaySliderForms & fields Toolbars & buttons HTML5- Audio- Video- GeoLocation
Lists - Nested, Grouped, SortableCarouselPickerOverlaySliderForms & fieldsToolbars & buttonsHTML5 - Audio - Video - GeoLocation
Components
Ext.define('Contact', { extend: 'Ext.data.Model', config: { fields: ['firstName', 'lastName'] }});
var store = Ext.create('Ext.data.Store', { model: 'Contact', sorters: 'lastName',
grouper: { groupFn: function(record) { return record.get('lastName')[0]; } },
data: [ { firstName: 'Tommy', lastName: 'Maintz' }, { firstName: 'Rob', lastName: 'Dougan' }, { firstName: 'Ed', lastName: 'Spencer' }, { firstName: 'Jamie', lastName: 'Avins' }, { firstName: 'Aaron', lastName: 'Conran' }, { firstName: 'Dave', lastName: 'Kaneda' }, { firstName: 'Jacky', lastName: 'Nguyen' }, { firstName: 'Abraham', lastName: 'Elias' }, { firstName: 'Jay', lastName: 'Robinson'}, { firstName: 'Nigel', lastName: 'White' }, { firstName: 'Don', lastName: 'Griffin' }, { firstName: 'Nico', lastName: 'Ferrero' }, { firstName: 'Jason', lastName: 'Johnston'} ]});
Ext.create('Ext.List', { fullscreen: true, itemTpl: '<div class="contact">{firstName} <strong>{lastName}</strong></div>', store: store, grouped: true});
Forms
Ext.create('Ext.form.Panel', { fullscreen: true, items: [ { xtype: 'textfield', name: 'name', label: 'Name' }, { xtype: 'emailfield', name: 'email', label: 'Email' }, { xtype: 'passwordfield', name: 'password', label: 'Password' } ]});
form.submit({ url: 'url/to/submit/to', method: 'POST', success: function() { alert('form submitted successfully!'); }});
Scrolling
ScrollingMomentum/bounce physics
Hardware accelerated
Throughout all components: - Lists - Carousel - Pickers
Eventos Touch
Baseado em Eventos Nativos
Abstraído para Performance
Eventos Adicionais:- Tap- Double tap- Tap & hold - Swipe- Rotate- Drag & drop
Data Package
Models, Stores, e Proxies- Associations- Validation- Local & server storage
Consumir web services- JSON/P - XML- YQL
REST
JSON-P
Local StorageWeb SQL (SQLite)
Temas
Use CSS3 & SASS - Flexible themes - Highly optimized
e.g.
Theming
$base-color: #ff6699
Use CSS3 & SASS - Flexible themes - Highly optimized
e.g.
Theming
$base-color: #ff6699
CSS3 comSass e Compass
"css": [ { "path": "../../resources/css/base.css", "update": "delta" }, { "path": "resources/css/sencha-touch.css", "platform": ['chrome', 'safari', 'ios'], "update": "delta" }, { "path": "resources/css/android.css", "platform": ['android'], "update": "delta" }, { "path": "resources/css/bb.css", "platform": ['blackberry'], "update": "delta" }, { "path": "resources/css/wp.css", "platform": ['ie10'], "update": "delta" } ]
Gráficos
Touch Charts
Demo 1
Tem Acesso Nativo?
Acesso Nativo
App in PurchasesCâmeraContatos (read only)*Connection (online/offline)Device Info (nome, plataforma, uuid)GeoLocationNotifications (vibrar)OrientationPush Notifications
Sencha Packager*PhoneGapEmulator
Sencha Touch não tem
AcelerômetroCompass
File
Phone Gap
4
function onSuccess(acceleration) { alert('Acceleration X: ' + acceleration.x + '\n' + 'Acceleration Y: ' + acceleration.y + '\n' + 'Acceleration Z: ' + acceleration.z + '\n' + 'Timestamp: ' + acceleration.timestamp + '\n');};
function onError() { alert('onError!');};
navigator.accelerometer.getCurrentAcceleration(onSuccess, onError);
Acceleration
function capturePhoto() { navigator.camera.getPicture(onPhotoDataSuccess, onFail, { quality: 50, destinationType: destinationType.DATA_URL }); }
Capturar Foto
function capturePhotoEdit() { navigator.camera.getPicture(onPhotoDataSuccess, onFail, { quality: 20, allowEdit: true, destinationType: destinationType.DATA_URL }); }
Capturar Foto com Edição
function getPhoto(source) { navigator.camera.getPicture(onPhotoURISuccess, onFail, { quality: 50, destinationType: destinationType.FILE_URI, sourceType: source }); }
<button onclick="getPhoto(pictureSource.PHOTOLIBRARY);">Biblioteca</button><br><button onclick="getPhoto(pictureSource.SAVEDPHOTOALBUM);">Album de Fotos</button>
Busca Foto do Dispositivo
function onSuccess(heading) { alert('Heading: ' + heading.magneticHeading);};
function onError(error) { alert('CompassError: ' + error.code);};
navigator.compass.getCurrentHeading(onSuccess, onError);
Compass/Bússula
function checkConnection() { var networkState = navigator.connection.type;
var states = {}; states[Connection.UNKNOWN] = 'Unknown connection'; states[Connection.ETHERNET] = 'Ethernet connection'; states[Connection.WIFI] = 'WiFi connection'; states[Connection.CELL_2G] = 'Cell 2G connection'; states[Connection.CELL_3G] = 'Cell 3G connection'; states[Connection.CELL_4G] = 'Cell 4G connection'; states[Connection.NONE] = 'No network connection';
alert('Connection type: ' + states[networkState]);}
checkConnection();
Conexão
function onDeviceReady() { var element = document.getElementById('deviceProperties');
element.innerHTML = 'Device Name: ' + device.name + '<br />' + 'Device Cordova: ' + device.cordova + '<br />' + 'Device Platform: ' + device.platform + '<br />' + 'Device UUID: ' + device.uuid + '<br />' + 'Device Model: ' + device.model + '<br />' + 'Device Version: ' + device.version + '<br />'; }
Propriedades do Dispositivo
var ref = window.open('http://loiane.com', '_blank', 'location=yes'); ref.addEventListener('loadstart', function() { alert('start: ' + event.url); }); ref.addEventListener('loadstop', function() { alert('stop: ' + event.url); }); ref.addEventListener('exit', function() { alert(event.type); });
In App Browser
navigator.notification.alert( 'Alerta!', // message alertDismissed, // callback 'Titulo', // title 'Botão' // buttonName);
Notification - Alert
function showConfirm() { navigator.notification.confirm( 'Confirmar?', // message onConfirm, // callback to invoke with index of button pressed 'Titulo', // title 'OK,Cancel' // buttonLabels );}
Notification - Confirm
// Beepa 3 vezes function playBeep() { navigator.notification.beep(3); }
Notification - Beep
Não funciona no iOS
// Vibra por 2 segundosfunction vibrate() { navigator.notification.vibrate(2000);}
Notification - Vibrar
Demo 2
Sencha Touch+ PhoneGap
5
HTML 5CSS 3
JS
UIWebViewWebView
APIs JS
Stores
Workflow deDesenvolvimento
Mock Up
Desenvolvimento
Testes Simulação
Dispositivo
Store
MOCKUP
Resultado
sencha generate app Contatos
../Contatos
Testes Locais
Testes Automatizados
Hora de Integrar!
app.json
"js": [ { "path": "touch/sencha-touch.js" }, { "path": "cordova-2.5.0.js" }, { "path": "app.js", "bundle": true, "update": "delta" } ],
navigator.contacts.find(! fields,! function(deviceContacts) {! //loop over deviceContacts and create Contact model instances! var contacts = [];! for (var i = 0; i < deviceContacts.length; i++) {! var deviceContact = deviceContacts[ i ];
! ! ! ! ! console.log(deviceContact);
! ! ! ! ! var phone = deviceContact.phoneNumbers[0];! ! ! ! ! if (phone){! ! ! ! ! ! phone = phone.value;! ! ! ! ! } else{! ! ! ! ! ! phone = "";! ! ! ! ! }
! ! ! ! ! console.log("phone " + phone);
! var contact = Ext.create('MyContacts.model.Contact',{! id: deviceContact.id,! givenName: deviceContact.name.givenName,! familyName: deviceContact.name.familyName,! phoneNumber: phone,! birthday: new Date(deviceContact.birthday),! notes: deviceContact.note! });! contact.deviceContact = deviceContact;! contacts.push(contact);! }! //return model instances in a result set operation.setResultSet( ! Ext.create('Ext.data.ResultSet', { ! records: contacts, ! total : contacts.length }) );! //announce success! operation.setSuccessful();! operation.setCompleted(); console.log('operation complete');! //finish with callback! if (typeof callback == "function") {! callback.call(scope || thisProxy, operation);! }! },
MyContacts.proxy.ContactsProxy
./create ContatosIOS com.loiane
../../../ContatosIOS
Demo 3
Emuladores
RIPPLE
Ferramentas de Debug
iWebInspector
Weinre
Build
sencha app build
sencha app build native
XCodeEclipse
build.phonegap.com
Sussa*
Plugins
SQLite nativoBarCode Scanner
etc
https://github.com/phonegap/phonegap-plugins
https://github.com/brodyspark/PhoneGap-SQLitePlugin-iOS
IssuesApp Store
Parece uma App
Parece app iOS
diferente web
Aprenda a desenvolver para mobile,
não webApp únicaButtons,
iOS Human Interface Design Guidelines Eventos Touch,
não Web
Pinch,Zoom#fail
Agregador de links
App Intuitiva
Hyperlink