Addressing review suggestions and fixing text-to-speech initialization.

This commit is contained in:
Rodrigo Damazio
2011-06-10 19:52:18 -03:00
parent 0afdeb9bcc
commit eada19f516
3 changed files with 87 additions and 47 deletions
@@ -132,9 +132,14 @@ public abstract class AntSensorManager extends SensorManager {
Log.i(TAG, "destroying AntSensorManager"); Log.i(TAG, "destroying AntSensorManager");
try { try {
context.unregisterReceiver(statusReceiver); context.unregisterReceiver(statusReceiver);
} catch (IllegalArgumentException e) {
Log.w(TAG, "Failed to unregister ANT status receiver", e);
}
try {
context.unregisterReceiver(dataReceiver); context.unregisterReceiver(dataReceiver);
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
Log.w(TAG, "Failed to unregister ANT receivers", e); Log.w(TAG, "Failed to unregister ANT data receiver", e);
} }
try { try {
@@ -44,35 +44,35 @@ public class FroyoStatusAnnouncerTask extends StatusAnnouncerTask {
new OnUtteranceCompletedListener() { new OnUtteranceCompletedListener() {
@Override @Override
public void onUtteranceCompleted(String utteranceId) { public void onUtteranceCompleted(String utteranceId) {
if (audioManager != null) { int result = audioManager.abandonAudioFocus(null);
Log.d(TAG, "FroyoStatusAnnouncerTask: Abandoning audio focus."); if (result == AudioManager.AUDIOFOCUS_REQUEST_FAILED) {
audioManager.abandonAudioFocus(null); Log.w(TAG, "FroyoStatusAnnouncerTask: Failed to relinquish audio focus");
} }
} }
}; };
public FroyoStatusAnnouncerTask(Context context) { public FroyoStatusAnnouncerTask(Context context) {
super(context); super(context);
audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
} }
@Override @Override
protected void onTtsInit(int status) { protected void onTtsReady() {
super.onTtsInit(status); super.onTtsReady();
if (status == TextToSpeech.SUCCESS && tts != null) { tts.setOnUtteranceCompletedListener(utteranceListener);
tts.setOnUtteranceCompletedListener(utteranceListener);
}
} }
@Override @Override
protected void speakAnnouncment(String announcement) { protected synchronized void speakAnnouncement(String announcement) {
int result = audioManager.requestAudioFocus(null, int result = audioManager.requestAudioFocus(null,
TextToSpeech.Engine.DEFAULT_STREAM, TextToSpeech.Engine.DEFAULT_STREAM,
AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK); AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK);
if (result == AudioManager.AUDIOFOCUS_REQUEST_FAILED) { if (result == AudioManager.AUDIOFOCUS_REQUEST_FAILED) {
Log.w(TAG, "FroyoStatusAnnouncerTask: Request audio focus failed."); Log.w(TAG, "FroyoStatusAnnouncerTask: Request for audio focus failed.");
} }
// We don't care about the utterance id. // We don't care about the utterance id.
// It is supplied here to force onUtteranceCompleted to be called. // It is supplied here to force onUtteranceCompleted to be called.
tts.speak(announcement, TextToSpeech.QUEUE_FLUSH, SPEECH_PARAMS); tts.speak(announcement, TextToSpeech.QUEUE_FLUSH, SPEECH_PARAMS);
@@ -66,6 +66,11 @@ public class StatusAnnouncerTask implements PeriodicTask {
/** /**
* The response received from the TTS engine after initialization. * The response received from the TTS engine after initialization.
*/ */
private int initStatus = TextToSpeech.ERROR;
/**
* Whether the TTS engine is ready.
*/
private boolean ready = false; private boolean ready = false;
/** /**
@@ -81,13 +86,14 @@ public class StatusAnnouncerTask implements PeriodicTask {
public void onCallStateChanged(int state, String incomingNumber) { public void onCallStateChanged(int state, String incomingNumber) {
speechAllowed = state == TelephonyManager.CALL_STATE_IDLE; speechAllowed = state == TelephonyManager.CALL_STATE_IDLE;
if (!speechAllowed && tts.isSpeaking()) { if (!speechAllowed && tts != null && tts.isSpeaking()) {
// If we're already speaking, stop it. // If we're already speaking, stop it.
tts.stop(); tts.stop();
} }
} }
}; };
public StatusAnnouncerTask(Context context) { public StatusAnnouncerTask(Context context) {
this(context, new StringUtils(context)); this(context, new StringUtils(context));
} }
@@ -97,33 +103,6 @@ public class StatusAnnouncerTask implements PeriodicTask {
this.stringUtils = stringUtils; this.stringUtils = stringUtils;
} }
/**
* Called when the TTS engine is initialized.
*/
protected void onTtsInit(int status) {
Log.i(TAG, "TrackRecordingService.TTS init: " + status);
// TTS should be valid here but NPE exceptions were reported to the market.
this.ready = status == TextToSpeech.SUCCESS && tts != null;
if (ready) {
// Force the language to be the same as the string we will be speaking,
// if that's available.
Locale speechLanguage = Locale.getDefault();
int languageAvailability = tts.isLanguageAvailable(speechLanguage);
if (languageAvailability == TextToSpeech.LANG_MISSING_DATA ||
languageAvailability == TextToSpeech.LANG_NOT_SUPPORTED) {
// English is probably supported.
// TODO: Somehow use announcement strings from English too.
Log.w(TAG, "Default language not available, using English.");
speechLanguage = Locale.ENGLISH;
}
tts.setLanguage(speechLanguage);
// Slow down the speed just a bit as it is hard to hear when exercising.
tts.setSpeechRate(TTS_SPEECH_RATE);
}
}
/** /**
* {@inheritDoc} * {@inheritDoc}
* *
@@ -144,12 +123,15 @@ public class StatusAnnouncerTask implements PeriodicTask {
* to avoid needing to instantiate an entire {@link TrackRecordingService} * to avoid needing to instantiate an entire {@link TrackRecordingService}
* just to test the announcer. * just to test the announcer.
*/ */
protected void runWithStatistics(TripStatistics statistics) { // @VisibleForTesting
void runWithStatistics(TripStatistics statistics) {
if (statistics == null) { if (statistics == null) {
Log.e(TAG, "StatusAnnouncer stats not initialized."); Log.e(TAG, "StatusAnnouncer stats not initialized.");
return; return;
} }
if (!ready || tts == null) {
checkReady();
if (!ready) {
Log.e(TAG, "StatusAnnouncer Tts not ready."); Log.e(TAG, "StatusAnnouncer Tts not ready.");
return; return;
} }
@@ -162,10 +144,10 @@ public class StatusAnnouncerTask implements PeriodicTask {
String announcement = getAnnouncement(statistics); String announcement = getAnnouncement(statistics);
Log.d(Constants.TAG, "Announcement: " + announcement); Log.d(Constants.TAG, "Announcement: " + announcement);
speakAnnouncment(announcement); speakAnnouncement(announcement);
} }
protected void speakAnnouncment(String announcement) { protected void speakAnnouncement(String announcement) {
tts.speak(announcement, TextToSpeech.QUEUE_FLUSH, null); tts.speak(announcement, TextToSpeech.QUEUE_FLUSH, null);
} }
@@ -256,6 +238,59 @@ public class StatusAnnouncerTask implements PeriodicTask {
listenToPhoneState(phoneListener, PhoneStateListener.LISTEN_CALL_STATE); listenToPhoneState(phoneListener, PhoneStateListener.LISTEN_CALL_STATE);
} }
/**
* Called when the TTS engine is initialized.
*/
private void onTtsInit(int status) {
Log.i(TAG, "TrackRecordingService.TTS init: " + status);
synchronized (this) {
// TTS should be valid here but NPE exceptions were reported to the market.
initStatus = status;
checkReady();
}
}
/**
* Ensures that the TTS is ready (finishing its initialization if needed).
*/
private void checkReady() {
synchronized (this) {
if (ready) {
// Already done;
return;
}
ready = initStatus == TextToSpeech.SUCCESS && tts != null;
Log.d(TAG, "Status announcer ready: " + ready);
if (ready) {
onTtsReady();
}
}
}
/**
* Finishes the TTS engine initialization.
* Called once (and only once) when the TTS engine is ready.
*/
protected void onTtsReady() {
// Force the language to be the same as the string we will be speaking,
// if that's available.
Locale speechLanguage = Locale.getDefault();
int languageAvailability = tts.isLanguageAvailable(speechLanguage);
if (languageAvailability == TextToSpeech.LANG_MISSING_DATA ||
languageAvailability == TextToSpeech.LANG_NOT_SUPPORTED) {
// English is probably supported.
// TODO: Somehow use announcement strings from English too.
Log.w(TAG, "Default language not available, using English.");
speechLanguage = Locale.ENGLISH;
}
tts.setLanguage(speechLanguage);
// Slow down the speed just a bit as it is hard to hear when exercising.
tts.setSpeechRate(TTS_SPEECH_RATE);
}
@Override @Override
public void shutdown() { public void shutdown() {
// Stop listening to phone state. // Stop listening to phone state.