jueves, 17 de mayo de 2012

Desarrollo de apps con Titanium:Captura y reproducción de Audio

Muchas de las veces queremos desarrollar apps para capturar audio y después de ello guardarlas para luego reproducirlas, esto ha impulsado mucho la combinación de notas en audio más la nube que ha sido una combinación perfecta en esta temporada tecnologica.Para ello necesitamos tener un esqueleto de interfaz:


//crea ventana
var win = Titanium.UI.currentWindow;
//variables
var archivo;
var tiempo;
var sonido;
var duracion = 0;

var etiqueta = Titanium.UI.createLabel({
 text: ' ',
 top:150,
 color: '#999',
 textAlign:'center',
 width: 250,
 height:'auto'
});

win.add(etiqueta);

//label volumen
var volumen = Titanium.UI.createLabel({
 text: "Volumen: "+Ti.Media.volume,
 bottom:50,
 color:'#999',
 textAlign:'center',
 width: 250,
 height: 'auto'
});
//label de switch
var etiquetaSwitch = Titanium.UI.createLabel({
 text:'Alta fiedilidad: ',
 width: 250,
 height:'auto',
 textAlign:'center',
 color:'#999',
 bottom:115
});
//switch
var switchL = Titanium.UI.createSwitch({
 value:false,
 bottom:80
});

win.add(etiquetaSwitch);
win.add(switchL);
//boton del play
var play = Titanium.UI.createButton({
 title:'Reproduce Grabacion',
 width:200,
 height:40,
 top:80
 });
win.add(play);
//boton de grabacion
var start = Titanium.UI.createButton({
 title:'Comenzar Grabacion',
 width:200,
 height:40,
 top:20
});

win.add(start);


Y veremos una interfaz como esta:


Ahora le daremos funcionalidad haciendo lo siguiente:

//crea ventana
var win = Titanium.UI.currentWindow;
//variables
var archivo;
var tiempo;
var sonido;
var duracion = 0;

var etiqueta = Titanium.UI.createLabel({
 text: ' ',
 top:150,
 color: '#999',
 textAlign:'center',
 width: 250,
 height:'auto'
});

win.add(etiqueta);

//label volumen
var volumen = Titanium.UI.createLabel({
 text: "Volumen: "+Ti.Media.volume,
 bottom:50,
 color:'#999',
 textAlign:'center',
 width: 250,
 height: 'auto'
});
//label de switch
var etiquetaSwitch = Titanium.UI.createLabel({
 text:'Alta fiedilidad: ',
 width: 250,
 height:'auto',
 textAlign:'center',
 color:'#999',
 bottom:115
});
//switch
var switchL = Titanium.UI.createSwitch({
 value:false,
 bottom:80
});

win.add(etiquetaSwitch);
win.add(switchL);
//boton del play
var play = Titanium.UI.createButton({
 title:'Reproduce Grabacion',
 width:200,
 height:40,
 top:80
 });
win.add(play);
//boton de grabacion
var start = Titanium.UI.createButton({
 title:'Comenzar Grabacion',
 width:200,
 height:40,
 top:20
});

win.add(start);

//Creamos la instancia de un objeto del metodo AudioRecorder llamado grabando
var grabacion = Ti.Media.createAudioRecorder();

