Hello all,

First of all, I apologize if this thread is not in the right place, and ask the moderators to kindly re-direct it appropriately.

With the advent of Qt 5.2 beta, we have access to QtAndroidExtras, which is very nice. I want to use this to invoke Android's text to speech functionality, and it appears that the class for doing this is android.speech.tts.TextToSpeech.

On the Qt side, I have this:

Qt Code:
  1. void TTSClient::speak(const QString &msg) {
  2. QAndroidJniObject myTtsObj("org.qtproject.qt5.android.bindings.MyTextToSpeech");
  3. if (myTtsObj.isValid())
  4. myTtsObj.callMethod<void>("speak", "(Ljava/lang/String;)V", QAndroidJniObject::fromString(msg).object<jstring>());
  5. else
  6. qDebug() << "TTSClient::speak() - Failed: invalid QAndroidJniObject!";
  7. }
To copy to clipboard, switch view to plain text mode 

While on the Java side, I have this:

Qt Code:
  1. package org.qtproject.qt5.android.bindings;
  2.  
  3. import android.speech.tts.TextToSpeech;
  4. import android.speech.tts.TextToSpeech.OnInitListener;
  5.  
  6. public class MyTextToSpeech implements OnInitListener {
  7.  
  8. private TextToSpeech tts;
  9.  
  10. public MyTextToSpeech() {
  11. // tts = new TextToSpeech(<something that is-a android.content.Context>, this);
  12. }
  13.  
  14. @Override
  15. public void onInit(int status) {
  16. System.out.println("MyTextToSpeech.onInit() - Got status: " + status);
  17. }
  18.  
  19. @Override
  20. public void finalize() throws Throwable {
  21. if (tts != null) {
  22. tts.stop();
  23. tts.shutdown();
  24. }
  25. super.finalize();
  26. }
  27.  
  28. public void speak(String msg) {
  29. System.out.println("MyTextToSpeech.speak() - " + msg);
  30. // rest to be implemented once TextToSpeech constructor is sorted out!
  31. }
  32. }
To copy to clipboard, switch view to plain text mode 

My Java class has-a TextToSpeech. The TextToSpeech class does not expose a default constructor, and at minimum requires two things: a Context, and an OnInitListener. The second part is easy. The first is giving me a terrible headache! At first I thought I could simply pass in an instance of android.app.Application, which is-a Context. So, I altered my Java constructor accordingly, and created an Application in Qt:

Qt Code:
  1. QAndroidJniEnvironment jniEnv;
  2. jclass appClass = jniEnv->FindClass("android/app/Application");
  3. jmethodID appCtor = jniEnv->GetMethodID(appClass, "<init>", "()V");
  4. jobject appObj = jniEnv->NewObject(appClass, appCtor);
  5. QAndroidJniObject myTtsObj("org.qtproject.qt5.android.bindings.MyTextToSpeech", "(Landroid/app/Application;)V", appObj);
To copy to clipboard, switch view to plain text mode 

But the MyTextToSpeechClass constructor call would seemingly hang when it tried to initialize the TextToSpeech member, and on any subsequent attempt to call TTSClient::speak() would crash with a NullPointerException:

Qt Code:
  1. E/AndroidRuntime(11258): FATAL EXCEPTION: Thread-579
  2. E/AndroidRuntime(11258): java.lang.NullPointerException
  3. E/AndroidRuntime(11258): at android.content.ContextWrapper.getPackageName(ContextWrapper.java:135)
  4. E/AndroidRuntime(11258): at android.speech.tts.TextToSpeech.<init>(TextToSpeech.java:606)
  5. E/AndroidRuntime(11258): at android.speech.tts.TextToSpeech.<init>(TextToSpeech.java:582)
  6. E/AndroidRuntime(11258): at android.speech.tts.TextToSpeech.<init>(TextToSpeech.java:567)
  7. E/AndroidRuntime(11258): at org.qtproject.qt5.android.bindings.MyTextToSpeech.<init>(MyTextToSpeech.java:13)
  8. E/AndroidRuntime(11258): at dalvik.system.NativeStart.run(Native Method)
  9. I/Process (11258): Sending signal. PID: 11258 SIG: 9
To copy to clipboard, switch view to plain text mode 

Then I thought to try using an instance of QtApplication (which is placed by Qt in android\src\org\qtproject\qt5\android\bindings) but this crashed without even having the decency to say much about it:

Qt Code:
  1. F/libc (13574): Fatal signal 11 (SIGSEGV) at 0x0000002c (code=1), thread 13589 (.MyProjectName)
To copy to clipboard, switch view to plain text mode 

Finally, I thought to make my Java class extend android.app.Activity, which is-a Context as well. But, this crashed too:

Qt Code:
  1. W/dalvikvm(11794): threadid=12: thread exiting with uncaught exception (group=0x416aa700)
  2. E/AndroidRuntime(11794): FATAL EXCEPTION: Thread-583
  3. E/AndroidRuntime(11794): java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
  4. E/AndroidRuntime(11794): at android.os.Handler.<init>(Handler.java:197)
  5. E/AndroidRuntime(11794): at android.os.Handler.<init>(Handler.java:111)
  6. E/AndroidRuntime(11794): at android.app.Activity.<init>(Activity.java:759)
  7. E/AndroidRuntime(11794): at org.qtproject.qt5.android.bindings.MyTextToSpeech.<init>(MyTextToSpeech.java:11)
  8. E/AndroidRuntime(11794): at dalvik.system.NativeStart.run(Native Method)
To copy to clipboard, switch view to plain text mode 

I guess my over-arching question is: how do I supply the requisite Context to my TextToSpeech member variable?

Any guidance is very appreciated. I think I must be missing some crucial concepts.

Thank you for your time.