android 开发 W/TextToSpeech: speak failed: not bound to TTS engine

本文讲述了开发者在使用AndroidTextToSpeech进行语音播报时遇到的notboundtoTTSengine错误,通过分析错误原因,提供了解决方案,包括在AndroidManifest.xml中添加TTS服务查询,以及针对中文语音数据缺失的处理方法。
摘要由CSDN通过智能技术生成

问题

笔者使用TTS(TextToSpeech)对于文本内容进行语音播报,控制台报错

android 开发 speak failed:not bound to TTS engine

详细问题

笔者核心代码:

import android.os.Bundle;
import android.speech.tts.TextToSpeech;
import android.speech.tts.TextToSpeech.OnInitListener;
import android.util.Log;
import android.view.View;

import androidx.appcompat.app.AppCompatActivity;

import com.google.android.material.floatingactionbutton.FloatingActionButton;

import java.util.Locale;

public class LoginActivity extends AppCompatActivity implements OnInitListener {
    private FloatingActionButton speakButton;
    private TextToSpeech textToSpeech;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_login);

        // 初始化TextToSpeech引擎
        textToSpeech = new TextToSpeech(this, this);

        // 找到按钮
        speakButton = findViewById(R.id.speakButton);

        // 设置按钮点击事件
        speakButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // 在这里添加进行语音播报的代码
                speakOut("Your text to be spoken");
            }
        });
    }

    // 初始化TextToSpeech引擎的回调
    @Override
    public void onInit(int status) {
        if (status == TextToSpeech.SUCCESS) {
            // 设置语音引擎的语言,例如英语
            int result = textToSpeech.setLanguage(Locale.ENGLISH);

            if (result == TextToSpeech.LANG_MISSING_DATA ||
                    result == TextToSpeech.LANG_NOT_SUPPORTED) {
                Log.e("TTS", "Language is not supported.");
            }
        } else {
            Log.e("TTS", "Initialization failed.");
        }
    }

    // 进行语音播报的方法
    private void speakOut(String text) {
        textToSpeech.speak(text, TextToSpeech.QUEUE_FLUSH, null, null);
    }

    // 在Activity销毁时释放TextToSpeech引擎
    @Override
    protected void onDestroy() {
        if (textToSpeech != null) {
            textToSpeech.stop();
            textToSpeech.shutdown();
        }
        super.onDestroy();
    }
}

运行控制台报错内容:

W/TextToSpeech: speak failed: not bound to TTS engine

解决方案

步骤1、 在package\app\src\main\AndroidManifest.xml中配置如下内容:
具体操作如下图所示:
在这里插入图片描述
具体代码:

<queries>
    <intent>
        <action android:name="android.intent.action.TTS_SERVICE"/>
    </intent>
</queries>

若进行英语播报,进行到此处问题即可解决。若是需要进行中文播报,需继续,进行步骤2的配置。

步骤2、修改上述代码:
尤其为onInit函数中代码内容:

	// 初始化TextToSpeech引擎的回调
    @Override
    public void onInit(int status) {
        if (status == TextToSpeech.SUCCESS) {
            int result = textToSpeech.setLanguage(Locale.CHINESE);
            if (result == TextToSpeech.LANG_MISSING_DATA ||
                    result == TextToSpeech.LANG_NOT_SUPPORTED) {
                Log.e("TTS", "不支持中文语音合成。");
                if (result == TextToSpeech.LANG_MISSING_DATA) {
                    Log.e("TTS", "缺少中文语音数据,正在下载...");
                    Intent installIntent = new Intent();
                    installIntent.setAction(TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA);
                    startActivity(installIntent);
                }
            } else {
                // 检查语音数据是否已下载
                if (textToSpeech.isLanguageAvailable(Locale.CHINESE) >= TextToSpeech.LANG_AVAILABLE) {
                    Log.i("中文语音数据已完整下载");
		    		speakOut("打开该页面语音播报内容");
                    paused = false; // 在初始化完成后将paused设置为false
                } else {
                    Log.e("TTS", "中文语音数据未完整下载。");
                }
            }
        } else {
            Log.e("TTS", "TextToSpeech引擎初始化失败。");
        }
    }

完整代码:

