PhoneGap:
Desenvolvimento Mobile
   Multiplataforma

     Loiane Groner
Loiane Groner
Java JUG Leader
Sencha Community Leader


                          7+ XP TI
 Software Project
Manager @ Citibank
                     http://loiane.com
                          @loiane
Autora Técnica
Internacional
1



   Pq Mobile?
       Pq
Multiplataforma?
http://wearesocial.sg/blog/2013/04/social-brands-go-mobile-or-stand-still/
Android          Java

  BackBerry         Java

     iOS         Objective-C

   Palm OS      C, C++, Pascal

  Symbian            C++

Windows Phone        C#
2




    HTML 5
3



    Web x
    Nativo
Acesso
         Device

Nativo    Sim

Web      Parcial
Acesso
                   Velocidade
         Device

Nativo    Sim        Sim

Web      Parcial       ?
Acesso                     Tempo
                   Velocidade
         Device                 Desenvolvimento




Nativo    Sim        Sim          Caro

Web      Parcial       ?          Sussa
Acesso                     Tempo          App
                   Velocidade
         Device                 Desenvolvimento
                                                  Store

Nativo    Sim        Sim          Caro            Sim

Web      Parcial       ?          Sussa           Não
Acesso                     Tempo          App     Cross
                   Velocidade
         Device                 Desenvolvimento
                                                  Store   Platform

Nativo    Sim        Sim          Caro            Sim      Não

Web      Parcial       ?          Sussa           Não       Sim
App
Híbrida?
4


     Web x
    Nativo x
    Híbrido
Acesso                     Tempo          App     Cross
                    Velocidade
          Device                 Desenvolvimento
                                                   Store   Platform

Nativo     Sim        Sim          Caro            Sim      Não

 Web      Parcial       ?          Sussa           Não       Sim

Híbrido    Sim          ?         Sussa*           Sim       Sim
Acesso                     Tempo          App     Cross
                        Velocidade
              Device                 Desenvolvimento
                                                       Store   Platform

Nativo         Sim        Sim          Caro            Sim      Não

 Web          Parcial       ?          Sussa           Não       Sim

Híbrido        Sim          ?         Sussa*           Sim       Sim

          ?      Já vamos discutir

     Sussa*      Já vamos discutir
?
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.”
5



    PhoneGap
•2008: início
•2008:suporte a iPhone, Android e Blackberry 4
•2009: suporte a Symbian e webOS
•2011: suporte a Windows Phone 7
•2011: Projeto sob Apache - novo nome
A partir do Phonegap 1.5.0
Apache Cordova



•Cordova é o projeto Open Source
•PhoneGap é a implementação
•http://incubator.apache.org/cordova/
O que é Phonegap /
     Cordova?


•Chromeless webkit
browser
•Plataforma mobile
HTML 5 (wrapper)
•Acesso Nativo
Phonegap é
         WORA?
Write Once, Run Anywhere?
Write Once
DEBUG Anywhere
Desenvolva   Desenvolva
Desenvolva   Desenvolva



  Teste        Teste
Desenvolva   Desenvolva



  Teste        Teste



  Build        Build
{
Desenvolva   Desenvolva                 Desenvolva
                          Híbrido
  Teste        Teste                        Teste


  Build        Build                Build           Build
6



Trabalhando com
   Phonegap
UIWebView
          WebView



HTML 5
 CSS 3               Stores
  JS


          APIs JS
7



Gerando uma
    App
./create
   ../../../AppName
com.loiane.mobileConf
        AppName
8



    API
Acceleration


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);
Capturar Foto




function capturePhoto() {
    navigator.camera.getPicture(onPhotoDataSuccess, onFail, { quality: 50,
     destinationType: destinationType.DATA_URL });
  }
Capturar Foto com Edição



function capturePhotoEdit() {

    navigator.camera.getPicture(onPhotoDataSuccess, onFail, { quality: 20,
allowEdit: true,
     destinationType: destinationType.DATA_URL });
  }
Busca Foto do Dispositivo


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>
Compass/Bússula


function onSuccess(heading) {
   alert('Heading: ' + heading.magneticHeading);
};

function onError(error) {
   alert('CompassError: ' + error.code);
};

navigator.compass.getCurrentHeading(onSuccess, onError);
Conexão
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();
Propriedades do Dispositivo


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 />';
 }
