miércoles, 30 de noviembre de 2011

El sitio web falla cuando se intercambia la vista de compatibilidad, cómo reparar estas fallas de programacion de CSS.

si tu sitio web falla cuando usas Internet Explorer e intercambias la vista de compatibilidad, es ---casi siempre-- por fallas de programación nuestras.  

Por experiencia propia he visto que es mas práctico hacer un sitio web probandolo primero en Internet Explorer en sus variados modos de compatibilidad, y luego probarlo en Chrome o Firefox, quienes siempre responderán bien ante los cambios.

Pronto actualizaré la entrada del blog para mostrar cómo solventar estos problemas así que sigueme en el blog para mantenerte actualizado, en este momento estoy algo ocupado para actualizarlo pero pretendo hacerlo muy pronto, que casi siempre son fallas del uso de los Estilos CSS, aunque no esta de menos decir que a veces IE también se pasa de la raya y complica las cosas...pero no es tanto como se tiende a pensar.

nos vemos pronto con la solución...para irte avanzando en algo, primero haz que tu sitio web funcione en IE en los variados modos de compatibilidad, y veras funcionará de maravillas en el resto, y no al revés como mucha gente piensa: primero en firefox y luego a desmadrar a IE...error.

domingo, 17 de abril de 2011

Cómo ver el registro de errores de una aplicación Java en un BlackBerry (Show Stack Trace)

Muchas veces tenemos un programa que comete una infracción y genera una excepción, por ejemplo, dividir entre cero genera una excepción.  El asunto es que en un emulador podemos ver el Stack Trace de una aplicación Java, pero no se ve nada en el dispositivo real, hay una solución muy sencilla:

Para ver el "Stack Trace" en un dispositivo BlackBerry, hay que presionar las teclas:  ALT+LGLG

Aquí muestro una captura de pantalla luego de presionar ALT y la secuencia de teclas LGLG:

viernes, 15 de abril de 2011

Rastreo satelital usando tu móvil y su GPS incorporado.



Rastreo Satelital usando tu Móvil con GPS conectado a Google Latitude.


Objetivo:

Activar el rastreo satelital mediante Google Latitude para guardar toda la trayectoria de un viaje sin necesidad de comprar un GPS, en cambio usando el GPS del teléfono móvil.

Seguridad:

Google Latitude es seguro. No cualquier podrá ver tu ubicación, solo las personas que tu indiques en el panel de control.



Pre requisitos:

1-Tener un teléfono con GPS (opcional si se quiere precisión exacta)
2-Tener una cuenta de google.
3-Tener una cuenta en Google Latitude, y configurarla para que haga rastreo.
4-Instalar Google Maps en tu móvil.
5-Configurar Google Latitude en tu Google Maps móvil.


Registro Histórico de Viajes

Panel de control de Google Latitude mostrando un historial de trayectorias capturadas desde mi móvil. (Mi teléfono no tiene GPS, así que en cambio se usa el posicionamiento por antenas, es menos preciso, pero también es útil hasta cierto punto)
























miércoles, 13 de abril de 2011

Manejo de Fecha y Hora en J2ME

Fecha y Hora con J2ME

Las clases de manejo de fecha y hora en J2ME han sido reducidas para la versión móvil de estas. Básicamente este es el procedimiento:

// aquí 'd' contiene la fecha y hora actual, obtenida por la llamada a "new Date()"
Date d = new Date();

// se instancia un calendario, usando Calendar.getInstance(...) , la llamada a TimeZone es opcional.
Calendar cal = Calendar.getInstance(
  TimeZone.getDefault());

// se asocia al calendario con la fecha y hora actual
cal.setTime(d);

// listo, ya se puede usar el objeto de clase Calendar para obtener fecha y hora.
// en este ejemplo, la variable "hoyEs" contendrá: "2011/04/15" 
String hoyEs = cal.get(Calendar.YEAR)+"/"+(1+cal.get(Calendar.MONTH))+"/"+(cal.get(Calendar.DAY_OF_MONTH));


Importante:Calendar.MONTH y otros son indexadas a cero. es decir:  Enero es 0. Febrero es 1, etc.


lunes, 11 de abril de 2011

HTTP response code: 411 (solución para este error)

Error 411 en respuesta a un POST por HTTP

Estuve 2 horas tratando de averiguar porqué se generaba el error 411 al enviar datos mediante POST a un pequeño script de pruebas en PHP.

El error 411 indica que hay un error en el tamaño indicado en el encabezado del POST, este tamaño hace referencia al numero de bytes de los datos a enviar en el POST hacia el servidor, este número de bytes se envía mediante el encabezado: "Content-Length".

Todo estaba bien puesto, sin embargo el error prevalecía. Revisé todo, y el error persistió, hasta que di con la falla:
el método OutputStream .flush() causa el error 411 por agregar alguna discordancia con el parámetro de encabezado 'Content-Length'

Cómo resolverlo y enviar un POST desde un Midlet:

