Sencha Touch +
Phone Gap
Loiane Groner
Encontro 21 Maio 2013
IBM São Paulo
Loiane Groner
Java JUG Leader
Sencha Community Leader
7+ XP Java
4+ 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 Layouts
Themas e Ícones
Orientação e Animação
Eventos Touch e Scroller
Pacote de Dados
MVC
Componentes
Lists
- Nested, Grouped, Sortable
Carousel
Picker
Overlay
Slider
Forms & fields Toolbars & buttons HTML5
- Audio
-Video
- GeoLocation
Lists
- Nested, Grouped, Sortable
Carousel
Picker
Overlay
Slider
Forms & fields
Toolbars & buttons
HTML5
- Audio
- Video
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
Scrolling
Momentum/bounce physics
ardware accelerated
hroughout 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 Storage
Web SQL (SQLite)
CORS
http://enable-cors.org/
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 com
Sass 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 Purchases
Câmera
Contatos (read only)*
Connection (online/offline)
Device Info (nome, plataforma, uuid)
GeoLocation
Notifications (vibrar)
Orientation
Push Notifications
Sencha Packager*
PhoneGap
Emulator
Sencha Touch não tem
Acelerômetro
Compass
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 segundos
function vibrate() {
navigator.notification.vibrate(2000);
}
Notification - Vibrar
Demo 2
Sencha Touch
+ PhoneGap
5
HTML 5
CSS 3
JS
UIWebView
WebView
APIs JS
Stores
Workflow de
Desenvolvimento
Mock Up
Desenvolvimento
Testes Simulação
Dispositivo
Store
M
O
C
K
U
P
Resultado
sencha generate app
Contatos
../Contatos
Testes Locais
Testes
Automatizados
http://bryntum.com
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
R
I
P
P
L
E
Ferramentas de
Debug
iWebInspector
Weinre
Build
sencha app build
sencha app build native
XCode
Eclipse
build.phonegap.com
Sussa*
Plugins
SQLite nativo
BarCode Scanner
etc
https://github.com/phonegap/phonegap-plugins
https://github.com/brodyspark/PhoneGap-
SQLitePlugin-iOS
Issues
App Store
Parece uma
App
Parece
app iOS
diferente
web
Aprenda a
desenvolver
para mobile,
não web
App
únicaButtons,
iOS Human Interface
Design Guidelines Eventos Touch,
não Web
Pinch,
Zoom
#fail
Agregador de
links
App Intuitiva
Hyperlink
Obrigada!
http://loiane.com
@loiane

Sencha Touch e PhoneGap: SouJava - IBM Maio 2013