Programando para la Blackberry – Everlasting Flame
Ver primera parte: Intro
En la introducción se vió un poco sobre lo que es programar una aplicación para la BlackBerry haciendo un pequeño “Hola Mundo” muy sencillo. Ahora toca explicar las bases de la aplicación que se menciona en aquel post llamada “Everlasting Flame”. El nombre es el título de una canción del grupo de Thrash Aleman Kreator. Tengo la mala costumbre de nombrar a todos mis proyectos con titulos de canciones metaleras.
Primero un poco de teoría. Las aplicaciones de BlackBerry pueden ser de dos tipos: sin GUI o con GUI. Típicamente el punto de entrada de las que tienen GUI es cuando el usuario selecciona el ícono correspondiente en la pantalla. Las que no tienen GUI generalmente cuentan con otro punto de entrada, como al momento de hacer una llamada telefónica, enviar un SMS, solicitar datos, etc. En nuestro caso nuestra aplicación es sin GUI y su punto de entrada es al momento de realizar una llamada telefónica.
En el API de RIM hay dos clases que nos interesan actualmente: Applicationy UiApplication para aplicaciones sin UI o con UI, respectivamente. También nos interesa el PhoneListener que nos sirve para registrar una clase que consume los eventos generados por la aplicación de teléfono en la BlackBerry. También nos interesa la clase Phone que nos permite interactuar con la aplicación que se encarga de marcar el teléfono en la BlackBerry.
Como se mencionó en el post de introducción, el funcionamiento es el siguiente: marco un número e inicia un contador. Si llego a un determinado número de segundos (soft limit) el teléfono me avisa inyectando un tono DTMF a la llamada. Si llego a otro límite mayor (hard limit) la llamada se termina automáticamente. Para esto vamos a usar las clases antes mencionadas.
Nuestro programa consta básicamente de 2 clases: la clase principal que extiende a Application, y una clase que implementa la interfaz PhoneListener, o más específicamente extiende a AbstractPhoneListener, misma que implementa a PhoneListener y nos evita el tener que implementar todos los métodos abstractos de PhoneListener, enfocándonos solo a aquellos que necesitamos.
El contenido de la clase principal, EverlastingFlame.java:
package com.divinesoft.blackberry.everlastingflame;
import net.rim.blackberry.api.phone.Phone;
import net.rim.blackberry.api.phone.PhoneListener;
import net.rim.device.api.system.Application;
public class EverlastingFlame extends Application{
private PhoneListener phoneListener;
private EverlastingFlame(){
/*These options will be set from the GUI in the future*/
System.out.println("Setting program options");
Options.setSoftLimit(270); //in seconds
Options.setHardLimit(290); //in seconds
System.out.println("Instantiating CustomPhoneListener");
phoneListener = new CustomPhoneListener(Options.getSoftLimit(),
Options.getHardLimit());
System.out.println("Registering PhoneListener...");
Phone.addPhoneListener(phoneListener);
}
public static void main(String[] args) {
System.out.println("On Endless main");
EverlastingFlame ef = new EverlastingFlame();
ef.enterEventDispatcher();
}
}
Esta clase extiende a Application y tan solo declara su constructor y el punto de entrada de la aplicación. En el punto de entrada crea una nueva instancia de la aplicación y entra al ciclo de despacho de eventos ejecutando el método enterEventDispatcher. Esto es necesario para que se ejecute el código que se encarga de responder a eventos. El constructor crea un nuevo objeto CustomPhoneListener (del cual veremos el código a continuación) y lo registra mediante un método estático ante la clase Phone para recibir eventos del teléfono.
La clase CustomPhoneListener:
package com.divinesoft.blackberry.everlastingflame;
import java.util.Timer;
import java.util.TimerTask;
import net.rim.blackberry.api.phone.AbstractPhoneListener;
import net.rim.blackberry.api.phone.Phone;
import net.rim.blackberry.api.phone.PhoneCall;
import net.rim.device.api.system.ControlledAccessException;
import net.rim.device.api.system.EventInjector;
import net.rim.device.api.system.KeypadListener;
import net.rim.device.api.ui.Keypad;
public class CustomPhoneListener extends AbstractPhoneListener{
private Timer callTime;
private int callTimeSeconds = 0;
private int softLimit, hardLimit = 0;
public CustomPhoneListener(int softLimit, int hardLimit){
this.softLimit = softLimit;
this.hardLimit = hardLimit;
}
public void callConnected(int callId){
System.out.println("Call Connected");
callTime = new Timer();
TimerTask callTimeTask = new TimerTask(){
public void run(){
callTimeSeconds++;
System.out.println(callTimeSeconds);
if(callTimeSeconds == softLimit){
System.out.println("Soft limit reached");
injectDTMFTone(Phone.getActiveCall());
}else if(callTimeSeconds == hardLimit){
System.out.println("Hard limit reached, hanging up!");
injectEndCall();
}
}
};
callTime.schedule(callTimeTask, 0,1000);
}
private void injectEndCall(){
System.out.println("Injecting event to end current call...");
try{
EventInjector.KeyCodeEvent ev = new EventInjector.KeyCodeEvent(
EventInjector.KeyCodeEvent.KEY_DOWN,(char)Keypad.KEY_END,
KeypadListener.STATUS_ALT, 500);
EventInjector.invokeEvent(ev);
}catch(ControlledAccessException cae){
System.out.println("Tried to end the call, but couldn't. I need permission!");
}
}
private void injectDTMFTone(PhoneCall phoneCall){
System.out.println("Sending DTMF tone...");
phoneCall.sendDTMFTone('7');
}
public void callDisconnected( int callId ) {
//kill the thread
callTime.cancel();
//and restart the timer
callTimeSeconds = 0;
}
}
Esta clase extiende a AbstractPhoneListener y lo que hace es definir qué sucede cuando se ejecutan ciertos eventos del teléfono. Su constructor recibe ambos límites como parámetros y los inicializa. Al conectarse una llamada (callConnected) se inicializa un objeto Timer. A este objeto Timer se le registra un objeto TimerTask, que es el que nos sirve para ejecutar una tarea recurrente. En este caso TimerTask es un objeto que en su método run lo que hace es incrementar un contador y comprar su actual valor con el softlimit o el hardlimit, llamando al método necesario para tomar la acción adecuada.
Como podemos observar, nos interesa contar segundos, y es por esto que registramos el TimerTask que suceda sin delay (primer argumento) y cada 1000 milisegundos (segundo argumento). Cada segundo se ejecuta el método run del TimerTask registrado. Al desconectarse la llamada se ejecuta callDisconnected, se detiene el objeto Timer y se pone a 0 el contador para iniciar de nuevo cuando se vuelva a realizar otra llamada. Los métodos injectDTMFTone e injectEndCall hacen exactamente lo que su nombre indica.
Como ven, es bastante sencillo agregar esta funcionalidad a la BlackBerry. En este caso falta explicar cómo se guardan las opciones del usuario y una GUI para configurar la aplicación.




