diff --git a/app/src/main/java/eu/faircode/email/ServiceSynchronize.java b/app/src/main/java/eu/faircode/email/ServiceSynchronize.java index baaebe6348..54fd635e53 100644 --- a/app/src/main/java/eu/faircode/email/ServiceSynchronize.java +++ b/app/src/main/java/eu/faircode/email/ServiceSynchronize.java @@ -621,6 +621,8 @@ public class ServiceSynchronize extends ServiceBase implements SharedPreferences liveAccountNetworkState.postDestroy(); + TTSHelper.shutdown(); + try { stopForeground(true); } catch (Throwable ex) { diff --git a/app/src/main/java/eu/faircode/email/TTSHelper.java b/app/src/main/java/eu/faircode/email/TTSHelper.java index dbbc7258fe..0fae06e459 100644 --- a/app/src/main/java/eu/faircode/email/TTSHelper.java +++ b/app/src/main/java/eu/faircode/email/TTSHelper.java @@ -5,42 +5,82 @@ import android.speech.tts.TextToSpeech; import androidx.annotation.NonNull; +import java.util.ArrayList; +import java.util.List; import java.util.Locale; public class TTSHelper { - private static boolean initialized; - private static TextToSpeech instance; + private static Integer status = null; + private static TextToSpeech instance = null; + private static List queue = new ArrayList<>(); + private static final Object lock = new Object(); + + // https://developer.android.com/reference/android/speech/tts/TextToSpeech + // https://android-developers.googleblog.com/2009/09/introduction-to-text-to-speech-in.html static void speak( @NonNull final Context context, @NonNull final String utteranceId, @NonNull final String text, @NonNull final Locale locale) { - // https://developer.android.com/reference/android/speech/tts/TextToSpeech - // https://android-developers.googleblog.com/2009/09/introduction-to-text-to-speech-in.html - final Runnable speak = new Runnable() { + Runnable speak = new Runnable() { @Override public void run() { - boolean available = (instance.setLanguage(locale) >= 0); - EntityLog.log(context, "TTS queued language=" + locale + " available=" + available + " text=" + text); - instance.speak(text, TextToSpeech.QUEUE_ADD, null, utteranceId); + try { + boolean available = (instance.setLanguage(locale) >= 0); + EntityLog.log(context, "TTS queued" + + " language=" + locale + + " available=" + available + + " utterance=" + utteranceId + + " text=" + text); + instance.speak(text, TextToSpeech.QUEUE_ADD, null, utteranceId); + } catch (Throwable ex) { + Log.e(ex); + } } }; - if (initialized) { - speak.run(); - return; + synchronized (lock) { + if (status == null) { + queue.add(speak); + if (instance == null) + try { + Log.i("TTS init"); + instance = new TextToSpeech(context, new TextToSpeech.OnInitListener() { + @Override + public void onInit(int initStatus) { + synchronized (lock) { + status = initStatus; + boolean ok = (status == TextToSpeech.SUCCESS); + Log.i("TTS status=" + status + " ok=" + ok + " queued=" + queue.size()); + if (ok) + for (Runnable speak : queue) + speak.run(); + queue.clear(); + } + } + }); + } catch (Throwable ex) { + Log.e(ex); + status = TextToSpeech.ERROR; + } + } else if (status == TextToSpeech.SUCCESS) + speak.run(); } + } - instance = new TextToSpeech(context, new TextToSpeech.OnInitListener() { - @Override - public void onInit(int status) { - initialized = (status == TextToSpeech.SUCCESS); - Log.i("TTS status=" + status + " ok=" + initialized); - if (initialized) - speak.run(); - } - }); + static void shutdown() { + synchronized (lock) { + if (instance != null) + try { + Log.i("TTS shutdown"); + instance.shutdown(); + instance = null; + } catch (Throwable ex) { + Log.e(ex); + } + status = null; + } } }