/*
Para una compresion por default usamos Ti.Media.AUDIO_FORMAT_LINEAR_PCM
Nos comprimira el archivo en un tamanio pequenio y optimo para el telefono
Para un formato por default usamos Ti.Media.AUDIO_FILEFORMAT_CAF
Nos dara una buena calidad en el audio
*/
grabacion.compression = Ti.Media.AUDIO_FORMAT_LINEAR_PCM;
grabacion.format = Ti.Media.AUDIO_FILEFORMAT_CAF;
Ti.Media.addEventListener('recordinginput',function(e){
 //en caso de grabacion se da un click en el evento de start
 if(!e.available && grabacion.recording){
  start.fireEvent('click',{});
 }
});
//si se modifico el volumen se actualizara
Ti.Media.addEventListener('volume', function(e){
 volumen.text = "Volumen: "+e.volume;
});
//muestra los niveles de sonido y duracion
function muetraNiveles() 
{
 var peak = Ti.Media.peakMicrophonePower;
    var avg = Ti.Media.averageMicrophonePower;
    duracion ++;
    etiqueta.text ='Duracion: '+duracion+' segundos\npeak power: '+peak+'\navg power: '+avg;
}
//evento al comenzar grabacion
start.addEventListener('click', function()
   {
    if(start.title == "Detener Grabacion")
    {
     //guarda lo grabado en archivo
     archivo = grabacion.stop();
     //cambia la etiqueta start
     start.title= "Comienzar Grabacion";
     //nos muestra la opcion de reproducir
     play.show();
     //limpia el intervalo de tiempo
     clearInterval(tiempo);
     Ti.Media.stopMicrophoneMonitor();
 } else {
  //dar error en caso de que no haiga hardware necesario
    if (!Ti.Media.canRecord) {
      Ti.UI.createAlertDialog({
        title:'Error!',
        message:'No hay dispositivo de grabacion disponible'
      }).show();
return; }
 //cambia etiqueta start
    start.title = "Detener Grabacion";
    //comienza grabar
    grabacion.start();
    //esconde etiqueta Reproducir
    play.hide();
    Ti.Media.startMicrophoneMonitor();
    //inicia en ceros duracion y luego nos muestra el tiempo transcurido
    duracion = 0;
    tiempo = setInterval(muestraNiveles,1000);
  }
});
play.addEventListener('click', function()
{
  if (sonido && sonido.playing)
  {
   //detiene la grabacion
    sonido.stop();
    //libera
    sonido.release();
    sonido = null;
    //cambia etiqueta
    play.title = 'Reproduce Grabacion';
} else {
 //guarda el nuevo archivo
    sonido = Titanium.Media.createSound({sonido:archivo});
    sonido.addEventListener('complete', function()
    {
     //cambia etiqueta play
      play.title = 'Reproduce Grabacion';
    });
    //cambia etiqueta play y reproduce
    sonido.play();
    play.title = 'Detiene Grabacion';
  }
});
//cambia formato por medio del switch
switchL.addEventListener('change',function(e)
{
  if (!switchL.value)
  {
    grabacion.compression = Ti.Media.AUDIO_FORMAT_ULAW;
     }
else {
       grabacion.compression = Ti.Media.AUDIO_FORMAT_LINEAR_PCM;
     }
});



Y como resultado veremos lo siguiente:


Desarrollo de apps con Titanium:Integración de Facebook

Sin duda uno de lo grandes impactos al momento de crear una aplicación es la integración de las redes sociales, en esta entrada hablaremos sobre como crear un login y hacer un post en tu muro del usuario.

Para ello debemos tener creada un aplicación en Facebook el cual es relativamente sencillo, si tienen alguna duda pueden entrar a esta liga que encontre en la cual explica como crear un aplicación en Facebook:


Ahora lo que nos interesa será esto, ya verán por que:


Ahora veremos como hacer un login, y como implementaremos lo anterior en el código :


//crea ventana
var win = Titanium.UI.currentWindow;
//funcion que hace el login de Facebook
function loginFacebook(){
 //Si el usuario no se logio entonces pedir permisos
 if(Titanium.Facebook.loggedIn == false){
  //Aqui colocaremos nuetra APP ID
  Titanium.Facebook.appid='168079606553295';
  Titanium.Facebook.permissions = ['publish_stream'];
  //Permiso que tu app necesita del login
  Titanium.Facebook.addEventListener('login',function(e){
   if(e.success) {
    alert('Te has logiado');
    botonFacebook.title='Postea muro'
   }else if(e.error){
    alert('Error: '+ e.error);
   }else if(e.cancelled){
    alert('Has cancelado el login');
   }
  });
  //Llama un metodo de la API de Facebook para hacer el login
  Titanium.Facebook.authorize();
 }
}

var botonFacebook = Titanium.UI.createButton({
 width: 280,
 height: 35,
 top: 330,
 title: 'Login Facebook'
});
win.add(botonFacebook);
botonFacebook.addEventListener('click', function(e){
 loginFacebook();
});


