viernes, 11 de mayo de 2012

Adecuación de la aplicación SMSMorseConverter


Como comentamos en el blog anterior, nuestros objetivos eran los siguientes:

- Adecuar la aplicación de traducción de mensajes a código Morse para que sea funcional para las personas sordo-ciegas.
-Realizar una batería de pruebas con diversas situaciones de uso de la aplicación y limpiar esos posibles errores, como hicimos con la aplicación AudioSense.

A la hora de adecuar la aplicación para los usuarios hacia los que va dirigida ésta, lo que estábamos buscando era una funcionalidad práctica y sencilla. Por ello, lo que pensamos para que pudiesen elegir los mensajes de una forma más sencilla fue que seleccionaran los mensajes a través de los botones de volumen (situados en los laterales de los dispositivos android), seleccionando los mensajes por numero (el 1 el que tiene la fecha más reciente) con un máximo de 10 mensajes (que se puede configurar a más o a menos). Para implementarlo lo que hicimos fue crear un KeyEvent que es la clase encargada de dar funcionalidad a los botones físicos.

Para configurar los botones creamos un método que regulase que hacer cuando pulsásemos los botones físicos y definimos acciones con ellos (clase Event) y los distintos botones. Para diferenciar que botón era pulsado creamos un switch con dos case y un default. En el primer case se situaba subir el volumen, y cuando lo reconocía ejecutaba el método que había dentro del case y el segundo era el de bajar el volumen. Si no se pulsaba ninguna de estas dos teclas los botones hacían lo que venga definido por el sistema operativo de Android.

