Skip to content

Commit

Permalink
Fix voiceLanguage NPE and add tests for NavigationSpeechPlayer
Browse files Browse the repository at this point in the history
  • Loading branch information
danesfeder committed Jun 29, 2018
1 parent b99a0c7 commit 99d5a66
Show file tree
Hide file tree
Showing 24 changed files with 805 additions and 268 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import android.location.Location;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.support.annotation.NonNull;
import android.text.TextUtils;

import com.mapbox.api.directions.v5.DirectionsCriteria;
Expand All @@ -22,7 +23,9 @@
import com.mapbox.services.android.navigation.ui.v5.route.ViewRouteFetcher;
import com.mapbox.services.android.navigation.ui.v5.route.ViewRouteListener;
import com.mapbox.services.android.navigation.ui.v5.summary.SummaryModel;
import com.mapbox.services.android.navigation.ui.v5.voice.NavigationInstructionPlayer;
import com.mapbox.services.android.navigation.ui.v5.voice.NavigationSpeechPlayer;
import com.mapbox.services.android.navigation.ui.v5.voice.SpeechAnnouncement;
import com.mapbox.services.android.navigation.ui.v5.voice.SpeechPlayerProvider;
import com.mapbox.services.android.navigation.v5.milestone.BannerInstructionMilestone;
import com.mapbox.services.android.navigation.v5.milestone.Milestone;
import com.mapbox.services.android.navigation.v5.milestone.MilestoneEventListener;
Expand Down Expand Up @@ -58,7 +61,7 @@ public class NavigationViewModel extends AndroidViewModel {
private ViewRouteFetcher navigationViewRouteEngine;
private LocationEngineConductor locationEngineConductor;
private NavigationViewEventDispatcher navigationViewEventDispatcher;
private NavigationInstructionPlayer instructionPlayer;
private NavigationSpeechPlayer instructionPlayer;
private ConnectivityManager connectivityManager;
private RouteProgress routeProgress;
private String feedbackId;
Expand Down Expand Up @@ -212,9 +215,19 @@ private void initUnitType(NavigationUiOptions options) {
unitType = options.directionsRoute().routeOptions().voiceUnits();
}

private void initTimeFormat(MapboxNavigationOptions options) {
timeFormatType = options.timeFormatType();
}

private void initVoiceInstructions(NavigationViewOptions options) {
boolean languageSupported = options.directionsRoute().voiceLanguage() != null;
instructionPlayer = new NavigationInstructionPlayer(getApplication(), language, languageSupported, accessToken);
boolean isVoiceLanguageSupported = options.directionsRoute().voiceLanguage() != null;
SpeechPlayerProvider speechPlayerProvider = initializeSpeechPlayerProvider(isVoiceLanguageSupported);
instructionPlayer = new NavigationSpeechPlayer(speechPlayerProvider);
}

@NonNull
private SpeechPlayerProvider initializeSpeechPlayerProvider(boolean voiceLanguageSupported) {
return new SpeechPlayerProvider(getApplication(), language, voiceLanguageSupported, accessToken);
}

private void initNavigation(Context context, MapboxNavigationOptions options) {
Expand All @@ -238,10 +251,6 @@ private void addMilestones(NavigationViewOptions options) {
}
}

private void initTimeFormat(MapboxNavigationOptions options) {
timeFormatType = options.timeFormatType();
}

private ProgressChangeListener progressChangeListener = new ProgressChangeListener() {
@Override
public void onProgressChange(Location location, RouteProgress routeProgress) {
Expand All @@ -267,7 +276,9 @@ public void userOffRoute(Location location) {
@Override
public void onMilestoneEvent(RouteProgress routeProgress, String instruction, Milestone milestone) {
if (milestone instanceof VoiceInstructionMilestone) {
instructionPlayer.play((VoiceInstructionMilestone) milestone);
SpeechAnnouncement speechAnnouncement = SpeechAnnouncement.builder()
.voiceInstructionMilestone((VoiceInstructionMilestone) milestone).build();
instructionPlayer.play(speechAnnouncement);
}
updateBannerInstruction(routeProgress, milestone);
sendEventArrival(routeProgress, milestone);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,27 +17,28 @@
*
* @since 0.6.0
*/
class AndroidSpeechPlayer implements InstructionPlayer {
class AndroidSpeechPlayer implements SpeechPlayer {

private static final String DEFAULT_UTTERANCE_ID = "default_id";

private TextToSpeech textToSpeech;
private SpeechListener speechListener;

private boolean isMuted;
private boolean languageSupported = false;
private InstructionListener instructionListener;

/**
* Creates an instance of {@link AndroidSpeechPlayer}.
*
* @param context used to create an instance of {@link TextToSpeech}
* @param context used to create an instance of {@link TextToSpeech}
* @param language to initialize locale to set
* @since 0.6.0
*/
AndroidSpeechPlayer(Context context, final String language, final InstructionListener instructionListener) {
AndroidSpeechPlayer(Context context, final String language, final SpeechListener speechListener) {
textToSpeech = new TextToSpeech(context, new TextToSpeech.OnInitListener() {
@Override
public void onInit(int status) {
setInstructionListener(instructionListener);
setSpeechListener(speechListener);

boolean ableToInitialize = status != TextToSpeech.ERROR && language != null;
if (!ableToInitialize) {
Expand All @@ -52,11 +53,13 @@ public void onInit(int status) {
/**
* Plays the given voice instruction using TTS
*
* @param instruction voice instruction to be synthesized and played
* @param speechAnnouncement with voice instruction to be synthesized and played
*/
@Override
public void play(String instruction) {
boolean canPlay = languageSupported && !isMuted && !TextUtils.isEmpty(instruction);
public void play(SpeechAnnouncement speechAnnouncement) {
boolean isValidAnnouncement = speechAnnouncement != null
&& !TextUtils.isEmpty(speechAnnouncement.announcement());
boolean canPlay = isValidAnnouncement && languageSupported && !isMuted;
if (!canPlay) {
return;
}
Expand All @@ -65,7 +68,7 @@ public void play(String instruction) {

HashMap<String, String> params = new HashMap<>(1);
params.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, DEFAULT_UTTERANCE_ID);
textToSpeech.speak(instruction, TextToSpeech.QUEUE_ADD, params);
textToSpeech.speak(speechAnnouncement.announcement(), TextToSpeech.QUEUE_ADD, params);
}

/**
Expand Down Expand Up @@ -129,17 +132,17 @@ private void initializeWithLanguage(Locale language) {

private void fireInstructionListenerIfApi14() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) {
instructionListener.onStart();
speechListener.onStart();
}
}

private void setInstructionListener(final InstructionListener instructionListener) {
this.instructionListener = instructionListener;
private void setSpeechListener(final SpeechListener speechListener) {
this.speechListener = speechListener;

if (Build.VERSION.SDK_INT < Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) {
textToSpeech.setOnUtteranceCompletedListener(new Api14UtteranceListener(instructionListener));
textToSpeech.setOnUtteranceCompletedListener(new Api14UtteranceListener(speechListener));
} else {
textToSpeech.setOnUtteranceProgressListener(new UtteranceListener(instructionListener));
textToSpeech.setOnUtteranceProgressListener(new UtteranceListener(speechListener));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@
import android.speech.tts.TextToSpeech;

class Api14UtteranceListener implements TextToSpeech.OnUtteranceCompletedListener {
private InstructionListener instructionListener;
private SpeechListener speechListener;

Api14UtteranceListener(InstructionListener instructionListener) {
this.instructionListener = instructionListener;
Api14UtteranceListener(SpeechListener speechListener) {
this.speechListener = speechListener;
}

@Override
public void onUtteranceCompleted(String utteranceId) {
instructionListener.onDone();
speechListener.onDone();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.mapbox.services.android.navigation.ui.v5.voice;

import android.media.AudioFocusRequest;
import android.media.AudioManager;
import android.os.Build;
import android.support.annotation.RequiresApi;

@RequiresApi(api = Build.VERSION_CODES.O)
class Api26AudioFocusDelegate implements AudioFocusDelegate {

private static final int FOCUS_GAIN = AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK;

private final AudioManager audioManager;
private final AudioFocusRequest audioFocusRequest;

Api26AudioFocusDelegate(AudioManager audioManager) {
this.audioManager = audioManager;
audioFocusRequest = new AudioFocusRequest.Builder(FOCUS_GAIN).build();
}

@Override
public void requestFocus() {
audioManager.requestAudioFocus(audioFocusRequest);
}

@Override
public void abandonFocus() {
audioManager.abandonAudioFocusRequest(audioFocusRequest);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.mapbox.services.android.navigation.ui.v5.voice;

interface AudioFocusDelegate {

void requestFocus();

void abandonFocus();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.mapbox.services.android.navigation.ui.v5.voice;

import android.media.AudioManager;
import android.os.Build;

class AudioFocusDelegateProvider {

private final AudioFocusDelegate audioFocusDelegate;

AudioFocusDelegateProvider(AudioManager audioManager) {
audioFocusDelegate = buildAudioFocusDelegate(audioManager);
}

AudioFocusDelegate retrieveAudioFocusDelegate() {
return audioFocusDelegate;
}

private AudioFocusDelegate buildAudioFocusDelegate(AudioManager audioManager) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
return new Api26AudioFocusDelegate(audioManager);
}
return new SpeechAudioFocusDelegate(audioManager);
}
}

This file was deleted.

Loading

0 comments on commit 99d5a66

Please sign in to comment.