Nosotros agregamos en el código lo que es la APP ID para pedir permiso a que pueda hacer un login el usuario, más adelante veremos para que lo usamos.Ahora veremos por el momento nuestra captura de pantalla:


Ahora haremos un post  en el muro del usuario con una imágen y una pequeña descripción agregandole esta sentencia dentro de la función de loginFacebook:


 }else{
  //Si ya haz accedido entonces
  //Postea foto
 var f = Ti.Filesystem.getFile('paper.png');
 var imagen = f.read();
 var dato = {
  caption: 'Testeo de Post',
  picture: imagen
  };
  //Postea en este directorio me/photos, anexamos imagen
  Titanium.Facebook.requestWithGraphPath('me/photos', dato, "POST", function(e){
   if(e.success){
    alert("Excelente tu imagen sea posteado en tu muro");
   }else{
    alert('Tu imagen no se pudo postear en tu muro :( intenta denuevo');
   }
  });
 }
}


Y veremos lo siguiente en nuestra app:


Desarrollo de apps con Titanium:Envío de email

Para tener una aplicación muy completa muchos desarrolladores colocan su email para alguna sugerencia y esto es bueno ya que retroalimentan al desarrollador.A continuación haremos una mini-app en la que enviaremos un pequeño contenido con un titulo.

Para ello necesitamos hacer lo siguiente:


//crea ventana
var win = Titanium.UI.currentWindow;
//Nos ayuda crear la forma para enviar un correo
var email = Titanium.UI.createEmailDialog();
//Campo de texto para el titulo, dentro del mismo un aviso
var titulo = Titanium.UI.createTextField({
 width: 200,
 height: 35,
 top: 90,
 value: 'Titulo del mensaje',
 borderStyle: 4
});
win.add(titulo);
//Crearemos un area de texto, a diferencia de campo es que este es mas grande
var texto = Titanium.UI.createTextArea({
 width: 200,
 height: 140,
 top: 130,
 value: 'Cuerpo del mensaje',
 font: {fontSize: 15},
 borderStyle: 4
});
win.add(texto);
//funcion para llenar datos del correo
function llenado(){
 //titulo
 email.subject = titulo.value;
 //correo
 email.toRecipients = ['saul.gausin@gmail.com'];
 //cuerpo del mensaje
 email.messageBody = texto.value;
 //nos envia a nuestra app de correo
 email.open();
}

//boton de enviar
var boton = Titanium.UI.createButton({
 width: 300,
 height: 35,
 top: 280,
 title: 'Enviar correo'
});

//evento de boton
boton.addEventListener('click',function(e){
 if(titulo.value == 'Titulo del mensaje' || titulo.value == null){
  alert('Necesitas tener un titulo.');
 }else if(texto.value == 'Cuerpo del mensaje' || texto.value == null){
  alert('Necesitas tener un contenido.');
 }else{
  llenado();
 }
});

win.add(boton);

Y lo que nos despliegará será lo siguiente :


Le agregamos unas cuantas excepciones si no han sido modificados los campos y si no tiene nada en el campo, y esas excepciones no nos dejan enviar el correo hasta que haya contenido alguno.


martes, 15 de mayo de 2012

Desarrollo de apps con Titanium:Captura/Selección de imágen

Ahora hablaremos sobre como hacer una captura o selección de imágen usando un dialogo, un dialogo es una forma de desplegar varias opciones al usuario  y así se ve:


Para haer que un dialogo se despliegue necesitamos hacer el siguiente código:

//crea ventana
var win = Titanium.UI.currentWindow;
//creamos un dialogo con las siguientes opciones para obtener una imagen segun la opcion elegida
var dialogo = Titanium.UI.createOptionDialog({
 title:'Elige la fuente de la imagen ',
 options: ['Camara','Galeria','Cancelar'],
 cancel:2 //Esto es para eligir cual sera la opcion cancelar
 //Donde comenzamos de 0 como por ejemplo tenemos cancelar
 // 0 Camara, 1 Galeria y 2 Cancelar
});
//agregamos el evento
dialogo.addEventListener('click',function(e){
 Ti.API.info('Seleccionaste'+e.index);
});
//boton para eligir foto
var eligirFoto = Titanium.UI.createButton({
 title: 'Elige',
 top: 20,
 right: 20
 
});

