Global TTS in Android

本秂侑毒 提交于 2019-12-31 01:51:09

问题


Hi I am devloping an application for blind users so that I use very often text to speech as practicaly the only one method how to respond on user actions. I decided to make one global TTS instance running as long as the app. I have implemented it this way

package com.simekadam.blindguardian;

import android.content.Context;
import android.speech.tts.TextToSpeech;
import android.speech.tts.TextToSpeech.OnInitListener;

public class SpeechHelper implements OnInitListener {

private static TextToSpeech mTts;
private String text; 
private static final SpeechHelper helper = new SpeechHelper();

public static SpeechHelper getInstance(){

    return helper;
}


public void say(String text, Context context){

    if(mTts == null){
        this.text = text;
        mTts = new TextToSpeech(context, (OnInitListener) helper);

    }
    else{
        mTts.speak(text, TextToSpeech.QUEUE_FLUSH, null);
    }
}


@Override
public void onInit(int status) {
    // TODO Auto-generated method stub
    if (status == TextToSpeech.SUCCESS) {
        mTts.speak(text, TextToSpeech.QUEUE_FLUSH, null);
    }
}

public void stopTTS(){
    if(mTts != null){
        mTts.shutdown();
        mTts.stop();
        mTts = null;
    }
}

}

At first - its working BUT ..I wanted to check the availability of speech data like that

protected void onCreate(Bundle savedInstanceState){
    super.onCreate(savedInstanceState);
    Intent checkIntent = new Intent();
    checkIntent.setAction(TextToSpeech.Engine.ACTION_CHECK_TTS_DATA);
    startActivityForResult(checkIntent, MY_DATA_CHECK_CODE);
    text = getIntent().getExtras();
}


protected void onActivityResult(
        int requestCode, int resultCode, Intent data) {
    if (requestCode == MY_DATA_CHECK_CODE) {
        if (resultCode == TextToSpeech.Engine.CHECK_VOICE_DATA_PASS) {
            // success, create the TTS instance
            mTts = new TextToSpeech(this, (OnInitListener) this);
            mTts.setLanguage(new Locale("cze", "CZE"));
        } else {
            // missing data, install it
            Intent installIntent = new Intent();
            installIntent.setAction(
                TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA);
            startActivity(installIntent);
        }
    }       
}

Its code from Android developer portal, but I cant start Activity for result from class which is not child of android.Activity.. Please how to check it without using activities, and is it this approach of invoke TTS correct? (I have implemented it all with Activities before, but there was a couple of memory leaks, due to incorrectly closed TTS - and when I closed it properly, it must been created again on every call - just too slow..)


回答1:


Initialize your global instance from onActivityResult(), after you know that TTS data is available. Your app needs an activity, so do it from the entry activity, all subsequent ones will be able to use your global instance once it is initialized. Also think about when and how you will shut it down.




回答2:


You don't need to use the ACTION_CHECK_TTS_DATA. Instead use isLanguageAvailable like this: (make sure to call this only after onInit is complete)

    // check if language is available
    switch (tts.isLanguageAvailable(locale))
    {
        case TextToSpeech.LANG_AVAILABLE:
        case TextToSpeech.LANG_COUNTRY_AVAILABLE:
        case TextToSpeech.LANG_COUNTRY_VAR_AVAILABLE:
            Log.d(TAG, "SUPPORTED");
            break;
        case TextToSpeech.LANG_MISSING_DATA:
            Log.d(TAG, "MISSING_DATA");//launch the install data activity
            break;
        case TextToSpeech.LANG_NOT_SUPPORTED:
            Log.d(TAG, "NOT SUPPORTED");//report failure
            break;
    }



回答3:


Here's some answers by gregm again to similar questions:

TTS - CHECK_VOICE_DATA_FAIL - Check engine availlable or

Why is the ACTION_CHECK_TTS_DATA Intent "awkward to use"?

that also recommend just using TextToSpeech.isLanguageAvailable() instead of ACTION_CHECK_TTS_DATA, along with a pointer to a helper class.

I've tested this on some android 4.1.2 phones with Locale.US, and it activates the TTS engine fine, and plays nicely with 3rd party engines. When testing on an old android 1.6 phone (G1), looks like the stock TTS engine is not installed (LANG_MISSING_DATA). The following code in that case will redirect to the store to install:

Intent installIntent = new Intent();
installIntent.setAction(TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA);
startActivity(installIntent);

After which, using the tts engine within the app works fine. Basically, the old blog post from the android guys is a bit overkill and dated, as it does not play nicely with Android 4.x in my experience (ANDROID_CHECK_TTS_DATA always returned CHECK_VOICE_DATA_MISSING_DATA on me in Android 4.x).



来源:https://stackoverflow.com/questions/8159749/global-tts-in-android

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!