public static String post(String url,String datos) 
  throws IOException
    {
        HttpConnection c = null;
        InputStream is = null;
        OutputStream os = null;
        int rc;
        String respuesta="";

        try {
            c =(HttpConnection)Connector.open(
                url,Connector.READ_WRITE);
            byte[] request_body = datos.getBytes();
            c.setRequestMethod(HttpConnection.POST);
            c.setRequestProperty("User-Agent","Mozilla/4.0");
            c.setRequestProperty("Content-Type"
                ,"application/x-www-form-urlencoded");
            c.setRequestProperty("Content-Length"
              ,Integer.toString(request_body.length));
            
            os = c.openOutputStream();
            os.write(request_body);
            // esta linea causa el error 411
            // os.flush();  <-- quitar esto

            rc = c.getResponseCode();
            if (rc != HttpConnection.HTTP_OK) {
                throw new IOException(
                 "HTTP response code: " + rc);
            }

            is = c.openInputStream();
            int len = (int)c.getLength();
            if (len > 0) {
                 int actual = 0;
                 int bytesread = 0 ;
                 byte[] data = new byte[len];
                 while ((bytesread != len) && (actual != -1)) {
                    actual = is.read(data, bytesread, len - bytesread);
                    bytesread += actual;
                     respuesta += new String(data);
                 }
            } else {
                int ch;
                while ((ch = is.read()) != -1) {
                    //procesar((byte)ch);
                }
            }
        } catch (ClassCastException e) {
            throw new IllegalArgumentException("Not an HTTP URL");
        } finally {
            if (is != null)
                is.close();
            if (os != null)
                os.close();
            if (c != null)
                c.close();
        }
        return respuesta.trim();
    }





URL Encoder para J2ME

URL Encoder para J2ME




Fíjese en esta URL de ejemplo:


http://miservidor.com/miservletpost/?cedula=12.121.121&nombre=juan perez&direccion=direccion de pruebas con espacios y otros caracteres especiales como estos: \?


Notese que tiene espacios, caracteres especiales en el campo de ejemplo 'direccion' (caracteres ":\?"), que pueden ser confundidos con caracteres reservados propios del protocolo http u otros del sistema operativo o del explorador de internet. Esta url de pruebas no podrá ser enviada a través de una conexión Http sin dañarse.


La dirección de pruebas que hemos puesto es y debe ser almacenada así en el servidor (en un caso de ejemplo):
"direccion de pruebas con espacios y otros caracteres especiales como estos: \?"


Por tanto para que pueda llegar así al servidor de destino con el propósito de ser almacenada entonces debe ser codificada para ser transportada seguramente a través de una conexión http.


Aquí es donde entra la función URLEncode, esta función está disponible fácilmente en el paquete java.lang de J2EE o J2SE, pero no tan fácilmente en J2ME.


Para resolver, se codifica la URL, y esta quedaría así:
http://miservidor.com/miservletpost/?cedula=12.121.121&nombre=juan%20perez&direccion=direccion%20de%20pruebas%20con%20espacios%20y%20otros%20caracteres%20especiales%20como%20estos:%20%5C?


Esta URL si es segura y puede ser transportada al servidor, en donde deberá ser decodificada. En php se puede decodificar fácilmente usando una llamada a urldecode("cadena codficada").


Como referencia puede revisar:


PHP:
http://php.net/manual/es/function.urlencode.php
http://www.php.net/manual/es/function.urldecode.php


JAVA:
http://download.oracle.com/javase/1.5.0/docs/api/java/net/URLEncoder.html


J2ME Información:
http://developers.sun.com/mobility/midp/ttips/HTTPPost/


Para JavaME, use la siguiente rutina:


   static public String urlEncode(String sUrl) 
   {
        StringBuffer urlOK = new StringBuffer();
        for(int i=0; i<sUrl.length(); i++) 
        {
            char ch=sUrl.charAt(i);
            switch(ch)
            {
                case '<': urlOK.append("%3C"); break;
                case '>': urlOK.append("%3E"); break;
                case '/': urlOK.append("%2F"); break;
                case ' ': urlOK.append("%20"); break;
                case ':': urlOK.append("%3A"); break;
                case '-': urlOK.append("%2D"); break;
                default: urlOK.append(ch); break;
            } 
        }
        return urlOK.toString();
    }

Desarrollo para Blackberry ? o para todos los teléfonos Java...?

Cuando decidí crear aplicaciones para teléfonos me cuestione:  "para Blackberries o para todos ?".  Decidí que para todos, sería lo mejor:

Hay que cuestionarse:
  • si se me quema el Blackberry, no podré usar mi sistema de venta en línea hasta que me compre otro Blackberry ?
  • Podría en cambio adquirir un teléfono muy barato y continuar operando ?
  • Si contrato un vendedor, debo comprarle un BlackBerry para que venda mi producto en la calle 
Esas cosas hay que preguntárselas.

BlackBerry insiste en que hay muchos beneficios al desarrollar con su propia API, pero la verdad es que no es tan cierto, quizá si para acceder al Messenger u otros componentes propios del BlackBerry, como el canal de datos PIN.

De que hay que preocuparse para que nuestra aplicación corra en un Blackberry:

Una sola cosa:  -no tocar las API Firmadas (Signed) por RIM- sino nuestra aplicación fallará cuando queramos correrla en este dispositivo, ya que RIM controla el acceso a ellas con un sistema de pago de licencia: "Api Sign", es un mecanismo para evitar que cualquiera use las funciones de esta empresa, evitará código maligno y cosas similares, uno debe pagar unos 20us$ para poder obtener un "sign key" para entonces usarlo en nuestras aplicaciones creadas.  

Podemos hacer muchas cosas sin tocar esas API sensibles de BlackBerry, que según ellos nos permite una gran facilidad en muchas cosas, como por ejemplo la Persistencia de Datos.

Cuales API de RIM estan firmadas y provocaran un "Crash" de la aplicación cuando corra en Blackberry ?