eligirFoto.addEventListener('click',function(e){
 dialogo.show();//muestra dialogo
});
win.add(eligirFoto);

Y obtendremos esto:

Dicho dialogo es desplegado después de haber dado click en el botón.Ahora que ya tenemos este dialogo haremos lo funcional, osea que haremos que tome primero la cámara del telefono y después que tome de la galería.A continuación veremos como tomarlo del teléfono.

//agregamos el evento
dialogo.addEventListener('click',function(e){
 Ti.API.info('Seleccionaste'+e.index);
 //Si eligio Camara
 if(e.index== 0 )
 {
  //Desde nuestra camara
  Titanium.Media.showCamera({
   success:function(event)
   {   
    //Guarda imagen en esta varible
    var imagen = event.media;
    if(event.mediaType == Ti.Media.MEDIA_TYPE_PHOTO)
    {
     //coloca la imagen como una vista
     var imagenView = Titanium.UI.createImageView({
      top:20,
      left:20,
      width: 280,
      height: 320
     });
     imagenView.image=imagen;
     win.add(imagenView);
    }
   },
   cancel:function()
   {
    //Ha sido cancelado, la opcion de tomar imagen desde la camara
   },
   error:function(error)
   {
    //crea una alerta
    var alerta = Titanium.UI.createAlertDialog({
     title:'Camara'
     });
    //Daremos aviso si no tuvo camara o si realmente es otra cosa
    if(error.code == Titanium.Media.NO_CAMERA)
    {
     alerta.setMessage('El dispositivo tiene camara disponible');
    }else{
     alerta.setMessage('Error desconosido');
    }
    //nos muestra la alerta
    alerta.show();
    },
    //permitimos que nuestro dispositivo edite la imagen
   allowImageEditing:true,
   //permitimos a nuestro dispositivo que guarde la imagen en la galeria
   saveToPhotoGallery:true
 });
 }else{
  //canelado
  
 }
});

 Y que obtendremos será un evento en el cual guarda la imágen capturada con el dispositivo, en caso de no tener cámara alguna nos mostrará una alerta diciendonós si el dispositivo no tiene cámara o si fue otro error.Ahora veremos como tomar imágenes desde una galería de fotos:


if(e.index == 1){
  //obtiene una imagen de la galeria de fotos del telefono
  Titanium.Media.openPhotoGallery({
   //Si se cumple
   success:function(event){
    //guarda imagen en variable
    var imagen= event.media
    //Lo coloca como una vista
    if(event.mediaType == Ti.Media.MEDIA_TYPE_PHOTO){
     var imagenVista = Titanium.UI.createImageView({
      top:20,
      left:20,
      width: 280,
      height: 320
     });
     imagenVista.image=imagen;
     win.add(imagenVista);
    }
   },
   //Si no cumple cancela
   cancel:function(){
   //El usuario cancelo la opcion
   }
     });
    }else{
  //cancelado
 }


Con esto podremos tomar imágenes desde nuestra galería del dispositivo ó desde la cámara del mismo.

lunes, 14 de mayo de 2012

Desarrollo de apps con Titanium:Agregando filtro a un TableView

Ahora lo que haremos es agregarle un filtro a nuestra tabla, esto nos sirve mucho para cuando manejamos muchos datos y queremos encontrar de una manera más comoda algo.Para esto tomaré como base la app que vimos en esta entrada:

http://dispositivosmoviles-saulg.blogspot.mx/2012/05/desarrollo-de-apps-con.html

Ahora veremos como implementar un filtro en una tabla, para ello debemos agregar el siguiente código antes de definir una tabla:
//definimos la barra del buscador de la tabla
var buscador = Titanium.UI.createSearchBar({
 showCancel:true,//muestra opcion de cancelar
 height:43,
 top:0
});