9 Comentarios
Arturo
Hola Cesar, primero ke nada muchas grx por la info, esta super explicado, lo unico creo malo para mi es que no soy un programador experto, mas que nada me gustaria saber donde puedo conseguir las API’s ke mencionas para poder calar tu programa en mi BB bold y segundo no se si han pensado crear esta aplicacion para que pueda instalarla desde el desktop manager de la BB. =).,
Cesar
Que tal Arturo. Si quisieras compilar la aplicación desde el código fuente entonces si necesitas la API de RIM (el fabricante de las blackberry) además de las firmas digitales que cuestan 20 dlls. Sin embargo no es necesario compilar desde el código fuente solamente para instalar la aplicación, se puede descargar la aplicación e instalarla desde el aire o con el desktop manager como lo haces con cualquier otra.
Si he pensado en distribuir la aplicación, pero aun sigo buscando una alternativa económicamente viable para mi, es decir, ver como puedo recuperar mi inversión de tiempo y dinero. Mi idea es seguir con el desarrollo de esta aplicación, agregar más opciones y hacerla más fácil de usar.
Te comento que yo tengo usando esta aplicación desde que inicios de Diciembre y no he tenido problemas serios. Han salido algunos detalles con el uso diario, pero se han ido resolviendo y es por esto que aún no la hago pública. Te invito a que sigas visitando este blog para enterarte de cuando se encuentre disponible a la venta la versión 1.0 de Everlasting Flame.
Arturo
Hola de nuevo Cesar, gracias por tu pronta respuesta, estaré al pendiente de lo que mencionas, aun asi cuando crees tener algun tipo de demo. Tu de donde eres??? Ya que tambien me gustaria saber si das algun tipo de cursos de programacion en java???
gracias =)_,
Cesar
No creo tener disponible un demo mas allá de lo que se muestre aquí en el blog. Soy de Sonora, México y he dado cursos de programación en Java, más no actualmente.
Como dije, el plan es vender la aplicación. En la medida de que mi tiempo libre lo permita, podre terminar la funcionalidad básica planeada y la logística necesaria para venderla.
Saludos y gracias por el interés!
Geek & Roll - Blog Archive » Estado de Everlasting Flame - nuevo proyecto.
[...] definitiva para los usuarios del “plan sin fin universitario” de Telcel (ver aquí y aquí) va a ver la luz muy pronto. He creado un proyecto en Google Code donde estará guardado el [...]
ZAC
Disculpa… antes que nada gracias por la explicacion y por compartir el esfuerzo pero la verdad ya tiene años que no uso java. Tendras .algun link para bajar ya la instalacion lista para instalarsela a mi Blackberry igual si tienes algun manual o link para repasar java ya ahora como principiante. Saludos
Cesar
Claro que si checa http://www.cesarolea.com/everlastingflame/
Si ELF es util para ti, no te olvides de donar!
santiago
CESAR BUENOS DIAS
LA VERDAD LLEVO TIEMPO TRATANDO DE INSTALAR EN LA BB 8520 ESTE GRANDIOSO PROGRAMA PERO NO EH PODIDO YA QUE ME DICE QUE EL ALX NO ES COMPATIBLE CON MI BB….
TE AGRADECERIA SI ME GUIARAS PARA PODER DESCARGARLO
DIOS TE BENDIGA
GRACIAS
Laura
Hola Cesar,
Antes que nada, gracias por la información, está muy entendible, mucho más que todo el código que he contrado por ahí.
Estoy tratando de desarrollar una aplicación que envíe las coordenas a un servidor cada cierto tiempo, pero esta aplicación debe ejecutarse en background al encender el teléfono. Ya tengo la aplicación con GUI y todo funciona bien.
El problema es que cuando trato de hacerla sin la interfaz de usuario y auto-run y módulo del sistema, no se ejecuta para nada. La aplicación ya está firmada pero no funciona.
Si me puedes ayudar te lo agradecería mucho.
Haz un comentario:
Es necesario que dejes tu nombre y correo electrónico (no se publicarán).
Si dejas un comentario anónimo, con insultos o ajeno al tema, iremos hasta tu casa y le diremos a tu mamá la cantidad de porno que hay en tu computadora. Si, lo sabemos.