Todo lo diga "net.rim" son api firmadas por RIM y requieren que paguemos para usarlas en un teléfono real, funcionarán en un emulador, pero no en la vida real.  Además, al usar una sola de estas funciones de RIM se causará que la aplicación no corra en ningún otro teléfono del mercado.

Cómo saber que cosas fallarán y cuales no.

Que hago yo:  voy al menú "acerca de..." del BlackBerry y presto atención a estos datos marcados en color:
BlackBerry™ 7130e
Dispositivo de bolsillo inalámbrico (CDMA)
v4.2.1.110 (Plataforma 2.3.0.24)
Kernel de cifrado v3.8.4.34
Configuración de MicroEdition: CLDC-1.1
Perfil de MicroEdition: MIDP-2.0
Versión MicroEdition JTWI: 1.0
Versión MicroEdition Media: 1.1
Versión MicroEdition PIM: 1.0
Versión del archivo MicroEdition: 1.0


CLDC, MIDP y JTWI son las versiones de las API de J2ME que este teléfono tiene incorporadas para dar soporte. Tendremos que buscar estas versiones de estas librerias y desarrollar para estas versiones o compatibles. Debemos usar solo las funciones de estas librerias en estas versiones, sino la aplicación fallará.

Para este caso de ejemplo, el cual es un screenshot de mi teléfono, uso para el desarrollo la versión 3.0 de J2ME SDK, disponible en:    J2ME SDK 3.0 WebSite Oficial

Persistencia de Datos sin usar código de RIM

Hay una solución: Floggy. Este Framework permite aplicar persistencia a nivel de J2ME sin tocar ninguna API sensible de BlackBerry.

En resumen...

Por esto y mucho mas decidí no usar el API de BlackBerry, sino usar J2ME puro, hasta donde pueda, y cuando realmente requiera hacer algo para un teléfono -específicamente BlackBerry- entonces pagaré, mientras...no doy un dolar.




jueves, 7 de abril de 2011

Enviar un Mensaje de Texto (SMS) usando Comandos AT+ (desde un Pc)

Objetivo

Enviar un mensaje de texto desde un computador con un teléfono con una línea GSM activa.

Propósito

Muchas aplicaciones de hoy en día necesitan de conectividad aérea, o inalámbrica (wireless), aunque hay muchos equipos que pueden enviar mensajes de texto (como un Gateway SMS) no hay tanta información disponible para saber cómo comunicarse con un Modem para enviar un mensaje de texto desde el PC.

Las aplicaciones derivadas son muchas y variadas. En este documento me enfocaré en enviar UN mensaje de texto, para enviar mensajes masivos se requiere un Gateway SMS, pero para el propósito educativo de este documento solo enviaremos un mensaje desde el computador con un teléfono GSM.

Los Comandos AT+ y los teléfonos capaces de procesarlos

No todos los teléfonos soportan los comandos AT+, algunos solo soportan un subconjunto limitado de comandos AT, básicos para hacer llamadas y recibir datos.  Los comandos AT+ permiten a un computador conectado al modem la capacidad de enviar y recibir datos con funciones avanzadas, entre ellas el envío de mensajes de texto.

mas información aquí:
http://es.wikipedia.org/wiki/Conjunto_de_comandos_Hayes

El teléfono conectado al PC

No todos los teléfonos pueden conectarse al PC a modo de Modem. Una cosa muy distinta y que no se debe confundir es conectar un teléfono al PC para cargar la bateria, o para transferirle archivos o para verlo como un pendrive y otra muy distinta es conectarse al teléfono a modo de Modem. En el manual de especificaciones del teléfono suele indicarlo. Normalmente se puede usar cómo modem cuando el vendedor nos indica que: "el teléfono puede usarse para conectarlo al computador para navegar en internet desde éste.".  
No le pregunte al vendedor acerca de cosas cómo "modem" o "comandos At", no tendrá remota idea de lo que le está preguntando y solo logrará hacerlo enojar.
Si el teléfono puede conectarse al PC y puede ser usado como módem, entonces ahora solo hay que comprobar que sea capaz de procesar comandos AT+ y que sea capaz de dar las funciones de envío y recepción de mensajes de texto.
Un modelo Sony Ericcson K510 es muy económico y permite hacer todo esto. 
Cómo comprobar que se puedan usar comandos At+ en el teléfono:

Asumiré que tiene conocimientos básicos en el uso de un Modem, de su configuración, instalación y verificación:

Enviar al módem los comandos:

AT+CMGF=0  
AT+CSMS=0
debe retornar un valor de respuesta distinto de error, por ejemplo: "1,1,1"

Si devuelve por ejemplo "1,1,1" quiere decir que el teléfono es capaz de entrar al modo "PDU" y que es capaz de procesar mensajes SMS.  (Sino deberá comprar otro teléfono....si, otro, y quizá otro mas..)

Algoritmo para enviar un mensaje de texto.

Este algoritmo muestra los pasos a seguir para codificar una trama de datos capaz de ser recibida por un teléfono GSM capaz de procesar comandos At extendidos (At+)
Los siguientes pasos son avanzados, y está orientado a programadores con conocimiento en transmisión de datos a puertos, por tanto obviaré escribir para un lenguaje específico, en cambio lo haré a modo de pseudo-algoritmo.
mensaje_a_enviar = "hola como estas"
mpdu = convertir_a_pdu(mensaje_a_enviar)  // devuelve por ejemplo: C8273308823EA7496AB0
El código fuente para convertir un texto a formato PDU es un algoritmo estándar y está disponible aquí: pduconv.h  y  pduconv.cpp
octetos = contar_octetos_de_mensaje_pdu(mpdu)
//ejemplo: octetos = 10 -> 1-C8 2-27 3-33 ....08 82 3E A7 49 6A 10-B0
hoctetos = convertir_a_hexadecimal(octetos)
// hoctetos = 0A, que significa 10 en decimal, debe mantenerse como un valor "String", ya que luego se encadenará a una trama de datos

