2016-04-23 13 views
0

Ich habe eine Klasse DistanceAnnouncer, die Android Text-to-Speech-Engine verwendet, um die Entfernung zwischen zwei Standorten bekannt zu geben. Es ist wie folgt aufgebaut:Kein Ton in Android TTS - falscher Kontext?

public class DistanceAnnouncer { 
    private TextToSpeech speaker; 

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

Entfernung wird durch diese Methode, um Benutzer gesprochen:

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

In meinem MainActivity ich ein Klasse-Level-Objekt erstellen ...

protected void onCreate(Bundle savedInstanceState) { 

    distanceAnnouncer = new DistanceAnnouncer(this); 

Welche wird dann in der anonymen Methode verwendet, wenn Sie auf eine Dialogschaltfläche klicken (siehe unten). Das funktioniert gut. Aber jetzt möchte ich Code umgestalten, um weniger Speicher zu verwenden und Variablen auf Klassenebene loszuwerden. Um es zu testen, erstellte ich ein neues Testobjekt und gab es MainActivity.this als einen Kontext (im Gegensatz zu Klassenobjekt, das in Konstruktor this empfängt). Das alte Objekt funktioniert immer noch, das neue funktioniert nicht. Es gibt keine Ausnahmen. Der Code wird ausgeführt, aber es gibt keinen Ton.

Code:

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

Ich vermute, das Kontext Problem, aber in diesem Fall, was ist der Unterschied zwischen den zwei Kontexten? Sie sollten gleich sein, oder?

EDIT: Voll DistanceAnnouncer Klassencode:

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 { 

     } 
    } 
} 

EDIT 2: Anwendungsprotokoll, gefiltert nach 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 

wie das System scheint verbindet erste zu System TTS-Dienst aber nicht der zweite. Aber aus welchem ​​Grund? Ich habe auch versucht, die erste zu entfernen und nur die zweite zu lassen (vielleicht sind mehrere TTS pro Aktivität nicht erlaubt?), Aber keinen Erfolg.

Antwort

1

Halten Sie einfach die eine DistanceAnnouncer Instanz als eine Elementvariable von MainActivity.

Das Problem beim Erstellen einer neuen Instanz im AlertDialog ist, dass die TTS-Engine nicht sofort verfügbar ist. Nun rufen Sie ...

DistanceAnnouncer newDistanceAnnouncer = new DistanceAnnouncer(MainActivity.this); 

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

... die dann versucht Trog die TTS-Engine zu sprechen, bevor es richtig heißt initialisiert wurde, bevor onInit() ausgeführt wurde.