//muestra en la consola el valor que busca
buscador.addEventListener('change',function(e){
 Ti.API.info('Busco : '+ e.value);
});
//cuando borra en el campo de texto quita el enfoque al buscador
buscador.addEventListener('return',function(e){
 buscador.blur();
});
//cuando cancela el usuario quita el enfoque a el
buscador.addEventListener('cancel',function(e){
 buscador.blur();
});

Ya definido el buscador vamos a agregar las siguientes propiedades a nuestra tabla para que pueda funcionar nuestro filtro:


Nosotros colocamos a la tabla la propiedad de search y ahi va el nombre de nuestro filtro que lo llamamos buscador, también nosotros agregamos la propiedad filterAttribute aquí es donde va ir la variable que utilizaremos para guardar nuestro filtro.

var win = Titanium.UI.currentWindow;
//declaracion del arreglo vacio
var datos = [];
//declaramos el objeto del cliente http
var xhr = Titanium.Network.createHTTPClient();

//definimos la barra del buscador de la tabla
var buscador = Titanium.UI.createSearchBar({
 showCancel:true,//muestra opcion de cancelar
 height:43,
 barColor: '#385292',
 top:0
});

//muestra en la consola el valor que busca
buscador.addEventListener('change',function(e){
 Ti.API.info('Busco : '+ e.value);
});
//cuando borra en el campo de texto quita el enfoque al buscador
buscador.addEventListener('return',function(e){
 buscador.blur();
});
//cuando cancela el usuario quita el enfoque a el
buscador.addEventListener('cancel',function(e){
 buscador.blur();
});
//creacion de la tabla
var tabla = Ti.UI.createTableView({
 height: 366,
 width: 320,
 top: 0,
 left: 0,
 hideSearchOnSelection: true,
 rowHeight:70, //Le decimos el tamaño de nuestras filas
 search: buscador,
 fitlerAttribute:'filter' //filtrado sera lo que aparecera en nuestras filas
});
//agregamos tabla
win.add(tabla);
//este metodo procesara los datos remotos
xhr.onload = function() {
 var xml = this.responseXML;
 //obtenemos el elemento del de la lista desde nuestro responseXML
 var items = xml.documentElement.getElementsByTagName("item");
 //ciclo por cada item en xml
 for (var i = 0; i < items.length; i++){
   
  //creacion de la fila de la tabla
  var fila = Titanium.UI.createTableViewRow({
   hasChild: true,//con esto decimos que tendrá una subsección la fila
   className: 'fila-rss',//propiedad de solo usar memoria necesaria, osea que solo las filas que veamos
   filter: items.item(i).getElementsByTagName("title").item(0).text//esta variable nos ayuda a saber que filas son las que buscamos con el buscador
  });
  //etiqueta de titulo
  var tituloLabel = Titanium.UI.createLabel({
   text:items.item(i).getElementsByTagName("title").item(0).text,
   //propiedades de la letra
   font:{fontSize: 14, fontWeight: 'bold'},
   left:70,
   color:'#000000',
   top:5,
   height:20,
   width: 210
  });
  fila.add(tituloLabel);
  //etiqueta de descripcion
  var descripcionLabel = Titanium.UI.createLabel({
   text:items.item(i).getElementsByTagName("description").item(0).text,
   font:{fontSize: 10, fontWeight:'normal'},
   left: 70,
   color:'#000000',
   top: 25,
   height: 40,
   width: 200
  });
  if(descripcionLabel.text == ''){
   descripcionLabel.text = 'Descripcion no disponible.';
  }
  fila.add(descripcionLabel);
  //Agregamos un icono en el lado izquierdo a cada fila
  var icono = Titanium.UI.createImageView({
   image:'paper.png',
   width: 30,
   height: 30,
   left: 10,
   top: 10
  });
  fila.add(icono);
  //agregamos la fila al arreglo datos
  datos.push(fila);
 }//termina nuestro ciclo
 //Ahora le especificamos la propiedad de datos a nuestra tabla
 tabla.data = datos;
};
 
//este metodo sera usado en caso de que haiga algun
//error accesando a los datos remotamente
xhr.onerror = function() {
 //Nos desplegara el log del error en la consola
 Ti.API.error(this.status + ' - ' + this.statusText);
};
 