In App Browser




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); });
Notification - Alert




navigator.notification.alert(
   'Alerta!', // message
   alertDismissed,        // callback
   'Titulo',      // title
   'Botão'          // buttonName
);
Notification - Confirm



function showConfirm() {
  navigator.notification.confirm(
     'Confirmar?', // message
     onConfirm,          // callback to invoke with index of button pressed
     'Titulo',     // title
     'OK,Cancel'      // buttonLabels
  );
}
Notification - Beep




// Beepa 3 vezes
function playBeep() {
   navigator.notification.beep(3);
}




                      Não funciona no iOS
Notification - Vibrar




// Vibra por 2 segundos
function vibrate() {
    navigator.notification.vibrate(2000);
}
Demo
9



    UI
Frameworks
jQT
Contatos
function onDeviceReady() {
    // acha todos os contatos com 'Loiane' em qualquer campo nome
    var options = new ContactFindOptions();
    options.filter="Loiane";
    var fields = ["displayName", "name"];
    navigator.contacts.find(fields, onSuccess, onError, options);
  }

 // onSuccess: loga o contato que foi achado
 function onSuccess(contacts) {
   for (var i=0; i<contacts.length; i++) {
     console.log("Display Name = " + contacts[i].displayName);
   }
 }

 // onError: Failed to get the contacts
 function onError(contactError) {
   alert('onError!');
 }
Touch
Demo
Workflow de
Desenvolvimento
Mock Up                    Store




                           Dispositivo
Desenvolvimento




             Testes   Simulação
M
O
C
K
U
P
Resultado
Emuladores
R
I
P
P
L
E
Ferramentas de
    Debug
iWebInspector
Weinre
10



     Produção
XCode
       Eclipse
build.phonegap.com
11



     Plugins
Sussa*
SQLite nativo
     BarCode Scanner
           etc
https://github.com/phonegap/phonegap-plugins

  https://github.com/brodyspark/PhoneGap-
               SQLitePlugin-iOS
echo.js

window.echo = function(str, callback) {
   cordova.exec(callback, function(err) {
      callback('Nothing to echo.');
   }, "Echo", "echo", [str]);
};
config.xml


<plugin name="Echo" value="org.apache.cordova.plugin.Echo" />
iOS
Diretório Plugins -Novo Arquivo Objective-C
                   == Echo


   /********* Echo.h Cordova Plugin Header *******/

   #import <Cordova/CDV.h>

   @interface Echo : CDVPlugin

   - (void)echo:(CDVInvokedUrlCommand*)command;

   @end
/********* Echo.m Cordova Plugin Implementation *******/

#import "Echo.h"
#import <Cordova/CDV.h>

@implementation Echo

- (void)echo:(CDVInvokedUrlCommand*)command
{
   CDVPluginResult* pluginResult = nil;
   NSString* echo = [command.arguments objectAtIndex:0];

    if (echo != nil && [echo length] > 0) {
       pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:echo];
    } else {
       pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR];
    }

    [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
}

@end
Android
src/org/apache/cordova/plugin/Echo.java
package org.apache.cordova.plugin;

import org.apache.cordova.api.CordovaPlugin;
import org.apache.cordova.api.PluginResult;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

/**
 * This class echoes a string called from JavaScript.
 */
public class Echo extends CordovaPlugin {
   @Override
   public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
     if (action.equals("echo")) {
        String message = args.getString(0);
        this.echo(message, callbackContext);
        return true;
     }
     return false;
   }

    private void echo(String message, CallbackContext callbackContext) {
      if (message != null && message.length() > 0) {
         callbackContext.success(message);
      } else {
         callbackContext.error("Expected one non-empty string argument.");
      }
    }
}
Como Usar



window.echo("echome", function(echoValue) {
  alert(echoValue == "echome"); // mostra alerta true.
});
Melhores
Práticas
Issues
App Store
Parece uma
             diferente      App                  Aprenda a
                 web                            desenvolver
     Parece                                     para mobile,
    app iOS                                       não web
                                      App
              Buttons,                única               Hyperlink
         iOS Human Interface
          Design Guidelines                   Eventos Touch,
                                                 não Web

Agregador de
    links
                                                       Pinch,
                                                       Zoom
                                                        #fail
   App Intuitiva
Exemplos
 de Apps

           http://phonegap.com/app/
