diff options
author | Volker Hilsheimer <volker.hilsheimer@qt.io> | 2022-05-24 21:26:35 +0200 |
---|---|---|
committer | Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> | 2022-06-09 22:37:29 +0000 |
commit | 8ca5df5798cc2d026daa7d137d66f6dcf467ec2e (patch) | |
tree | 4f600e862b4c0b3eb74c4c745d11ea36cdb2a9c5 | |
parent | 73e1f03ba90b8c0c96a7e8935aa3c5e9647c7361 (diff) |
Use new JNI facilities in Android engine
Construct the Java object using QJniObject::construct, and rely on the
implicitly deduced signature strings everywhere. This means we have to
explicitly specify the object type we pass into APIs, and register a
JNI type string for the Java Locale class.
Change-Id: Ie5babe737764cbb7e0a8c789efabbd8219e6593d
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
(cherry picked from commit 0cee1827f56b7bdb337c8b20d84078375fadb82a)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
3 files changed, 36 insertions, 41 deletions
diff --git a/src/plugins/tts/android/jar/src/org/qtproject/qt/android/speech/QtTextToSpeech.java b/src/plugins/tts/android/jar/src/org/qtproject/qt/android/speech/QtTextToSpeech.java index b79a446..ea0069b 100644 --- a/src/plugins/tts/android/jar/src/org/qtproject/qt/android/speech/QtTextToSpeech.java +++ b/src/plugins/tts/android/jar/src/org/qtproject/qt/android/speech/QtTextToSpeech.java @@ -110,13 +110,8 @@ public class QtTextToSpeech if (utteranceId.equals("UtteranceId")) { notifySpeaking(mId); } - } - }; - - public static QtTextToSpeech open(final Context context, final long id, String engine) - { - return new QtTextToSpeech(context, id, engine); - } + } + }; QtTextToSpeech(final Context context, final long id, String engine) { mId = id; diff --git a/src/plugins/tts/android/src/qtexttospeech_android.cpp b/src/plugins/tts/android/src/qtexttospeech_android.cpp index 1583984..70b4c3a 100644 --- a/src/plugins/tts/android/src/qtexttospeech_android.cpp +++ b/src/plugins/tts/android/src/qtexttospeech_android.cpp @@ -44,6 +44,8 @@ static jclass g_qtSpeechClass = 0; typedef QMap<jlong, QTextToSpeechEngineAndroid *> TextToSpeechMap; Q_GLOBAL_STATIC(TextToSpeechMap, textToSpeechMap) +Q_DECLARE_JNI_TYPE(Locale, "Ljava/util/Locale;") + static void notifyError(JNIEnv *env, jobject thiz, jlong id, jlong reason) { Q_UNUSED(env); @@ -56,6 +58,7 @@ static void notifyError(JNIEnv *env, jobject thiz, jlong id, jlong reason) QMetaObject::invokeMethod(tts, "processNotifyError", Qt::AutoConnection, Q_ARG(int, reason)); } +Q_DECLARE_JNI_NATIVE_METHOD(notifyError) static void notifyReady(JNIEnv *env, jobject thiz, jlong id) { @@ -68,6 +71,7 @@ static void notifyReady(JNIEnv *env, jobject thiz, jlong id) QMetaObject::invokeMethod(tts, "processNotifyReady", Qt::AutoConnection); } +Q_DECLARE_JNI_NATIVE_METHOD(notifyReady) static void notifySpeaking(JNIEnv *env, jobject thiz, jlong id) { @@ -80,6 +84,7 @@ static void notifySpeaking(JNIEnv *env, jobject thiz, jlong id) QMetaObject::invokeMethod(tts, "processNotifySpeaking", Qt::AutoConnection); } +Q_DECLARE_JNI_NATIVE_METHOD(notifySpeaking) Q_DECL_EXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void */*reserved*/) { @@ -99,20 +104,16 @@ Q_DECL_EXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void */*reserved*/) if (vm->GetEnv(&uenv.venv, JNI_VERSION_1_6) != JNI_OK) return JNI_ERR; - JNIEnv *jniEnv = uenv.nativeEnvironment; - jclass clazz = jniEnv->FindClass("org/qtproject/qt/android/speech/QtTextToSpeech"); - - static const JNINativeMethod methods[] = { - {"notifyError", "(JJ)V", reinterpret_cast<void *>(notifyError)}, - {"notifyReady", "(J)V", reinterpret_cast<void *>(notifyReady)}, - {"notifySpeaking", "(J)V", reinterpret_cast<void *>(notifySpeaking)} - }; + QJniEnvironment jniEnv; + jclass clazz = jniEnv.findClass<QtJniTypes::QtTextToSpeech>(); if (clazz) { g_qtSpeechClass = static_cast<jclass>(jniEnv->NewGlobalRef(clazz)); - if (jniEnv->RegisterNatives(g_qtSpeechClass, - methods, - sizeof(methods) / sizeof(methods[0])) != JNI_OK) { + if (!jniEnv.registerNativeMethods(clazz, { + Q_JNI_NATIVE_METHOD(notifyError), + Q_JNI_NATIVE_METHOD(notifyReady), + Q_JNI_NATIVE_METHOD(notifySpeaking) + })) { return JNI_ERR; } } @@ -128,10 +129,8 @@ QTextToSpeechEngineAndroid::QTextToSpeechEngineAndroid(const QVariantMap ¶me const QString engine = parameters.value("androidEngine").toString(); const jlong id = reinterpret_cast<jlong>(this); - m_speech = QJniObject::callStaticObjectMethod( - g_qtSpeechClass, "open", - "(Landroid/content/Context;JLjava/lang/String;)Lorg/qtproject/qt/android/speech/QtTextToSpeech;", - QNativeInterface::QAndroidApplication::context(), id, QJniObject::fromString(engine).object()); + m_speech = QJniObject::construct<QtJniTypes::QtTextToSpeech>(QNativeInterface::QAndroidApplication::context(), + id, QJniObject::fromString(engine).object<jstring>()); (*textToSpeechMap)[id] = this; } @@ -150,7 +149,7 @@ void QTextToSpeechEngineAndroid::say(const QString &text) stop(QTextToSpeech::BoundaryHint::Default); m_text = text; - m_speech.callMethod<void>("say", "(Ljava/lang/String;)V", QJniObject::fromString(m_text).object()); + m_speech.callMethod<void>("say", QJniObject::fromString(m_text).object<jstring>()); } QTextToSpeech::State QTextToSpeechEngineAndroid::state() const @@ -243,7 +242,7 @@ void QTextToSpeechEngineAndroid::stop(QTextToSpeech::BoundaryHint boundaryHint) if (m_state == QTextToSpeech::Ready) return; - m_speech.callMethod<void>("stop", "()V"); + m_speech.callMethod<void>("stop"); setState(QTextToSpeech::Ready); } @@ -253,7 +252,7 @@ void QTextToSpeechEngineAndroid::pause(QTextToSpeech::BoundaryHint boundaryHint) if (m_state == QTextToSpeech::Paused) return; - m_speech.callMethod<void>("stop", "()V"); + m_speech.callMethod<void>("stop"); setState(QTextToSpeech::Paused); } @@ -285,7 +284,7 @@ bool QTextToSpeechEngineAndroid::setPitch(double pitch) pitch += 1.0f; // 0 == SUCCESS - return m_speech.callMethod<int>("setPitch", "(F)I", pitch) == 0; + return m_speech.callMethod<int>("setPitch", float(pitch)) == 0; } // Android API's rate is from [0.5, 2.0[, with 1.0 being normal. @@ -303,7 +302,7 @@ bool QTextToSpeechEngineAndroid::setRate(double rate) { rate = 1.0 + (rate >= 0 ? rate : (rate * 0.5)); // 0 == SUCCESS - return m_speech.callMethod<int>("setRate", "(F)I", rate) == 0; + return m_speech.callMethod<int>("setRate", float(rate)) == 0; } double QTextToSpeechEngineAndroid::volume() const @@ -315,7 +314,7 @@ double QTextToSpeechEngineAndroid::volume() const bool QTextToSpeechEngineAndroid::setVolume(double volume) { // 0 == SUCCESS - return m_speech.callMethod<jint>("setVolume", "(F)I", float(volume)) == 0; + return m_speech.callMethod<jint>("setVolume", float(volume)) == 0; } QList<QLocale> QTextToSpeechEngineAndroid::availableLocales() const @@ -325,9 +324,9 @@ QList<QLocale> QTextToSpeechEngineAndroid::availableLocales() const QList<QLocale> result; result.reserve(count); for (int i = 0; i < count; ++i) { - auto locale = locales.callObjectMethod("get", "(I)Ljava/lang/Object;", i); - auto localeLanguage = locale.callObjectMethod<jstring>("getLanguage").toString(); - auto localeCountry = locale.callObjectMethod<jstring>("getCountry").toString(); + auto locale = locales.callMethod<jobject>("get", i); + auto localeLanguage = locale.callMethod<jstring>("getLanguage").toString(); + auto localeCountry = locale.callMethod<jstring>("getCountry").toString(); if (!localeCountry.isEmpty()) localeLanguage += QString("_%1").arg(localeCountry).toUpper(); result << QLocale(localeLanguage); @@ -345,11 +344,10 @@ bool QTextToSpeechEngineAndroid::setLocale(const QLocale &locale) QString languageCode = parts.at(0); QString countryCode = parts.at(1); - QJniObject jLocale("java/util/Locale", "(Ljava/lang/String;Ljava/lang/String;)V", - QJniObject::fromString(languageCode).object(), - QJniObject::fromString(countryCode).object()); + QJniObject jLocale("java/util/Locale", QJniObject::fromString(languageCode).object<jstring>(), + QJniObject::fromString(countryCode).object<jstring>()); - if (!m_speech.callMethod<jboolean>("setLocale", "(Ljava/util/Locale;)Z", jLocale.object())) { + if (!m_speech.callMethod<jboolean>("setLocale", jLocale.object<QtJniTypes::Locale>())) { setError(QTextToSpeech::ErrorReason::Configuration, QCoreApplication::translate("QTextToSpeech", "No voice available for locale %1") .arg(locale.bcp47Name())); @@ -360,7 +358,7 @@ bool QTextToSpeechEngineAndroid::setLocale(const QLocale &locale) QLocale QTextToSpeechEngineAndroid::locale() const { - auto locale = m_speech.callObjectMethod("getLocale", "()Ljava/util/Locale;"); + auto locale = m_speech.callMethod<QtJniTypes::Locale>("getLocale"); if (locale.isValid()) { auto localeLanguage = locale.callObjectMethod<jstring>("getLanguage").toString(); auto localeCountry = locale.callObjectMethod<jstring>("getCountry").toString(); @@ -382,7 +380,7 @@ QVoice QTextToSpeechEngineAndroid::javaVoiceObjectToQVoice(QJniObject &obj) cons } else { gender = QVoice::Unknown; } - QJniObject locale = obj.callObjectMethod("getLocale", "()Ljava/util/Locale;"); + QJniObject locale = obj.callMethod<QtJniTypes::Locale>("getLocale"); QLocale qlocale; if (locale.isValid()) { auto localeLanguage = locale.callObjectMethod<jstring>("getLanguage").toString(); @@ -402,7 +400,7 @@ QList<QVoice> QTextToSpeechEngineAndroid::availableVoices() const QList<QVoice> result; result.reserve(count); for (int i = 0; i < count; ++i) { - auto jvoice = voices.callObjectMethod("get", "(I)Ljava/lang/Object;", i); + auto jvoice = voices.callMethod<jobject>("get", i); const QVoice voice = javaVoiceObjectToQVoice(jvoice); if (voice.locale() == ttsLocale) result << voice; @@ -412,8 +410,8 @@ QList<QVoice> QTextToSpeechEngineAndroid::availableVoices() const bool QTextToSpeechEngineAndroid::setVoice(const QVoice &voice) { - if (!m_speech.callMethod<jboolean>("setVoice", "(Ljava/lang/String;)Z", - QJniObject::fromString(voiceData(voice).toString()).object())) { + const QString id = voiceData(voice).toString(); + if (!m_speech.callMethod<jboolean>("setVoice", QJniObject::fromString(id).object<jstring>())) { setError(QTextToSpeech::ErrorReason::Configuration, QCoreApplication::translate("QTextToSpeech", "Could not set voice")); return false; @@ -423,7 +421,7 @@ bool QTextToSpeechEngineAndroid::setVoice(const QVoice &voice) QVoice QTextToSpeechEngineAndroid::voice() const { - auto voice = m_speech.callObjectMethod("getVoice", "()Ljava/lang/Object;"); + auto voice = m_speech.callMethod<jobject>("getVoice"); if (voice.isValid()) return javaVoiceObjectToQVoice(voice); return QVoice(); diff --git a/src/plugins/tts/android/src/qtexttospeech_android.h b/src/plugins/tts/android/src/qtexttospeech_android.h index a9404d5..f2a53a2 100644 --- a/src/plugins/tts/android/src/qtexttospeech_android.h +++ b/src/plugins/tts/android/src/qtexttospeech_android.h @@ -93,6 +93,8 @@ private: QString m_text; }; +Q_DECLARE_JNI_CLASS(QtTextToSpeech, "org/qtproject/qt/android/speech/QtTextToSpeech") + QT_END_NAMESPACE #endif |