//abre el feed de xml
xhr.open('GET', 'http://feeds.cristalab.com/clab')
 
//Ejecuta la llamada a el feed
xhr.send();

Y esto será lo que obtendremos:

Desarrollo de apps con Titanium:Trabajando con datos remotos

Ahora veremos los métodos que utiliza Titanium Studio para la lectura, análisis y guardado de datos, es importante saber manipular datos remotos para poder hacer una buena optimización de nuestra aplicación.Titanium nos provee una forma sencilla de hacer llamadas simples de XML bajo HTTP, y de igual manera implementando JSON.

Para comenzar primero veremos el siguiente código:
var win = Titatnium.UI.currentWindow;
//declaramos el objeto del cliente http
var xhr = Titanium.Network.createHTTPClient();

//este metodo procesara los datos remotos
xhr.onload = function() {
 //Despliega en la consola las respuesta
 Ti.API.info(this.responseText);
};

//este metodo sera usado en caso de que haiga algun
//error accesando a los datos remotamente
xhr.onerror = function() {
 //Nos desplegara el log del error en la consola
 Ti.API.error(this.status + ' - ' + this.statusText);
};

//abre el feed de xml
xhr.open('GET', 'http://www.elnorte.com/rss/ciencia.xml')

//Ejecuta la llamada a el feed
xhr.send();

Y lo que nos despliega el código en la consola es lo siguiente:


Ahora veremos como desplegarlo en tablas:
var win = Titanium.UI.currentWindow;
//declaracion del arreglo vacio
var datos = [];
//declaramos el objeto del cliente http
var xhr = Titanium.Network.createHTTPClient();
//creacion de la tabla
var tabla = Titanium.UI.createTableView({
 height: 366,
 width: 320,
 top: 0,
 left: 0
});
//agregamos tabla
win.add(tabla);
//este metodo procesara los datos remotos
xhr.onload = function() {
 var xml = this.responseXML;
 //obtenemos el elemento del de la lista desde nuestro responseXML
 var items = xml.documentElement.getElementsByTagName("item");
 //ciclo por cada item en xml
 for (var i = 0; i < items.length; i++){
  
  //creacion de la fila de la tabla
  var fila = Titanium.UI.createTableViewRow({
   title:items.item(i).getElementsByTagName("title").item(0).text
  });
  
  //agregamos la fila al arreglo datos
  datos.push(fila);
 }//termina nuestro ciclo
 //Ahora le especificamos la propiedad de datos a nuestra tabla
 tabla.data = datos;
};

//este metodo sera usado en caso de que haiga algun
//error accesando a los datos remotamente
xhr.onerror = function() {
 //Nos desplegara el log del error en la consola
 Ti.API.error(this.status + ' - ' + this.statusText);
};

//abre el feed de xml
xhr.open('GET', 'http://www.elnorte.com/rss/ciencia.xml')

//Ejecuta la llamada a el feed
xhr.send();

Y nos despliegará esto, que es un rss que lo tomé de la página de "El Norte":