int action = event.getAction();
        int keyCode = event.getKeyCode();
            switch (keyCode) {
            case KeyEvent.KEYCODE_VOLUME_UP:
                if (action == KeyEvent.ACTION_UP) {
               …
case KeyEvent.KEYCODE_VOLUME_DOWN:
                if (action == KeyEvent.ACTION_DOWN) {
              

Para comprobar que funcionaba el código al pulsar los botones pusimos que fuese aumentando (botón de subir el volumen) o disminuyendo (botón de bajar el volumen) una variable, número de mensaje seleccionado, que al pulsar cualquier de los botones nos mostraba por pantalla esta, y así pudimos comprobar que los botones tenían una funcionalidad correcta.

Para implementar el programa, introducimos varias condiciones dentro de los case de cada botón ya que era necesario que el programa reconociese que no había mensajes en la bandeja de entrada (lo hicimos mediante la condición cur.moveToPosition(0)==false), o que nunca pasara del decimo mensaje (forzando que una variable no pudiese pasar de 10), ya que habíamos decidido que el máximo número de mensajes que pudiese traducir el usuario fuese 10. Otra de las condiciones que pusimos fue que no pudiese bajar del primer mensaje ya que no tendría sentido. En el caso de no haber mensajes vibra 500ms como hemos mencionado anteriormente.

Después de esto, se nos ocurrió implementar que cada vez que pasases un mensaje mediante los botones de volumen te tradujese el número de mensaje a código Morse mediante vibraciones para que el usuario supiese en que mensaje estaba y así saber más fácilmente que mensaje quiere traducir. Recordar siempre que los mensajes están ordenados por fecha de antigüedad siendo el primero el más reciente.

En la pantalla lo único que pusimos fue un botón que ocupase la pantalla entera, para que cuando decida qué mensaje quiere traducir el usuario solo tenga que tocar la pantalla y el dispositivo empezará a traducir a código Morse el mensaje seleccionado. Sabrá si es el mensaje a traducir pues como hemos dicho antes se le muestra por vibraciones el número de mensaje asociado al mensaje en el que se sitúa.

Después intentamos hacer varias mejoras sobre el código que habíamos hecho. La primera era añadir la hora a la fecha del mensaje ya que podía llegar a ser útil para diferenciar mejor los mensajes. Para hacerlo añadimos al método que habíamos usado anteriormente para traducir la fecha  a un formato reconocido (dd-mm-aaaa), la hora (dd-mm-aaaa H: hh:mm). Para que diese la hora correcta tuvimos que dar la zona horaria de España (GMT+1), pero como estamos actualmente en horario de verano la hora que nos señalaba del mensaje era una hora menos que la que era realmente por eso pusimos al final GMT+2.

SimpleDateFormat datePattern = new SimpleDateFormat ("yyyy-MM-dd HH:mm");;
datePattern.setTimeZone(TimeZone.getTimeZone("GMT+2:00"));

La otra mejora que pensamos que podía ser útil, fue que pudiese elegir la velocidad del Morse, es decir, que durasen más (pulsación larga) o menos (pulsación corta) los tiempos de punto o raya. Esto podía ser útil para personas que están aprendiendo Morse o para gente con menos sensibilidad en el tacto. Les damos la posibilidad del tiempo base normal (100ms) o tiempo base lento (200ms). Para ello lo que implementamos fue el método onLongClickListener, que lo que hace es que distingue entre una pulsación larga y una pulsación corta del botón de la pantalla antes mencionado. Para poder implementar esta segunda velocidad lo que hicimos fue crear otra clase que se llamase MorseCodeConverterDouble que tuviese como velocidad base 200ms.

boton.setOnLongClickListener(new View.OnLongClickListener() {
public boolean onLongClick(View v) {

También para que para el usuario le fuese más fácil descifrar el mensaje en vez de darle el formato de mensaje que anteriormente habíamos pensado lo que hicimos fue implementarlo de otra manera:
T: ‘nº teléfono’. F:’fecha’. H: ‘hora’. M:’mensaje’ß Cadena de caracteres a traducir a código Morse.

Al final de la aplicación nos encontramos con un problema con las vibraciones, ya que cuando le dábamos al botón atrás o al botón home (botón central) o sucedía cualquier otro evento del móvil externo a la aplicación, y  ésta estaba traduciéndose un mensaje, no paraba de vibrar. Para solucionarlo lo que hicimos fue implementar todas las vibraciones desde una única variable declarada al principio de la actividad, y definimos el método onPause y onStop para cancelar las vibraciones (parecido a la aplicación AudioSense).

También cuando se está traduciendo un mensaje y cambiamos el numero de mensaje porque no nos interesa el que habíamos seleccionado (pulsamos los botones de volumen), se cancelan las vibraciones asociadas al mensaje para traducir el número de mensaje siguiente o anterior dependiendo del botón que haya pulsado el usuario. Esto es muy útil para cancelar la traducción del mensaje antes seleccionado por si no hubiese seleccionado el usuario el mensaje deseado y así no tiene que esperar a finalizar la traducción completa.

Como habíamos implementado esta doble velocidad de Morse (larga o corta pulsación), cambiamos el tiempo que estaba vibrando si no había mensajes de 500ms a 1000ms, para no crear confusión al usuario. Por tanto si no hay mensajes en la bandeja de entrada del dispositivo, vibrará 1 segundo tanto al pulsar la pantalla como al pulsar el botón de volumen.

Probando la aplicación final, nos dimos cuenta de que si girábamos la pantalla se cancelaban las vibraciones, por lo tanto como pensábamos que no era de utilidad, cancelamos el giro de pantalla desde el manifest.xml de la aplicación como en la aplicación AudioSense.

 El resultado final de la aplicación, una vez pasada ésta una batería de posibles casos de uso de la aplicación dónde surgían errores, los cuales se han corregido y son los que antes hemos mencionado, es el siguiente:



Pronto subiremos un vídeo explicativo de nuestras aplicaciones: Idiotizador, AudioSense, Morse y SMSMorseConverter.

sábado, 5 de mayo de 2012

SMSMorseConverter

      Una vez terminada a tiempo la aplicación AudioSense (con todas las mejoras propuestas) decidimos hacer la aplicación de traducción de mensajes a código Morse (SMSMorseConverter). Se trata de una aplicación que traduce a las personas ciegas/sordo-ciegas  los mensajes de texto de la bandeja de entrada de su dispositivo móvil a código Morse.
 
  Los primeros objetivos propuestos para esta aplicación fueron los siguientes:

- Desarrollar una aplicación Android, que traduzca los mensajes de la bandeja de entrada a código Morse a través de vibraciones.

- Investigar cómo acceder a los mensajes y extraerlos de la bandeja de entrada.

-  Conseguir coger el texto adecuado de cada mensaje.

- Enseñar los mensajes por pantalla para que el usuario pueda seleccionar el que quiera.

- Traducir la cadena de caracteres elegida a código Morse.

Lo primero que hicimos fue crear un programa capaz de acceder a los mensajes y que nos pasara a un TextView los mensajes para poder traducirlos. En un primer momento intentamos acceder con los métodos de la clase Intent, pero no éramos capaces de acceder a los mensajes de esta forma.

      Tras buscar posibles soluciones encontramos una más sencilla, el uso de la clase Cursor, con la que se puede acceder a los mensajes y a otros servicios de Android a través de la instrucción:
        
         Uri uri = Uri.parse("donde quieras acceder");
         cur = getContentResolver().query(uri, null, null, null,null);
        
     Para acceder a mensajes lo que teníamos que hacer era añadir Uri.parse("content://sms/inbox”), y así  conseguimos acceder a la bandeja de entrada de los mensajes del dispositivo.

          Para extraer el cuerpo del mensaje y el número de teléfono del usuario que nos manda el mensaje tenemos que hacerlo mediante el método getString a la columna correcta donde se encontraba el dato que queríamos. Pero aquí nos encontramos con un problema ya que nos dimos cuenta que esa columna no es la misma para cada uno de los dispositivos Android, por eso en vez de poner una constante, obtuvimos mediante el método (getColumnIndex()), la columna donde se encontraba el número de teléfono y el cuerpo del mensaje (variable para cada dispositivo). Finalmente decidimos que la fecha también pues era un parámetro importante para el usuario.
  
            Una vez hecho esto, solo teníamos que pasar al TextView con setText() la cadena de caracteres, y presentarlo en la pantalla de nuestra aplicación.
  
           Ya habíamos conseguido acceder a los mensajes. Ahora teníamos que poder seleccionar un mensaje de la lista y traducirlo a vibraciones. Para que pudiésemos seleccionar un mensaje de la lista vimos necesario implementar un ListView, que te proporciona una lista de elementos que puedes seleccionar, ya que era más sencillo que un conjunto de text Views.
  
           Para crear un ListView era necesario también crear un ArrayAdapter, donde tiene que estar incluida la lista de elementos que va a mostrar el ListView. Para crear este ArrayAdapter tuvimos algunos problemas ya que no sabíamos que parámetros te pedían en el constructor. Una vez conseguido buscando a través de Internet, al ejecutarlo en el emulador de Eclipse, nos salía un NullPointerException, y no entendíamos el porqué. Nos dimos cuenta que la razón era porque el emulador no tenía ningún  mensaje, y por lo tanto no se creaba una lista de elementos, haciendo que fuese null la lista y el ListView no la pudiera representar.
 
            Una vez probada en el móvil, ya vimos que funcionaba perfectamente hasta el momento.
 
           El siguiente paso era definir qué hacer cuando seleccionabas un elemento de la lista. Lo único que queríamos que hiciese por ahora es que cuando “dásemos” pusiese seleccionado, para comprobar que funcionaba. Pensamos que teníamos que poner el mismo método que usábamos cuando pulsamos un botón, setOnClickListener(), pero nos dimos cuenta de que no era así, ya que era un elemento de una lista, no un botón, por tanto el método que había que usar era:
 
   lista.setOnItemClickListener(new OnItemClickListener() {
         public void onItemClick(AdapterView<?> a, View v, int position, long id) {
 
            Éste nos permite realizar cualquier acción al pulsar un elemento de la lista, la cual la tenemos que definir (en nuestro caso, traducción a código Morse de la cadena de caracteres deseada), y además podíamos distinguir entre posiciones con el parámetro position.
           
            Después de haber conseguido esto, solo nos quedaba traducir el mensaje a código Morse. Buscando encontramos que ya había hechos algunos código que traducían  a código Morse. El que más nos gustó fue el de Android developers, al cual le pasas un String como parámetro y te lo traduce a vibraciones.

            Ya habíamos terminado la aplicación, pero nos dimos cuenta que el traductor solo tenía las letras básicas (no tenía la ñ) y no tenía ningún signo como el guión, el punto… Por eso añadimos al código de Android developers algunos caracteres más: “ñ”, “.”, “,”, ”?”, “!”, “-“, “:”; cambiando el código inicial.                                                                                                                           
 
            Con ello decidimos también tratar las vocales con acentos, es decir, el código inicial las trataba como caracteres desconocidos y nosotros los que hicimos fue hacer que las vocales con acentos fuesen tratadas como vocales sin éstos.
 
            Además, nos encontramos con un error en el código, ya que si ponías un parámetro desconocido, en vez de no vibrar, vibraba como si fuese un punto (en código Morse) por cada carácter desconocido, es decir, como la “e” en código Morse, creando confusión. Esto se producía porque si no reconocía un carácter, dejaban un espacio (GAP), y lo añadían al array de los parámetros de vibración, sin darse cuenta que el GAP, en el patrón de vibración se ponía en los huecos de vibración del patrón y por lo tanto vibraba el tiempo que tendría que estar en “silencio”. Para solucionarlo lo que hicimos fue añadir al array de no reconocer caracteres un 0 en vez de un tiempo de GAP.
 
Para que la aplicación no forzase cierre cuando en el dispositivo no hubiese mensajes lo que hicimos es que cuando no hay mensajes te muestre un elemento de la lista que ponga “no hay mensajes”, y si lo pulsamos el dispositivo vibra durante 500ms, para que la persona sepa que no hay mensajes.
 
Los mensajes los mostrábamos con la siguiente estructura y es la cadena de caracteres que se traducía a código Morse:
 
"Mensaje del telefono: nº de teléfono. Con fecha: fecha y con contenido: cuerpo del mensaje
 
Se muestra a continuación la primera interfaz gráfica:
  
        Después de hacer este programa nos dimos cuenta de que no era del todo funcional para las personas sordo ciegas (a las que iba dirigida la aplicación), ya que tenían que seleccionar el mensaje tocando en una parte concreta de la pantalla y no sería útil para ellos, por eso pensamos otra manera de implementarlo seleccionando los mensajes de una forma diferente.
 
    Próximos objetivos:

- Adecuar la aplicación de traducción de mensajes a código Morse para que sea funcional para las personas sordo-ciegas.

- Realizar una batería de pruebas con diversas situaciones de uso de la aplicación y limpiar esos posibles errores, como hicimos con la aplicación AudioSense.