2016-04-23 92 views
0

我有一个类DistanceAnnouncer,它使用Android文本到语音引擎来宣告两个位置之间的距离。它的构造是这样的:Android TTS中没有声音 - 错误的上下文?

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

哪然后在单击一个对话框按钮时使用匿名方法,如下所示。这工作正常。但是现在我想重构代码以使用更少的内存,并希望摆脱类级变量。为了测试它,我创建了一个新的测试对象,并将它作为Context(与构造函数中接收的类级对象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(); 
    } 

我怀疑这是上下文相关的问题,但在这种情况下,什么是两种环境之间的差异?他们应该是一样的,不是吗?

编辑:全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:应用程序日志,通过文字转语音过滤:

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服务,但不第二个。但是,为什么?我也尝试删除第一个,只留下第二个(也许几个TTS每个活动是不允许的?),但没有成功。

回答

1

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

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

DistanceAnnouncer newDistanceAnnouncer = new DistanceAnnouncer(MainActivity.this); 

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

...然后试图说话槽TTS引擎之前onInit()已经用完之前,已初始化即。