import android.content.Context;
import android.content.Intent;
import android.media.AudioManager;
import android.os.Bundle;
import android.speech.tts.TextToSpeech;
import android.util.Log;
import android.view.View;

import androidx.appcompat.app.AppCompatActivity;

import com.google.android.material.floatingactionbutton.FloatingActionButton;

import java.util.Locale;
public class LoginActivity extends AppCompatActivity implements TextToSpeech.OnInitListener {
    private FloatingActionButton speakButton;
    private TextToSpeech textToSpeech;
    private boolean paused = true; // Initialize paused to true

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_login);
        
        // 请求音频焦点
        AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
        int result = audioManager.requestAudioFocus(null, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN);
        if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
            Log.i("TTS", "Audio focus requested successfully.");
        } else {
            Log.e("TTS", "Failed to request audio focus.");
        }

        // 初始化TextToSpeech引擎
        textToSpeech = new TextToSpeech(this, this);

        // 找到按钮
        speakButton = findViewById(R.id.speakButton);

        // 设置按钮点击事件
        speakButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                System.out.println("点击按钮");
                // Do nothing if paused
                if (paused) {
                    return;
                }

                // 在这里添加进行语音播报的代码
                speakOut("点击按钮语音播报内容");
            }
        });
    }

    // 初始化TextToSpeech引擎的回调
    @Override
    public void onInit(int status) {
        if (status == TextToSpeech.SUCCESS) {
            int result = textToSpeech.setLanguage(Locale.CHINESE);
            if (result == TextToSpeech.LANG_MISSING_DATA ||
                    result == TextToSpeech.LANG_NOT_SUPPORTED) {
                Log.e("TTS", "不支持中文语音合成。");
                if (result == TextToSpeech.LANG_MISSING_DATA) {
                    Log.e("TTS", "缺少中文语音数据,正在下载...");
                    Intent installIntent = new Intent();
                    installIntent.setAction(TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA);
                    startActivity(installIntent);
                }
            } else {
                // 检查语音数据是否已下载
                if (textToSpeech.isLanguageAvailable(Locale.CHINESE) >= TextToSpeech.LANG_AVAILABLE) {
                    Log.i("TTS", "中文语音数据已完整下载");
                    speakOut("打开该页面语音播报内容");
                    paused = false; // 在初始化完成后将paused设置为false
                } else {
                    Log.e("TTS", "中文语音数据未完整下载。");
                }
            }
        } else {
            Log.e("TTS", "TextToSpeech引擎初始化失败。");
        }
    }


    // 进行语音播报的方法
    private void speakOut(String text) {
        textToSpeech.speak(text, TextToSpeech.QUEUE_FLUSH, null, null);
    }

    // 在Activity销毁时释放TextToSpeech引擎
    @Override
    protected void onDestroy() {
        if (textToSpeech != null) {
            textToSpeech.stop();
            textToSpeech.shutdown();
        }
        super.onDestroy();
    }
}

产生原因

按照官方文档要求,在Android11需要在manifest里声明TTS_SERVICE,以开启(英文)语音播报服务,而笔者的AndroidManifest.xml中缺少对TTS服务的配置。
(中文)语音数据未完整下载: 在笔者的代码中,由于涉及对中文语音播报服务。如果中文语音数据未完整下载,也将导致TTS引擎可能无法正确工作。

解决原因

具体来说,以下是问题解决的原因:

步骤1、通过在AndroidManifest.xml中添加TTS服务的查询,可以确保应用可以与TTS引擎正确通信。

步骤2.1、
中文语音数据未完整下载: 在onInit方法中,通过判断result是否等于TextToSpeech.LANG_MISSING_DATA来检测语音数据是否完整。如果数据不完整,会触发语音数据下载的操作。

if (result == TextToSpeech.LANG_MISSING_DATA) {
    Log.e("TTS", "缺少中文语音数据,正在下载...");
    Intent installIntent = new Intent();
    installIntent.setAction(TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA);
    startActivity(installIntent);
}

通过执行上述代码块,程序尝试在语音数据不完整时触发下载。

步骤2.2
设置语言为中文: 通过

textToSpeech.setLanguage(Locale.CHINESE)

将语音引擎的语言设置为中文。