Veremos como colocarle imágenes a cada fila y hacer que cada fila nos muestre el contenido, ya que en el anterior solamente vemos el título de la noticia:
var win = Titanium.UI.currentWindow;
//declaracion del arreglo vacio
var datos = [];
//declaramos el objeto del cliente http
var xhr = Titanium.Network.createHTTPClient();
//creacion de la tabla
var tabla = Titanium.UI.createTableView({
 height: 366,
 width: 320,
 top: 0,
 left: 0,
 rowHeight:70 //Le decimos el tamaño de nuestras filas
});
//agregamos tabla
win.add(tabla);
//este metodo procesara los datos remotos
xhr.onload = function() {
 var xml = this.responseXML;
 //obtenemos el elemento del de la lista desde nuestro responseXML
 var items = xml.documentElement.getElementsByTagName("item");
 //ciclo por cada item en xml
 for (var i = 0; i < items.length; i++){
  
  //creacion de la fila de la tabla
  var fila = Titanium.UI.createTableViewRow({
   hasChild: true,//con esto decimos que tendrá una subsección la fila
   className: 'fila-rss'//propiedad de solo usar memoria necesaria, osea que solo las filas que veamos
  });
  //etiqueta de titulo
  var tituloLabel = Titanium.UI.createLabel({
   text:items.item(i).getElementsByTagName("title").item(0).text,
   //propiedades de la letra
   font:{fontSize: 14, fontWeight: 'bold'},
   left:70,
   color:'#000000',
   top:5,
   height:20,
   width: 210
  });
  fila.add(tituloLabel);
  //etiqueta de descripcion
  var descripcionLabel = Titanium.UI.createLabel({
   text:items.item(i).getElementsByTagName("description").item(0).text,
   font:{fontSize: 10, fontWeight:'normal'},
   left: 70,
   color:'#000000',
   top: 25,
   height: 40,
   width: 200
  });
  if(descripcionLabel.text == ''){
   descripcionLabel.text = 'Descripcion no disponible.';
  }
  fila.add(descripcionLabel);
  //Agregamos un icono en el lado izquierdo a cada fila
  var icono = Titanium.UI.createImageView({
   image:'paper.png',
   width: 30,
   height: 30,
   left: 10,
   top: 10
  });
  fila.add(icono);
  //agregamos la fila al arreglo datos
  datos.push(fila);
 }//termina nuestro ciclo
 //Ahora le especificamos la propiedad de datos a nuestra tabla
 tabla.data = datos;
};

//este metodo sera usado en caso de que haiga algun
//error accesando a los datos remotamente
xhr.onerror = function() {
 //Nos desplegara el log del error en la consola
 Ti.API.error(this.status + ' - ' + this.statusText);
};

//abre el feed de xml
xhr.open('GET', 'http://www.elnorte.com/rss/ciencia.xml')

//Ejecuta la llamada a el feed
xhr.send();

Ahora veremos lo que nos despliega el código:

Ahora usaremos JSON, para ello nosotros usaremos Yahoo! YQL para acelerar el acceso a nuestros datos remotos.Para ello entramos a esta página http://developer.yahoo. com/yql/console :


Seleccionamos 'Data Tables', luego seleccionamos 'data' para después seleccionar 'feed'.Nos aparecerá algo como arriba pero con otra url, sustituimos por la misma que tenemos en la imágen y
seleccionamos JSON y Diagnostics,Para finalizar damos click en TEST y nos dará como resultado XML en formato JSON debajo de la etiqueta THE REST QUERY, una vez teniendo la url sustituimos esto ' por esto otro \' eliminaremos esta parte &callback=cbfunc que es la última.


Ahora modificaremos nuestro código:
var win = Titanium.UI.currentWindow;
//declaracion del arreglo vacio
var datos = [];
//declaramos el objeto del cliente http
var xhr = Titanium.Network.createHTTPClient();
//creacion de la tabla
var tabla = Titanium.UI.createTableView({
 height: 366,
 width: 320,
 top: 0,
 left: 0,
 rowHeight:70 //Le decimos el tamaño de nuestras filas
});
//agregamos tabla
win.add(tabla);
//este metodo procesara los datos remotos
xhr.onload = function() {
 //Creamos un objeto json usando la funcion JSON.parse; nos sirve para parsear datos en JSON
 var jsonObject = JSON.parse(this.responseText);
 //ciclo por cada item en json
 for (var i = 0; i < jsonObject.query.results.item.length; i++){
  //creacion de la fila de la tabla
  var fila = Titanium.UI.createTableViewRow({
   hasChild: true,//con esto decimos que tendrá una subsección la fila
   className: 'fila-rss',//propiedad de solo usar memoria necesaria, osea que solo las filas que veamos
   backgroundColor: '#FFFFFF'
  });
  //etiqueta de titulo
  var tituloLabel = Titanium.UI.createLabel({
   text:jsonObject.query.results.item[i].title,
   //propiedades de la letra
   font:{fontSize: 14, fontWeight: 'bold'},
   left:70,
   color:'#000000',
   top:5,
   height:20,
   width: 210
  });
  fila.add(tituloLabel);
  //etiqueta de descripcion
  var descripcionLabel = Titanium.UI.createLabel({
   text:jsonObject.query.results.item[i].description,
   font:{fontSize: 10, fontWeight:'normal'},
   left: 70,
   color:'#000000',
   top: 25,
   height: 40,
   width: 200
  });
  if(descripcionLabel.text == ''){
   descripcionLabel.text = 'Descripcion no disponible.';
  }
  fila.add(descripcionLabel);
  //Agregamos un icono en el lado izquierdo a cada fila
  var icono = Titanium.UI.createImageView({
   image:'paper.png',
   width: 30,
   height: 30,
   left: 10,
   top: 10
  });
  fila.add(icono);
  //agregamos la fila al arreglo datos
  datos.push(fila);
 }//termina nuestro ciclo
 //Ahora le especificamos la propiedad de datos a nuestra tabla
 tabla.data = datos;
};