8



    Quando não
      usar?
Demo
https://github.com/loiane/
              mobileConf2013




http://slideshare.net/loianeg
http://loiane.com
     @loiane



       Obrig ada!

MobileConf 2013: PhoneGap

  • 1.
    PhoneGap: Desenvolvimento Mobile Multiplataforma Loiane Groner
  • 2.
    Loiane Groner Java JUGLeader Sencha Community Leader 7+ XP TI Software Project Manager @ Citibank http://loiane.com @loiane
  • 3.
  • 4.
    1 Pq Mobile? Pq Multiplataforma?
  • 9.
  • 11.
    Android Java BackBerry Java iOS Objective-C Palm OS C, C++, Pascal Symbian C++ Windows Phone C#
  • 13.
    2 HTML 5
  • 16.
    3 Web x Nativo
  • 18.
    Acesso Device Nativo Sim Web Parcial
  • 19.
    Acesso Velocidade Device Nativo Sim Sim Web Parcial ?
  • 20.
    Acesso Tempo Velocidade Device Desenvolvimento Nativo Sim Sim Caro Web Parcial ? Sussa
  • 21.
    Acesso Tempo App Velocidade Device Desenvolvimento Store Nativo Sim Sim Caro Sim Web Parcial ? Sussa Não
  • 22.
    Acesso Tempo App Cross Velocidade Device Desenvolvimento Store Platform Nativo Sim Sim Caro Sim Não Web Parcial ? Sussa Não Sim
  • 24.
  • 25.
    4 Web x Nativo x Híbrido
  • 26.
    Acesso Tempo App Cross Velocidade Device Desenvolvimento Store Platform Nativo Sim Sim Caro Sim Não Web Parcial ? Sussa Não Sim Híbrido Sim ? Sussa* Sim Sim
  • 27.
    Acesso Tempo App Cross Velocidade Device Desenvolvimento Store Platform Nativo Sim Sim Caro Sim Não Web Parcial ? Sussa Não Sim Híbrido Sim ? Sussa* Sim Sim ? Já vamos discutir Sussa* Já vamos discutir
  • 28.
  • 29.
    Our biggest mistake wasbetting too much on HTML5
  • 30.
  • 31.
    “So, when MarkZuckerberg said HTML5 wasn't ready, we took a little offense to the comment.”
  • 33.
    5 PhoneGap
  • 34.
    •2008: início •2008:suporte aiPhone, Android e Blackberry 4 •2009: suporte a Symbian e webOS •2011: suporte a Windows Phone 7 •2011: Projeto sob Apache - novo nome
  • 35.
    A partir doPhonegap 1.5.0
  • 36.
    Apache Cordova •Cordova éo projeto Open Source •PhoneGap é a implementação •http://incubator.apache.org/cordova/
  • 37.
    O que éPhonegap / Cordova? •Chromeless webkit browser •Plataforma mobile HTML 5 (wrapper) •Acesso Nativo
  • 39.
    Phonegap é WORA? Write Once, Run Anywhere?
  • 40.
  • 41.
    Desenvolva Desenvolva
  • 42.
    Desenvolva Desenvolva Teste Teste
  • 43.
    Desenvolva Desenvolva Teste Teste Build Build
  • 44.
    { Desenvolva Desenvolva Desenvolva Híbrido Teste Teste Teste Build Build Build Build
  • 45.
  • 46.
    UIWebView WebView HTML 5 CSS 3 Stores JS APIs JS
  • 49.
  • 50.
    ./create ../../../AppName com.loiane.mobileConf AppName
  • 51.
    8 API
  • 53.
    Acceleration 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);
  • 54.
    Capturar Foto function capturePhoto(){ navigator.camera.getPicture(onPhotoDataSuccess, onFail, { quality: 50, destinationType: destinationType.DATA_URL }); }
  • 55.
    Capturar Foto comEdição function capturePhotoEdit() { navigator.camera.getPicture(onPhotoDataSuccess, onFail, { quality: 20, allowEdit: true, destinationType: destinationType.DATA_URL }); }
  • 56.
    Busca Foto doDispositivo 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>
  • 57.
    Compass/Bússula function onSuccess(heading) { alert('Heading: ' + heading.magneticHeading); }; function onError(error) { alert('CompassError: ' + error.code); }; navigator.compass.getCurrentHeading(onSuccess, onError);
  • 58.
    Conexão 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();
  • 59.
    Propriedades do Dispositivo functiononDeviceReady() { 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 />'; }
  • 60.
    In App Browser varref = 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); });
  • 61.
    Notification - Alert navigator.notification.alert( 'Alerta!', // message alertDismissed, // callback 'Titulo', // title 'Botão' // buttonName );
  • 62.
    Notification - Confirm functionshowConfirm() { navigator.notification.confirm( 'Confirmar?', // message onConfirm, // callback to invoke with index of button pressed 'Titulo', // title 'OK,Cancel' // buttonLabels ); }
  • 63.
    Notification - Beep //Beepa 3 vezes function playBeep() { navigator.notification.beep(3); } Não funciona no iOS
  • 64.
    Notification - Vibrar //Vibra por 2 segundos function vibrate() { navigator.notification.vibrate(2000); }
  • 65.
  • 66.
    9 UI Frameworks
  • 67.
  • 68.
    Contatos function onDeviceReady() { // acha todos os contatos com 'Loiane' em qualquer campo nome var options = new ContactFindOptions(); options.filter="Loiane"; var fields = ["displayName", "name"]; navigator.contacts.find(fields, onSuccess, onError, options); } // onSuccess: loga o contato que foi achado function onSuccess(contacts) { for (var i=0; i<contacts.length; i++) { console.log("Display Name = " + contacts[i].displayName); } } // onError: Failed to get the contacts function onError(contactError) { alert('onError!'); }
  • 70.
  • 71.
  • 72.
  • 73.
    Mock Up Store Dispositivo Desenvolvimento Testes Simulação
  • 74.
  • 75.
  • 76.
  • 77.
  • 78.
  • 79.
  • 80.
  • 81.
    10 Produção
  • 82.
    XCode Eclipse build.phonegap.com
  • 83.
    11 Plugins
  • 84.
  • 85.
    SQLite nativo BarCode Scanner etc https://github.com/phonegap/phonegap-plugins https://github.com/brodyspark/PhoneGap- SQLitePlugin-iOS
  • 86.
    echo.js window.echo = function(str,callback) { cordova.exec(callback, function(err) { callback('Nothing to echo.'); }, "Echo", "echo", [str]); };
  • 87.
  • 88.
  • 89.
    Diretório Plugins -NovoArquivo Objective-C == Echo /********* Echo.h Cordova Plugin Header *******/ #import <Cordova/CDV.h> @interface Echo : CDVPlugin - (void)echo:(CDVInvokedUrlCommand*)command; @end
  • 90.
    /********* Echo.m CordovaPlugin Implementation *******/ #import "Echo.h" #import <Cordova/CDV.h> @implementation Echo - (void)echo:(CDVInvokedUrlCommand*)command { CDVPluginResult* pluginResult = nil; NSString* echo = [command.arguments objectAtIndex:0]; if (echo != nil && [echo length] > 0) { pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:echo]; } else { pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR]; } [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; } @end
  • 91.
  • 92.
    src/org/apache/cordova/plugin/Echo.java package org.apache.cordova.plugin; import org.apache.cordova.api.CordovaPlugin; importorg.apache.cordova.api.PluginResult; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; /** * This class echoes a string called from JavaScript. */ public class Echo extends CordovaPlugin { @Override public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException { if (action.equals("echo")) { String message = args.getString(0); this.echo(message, callbackContext); return true; } return false; } private void echo(String message, CallbackContext callbackContext) { if (message != null && message.length() > 0) { callbackContext.success(message); } else { callbackContext.error("Expected one non-empty string argument."); } } }
  • 93.
    Como Usar window.echo("echome", function(echoValue){ alert(echoValue == "echome"); // mostra alerta true. });
  • 94.
  • 96.
  • 97.
    Parece uma diferente App Aprenda a web desenvolver Parece para mobile, app iOS não web App Buttons, única Hyperlink iOS Human Interface Design Guidelines Eventos Touch, não Web Agregador de links Pinch, Zoom #fail App Intuitiva
  • 98.
    Exemplos de Apps http://phonegap.com/app/
  • 100.
    8 Quando não usar?
  • 101.
  • 103.
    https://github.com/loiane/ mobileConf2013 http://slideshare.net/loianeg
  • 104.
    http://loiane.com @loiane Obrig ada!