Android 中的全局 TTS

发布于 2024-12-16 13:05:20 字数 2303 浏览 0 评论 0原文

您好,我正在为盲人用户开发一个应用程序,因此我经常使用文本转语音,作为响应用户操作的唯一一种方法。 我决定让一个全局 TTS 实例与应用程序的运行时间一样长。 我已经这样实现了

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;
    }
}

}

起初 - 它有效但是 ..我想检查语音数据的可用性,例如

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);
        }
    }       
}

来自 Android 开发人员门户的代码,但我无法启动 Activity 以获取不是 android.Activity 子级的类的结果。 请问如何在不使用活动的情况下检查它,这种调用TTS的方法是否正确? (我之前已经用 Activity 实现了这一切,但是由于错误地关闭了 TTS,出现了一些内存泄漏 - 当我正确关闭它时,它必须在每次调用时再次创建 - 太慢了..)

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..)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

为你鎻心 2024-12-23 13:05:20

在您知道 TTS 数据可用后,从 onActivityResult() 初始化您的全局实例。您的应用程序需要一个活动,因此从入口活动开始,一旦初始化,所有后续活动都将能够使用您的全局实例。还要考虑何时以及如何关闭它。

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.

貪欢 2024-12-23 13:05:20

您不需要使用 ACTION_CHECK_TTS_DATA。而是使用 isLanguageAvailable 像这样:
(确保仅在 onInit 完成后调用此函数)

    // 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;
    }

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;
    }
慕烟庭风 2024-12-23 13:05:20

以下是 gregm 对类似问题的一些回答:

TTS - CHECK_VOICE_DATA_FAIL - 检查引擎是否可用

为什么 ACTION_CHECK_TTS_DATA 意图“使用起来很尴尬”?< /a>

还建议仅使用 TextToSpeech.isLanguageAvailable() 而不是ACTION_CHECK_TTS_DATA,以及指向辅助类的指针。

我已经在一些带有 Locale.US 的 Android 4.1.2 手机上对此进行了测试,它可以很好地激活 TTS 引擎,并且可以与第 3 方引擎完美配合。在旧的 Android 1.6 手机 (G1) 上进行测试时,似乎未安装库存 TTS 引擎 (LANG_MISSING_DATA)。在这种情况下,以下代码将重定向到商店进行安装:

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

之后,在应用程序中使用 tts 引擎就可以正常工作了。基本上,来自 Android 人员的旧博客文章有点过时了,因为根据我的经验,它不能很好地与 Android 4.x 兼容(ANDROID_CHECK_TTS_DATA 总是返回 CHECK_VOICE_DATA_MISSING_DATA在 Android 4.x 中对我来说)。

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).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文