viernes, 10 de enero de 2014

Un ejemplo de Qt Android Extras: usando el Text To Speech de Android

Escribo esto como recordatorio por si me vuelve a tocar hacerlo otra vez. A veces la documentación de QT no es todo lo extensa que uno querría y con los extras de Android me he tenido que pegar un buen rato. Lo que quería hacer es llamar a la clase TexToSpeech del SDK de Android desde QT y lo que tenía como referencia era la documentación de QtAndroidExtras, el ejemplo de notificaciones que proporcionan y el intento de otra persona de hacer lo mismo que yo en un foro de QT.

Parecía que era suficiente, de hecho, cambiando un poco el ejemplo de las notificaciones por el código del foro debería haber sido más que suficiente. Pero el tipo del foro no tenia un código funcional, el mismo pedía ayuda y no había respuesta. Por otro lado el código de ejemplo de QT no hace más que llamar a un método estático y yo quería crear una clase Java que heredase TextToSpeech (cosa que al final no conseguí).

Pues bien, como decía, a modo de recordatorio dejaré una serie de problemas que me he encontrado y como los he ido sorteando. El formato del siguiente guión es el de notas mentales, o si lo preferís, un diálogo conmigo mismo.

1. Me defiendo en QT pero no tengo ni idea de programar en el SDK de Android.
No  hay mucha solución a esto, o aprendes o te buscas la vida buscando ejemplos. Ya se han citado los ingredientes a utilizar.

2. Se necesita crear un objeto de una clase en cuyo constructor toma como parámetro el contexto de la actividad.
La clase que escribas debe extender QtActivity, esta proporcionará el contexto a la hora de crear la otra, en este caso TextToSpeech.

3. Pero necesito que mi clase implemente onListener y ya hereda QtActivity.
Bueno... una cosa no quita la otra:

public class TestAndroidClient extends QtActivity implements TextToSpeech.OnInitListener


4. He creado la clase java y no se dónde ponerla, de hecho creo que no se instala a través del apk
Fíjate en el ejemplo de las notificaciones y crea una estructura similar. En la raíz de tu proyecto crea un directorio llamado android-source y dentro de este otro con el nombre src. A partir de ahí tendrás los subsiguientes, por ejemplo: org/qtproject/example/nombre-de-tu-app/TuClase.java



Asegúrate de que en el .pro del proyecto están las siguientes líneas:

QT+=android-extras
ANDROID_PACKAGE_SOURCE_DIR = $$PWD/android-source

En linux, una vez constrido, puedes hacer en el directorio de construcción (build-xxxx) en un terminal:

find . -name TuClase.java

y comprobar que la ruta es la correcta




5. Cuando trato de ejecutar la aplicación se cierra sin mostrar excepción y esto ocurre al llamar a mi clase.
Esto seguramente es porque no la encuentra. Comprueba que tienes creado el manifest.xml y que referencia correctamente a tu clase en un tag activity


    
        
   

6. Pero yo quiero hacer una clase que herede de TextToSpeech y que sea todo más dinámico.
Bueno pues no tengo solución para esto. De hecho, no he conseguido hacer una llamada que no sea estática a la clase Java creada. A decir verdad, tampoco he encontrado un ejemplo que lo haga.

7. Estoy intentando llamar a un método estático desde el código C++ y sigo sin conseguirlo.
Hay que fijarse en la firma de los parámetros de entrada y salida. También es importante usar el javaobject correcto desde C++ para que la función Java lo reconozca. Si tienes la siguiente función en java:

    public static void test(String msg)
    {
        System.out.println(msg );
        tts.speak(msg, TextToSpeech.QUEUE_FLUSH, null);

    }

La correspondiente llamada en C+++ será:

    QAndroidJniObject javaMessage = QAndroidJniObject::fromString(msg);
    QAndroidJniObject::callStaticMethod("org/qtproject/example/testandroidextras/TestAndroidClient",
                                              "test",
                                              "(Ljava/lang/String;)V",
                                              javaMessage.object());


Finalmente, el código fuente lo podéis encontrar en GitHub

No hay comentarios: