Android TextToSpeech ведет себя ненормально

Обновление: после некоторого копания мне удалось найти некоторую информацию в файле Logcat. См. внизу.

Редактировать 2: теперь я создал новую активность с нуля, чтобы уменьшить проблему. Он по-прежнему работает неправильно. Вот код:

public class MainActivity extends AppCompatActivity {
    private TextToSpeech textToSpeech;
    private boolean isInitialized = false;
    private MainActivity mainActivity;
    int ctr = 0;
    private String words[] = {"ord", "kula", "fotboll"};
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        mainActivity = this;

        textToSpeech = new TextToSpeech(this, new TextToSpeech.OnInitListener() {
            @Override
            public void onInit(int status) {
                if (status == TextToSpeech.SUCCESS){
                    textToSpeech.setOnUtteranceProgressListener(new UtteranceProgressListener() {
                        @Override
                        public void onStart(String utteranceId) {
                            System.out.println("---onStart");
                        }

                        @Override
                        public void onDone(String utteranceId) {
                           System.out.println("-----onDone");
                        }

                        @Override
                        public void onError(String utteranceId) {
                            System.out.println("-----onError");
                        }

                        @Override
                        public void onError(String utteranceId, int errorCode){
                            onError(utteranceId);
                            System.out.println("Error with code: " + errorCode);
                        }
                    });
                    isInitialized = true;
                    Locale locale = new Locale("swe");
                    textToSpeech.setLanguage(locale);
                }
            }
        });
        FloatingActionButton fab = findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                if (isInitialized){
                    System.out.println(textToSpeech.getLanguage().getDisplayLanguage());
                    textToSpeech.speak(words[ctr], TextToSpeech.QUEUE_FLUSH, null, "SpeakTest");
                    ctr++;
                    ctr %= words.length;
                } else {
                    Snackbar.make(view, "Speaker not ready", Snackbar.LENGTH_LONG)
                            .setAction("Action", null).show();
                }
            }
        });

    }
}

Что крайне удивительно, так это то, что произносятся только слова "орд" и "футбол", а не "кула". Если я поменяю words на {"kula", "kula", "kula"} и буду пробовать достаточно долго, вдруг начнет работать. Насколько я понял, в документации следует использовать теги здесь. Я пробовал se, swe, sv, все с тем же результатом. Далее команда System.out.println(textToSpeech.getLanguage().getDisplayLanguage()); дает svenska, что правильно.

Если я перехожу на en, он работает все время. Также я снова получаю System.out.println(textToSpeech.getLanguage().getDisplayLanguage()); = engelska правильно.

Что, черт возьми, происходит?

РЕДАКТИРОВАТЬ:

Я добавил UtteranceProgressListener в соответствии с этим, метод

onError(String id) устарело и должно быть заменено на onError(String id, int errorCode). Однако я расширил свой класс с помощью UtteranceProgressListener, и это вынуждает меня реализовать старый метод onError. Так всегда называется, значит что-то не так но не знаю что.

Это потому, что другой onError(String id, int code) никогда не вызывается.

Я обновил код.


У меня есть функция, которая должна произносить слово на определенном языке при вызове функции.

Еще пару дней назад он нормально работал на моем Sony Compact XZ2, а сейчас работает с перебоями. Иногда слово произносится, а иногда нет. Команда textToSpeech.getEngines() возвращает com.google.android.tts

Например, для шведского языка в setLanguage я пробовал "sv" и "sv-SV" при создании объекта Locale. Это не помогло.

Я только что заметил, что когда я нажимаю кнопку, которая вызывает playWord(text) кучу раз (> 40), она работает, а иногда и напрямую. Какая-то странная задержка.

Функция speakText вызывается из этой функции в моем Fragment:

private void playWord(){
    if (text2Speech.isReady()) {
        text2Speech.checkSpeaking();
        text2Speech.setLanguage(getAcronym(mTraining.getCurrentSrc()));
        text2Speech.speakText(front);
    } else {
        Toast.makeText(getContext(),"Speaker not ready yet", Toast.LENGTH_SHORT).show();
    }
}

Это класс, который обрабатывает речь. Я не получил никаких сообщений об ошибках. Это просто кажется случайным, когда динамик работает.

public class Text2Speech extends UtteranceProgressListener {
    private Context mContext;
    private TextToSpeech textToSpeech;
    private boolean isReady = false;
    public Text2Speech(Context context, final String src){
        mContext = context;
        System.out.println("text2Speech created");
        textToSpeech = new TextToSpeech(mContext, new TextToSpeech.OnInitListener() {
            @Override
            public void onInit(int status) {
                if (status == TextToSpeech.SUCCESS) {
                    isReady = true;
                    Locale locale = new Locale(src);
                    int ttsLang = textToSpeech.setLanguage(locale);
                    if (ttsLang == TextToSpeech.LANG_MISSING_DATA
                            || ttsLang == TextToSpeech.LANG_NOT_SUPPORTED) {
                        Log.e("TTS", "The Language is not supported!");
                    } else {
                        Log.i("TTS", "Language Supported.");
                    }
                    Log.i("TTS", "Initialization success.");
                } else {
                    Toast.makeText(mContext, "TTS Initialization failed!", Toast.LENGTH_SHORT).show();
                }
            }
        });
    }