// dar formato al telefono:
telefono = 0416991199  (el numero de destino, puse cualquier cosa..)
gtelefono = 58416991199  (numero en formato GSM, es el que usaremos)
// si numero es IMPAR se le agrega una 'F' al final., sino no.
gtelefonoAdaptado = esImpar(gtelefono) ? si: agregarF , no: dejarIgual
// en este caso 58416991199 tiene 11 digitos, es impar, agregar una F
// el valor de "gtelefonoAdaptado" quedaría así:  58416991199F

// dar vuelta --los octetos-- de 58416991199F
rev_telefono = 8514961991F9   (58 pasa a ser 85...41->14 etc...)

// contar los digitos del numero GSM
contador = contarDigitos(rev_telefono)  // 12 digitos 8514961991F9
// contador es: 12, y llevarlo a Hexadecimal,
hcontador = 0C  (0c es 12 en decimal)

// armar cadena de texto con el mensaje PDU y demás datos como indico aquí:

00 11 00 0C 91 8514961991F9 00 00 AA 0A C8273308823EA7496AB0
         X1    X2__________          X3 X4__________________
DONDE:
X1 = hcontador
X2 = rev_telefono
X3 = hoctetos
X4 = mpdu

//  así quedaría la trama de datos del mensaje de texto a enviar:
PDU_STRING=0011000C918514962555200000AA0AC8273308823EA7496AB0

// contar el numero de octetos de la cadena generada, sin contar el primero 00
// 11 00 0C 91 85 14 96 25 55 20 00 00 AA 0A C8 27 33 08 82 3E A7 49 6A B0
// tiene 24 octetos
NPDUSTRING = 24


// finalmente enviar al modem el mensaje de texto:
AT+CMGF=0
AT+CSMS=0
AT+CMGS=NPDUSTRING
>PDU_STRING <AGREGAR CARACTER DE ESCAPE:  CONTROL+Z>



Suerte.

Código creado y probado en C++ con un Sony Ericcson k510
por:  Christian Salazar, diciembre de 2008.

"Todo conocimiento es fácil de ser entendido por todos, luego que otro lo descubre primero, el truco está en descubrirlo"  (Isaac Netwon, científico inglés, nacido en 1642)

miércoles, 6 de abril de 2011

Cómo crear un programa en Java para móviles descargable de Internet usando el teléfono.

Objetivo:
  Hacer un programa en Java que se pueda descargar de internet desde el mismo teléfono, que se instale en el teléfono automáticamente y que se pueda acceder a el con un ícono. (Al estilo de los juegos para teléfono descargables de la web)


No todos los teléfonos tienen acceso a una memoria externa (memoria flash como la de una cámara digital), el lector puede pensar que basta con copiar los archivos java del programa existente al teléfono, pero no es así, no todos los teléfonos lo permiten.


Complementos de Lectura y Descargas Altamente Recomendados


Midlets y Blackberries (PDF)



Alternativas: Html para Móviles, jQuery Mobile

Aunque este texto que aqui pongo es para crear una aplicación java para un móvil, existen otras alternativas también válidas como:

http://jquerymobile.com/ , aquí puedes crear una página optimizada para un móvil de forma muy sencilla y visual. No es lo mismo a lo que aqui describo mas abajo, la diferencia es que en este blog describo los pasos para hacer una "aplicación en java" que podrá ser instalada y ejecutada en telefonos con soporte java, mientras que la opción de jquery mobile te permite hacer una "página web mobile", lo cual no es java sino html con formato para moviles. Es distinto..

¿ Cómo se hace una aplicación Java para un móvil ?

  Se creará una aplicación en lenguaje Java con configuración CLDC (para móviles con baja capacidad) que se pueda instalar en modo OTA (Over The Air), es decir con una descarga de internet  directa desde el teléfono y con su consecuente instalación automática, tanto en un teléfono BlackBerry como en otro diferente.

 El procedimiento básico es crear una aplicación con la tecnología J2ME CLDC, la cual generará dos archivos: un JAR (la aplicación como tal en java) y un JAD (es un archivo de configuración).  En algunos teléfonos basta con copiar estos dos archivos en una memoria para luego instalarlos haciendo click en ellos. Pero no todo es tan fácil..en un BlackBerry no se puede, al menos no en todos los modelos. La solución propuesta aquí es subir los archivos JAD y JAR a un hosting con PHP para crear luego un script PHP que permita descargar estos archivos con su tipo MIME correcto.  Por defecto en algunos Blackberries, el tipo mime que este asume no es el correcto, por tanto el script PHP se encargará de decirle a la BlackBerry que use el tipo Mime correcto.

En el telefono primero se descarga el archivo JAD, quien contiene toda la información, el icono y la clase Java a usar, y muy importante: el archivo jar (uno o varios) a descargar.  El telefono usa la informacion del JAD para descargar el archivo JAR, y procede luego a instalarlo. Por tanto en este documento veremos todas las etapas de esta configuración.



Este ejemplo se probó en dos teléfonos y funciona:  
  • Blackberry 7130e con OS: 4.2.1
  • Un Huawei cualquiera (modelo Qwerty)
