From fe0d09eb28acd7aeb54724ca73c6ed1569b2d25a Mon Sep 17 00:00:00 2001 From: sspanak Date: Tue, 13 May 2025 12:50:48 +0300 Subject: [PATCH] fixed ClassNotFoundException: Didn't find class "android.speech.RecognitionSupportCallback" on Sonim XP3800 and possibly other old devices --- .../sspanak/tt9/ime/voice/VoiceInputOps.java | 27 ++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/io/github/sspanak/tt9/ime/voice/VoiceInputOps.java b/app/src/main/java/io/github/sspanak/tt9/ime/voice/VoiceInputOps.java index ad124206..51fda586 100644 --- a/app/src/main/java/io/github/sspanak/tt9/ime/voice/VoiceInputOps.java +++ b/app/src/main/java/io/github/sspanak/tt9/ime/voice/VoiceInputOps.java @@ -10,6 +10,7 @@ import android.speech.SpeechRecognizer; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import java.lang.reflect.Constructor; import java.util.ArrayList; import io.github.sspanak.tt9.R; @@ -38,7 +39,7 @@ public class VoiceInputOps { ConsumerCompat onError ) { listener = new VoiceListener(ims, onStart, this::onStop, this::onError); - recognizerSupport = DeviceInfo.AT_LEAST_ANDROID_13 ? new SpeechRecognizerSupportModern(ims) : new SpeechRecognizerSupportLegacy(ims); + recognizerSupport = lazyLoadSupportClass(ims); onStopListening = onStop != null ? onStop : result -> {}; onListeningError = onError != null ? onError : error -> {}; @@ -47,6 +48,30 @@ public class VoiceInputOps { } + /** + * Android normally loads all classes even if they are not used on specific version. This here + * prevents the following error on older devices like Sonim XP3800: + * java.lang.NoClassDefFoundError: Failed resolution of: Landroid/speech/RecognitionSupportCallback; + * Caused by: java.lang.ClassNotFoundException: Didn't find class "android.speech.RecognitionSupportCallback" + * + */ + private SpeechRecognizerSupportLegacy lazyLoadSupportClass(Context context) { + if (DeviceInfo.AT_LEAST_ANDROID_13) { + try { + Package voicePackage = SpeechRecognizerSupportLegacy.class.getPackage(); + String className = voicePackage != null ? voicePackage.getName() + ".SpeechRecognizerSupportModern" : ""; + Class clazz = Class.forName(className); + Constructor ctor = clazz.getDeclaredConstructor(Context.class); + return (SpeechRecognizerSupportLegacy) ctor.newInstance(context); + } catch (Exception e) { + return new SpeechRecognizerSupportLegacy(context); + } + } + + return new SpeechRecognizerSupportLegacy(context); + } + + static String getLocale(@NonNull Language lang) { return lang.getLocale().toString().replace("_", "-"); }