    public boolean isReady(){
        return isReady;
    }
    public void checkSpeaking(){
        if (textToSpeech.isSpeaking()){
            textToSpeech.stop();
        }
    }

    public void showMessage(String msg){
        Toast.makeText(mContext, msg, Toast.LENGTH_SHORT).show();
    }
    public void speakText(String text){
        int speechStatus = textToSpeech.speak(text, TextToSpeech.QUEUE_FLUSH, null);
        switch (speechStatus){
            case TextToSpeech.ERROR_INVALID_REQUEST:
                showMessage("Invalid Request");
                break;
            case TextToSpeech.ERROR_NETWORK:
                showMessage("Network Error");
                break;
            case TextToSpeech.ERROR_NETWORK_TIMEOUT:
                showMessage("Network Timeout");
                break;
            case TextToSpeech.ERROR_NOT_INSTALLED_YET:
                showMessage("Error Not Yet Downloaded");
                break;
            case TextToSpeech.ERROR_OUTPUT:
                showMessage("Output Error");
                break;
            case TextToSpeech.ERROR_SERVICE:
                showMessage("Error of TTS service");
                break;
            case TextToSpeech.ERROR_SYNTHESIS:
                showMessage("Error synthesizing");
                break;
            case TextToSpeech.LANG_NOT_SUPPORTED:
                showMessage("Language nor supported");
                break;

        }
        if (speechStatus == TextToSpeech.ERROR) {
            Log.e("TTS", "Error in converting Text to Speech!");
        }
        System.out.println("speech status - text " + speechStatus + " - " + text);
    }

    public void setLanguage(String src){
        Locale locale = new Locale(src);
        int tts = textToSpeech.setLanguage(locale);
        System.out.println(tts + "  " + src);
        if (tts == TextToSpeech.LANG_MISSING_DATA
                || tts == TextToSpeech.LANG_NOT_SUPPORTED) {
            Toast.makeText(mContext, "Language not yet supported.", Toast.LENGTH_LONG).show();
        }
    }

    public void stop(){
        textToSpeech.stop();
        textToSpeech.shutdown();
    }

@Override
public void onStart(String utteranceId) {
    Log.e("START", "start speaking");
}

@Override
public void onDone(String utteranceId) {
    Log.e("DONE", "done speaking");
}

@Override
public void onError(String utteranceID){
    Log.e("Error", "Not infromative");
}

// This is not called!
@Override
public void onError(String utteranceId, int errorCode) {
    Log.e("Error", "Error speaking");
}
}

Вот сообщение об ошибке в Logcat:

NetworkSynthesizer: ExecutionException during NetworkFetchTask
    java.util.concurrent.ExecutionException: clx: RESOURCE_EXHAUSTED: Quota exceeded for quota metric 's3-sessions' and limit 's3-session-limit' of service 'speechs3proto2-pa.googleapis.com' for consumer 'project_number:529030122437'.
        at java.util.concurrent.FutureTask.report(FutureTask.java:123)
        at java.util.concurrent.FutureTask.get(FutureTask.java:207)
        at avf.a(PG:37)
        at avf.a(PG:154)
        at com.google.android.tts.service.GoogleTTSService.onSynthesizeText(PG:250)
        at android.speech.tts.TextToSpeechService$SynthesisSpeechItem.playImpl(TextToSpeechService.java:1033)
        at android.speech.tts.TextToSpeechService$SpeechItem.play(TextToSpeechService.java:819)
        at android.speech.tts.TextToSpeechService$SynthHandler$1.run(TextToSpeechService.java:583)
        at android.os.Handler.handleCallback(Handler.java:873)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:280)
        at android.os.HandlerThread.run(HandlerThread.java:65)
     Caused by: clx: RESOURCE_EXHAUSTED: Quota exceeded for quota metric 's3-sessions' and limit 's3-session-limit' of service 'speechs3proto2-pa.googleapis.com' for consumer 'project_number:529030122437'.
        at cze.a(PG:58)
        at cze.a(PG:29)
        at dao.a(PG:21)
        at ave.a(PG:36)
        at ave.call(PG:80)
        at java.util.concurrent.FutureTask.run(FutureTask.java:266)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
        at java.lang.Thread.run(Thread.java:764)