Captura de pantalla en el Blackberry 7130e:

Imagen de cómo se verá el icono
Pantalla que aparecerá
Primero que todo se necesita programar en Java, usando J2ME, para que la aplicación se vea en todos los telefonos que soporten Java, al principio quise programar con el Api de Blackberry, pero despues pense que era mejor trabajar en Java para no depender de la plataforma de Blackberry, además de que para usar el Api de Blackberry se debe pagar por el derecho de uso del API, alrededor de 20 dolares, sino se generarán errores de acceso denegado al correr la aplicación en un dispositivo físico (en el emulador de blackberry no falla, pero en el físico si).

Descarga de Java Me

El sitio oficial de JavaMe es: http://www.oracle.com/technetwork/java/javame/overview/index.html  , allí encontrará enlaces y herramientas útiles, por ahora me enfocaré en descargar la herramienta principal de desarrollo en Java para Moviles:  Descargar Java ME SDK 3.0,  descarge este componente a su equipo y luego instalelo.  Se le pedirá un usuario y una clave, pero puede obviarlo dejando en blanco los campos. Es opcional.  También puede probar este enlace directo: Descargar

Una vez instalado el componente de Java Me SDK, se ejecuta y debe aparecer este IDE (Integrated Development Environment)









Este IDE es una plataforma de desarrollo, aqui se compila el código a crear, como resultado generará dos archivos:  un JAD y un JAR, que serán los archivos finales de este tutorial, se deberán subir a un sitio web de nuestra propiedad  (o un hosting que soporte PHP) para publicarlos.

Truco:  cuando los archivos JAD y JAR esten listos no basta con subirlos a cualquier hosting, debe crearse un programa PHP para que descargue contenido MIME:  "text/vnd.sun.j2me.app-descriptor" con el objeto de que el teléfono o dispositivo pueda hacer su trabajo de instalación, de lo contrario el teléfono no instalará la aplicación.

Sigamos, hacer click en New Project, aparecerá el asistente, seleccionar MIDP Application, en la siguiente pantalla dejar las opciones por defecto (para demostración nada mas),  el asistente trae una opción que dice: "Create Hello Midlet", es para crear una aplicación muy básica para efectos de pruebas, la usaré en este tutorial.

La siguiente pantalla del asistente pide el tipo de aplicación, seleccionar:
  • Emulator Platform: CLDC - "Java(tm) Platform Micro Edition SDK 3.0" (es el tipo de aplicación, debemos seleccionar siempre CLDC, lo cual significa que es la configuración de Java para teléfonos de baja capacidad, incluyendo Blackberries) 
  • Device: ClamshellCldcPhone1  (es el tipo de emulador para las pruebas, mostrará un telefono virtual en pantalla para pruebas)
  • Device Configuration:  marcar: CLDC-1.1
  • Device Profile: marcar: MIDP-2.0
click en botón finish y se creará una aplicación básica, se debe ver así:

En la pantalla que se muestra aquí seleccionar el proyecto y hace click en el ícono Run, para ejecutar la aplicación (la fecha verde).


Aparecerá el emulador del teléfono virtual seleccionado anteriormente, asi:


Listo, con estos pasos se ha creado una aplicación muy básica que muestra el mensaje "Hello World" y que además corre bien en el emulador.

El archivo JAR y JAD.

Estos archivos se encuentran en la carpeta /dist del proyecto creado, son generados cuando se hace el Build del proyecto, pero hay que corregir algo:  si los nombres de archivo estan en la forma "Camel" (con mayusculas y minúsculas) entonces será problemático al momento de descargalos de internet, sobre todo con servidores basados en Linux.

Por tanto, se debe configurar el proyecto (click derecho en proyecto y luego ir a propiedades) para que los nombres de los archivos JAR y JAD sean en minúsculas solamente al momento de ser generados tras aplicar el comando "Build".

ir a propiedades del proyecto: "Creating Jar". Poner en minúsculas los nombres de archivo jar y jad


Datos de Configuración del JAD.

El archivo JAD generado es un archivo de texto, con parametros que usará el teléfono al momento de descargar la aplicación de internet.  Aquí se deben cuidar tres parámetros: el icono, el nombre del midlet a usar y la ruta de descarga del JAR.

La ruta de descarga del JAR se requiere cuando uno accede al website de descarga de la aplicación java desde internet. Se descarga primero el archivo JAD (el que tiene la información), luego el teléfono usa la información del JAD para descargar de nuevo la aplicación JAR, luego ejecuta del JAR el midlet indicado. Tenga esto en cuenta a futuro.

