java - Android TTS 中没有声音 - 上下文错误?

标签 java android android-context google-text-to-speech

我有一个类 DistanceAnnouncer,它使用 Android 文本转语音引擎来宣布两个位置之间的距离。它是这样构造的:

public class DistanceAnnouncer {
    private TextToSpeech speaker;

    public DistanceAnnouncer(Context context) {
        speaker = new TextToSpeech(context, new TextToSpeech.OnInitListener() { 
        ...

通过这种方法向用户说出距离:

public void speak(Location targetLocation, Location currentLocation) {
   float distanceInMeters = targetLocation.distanceTo(currentLocation);
   speaker.speak(String.valueOf(distanceInMeters) + " meters",TextToSpeech.QUEUE_FLUSH,null);

在我的 MainActivity 中,我创建了一个类级对象...

protected void onCreate(Bundle savedInstanceState) {

    distanceAnnouncer = new DistanceAnnouncer(this);

然后在单击对话框按钮时在匿名方法中使用,如下所示。这很好用。但是现在我想重构代码以使用更少的内存并希望摆脱类级变量。为了测试它,我创建了一个新的测试对象并将其作为上下文提供给 MainActivity.this(与在构造函数中接收 this 的类级对象相对)。旧对象仍然有效,新对象无效。没有抛出异常。代码已执行但没有声音。

代码:

    public void NewTargetButtonClicked(View view) {
        final EditText entryEditText = new EditText(this);

        AlertDialog.Builder alert = new AlertDialog.Builder(this);
        alert.setTitle(R.string.enter_coordinates_prompt);
        alert.setView(entryEditText);
        alert.setCancelable(true);
        alert.setPositiveButton(R.string.ok_button_text, new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                if (entryEditText.getText() == null) return;

                Location newLocation = getLocationFromCoords(entryEditText.getText().toString());
                //pagaidām protam apstrādāt tikai decimālgrādus
                if (!(newLocation == null)) {
                    mTargetLocation = newLocation;
                    refreshDistance();
                    Button targetButton = (Button) MainActivity.this.findViewById(R.id.newTargetButton);
                    targetButton.setText(R.string.set_new_target);

                    DistanceAnnouncer newDistanceAnnouncer = new DistanceAnnouncer(MainActivity.this);
                    //THIS DOESN'T WORK:                    
                    newDistanceAnnouncer.speak(mTargetLocation,mCurrentLocation);

                    //THIS WORKS:
                    distanceAnnouncer.speak(mTargetLocation,mCurrentLocation);

                    CheckBox speakCheckbox = (CheckBox) MainActivity.this.findViewById(R.id.speakDistanceCheckbox);
                    speakCheckbox.setVisibility(View.VISIBLE);
                }
            }
        });
        AlertDialog alertDialog = alert.create();

        alertDialog.show();
    }

我怀疑这是上下文问题,但在这种情况下,两个上下文之间的区别是什么?它们应该是一样的,不是吗?

编辑:Full DistanceAnnouncer 类代码:

package com.blueit.audioguide;

import android.app.Activity;
import android.content.Context;
import android.location.Location;
import android.speech.tts.TextToSpeech;

import java.util.Locale;

/**
 * Created by janeks on 23.04.2016..
 */
public class DistanceAnnouncer {
    private TextToSpeech speaker;

    public DistanceAnnouncer(Context context) {
        speaker = new TextToSpeech(context, new TextToSpeech.OnInitListener() {
            @Override
            public void onInit(int status) {
                if(status != TextToSpeech.ERROR) {
                    speaker.setLanguage(Locale.ENGLISH);
                }
            }
        });
    }

    public void speak(Location targetLocation, Location currentLocation) {
        if (targetLocation == null) return;
        if (currentLocation == null) return;

        if ((!(targetLocation == null)) && (!(currentLocation == null))) {
            float distanceInMeters = targetLocation.distanceTo(currentLocation);
            if (distanceInMeters < 1000) {
                distanceInMeters = Math.round(distanceInMeters);
                speaker.speak(String.valueOf(distanceInMeters) + " meters",TextToSpeech.QUEUE_FLUSH,null);
            } else if ((distanceInMeters >= 1000) && (distanceInMeters <= 100000)) {
                float distanceInKilometers = distanceInMeters / 1000;
                distanceInKilometers = Math.round(distanceInKilometers * 10) / 10;
                speaker.speak(String.valueOf(distanceInKilometers) + " kilometers",TextToSpeech.QUEUE_FLUSH,null);
            }  else if (distanceInMeters > 100000) {
                float distanceInKilometers = distanceInMeters / 1000;
                distanceInKilometers = Math.round(distanceInKilometers);
                speaker.speak(String.valueOf(distanceInKilometers) + " kilometers",TextToSpeech.QUEUE_FLUSH,null);
            }
        } else {

        }
    }
}

编辑 2:应用程序日志,由 TextToSpeech 过滤:

04-23 16:00:03.911 30815-30815/com.blueit.audioguide I/TextToSpeech: Sucessfully bound to com.google.android.tts
04-23 16:00:03.988 30815-30815/com.blueit.audioguide I/TextToSpeech: Connected to ComponentInfo{com.google.android.tts/com.google.android.tts.service.GoogleTTSService}
04-23 16:00:03.995 30815-30932/com.blueit.audioguide I/TextToSpeech: Set up connection to ComponentInfo{com.google.android.tts/com.google.android.tts.service.GoogleTTSService}
04-23 16:01:35.048 30815-30815/com.blueit.audioguide I/TextToSpeech: Sucessfully bound to com.google.android.tts
04-23 16:01:44.346 30815-30815/com.blueit.audioguide W/TextToSpeech: speak failed: not bound to TTS engine

似乎系统将第一个连接到系统 TTS 服务,但没有连接第二个。但是为什么?我也尝试删除第一个,只留下第二个(也许不允许每个 Activity 多个 TTS?),但没有成功。

最佳答案

只保留一个DistanceAnnouncer实例作为MainActivity的成员变量。

总是在 AlertDialog 中创建新实例的问题是 TTS 引擎不是即时可用的。现在你打电话...

DistanceAnnouncer newDistanceAnnouncer = new DistanceAnnouncer(MainActivity.this);

//THIS DOESN'T WORK:                    
newDistanceAnnouncer.speak(mTargetLocation,mCurrentLocation);

...然后在正确初始化之前尝试通过 TTS 引擎说话,即在 onInit() 运行之前。

关于java - Android TTS 中没有声音 - 上下文错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36810632/

相关文章:

Java FloodFill Problem 堆栈溢出错误

java - 在泛型方法的实现中强制类型安全

c# - Java 与 .Net 中的对象生命周期

java - 如何在 Android 中获取类(非 Activity )的上下文?

java - 如何升级Webdriver容器中的chrome版本

java - 如何在不继续不受信任的证书页面的情况下从 Angular2 发出 https 请求

android - 使用 Android NDK 为 x86 编译 FFmpeg 3.1.1

android - Android 的图像效果?

java - 不要将 Android 上下文类放在静态字段中;这是内存泄漏

android - 如何停止定时器 Android