2019-03-16 21:35:46.917 1356-5238/? E/ActivityManager: Sending non-protected broadcast com.sonymobile.intent.action.POWER_BACK_OFF_FACTOR_CHANGED from system 2179:com.android.phone/1001 pkg com.android.phone
    java.lang.Throwable
        at com.android.server.am.ActivityManagerService.checkBroadcastFromSystem(ActivityManagerService.java:21814)
        at com.android.server.am.ActivityManagerService.broadcastIntentLocked(ActivityManagerService.java:22423)
        at com.android.server.am.ActivityManagerService.broadcastIntent(ActivityManagerService.java:22565)
        at android.app.IActivityManager$Stub.onTransact$broadcastIntent$(IActivityManager.java:10171)
        at android.app.IActivityManager$Stub.onTransact(IActivityManager.java:167)
        at com.android.server.am.ActivityManagerService.onTransact(ActivityManagerService.java:3416)
        at android.os.Binder.execTransact(Binder.java:731)
2019-03-16 21:35:46.917 12061-13318/? E/TTS.GoogleTTSServiceImp: Synthesis failure with error status code: -4
2019-03-16 21:35:46.918 12061-13318/? W/PlaybackSynthesisRequest: done() was called before start() call
2019-03-16 21:35:46.919 6468-6489/com.erikbylow.tailoreddictfire D/SPEECH: Error

Когда я включаю Wi-Fi, он работает.

Догадка: Может ли быть так, что языки отсутствовали и не загружались, когда я не использовал WiFi? Когда я включил WiFi, языки были загружены?

Для меня эта ошибка: clx: RESOURCE_EXHAUSTED: Quota exceeded for quota metric... выглядит так, как будто всегда был сетевой запрос, но после включения WiFi я мог использовать TextToSpeach в режиме полета.

С другой стороны, пробовал с русским в режиме полета, не помогло. Я включил интернет без Wi-Fi, тогда он работал. Снова включил WiFi и тут заработал и русский. По крайней мере, это говорит о том, что нужно что-то скачать?

Я хотел бы выяснить, в чем причина проблемы и как ее решить, поскольку это приложение в Google Play. (Хотя сейчас рядом со мной ровно 0 активных пользователей...) :).


person El_Loco    schedule 09.03.2019    source источник
comment
Я думаю, вы могли бы отследить проблему с помощью операторов журнала.   -  person Nerdy Bunz    schedule 12.03.2019
comment
Это то, что я пытаюсь сделать с помощью UtteranceProgressListener, но это не возвращает никаких кодов ошибок на моем физическом устройстве.   -  person El_Loco    schedule 12.03.2019
comment
Да, но что-то отличается между ситуациями, когда это работает, и когда это не так. Вы также можете попробовать создать чрезвычайно простой (настолько простой, насколько это возможно) проект, который произносит слово при нажатии кнопки. Вы, вероятно, обнаружите, что он работает нормально... так что вы знаете, что проблема существует где-то посередине.   -  person Nerdy Bunz    schedule 13.03.2019
comment
Кроме того... я не думаю, что необходимо проверять isSpeaking, потому что QUEUE_FLUSH автоматически прерывает и перезапускает текущую речь... это может быть проблемой.   -  person Nerdy Bunz    schedule 13.03.2019
comment
Да, я сделал это, и это, кажется, работает нормально. Было бы лучше, если бы OnUtteranceListener возвращал код ошибки.   -  person El_Loco    schedule 13.03.2019
comment
Причина, по которой он не возвращает код ошибки, заключается в том, что любой речевой движок на этом устройстве Sony был закодирован до Android API, где был представлен этот метод... они не могут использовать метод, которого еще не существует. ... или они просто решили не использовать его.   -  person Nerdy Bunz    schedule 13.03.2019
comment
Это не сработало, когда я уменьшил проблему и начал новую деятельность.   -  person El_Loco    schedule 14.03.2019
comment
Ну, если это так, то, похоже, проблема вышла из-под вашего контроля / не по вашей вине. Однако вы можете опубликовать новый вопрос с сокращенным кодом.   -  person Nerdy Bunz    schedule 14.03.2019
comment
Я нашел некоторую информацию в logcat, когда я включаю WiFi, он работает отлично.   -  person El_Loco    schedule 16.03.2019
comment
Ах да.. это потому, что движок google tts делает много вещей в фоновом режиме в сети, но пытается это скрыть. Означает ли это новое открытие, что ваш вопрос решен? Если нет, вам могут быть полезны эти ответы: пунктуация читается вслух"> stackoverflow.com/questions/8573030/, stackoverflow.com/questions/50962724/, stackoverflow.com/questions/51510129/   -  person Nerdy Bunz    schedule 17.03.2019
comment
Работает, но я ничего не менял. Я проверил, какой движок TTS загружен, и это всегда Google. Что означает превышение этой квоты для метрики квоты "s3-session" и предела "s3-session-limit"? Похоже на сетевой запрос. Сейчас попробовал в режиме полета, тоже работает.   -  person El_Loco    schedule 17.03.2019