Pasos:
  1. generar un icono.  Seleccione un pequeño icono de 20x20 pixels al menos, en formato PNG o JPG, y subalo al proyecto:

    Click derecho en "Resources" (en el panel a la izquierda) y seleccionar del menu flotante: "add folder", para luego explorar la ubicación de -la carpeta que contiene al icono-, no el icono como tal.

    debe quedar algo como esto:

  2. Configurar el JAD:
    Desde el IDE, hacer click derecho sobre el proyecto y seleccionar Propiedades, aparecerá esta ventana, aquí seleccionar a la izquierda "Application Descriptor", debe verse así:
    pantalla de propiedades del proyecto, pestaña Midlets
    luego ir a la pestaña "Midlets", seleccionar el midlet (o hacer click en add) y luego en el botón "Edit".

    note que /icon.png es el icono que se subio antes, si el icono se puso en otra parte debe indicarse aqui, de todos modos es bueno verificar la ubicacion del icono usando winRar para ver el contenido del JAR generado.
    cuidado con las mayusculas y las minúscula

    finalmente editar los atributos del midlet en la pestaña "Attributes", allí se indicará la ruta de descarga del JAR.  Suponga que el sitio web donde se alojará el JAR y el JAD será: http://test.ascinformatix.com.  Se supone en este ejemplo que el JAR y el JAD se subirán a este servidor para luego ser bajados de ahí desde un teléfono, por tanto la URL de descarga del archivo JAR será:

    http://test.ascinformatix.com/mobileapplication1.jar
    (al pie del dialogo se debe marcar el check de Override y luego poner esta ruta )

    Todos estos parametros se le indican al archivo JAD usando el IDE, para que cada vez que genere el archivo JAD lo haga con estos atributos, tanto el icono, como la ruta de descarga del JAR como el nombre del Midlet que ejecutará.

  3. finalmente el archivo JAD siempre debe lucir así luego de hacer "Build"


    MIDlet-1: HelloMIDlet,/icon.png,hello.HelloMIDlet
    MIDlet-Jar-Size: 1767
    MIDlet-Jar-URL: http://test.ascinformatix.com/mobileapplication1.jar
    MIDlet-Name: MobileApplication1
    MIDlet-Vendor: Vendor
    MIDlet-Version: 1.0
    MicroEdition-Configuration: CLDC-1.1
    MicroEdition-Profile: MIDP-2.0

    Cuando desde un teléfono se quiera instalar la aplicación, uno primero descarga el JAD, luego el telefono lee el JAD y descargará el JAr desde: "MIDlet-Jar-URL",  instalará un ícono, indicado en: "MIDlet-1: HelloMIDlet,/icon.png,hello.HelloMIDlet", ejecutará la clase: hello.HelloMIDlet, y le dará como titulo e Id del midlet a: "HelloMIDlet"

Instalar la Aplicación Java a usando Descarga de Internet