int result = textToSpeech.setLanguage(Locale.CHINESE);

确保了TTS引擎使用中文语音数据进行合成。

步骤2.3
检查语音数据是否已完整下载: 通过检查语音数据是否已完整下载,以确保语音引擎能够正常使用。

if (textToSpeech.isLanguageAvailable(Locale.CHINESE) >= TextToSpeech.LANG_AVAILABLE) {
    Log.i("TTS", "中文语音数据已完整下载");
    speakOut("打开该页面语音播报内容");
    paused = false;
} else {
    Log.e("TTS", "中文语音数据未完整下载。");
}

这段代码会检查中文语音数据是否已完整下载,如果下载完成,则继续进行语音合成。

通过这些处理步骤,解决中文语音数据未完整下载的问题,使得TTS引擎能够正确初始化和使用。

总结

stackoverflow作为程序设计领域世界知名的问答网站,问答质量很高。但是该平台中国用户相对较少,对于中国用户可能会遇到的问题,该网站有时无法解决(譬如本文中所提及的中文语音数据下载相关内容)。这时,CSDN往往也可以作为一个不错的选择。

参加文献

speak failed:not bound to TTS engine解决方案
产生原因与解决原因部分内容 部分参考chatgpt

原创不易
转载请标明出处
如果对你有所帮助 别忘啦点赞支持哈
请添加图片描述

  • 28
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
这个问题可能是由于没有正确设置TTS引擎导致的。您可以尝试以下步骤来解决此问题: 1. 确认您的设备上已经安装了TTS引擎。您可以在“设置”中找到“语音输入和输出”选项,检查您的TTS引擎是否已启用。 2. 如果您的设备上没有TTS引擎,您可以在Google Play商店中搜索并下载TTS引擎。 3. 如果您的设备上已安装TTS引擎,请确保它已启用。您可以在“设置”中找到“语音输入和输出”选项,检查您的TTS引擎是否已启用。 4. 如果您已经安装和启用了TTS引擎,但仍然遇到问题,请尝试清除TTS引擎的缓存和数据。您可以在“设置”中找到“应用程序”选项,找到您的TTS引擎并清除其缓存和数据。 5. 最后,请确保您的应用程序有权限使用TTS引擎。您可以在您的应用程序清单文件中添加以下权限: ``` <uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> <uses-permission android:name="android.permission.WAKE_LOCK"/> <uses-permission android:name="android.permission.RECORD_AUDIO"/> <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/> <uses-permission android:name="android.permission.READ_PHONE_STATE"/> <uses-permission android:name="android.permission.READ_CONTACTS"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.VIBRATE"/> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/> <uses-permission android:name="android.permission.BLUETOOTH"/> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/> <uses-permission android:name="android.permission.READ_LOGS"/> <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/> <uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES"/> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/> <uses-permission android:name="android.permission.CAMERA"/> <uses-permission android:name="com.android.vending.BILLING"/> <uses-permission android:name="android.permission.GET_TASKS"/> <uses-permission android:name="android.permission.DOWNLOAD_WITHOUT_NOTIFICATION"/> <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/> <uses-permission android:name="android.permission.WRITE_SETTINGS"/> <uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/> <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/> <uses-permission android:name="android.permission.SYSTEM_OVERLAY_WINDOW"/> <uses-permission android:name="android.permission.MANAGE_DOCUMENTS"/> <uses-permission android:name="android.permission.PACKAGE_USAGE_STATS"/> <uses-permission android:name="android.permission.RECORD_VIDEO"/> <uses-permission android:name="android.permission.RECORD_AUDIO"/> <uses-permission android:name="android.permission.MEDIA_CONTENT_CONTROL"/> <uses-permission android:name="android.permission.ACCESS_MEDIA_LOCATION"/> <uses-permission android:name="android.permission.ACCESS_NOTIFICATION_POLICY"/> <uses-permission android:name="android.permission.FLASHLIGHT"/> <uses-permission android:name="android.permission.REQUEST_COMPANION_RUN_IN_BACKGROUND"/> <uses-permission android:name="android.permission.REQUEST_COMPANION_USE_DATA_IN_BACKGROUND"/> ``` 希望这些步骤可以帮助您解决问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

飞滕人生TYF

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值