Programando para la BlackBerry - Everlasting Flame II
Continuamos con el desarrollo de esta aplicación. Ya en la parte dos vimos cómo programar la funcionalidad básica: monitorear el tiempo de las llamadas y reaccionar de acuerdo a los límites establecidos (denominados soft y hard limit). Ahora sigue el turno de guardar a la memoria algunas de las opciones establecidas por el usuario y crear una interfaz gráfica para la configuración.
Como vimos, Everlasting Flame es una aplicación con la que el usuario no interactúa directamente y es por esto que no contiene una interfaz gráfica. La aplicación se ejecuta automáticamente cuando el teléfono inicia, de tal modo que al marcar un número comienza a contar el tiempo. Sin embargo es conveniente tener una interfaz de configuración donde podamos establecer los límites, así como también habilitar y deshabilitar el monitoreo de llamadas (por si queremos hacer una llamada más larga de lo normal sin que se corte).
Para este propósito se crea lo que se llama un punto de entrada alternativo, que como su nombre lo indica, servirá como punto de entrada a la aplicación ejecutando una serie de pasos distintos a los “normales”. En nuestro caso el punto de entrada normal es el que no tiene interfaz gráfica y el alternativo es iniciar la interfaz gráfica para configurar la aplicación. Lo primero es configurar el proyecto como aplicación del sistema (es decir, que no muestra interfaz gráfica) y que sea auto ejecutable. Esto se hace desde Eclipse modificando las propiedades del proyecto. Después creamos un proyecto nuevo vacío y en las propiedades lo configuramos como punto de entrada alternativo al proyecto original, pasando como parámetro alguna cadena de identificación (en mi caso, “init”).
De esta manera, cuando el usuario seleccione el icono de nuestra aplicación desde la BlackBerry, nuestra aplicación recibirá como argumento la cadena “init” y eso nos servirá como señal para iniciar la interfaz gráfica. Si la aplicación es iniciada automáticamente, no recibiremos la cadena “init” e iniciaremos la aplicación como antes. Modificamos EverlastingFlame.java de esta manera:
-
boolean startup = false;
-
-
for(int i=0; i < args.length; i++){
-
if(args[i].equals(“init”)){
-
startup = true;
-
}
-
}
-
-
if(startup){
-
MainGUI gui = new MainGUI();
-
gui.enterEventDispatcher();
-
}else{
-
EverlastingFlame ef = new EverlastingFlame();
-
ef.enterEventDispatcher();
-
}
-
}
Como vemos en el código, si recibimos la cadena “init” creamos una nueva instancia de MainGUI y ejecutamos su event dispatcher para que el sistema despliegue la pantalla. El código de MainGUI.java se muestra a continuación:
-
public class MainGUI extends UiApplication{
-
private MainScreen mainScreen;
-
-
public MainGUI(){
-
mainScreen = new EverlastingFlameScreen();
-
LabelField label = new LabelField(“Everlasting Flame Configuration”, LabelField.ELLIPSIS
-
| LabelField.USE_ALL_WIDTH);
-
mainScreen.setTitle(label);
-
pushScreen(mainScreen);
-
}
-
}
Esta clase extiende a UiApplication porque precisamente es una aplicación con interfaz gráfica. Contiene una MainScreen con el título de “Everlasting Flame Configuration”. Por último empujamos la pantalla para que sea mostrada en el teléfono. La MainScreen es realmente una instancia de EverlastingFlameScreen, una clase que hereda de MainScreen e implementa la interfaz gráfica y los eventos que nos interesan:
-
public class EverlastingFlameScreen extends MainScreen{
-
private CheckboxField chkActive;
-
-
public EverlastingFlameScreen(){
-
super();
-
-
chkActive = new CheckboxField(“Start monitoring service?”,Options.getActive());
-
add(chkActive);
-
}
-
-
protected boolean onSavePrompt(){
-
if(isDirty()){
-
“Do you want to save changes?”);
-
onSave();
-
boolean chkState = chkActive.getChecked();
-
Options.setActive(chkState);
-
if(Options.getActive()){
-
}else{
-
}
-
}else{
-
chkActive.setChecked(Options.getActive());
-
return false;
-
}
-
}
-
return true;
-
}
-
}
Para efectos de este ejemplo, la pantalla se compone solamente de un checkbox que sirve para habilitar o deshabilitar el servicio de monitoreo. Si este checkbox se encuentra activo, Everlasting Flame monitorea las llamadas, inyectando el tono DTMF y colgando cuando es necesario. De más está decir que si se encuentra desactivado, las llamadas transcurren normales. En el constructor se crea el checkbox en cuestión y se le pasa una cadena que será su etiqueta, así como también el estado inicial del checkbox (seleccionado o no seleccionado).
El estado inicial se obtiene de las opciones del usuario, gracias a una clase Options que nos sirve para guardar las preferencias del usuario en memoria no volátil (más de esto en la siguiente entrega de esta serie de posts). La magia ocurre en el método onSavePrompt. Este método se ejecuta cuando el sistema cree que hubo algún cambio que debe ser guardado. Nosotros sobreescribimos el método y agregamos una pequeña validación.
Cuando el sistema ejecuta onSavePrompt, verificamos el estado de la pantalla. isDirty nos indica que hubo cambios y por lo tanto hay que preguntar al usuario (por medio del método estático ask de la clase Dialog) si desea guardar. En caso de si desear guardar, verificamos si el usuario activó o desactivó el servicio y por último informamos al usuario que sus cambios han sido aplicados.
Queda solamente modificar el PhoneListener para tomar en cuenta el estado del servicio (activado o desactivado). Esto es muy sencillo utilizando la clase Options que se verá más adelante:
-
if(Options.getActive()){
-
if(callTimeSeconds == softLimit){
-
injectDTMFTone(Phone.getActiveCall());
-
}else if(callTimeSeconds == hardLimit){
-
injectEndCall();
-
}
-
}else{
-
}
Si el servicio se encuentra activo, realiza las mismas validaciones anteriores. En caso de encontrarse inactivo, simplemente no hace nada.
Lo que queda es explicar la clase Options y por supuesto agregar mayor funcionalidad a la interfaz gráfica, como por ejemplo la configuración de los límites, la acción a realizar en cada uno de ellos y cambiar el funcionamiento entre modo “naco” (funcione para todos los números) y modo “VIP” (sólo para números seleccionados).