//este metodo sera usado en caso de que haiga algun
//error accesando a los datos remotamente
xhr.onerror = function() {
 //Nos desplegara el log del error en la consola
 Ti.API.error(this.status + ' - ' + this.statusText);
};

//abre el feed de xml
xhr.open('GET', 'http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20feed%20where%20url%3D\'www.elnorte.com%2Frss%2Fciencia.xml\'&format=json&diagnostics=true')
//Ejecuta la llamada a el feed
xhr.send();

Esto es lo que nos despliega el código corriendo:


Vieron la diferencia?, si están leyendo probablemente dirán que esta loco veo lo mismo pero si lo corren verán de que estoy hablando ;) ... me refiero a velocidad .

Fuentes:

Ayuda de desarrollador de Appcelerator
http://developer.appcelerator.com/

Consola YQL
http://developer.yahoo.com/yql/


sábado, 12 de mayo de 2012

Desarrollo de apps con Titanium: Geolocalización

Una de las características de las aplicaciones que tienen gran éxito en el mercado sin duda es la geolocalización por ende explicaré un ejemplo sencillo, en el que colocaremos un pin dependiendo la latitud y longitud dada. 



Y esto es lo que despliega el código desde android:


En el código se crea una vista del mapa en el que pide como parámetros el tipo de mapa: TITANIUM.MAP.STANDARD_TYPE, TITANIUM.MAP.SATELLITE_TYPE y TITANIUM.MAP.HYBRID_TYPE.Estos se ven de la siguiente manera:


También tenemos latitud y longitud los cuales esos dependen de la ubicación exacta del mapa donde quieres que se despliegue la vista del map, de igual manera vemos unos que se llaman latitudDelta y longitudDelta con ellos le decimos cual es nivel de zoom que queremos en el mapa.

Animate es un valor booleano que nos permite el zoom y animación de movimiento dentro o fuera de la vista del mapa. Útil en el caso de la focalización dispositivos más antiguos, con capacidad de procesamiento de baja y / o ancho de banda bajo.

El parámetro region acepta por propiedad un arreglo de parámetros, el cual puede contener puntos de latitud y longitud que nosotros deseamos y colocarlos en el mapa de igual manera con los valores delta.userLocation es un valor booleano que puede apagarse o encenderse con un punto azul como indicador en el cual indica donde estás en relación con la vista del mapa.regionFit es un valor booleano que indica si la región seleccionada se ajusta a las dimensiones de vista dado.

La anotación agregada será descrita de la siguiente manera:

 
En la que tiene los mismos parámetros, con la excepción de algunos como leftButton, rightButton title, subtitle y pinColor.
Esta es la forma de usar colocar una imágen a un leftButton :




En la cual  tiene como parámetro image en donde colocas la dirección de la imágen a mostrar.

Ahora mostaré como colocarle una imágen en el rightButton y como agregarlo:



Y esta es la forma como se agregan eventos de la vista del mapa:


Los pines pueden ir de estos diferentes colores:

Verde
Titanium.Map.ANNOTATION_GREEN  

 Rojo
Titanium.Map.ANNOTATION_RED

Morado
Titanium.Map.ANNOTATION_PURPLE

Fuentes:

Imágenes fueron tomadas de esta presentación
http://www.slideshare.net/jhaynie/whats-great-in-appcelerator-titanium-08