No se pueden subir archivos JAR directamente a un Blackberry, puedes causar que este entre en un grave deadLock (nota #1), en cambio deben ser primero convertidos:  del Jar se crea un archivo COD, y luego se crea manualmente un archivo ALX el cual ahora si puede ser subido al Blackberry usando el Desktop Manager. (el programa que trae Blackberry para subir aplicaciones al telefono).

  (notas:  #1) deadLock es una falla que hace que el blackberry se reinicie solo sin permitir usarlo)


La mejor solución que encontré luego de varias vueltas fue la de hacer que la aplicación se instale en el teléfono a modo de descarga, es decir, uno abre el explorador de internet en el teléfono y descarga la aplicación Java directamente sobre el teléfono, quien a su vez hará la instalación.

Que cosas no se deben hacer:

    Al menos en el Blackberry, no se puede copiar la aplicación Java en una memoria externa o a través de USB y luego abrirla desde el Blackberry, en otros teléfonos si se puede, pero estamos tratando de hacer que el procedimiento sea igual para todos los teléfonos, Blackberries o no.

  Tampoco se puede simplemente descargar el JAR desde un website sin una configuración previa, es decir, subimos los JAR a un website asi ligeramente y luego desde el teléfono los descargamos: no funciona.  La razón es que al hacer eso el Blackberry no conocerá el MIME TYPE del archivo a descargar y tratará al archivo JAR como un archivo de texto o html y lo presentará como tal, mostrando en la pantalla un conjunto de caracteres.

entonces ?, siga leyendo:

Cómo Preparar el WebSite de Descarga de la Aplicación

  Hay que configurar el website para que un Blackberry u otro dispositivo pueda saber que es una aplicación Java y actúe como tal. Esto se hace configurando un script PHP que indique que el tipo MIME a descargar sea uno del tipo: "text/vnd.sun.j2me.app-descriptor". Por defecto, cuando un Blackberry quiere descargar un JAR desde internet asume erroneamente que es un tipo MIME: "html/text" y por consiguiente no ejecutará la aplicación, mostrando en cambio un conjunto de caracteres.
  1. Se suben los archivos JAR y JAD generados por la aplicación a un sitio web al que tengamos acceso y poder de usar el PHP, en este caso los archivos a subir son mobileapplication1.jad y .jar, cuidado con las mayusculas y minusculas.
    para ver la lista de archivos hacer click en "Files" en la barra de la izquierda, (o puede explorar el proyecto con Windows..)
  2. En mi caso, yo subiré los archivos vía FTP a un servidor de mi propiedad, ubicado en la dirección: test.ascinformatix.com. Suba usted los archivos a su hosting, donde tenga un servicio PHP disponible o su equivalente en Java o ASP.NET.
  3. Una vez los archivos existente en su hosting, compruebe que puedan ser descargados manualmente, probando estas url:  (yo usaré como hostname a test.ascinformatix.com)

    http://test.ascinformatix.com/mobileapplication1.jad y http://test.ascinformatix.com/mobileapplication1.jar

    puede crear un script html como este para probar:

    --- inicio archivo test.html, subalo a su hosting y pruebelo ---
    <body>
      <a href="/mobileapplication1.jad">descarga JAD</a>
      <a href="/mobileapplication1.jar">descarga JAR</a>
    </body>

    --- fin archivo test.html ---

  4. Una vez comprobado que los archivos son accesibles desde internet manualmente, entonces proceda a crear un script PHP que fuerze la descarga pero con mimeType:  "text/vnd.sun.j2me.app-descriptor"

    ---inicio archivo down.php---
    <?php 
      $localfile="D:/SERVIDOR/htmlRoot/mobileapplication1.jad";
      header('Content-disposition: attachment;
      filename='.$localfile);
      header('Content-type: text/vnd.sun.j2me.app-descriptor');
      readfile($localfile);
    ?>

    ---fin archivo down.php---

    note que uso la ruta física:  
    "D:/SERVIDOR/htmlRoot/mobileapplication1.jad"
    esta es la ubicación del archivo JAD -ya subido al servidor-, es para que el script php sepa donde ubicar al archivo JAD dentro del servidor. Este script entregará el archivo JAD indicado aqui directamente a quien lo solicite (el telefono) pero en el tipo MIME correcto, y por tanto el telefono podrá instalar la aplicación Java, si no hace esto el teléfono Blackberry no instalará la aplicación.

    para saber la ruta fisica de un archivo alojado en el servidor use las variables de PHP, por ejemplo este script ayuda a saber cual seria la ruta fisica, la cual en este ejemplo es: "D:/SERVIDOR/htmlRoot/"

    Para saber la ruta física de su servidor, use la variable de php: _SERVER["DOCUMENT_ROOT"], en un script como este:
    <?php
       echo $_SERVER["DOCUMENT_ROOT"];
    ?>

    el script anterior podría quedar así:

    ---inicio archivo down.php---
    <?php $localfile=
       $_SERVER["DOCUMENT_ROOT"]."/mobileapplication1.jad";

      header('Content-disposition: attachment;
      filename='.$localfile);
      header('Content-type: text/vnd.sun.j2me.app-descriptor');
      readfile($localfile);
    ?>
    ---fin archivo down.php---
  5. Solo queda crear una pequeña página HTML para poder navegarla desde los teléfonos móviles y así poder finalmente descargar la aplicación en el teléfono, quien la instalará automáticamente:

    (asumo que ha llamado "down.php" al script php que menciono mas arriba, y que ya existe en el servidor de su preferencia)




  6. pruebe primero que funcione desde el PC, navegando en:
    http://test.ascinformatix.com/index.html

    al hacer click en "descargar" el sistema debe abrir un dialogo "Guardar Como" para que guarde el JAD descargado en su PC, no debe mostrar el contenido del JAD en el navegador
    .

  7. ahora, finalmente pruebe desde el teléfono:
    navegue a: http://test.ascinformatix.com/index.html

    así debería verse la página http://test.ascinformatix.com/index.html  en el móvil.




    Suerte !

lunes, 4 de abril de 2011

Cómo descargar contenido desde un servidor web con PHP y control de contenidos MIME

Descarga de Contenido MIME Específico desde Internet

Objetivo:
Permitir a una aplicación la descarga de un archivo desde el servidor que contenga automáticamente la información que el usuario haya puesto en un formulario sin recurrir a descarga con elementos html <a href='...'>..</a> .  

Por ejemplo, un formulario web  pide nombre y cedula, y presenta un botón "Generar Informe",  al darle clic se genera una lista de registros (de lo que sea) asociados al cliente y ahora queremos que este informe se descargue automáticamente sin crear etiquetas html <a href='...'>...</a>, queremos que aparezca la clásica ventanita de descarga del explorador de internet.

Para resolver esto se crea un script, en resumidas cuentas y a modo de ejemplo: generareporte.php, el cual recibe los parametros seleccionados en el formulario web y genera un informe en formato CSV que automaticamente se descargará al usuario.

voy a obviar el formulario html por este momento, y me enfocaré en el script php:

--inicio archivo generareporte.php--

  $cedula = $_GET['cedula'];
  $nombre = $_GET['nombre'];
  
// generamos un nombre de archivo cualquiera

  $fnameOnly=$cedula.".reporte.dat";
  
// se crea la ruta completa del archivo donde se guardara el archivo localmente

  $localfile = "d:/descargasLocalpermisoWrite/".$fnameOnly;
  if($localfile != null
    {
       // se crea el archivo local
       $f = fopen($localfile,"w");
       fwrite($f,"registro de prueba;registro de prueba;registro de prueba;");
       fclose($f);

      
// se prepara el encabezado del documento a descargar

       header('Content-disposition: attachment; filename='.$localfile);
       header('Content-type: text/html');
       readfile($localfile);
    }
--fin archivo generareporte.php--



--inicio archivo reporte.html---

 <body>
 <h3>Descarga Reporte</h3><hr/>
 <!--  obviare aqui el desarrollo de un formulario que pida usuario y clave -->

 <a href='/generarreporte.php?cedula=8181818&nombre=juan'
     target='_blank'>generar  reporte</a> 

 </body>

--fin archivo--

al hacer click en el enlace "generar reporte" se descargará automáticamente un informe en formato CSV.

domingo, 3 de abril de 2011

Conocer el tiempo de una ciudad usando los Servicios Web de "Google Wheater".

Objetivo:

  Mostrar en una página HTML el tiempo y la temperatura de una ciudad usando los servicios web de Google Wheater.

Material Disponible (Código Fuente):
http://ascinformatix.com/material/googlewheater.rar


En esta oportunidad quiero presentar la forma básica para conocer el tiempo de una ciudad usando los servicios de Google Wheater.

Google provee varios servicios para programadores, pueden servirnos indistintamente del lenguaje que usemos. En este caso mostrare como saber la temperatura de una ciudad específica, su humedad, el estado del tiempo usando una simple llamada Http.  En otro parte del documento indicaré como implementar este servicio en el website usando una técnica mas avanzada: con Ajax y JSON, para que la actualización de estos datos ocurra "in bkackground",es decir sin recargar la página web para que el tiempo se actualize.

Ejemplo avanzado con presentación de datos obtenidos. Google Wheater  solo entrega datos XML, la presentación de estos datos es nuestro propio asunto..


--Aquí no trataré la instalación de PHP, ni el uso de Ajax, ni JSON, ni Javascript, solo me limitaré al ejemplo asumiendo que el usuario tiene los conocimientos y le es familiar el uso de las herramientas--


Cómo Funciona, lo más básico:

Google Wheater entrega datos XML cuando se le hace una consulta acerca de una ciudad en específico, no entrega ningún diseño, de forma alguna. Para obtener datos en formato XML que informen acerca del tiempo para una ciudad específica hay que hacer una llamada a esta URL:

http://www.google.com/ig/api?weather=caracas&hl=es

note los elementos:  wheater=caracas y hl=es.  los valores a usar aquí depende de nuestra necesidad, por ejemplo para consultar el tiempo en inglés de santiago de chile, se puede usar esta URL:
http://www.google.com/ig/api?weather=santiago&hl=en
Si prueba este ejemplo en un navegador web cualquiera no verá resultados inmediatos en pantalla, debido a que los datos devueltos son XML, en cambio si selecciona "ver código fuente" en la pagina en blanco que aparecerá como resultado de poner estas direcciones en el navegador vera datos como estos:


<?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="Santiago, Santiago Metropolitan Region"/><postal_code data="santiago"/><latitude_e6 data=""/><longitude_e6 data=""/><forecast_date data="2011-04-07"/><current_date_time data="2011-04-07 10:00:00 +0000"/><unit_system data="US"/></forecast_information><current_conditions><condition data="Cloudy"/><temp_f data="68"/><temp_c data="20"/><humidity data="Humidity: 100%"/><icon data="/ig/images/weather/cloudy.gif"/><wind_condition data="Wind: N at 0 mph"/></current_conditions><forecast_conditions><day_of_week data="Thu"/><low data="64"/><high data="88"/><icon data="/ig/images/weather/chance_of_rain.gif"/><condition data="Chance of Rain"/></forecast_conditions><forecast_conditions><day_of_week data="Fri"/><low data="61"/><high data="88"/><icon data="/ig/images/weather/mostly_sunny.gif"/><condition data="Mostly Sunny"/></forecast_conditions><forecast_conditions><day_of_week data="Sat"/><low data="59"/><high data="88"/><icon data="/ig/images/weather/mostly_sunny.gif"/><condition data="Mostly Sunny"/></forecast_conditions><forecast_conditions><day_of_week data="Sun"/><low data="61"/><high data="90"/><icon data="/ig/images/weather/mostly_sunny.gif"/><condition data="Mostly Sunny"/></forecast_conditions></weather></xml_api_reply>

Archivos Requeridos y Ejemplo en Linea

Para usar el servicio web de Google Wheater se requieren algunos archivos extra, como dije anteriormente Google Wheater solo entrega datos XML por tanto la presentación de estos es nuestro propio asunto.

Pasos para Implementar:

--Aquí no trataré la instalación de PHP, ni el uso de Ajax, ni JSON, ni Javascript, solo me limitaré al ejemplo asumiendo que el usuario tiene los conocimientos y le es familiar el uso de las herramientas--
Primero debe instalarse un script PHP que entregue los datos en un formato JSON, recuerde que Google Wheater entrega los datos en formato XML.  JSON nos permitirá leer estos datos desde una página html usando javascript, por ende podremos usar AJAX para hacer que la actualización de datos sea transparente.

1-Script PHP:  googletimereader.php

Este script hará la consulta a Google Wheater, leerá los datos en formato XML y los transformará en datos JSON, ese es su único objetivo.  Para invocar el script, este debe estar alojado en un sitio web que permita PHP, una llamada al script debería ser como esta:


al hacer una llamada a esta URL (arriba), se generará para nosotros una salida en formato JSON, como esta:
{"ciudad":"barquisimeto","descripcion":"Mayormente nublado"
,"temperatura":"22","humedad":"Humedad: 88%"
,"imagen":"\/ig\/images\/weather\/mostly_cloudy.gif"
,"viento":"Viento: E a 8 km\/h"}






ejemplo de google wheater


el tiempo en Barquisimeto es: no se pudo leer el tiempo.json_parse is not defined,data: ciudad = $_GET['ciudad']; $weather_current = $array["xml_api_reply"]["weather"]["current_conditions"]; $n = 0; foreach($weather_current as $item) { if(count($item)) { /* 0,data=Mayormente nublado 1,data=72 2,data=22 3,data=Humedad: 94% 4,data=/ig/images/weather/mostly_cloudy.gif 5,data=Viento: E a 13 km/h */ //echo $n.",data=".$item['data']; //echo "
"; if($n == 0) $dtt->descripcion = $item['data']; if($n == 2) $dtt->temperatura = $item['data']; if($n == 3) $dtt->humedad = $item['data']; if($n == 4) $dtt->imagen = $item['data']; if($n == 5) $dtt->viento = $item['data']; $n++; } } echo $json->encode($dtt); ?>

** es porque no se ha configurado php correctamente **.  Vuelva al item #1 (1-Script PHP:  googletimereader.php) y verifique que se muestre todo como indica este paso.


ejemplo de google wheater


el tiempo en Barquisimeto es: Parcialmente nublado 23°c Humedad: 82% 

descargar el material del tutorial