forked from organicmaps/organicmaps
[android] refactor: TTS refactored.
This commit is contained in:
parent
ec1de77a33
commit
b194d3d271
12 changed files with 325 additions and 165 deletions
|
@ -171,8 +171,7 @@
|
|||
android:name="com.mapswithme.maps.MwmActivity"
|
||||
android:launchMode="singleTask"
|
||||
android:theme="@style/MwmTheme.MainActivity"
|
||||
android:windowSoftInputMode="stateAlwaysHidden|adjustPan">
|
||||
</activity>
|
||||
android:windowSoftInputMode="stateAlwaysHidden|adjustPan"/>
|
||||
|
||||
<activity
|
||||
android:name="com.mapswithme.country.DownloadActivity"
|
||||
|
|
|
@ -13,13 +13,13 @@ extern "C"
|
|||
JNIEXPORT void JNICALL
|
||||
Java_com_mapswithme_maps_sound_TtsPlayer_nativeEnableTurnNotifications(JNIEnv * env, jclass thiz, jboolean enable)
|
||||
{
|
||||
return frm()->EnableTurnNotifications(enable == JNI_TRUE ? true : false);
|
||||
return frm()->EnableTurnNotifications(static_cast<bool>(enable));
|
||||
}
|
||||
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_com_mapswithme_maps_sound_TtsPlayer_nativeAreTurnNotificationsEnabled(JNIEnv * env, jclass clazz)
|
||||
{
|
||||
return frm()->AreTurnNotificationsEnabled() ? JNI_TRUE : JNI_FALSE;
|
||||
return static_cast<jboolean>(frm()->AreTurnNotificationsEnabled());
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
|
|
80
android/res/values/strings-tts.xml
Normal file
80
android/res/values/strings-tts.xml
Normal file
|
@ -0,0 +1,80 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<!--
|
||||
Supported voices. Should have language2[-country2][:code] format.
|
||||
Where:
|
||||
language2 - two-letter ISO 639-1 language code.
|
||||
country2 - two-letter ISO 3166-1 (alpha-2) country code.
|
||||
code - internal language code to be set in the core.
|
||||
If not specified, language2 is used.
|
||||
|
||||
Chinese is an exception. Matching is based on ISO 3166-1 (alpha-3) country code:
|
||||
zho_TWN, zho_MAC and zho_HKG correspond to zh-Hant.
|
||||
Otherwise we consider that this is zh-Hans.
|
||||
|
||||
TODO: Move language list to core.
|
||||
-->
|
||||
<string-array name="tts_languages_supported"
|
||||
translatable="false">
|
||||
<item>en</item>
|
||||
<item>ru</item>
|
||||
<item>pl</item>
|
||||
<item>sv</item>
|
||||
<item>tr</item>
|
||||
<item>fr</item>
|
||||
<item>nl</item>
|
||||
<item>de</item>
|
||||
<item>ar</item>
|
||||
<item>el</item>
|
||||
<item>it</item>
|
||||
<item>cs</item>
|
||||
<item>hu</item>
|
||||
<item>ro</item>
|
||||
<item>ja</item>
|
||||
<item>da</item>
|
||||
<item>es</item>
|
||||
<item>fi</item>
|
||||
<item>hi</item>
|
||||
<item>hr</item>
|
||||
<item>id</item>
|
||||
<item>ko</item>
|
||||
<item>pt</item>
|
||||
<item>sk</item>
|
||||
<item>sw</item>
|
||||
<item>th</item>
|
||||
<item>zh-tw:zh-Hant</item>
|
||||
<item>zh-cn:zh-Hans</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="tts_language_names"
|
||||
translatable="false">
|
||||
<item>English</item>
|
||||
<item>Русский</item>
|
||||
<item>Polski</item>
|
||||
<item>Svenska</item>
|
||||
<item>Türkçe</item>
|
||||
<item>Français</item>
|
||||
<item>Nederlands</item>
|
||||
<item>Deutsch</item>
|
||||
<item>العربية</item>
|
||||
<item>Ελληνικά</item>
|
||||
<item>Italiano</item>
|
||||
<item>Čeština</item>
|
||||
<item>Magyar</item>
|
||||
<item>Română</item>
|
||||
<item>日本語</item>
|
||||
<item>Dansk</item>
|
||||
<item>Español</item>
|
||||
<item>Suomi</item>
|
||||
<item>हिन्दी</item>
|
||||
<item>Hrvatski</item>
|
||||
<item>TODO: Indonesian</item>
|
||||
<item>한국어</item>
|
||||
<item>Português</item>
|
||||
<item>Slovenčina</item>
|
||||
<item>Kiswahili</item>
|
||||
<item>ไทย</item>
|
||||
<item>TODO: Chinese Traditional</item>
|
||||
<item>TODO: Chinese Simplified</item>
|
||||
</string-array>
|
||||
</resources>
|
|
@ -767,14 +767,13 @@ public class MwmActivity extends BaseMwmFragmentActivity
|
|||
{
|
||||
super.onStart();
|
||||
|
||||
TtsPlayer.INSTANCE.reinitIfLocaleChanged();
|
||||
if (!mIsFragmentContainer)
|
||||
popFragment();
|
||||
}
|
||||
|
||||
private void adjustZoomButtons(boolean routingActive)
|
||||
{
|
||||
boolean show = (routingActive || Config.getShowZoomButtons());
|
||||
boolean show = (routingActive || Config.showZoomButtons());
|
||||
UiUtils.showIf(show, mBtnZoomIn, mBtnZoomOut);
|
||||
|
||||
if (!show)
|
||||
|
|
|
@ -1,16 +1,17 @@
|
|||
package com.mapswithme.maps;
|
||||
|
||||
import android.app.Application;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.pm.PackageManager.NameNotFoundException;
|
||||
import android.os.Environment;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.util.Log;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.mapswithme.country.ActiveCountryTree;
|
||||
import com.mapswithme.country.CountryItem;
|
||||
import com.mapswithme.maps.background.Notifier;
|
||||
import com.mapswithme.maps.bookmarks.data.BookmarkManager;
|
||||
import com.mapswithme.maps.sound.TtsPlayer;
|
||||
import com.mapswithme.util.Config;
|
||||
import com.mapswithme.util.Constants;
|
||||
import com.mapswithme.util.UiUtils;
|
||||
|
@ -24,7 +25,8 @@ import com.parse.SaveCallback;
|
|||
|
||||
import java.io.File;
|
||||
|
||||
public class MwmApplication extends android.app.Application implements ActiveCountryTree.ActiveCountryListener
|
||||
public class MwmApplication extends Application
|
||||
implements ActiveCountryTree.ActiveCountryListener
|
||||
{
|
||||
private final static String TAG = "MwmApplication";
|
||||
|
||||
|
@ -32,32 +34,32 @@ public class MwmApplication extends android.app.Application implements ActiveCou
|
|||
private static final String PREF_PARSE_DEVICE_TOKEN = "ParseDeviceToken";
|
||||
private static final String PREF_PARSE_INSTALLATION_ID = "ParseInstallationId";
|
||||
|
||||
private static MwmApplication mSelf;
|
||||
private static MwmApplication sSelf;
|
||||
private static SharedPreferences sPrefs;
|
||||
private final Gson mGson = new Gson();
|
||||
private static SharedPreferences mPrefs;
|
||||
|
||||
private boolean mAreCountersInitialised;
|
||||
private boolean mAreCountersInitialized;
|
||||
private boolean mIsFrameworkInitialized;
|
||||
|
||||
public MwmApplication()
|
||||
{
|
||||
super();
|
||||
mSelf = this;
|
||||
sSelf = this;
|
||||
}
|
||||
|
||||
public static MwmApplication get()
|
||||
{
|
||||
return mSelf;
|
||||
return sSelf;
|
||||
}
|
||||
|
||||
public static Gson gson()
|
||||
{
|
||||
return mSelf.mGson;
|
||||
return sSelf.mGson;
|
||||
}
|
||||
|
||||
public static SharedPreferences prefs()
|
||||
{
|
||||
return mPrefs;
|
||||
return sPrefs;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -92,10 +94,10 @@ public class MwmApplication extends android.app.Application implements ActiveCou
|
|||
super.onCreate();
|
||||
|
||||
initParse();
|
||||
mPrefs = getSharedPreferences(getString(R.string.pref_file_name), MODE_PRIVATE);
|
||||
sPrefs = getSharedPreferences(getString(R.string.pref_file_name), MODE_PRIVATE);
|
||||
}
|
||||
|
||||
public synchronized void initNativeCore()
|
||||
public void initNativeCore()
|
||||
{
|
||||
if (mIsFrameworkInitialized)
|
||||
return;
|
||||
|
@ -107,6 +109,7 @@ public class MwmApplication extends android.app.Application implements ActiveCou
|
|||
ActiveCountryTree.addListener(this);
|
||||
initNativeStrings();
|
||||
BookmarkManager.getIcons(); // init BookmarkManager (automatically loads bookmarks)
|
||||
TtsPlayer.INSTANCE.init(this);
|
||||
mIsFrameworkInitialized = true;
|
||||
}
|
||||
|
||||
|
@ -226,9 +229,9 @@ public class MwmApplication extends android.app.Application implements ActiveCou
|
|||
|
||||
public void initCounters()
|
||||
{
|
||||
if (!mAreCountersInitialised)
|
||||
if (!mAreCountersInitialized)
|
||||
{
|
||||
mAreCountersInitialised = true;
|
||||
mAreCountersInitialized = true;
|
||||
Config.updateLaunchCounter();
|
||||
PreferenceManager.setDefaultValues(this, R.xml.prefs_misc, false);
|
||||
}
|
||||
|
|
|
@ -15,7 +15,6 @@ import android.text.TextUtils;
|
|||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.mapswithme.country.ActiveCountryTree;
|
||||
import com.mapswithme.country.CountrySuggestFragment;
|
||||
import com.mapswithme.maps.Framework;
|
||||
|
@ -24,7 +23,6 @@ import com.mapswithme.maps.R;
|
|||
import com.mapswithme.maps.base.BaseMwmFragment;
|
||||
import com.mapswithme.maps.base.OnBackPressListener;
|
||||
import com.mapswithme.maps.location.LocationHelper;
|
||||
import com.mapswithme.maps.sound.TtsPlayer;
|
||||
import com.mapswithme.maps.widget.SearchToolbarController;
|
||||
import com.mapswithme.util.InputUtils;
|
||||
import com.mapswithme.util.Language;
|
||||
|
@ -82,7 +80,7 @@ public class SearchFragment extends BaseMwmFragment
|
|||
}
|
||||
|
||||
// TODO: This code only for demonstration purposes and will be removed soon
|
||||
if (trySwitchOnTurnSound(query) || tryChangeMapStyle(query))
|
||||
if (tryChangeMapStyle(query))
|
||||
return;
|
||||
|
||||
runSearch();
|
||||
|
@ -333,20 +331,6 @@ public class SearchFragment extends BaseMwmFragment
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean trySwitchOnTurnSound(String query)
|
||||
{
|
||||
final boolean sound = "?sound".equals(query);
|
||||
final boolean nosound = "?nosound".equals(query);
|
||||
|
||||
if (!sound && !nosound)
|
||||
return false;
|
||||
|
||||
hideSearch();
|
||||
TtsPlayer.INSTANCE.enable(sound);
|
||||
|
||||
return sound;
|
||||
}
|
||||
// FIXME END
|
||||
|
||||
protected void showSingleResultOnMap(int resultIndex)
|
||||
|
|
|
@ -87,7 +87,7 @@ public class MapPrefsFragment extends BaseXmlSettingsFragment
|
|||
});
|
||||
|
||||
pref = findPreference(getString(R.string.pref_show_zoom_buttons));
|
||||
((SwitchPreference)pref).setChecked(Config.getShowZoomButtons());
|
||||
((SwitchPreference)pref).setChecked(Config.showZoomButtons());
|
||||
pref.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener()
|
||||
{
|
||||
@Override
|
||||
|
|
71
android/src/com/mapswithme/maps/sound/LanguageData.java
Normal file
71
android/src/com/mapswithme/maps/sound/LanguageData.java
Normal file
|
@ -0,0 +1,71 @@
|
|||
package com.mapswithme.maps.sound;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
public class LanguageData
|
||||
{
|
||||
public final Locale locale;
|
||||
public final String name;
|
||||
public final String internalCode;
|
||||
|
||||
private int mStatus;
|
||||
|
||||
private LanguageData(String name, Locale locale, String internalCode)
|
||||
{
|
||||
this.locale = locale;
|
||||
this.name = name;
|
||||
this.internalCode = internalCode;
|
||||
}
|
||||
|
||||
static LanguageData parse(String line, String name)
|
||||
{
|
||||
String[] parts = line.split(":");
|
||||
String internalCode = (parts.length > 1 ? parts[1] : null);
|
||||
|
||||
parts = parts[0].split("-");
|
||||
String language = parts[0];
|
||||
String country = (parts.length > 1 ? parts[1] : "");
|
||||
Locale locale = new Locale(language, country.toUpperCase());
|
||||
|
||||
return new LanguageData(name, locale, (internalCode == null ? language : internalCode));
|
||||
}
|
||||
|
||||
void setStatus(int status)
|
||||
{
|
||||
mStatus = status;
|
||||
}
|
||||
|
||||
public int getStatus()
|
||||
{
|
||||
return mStatus;
|
||||
}
|
||||
|
||||
public boolean matchesLocale(Locale locale)
|
||||
{
|
||||
String lang = locale.getLanguage();
|
||||
if (!lang.equals(this.locale.getLanguage()))
|
||||
return false;
|
||||
|
||||
if ("zh".equals(lang) && "zh-Hant".equals(internalCode))
|
||||
{
|
||||
// Chinese is a special case
|
||||
String country = locale.getCountry();
|
||||
return "TW".equals(country) ||
|
||||
"MO".equals(country) ||
|
||||
"HK".equals(country);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean matchesInternalCode(String internalCode)
|
||||
{
|
||||
return this.internalCode.equals(internalCode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "(" + mStatus + ") " + name + ": " + locale + ", internal: " + internalCode;
|
||||
}
|
||||
}
|
|
@ -1,14 +1,18 @@
|
|||
package com.mapswithme.maps.sound;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.speech.tts.TextToSpeech;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.mapswithme.maps.Framework;
|
||||
import com.mapswithme.maps.MwmApplication;
|
||||
import com.mapswithme.util.Language;
|
||||
import com.mapswithme.maps.R;
|
||||
import com.mapswithme.util.Config;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
|
||||
|
@ -16,143 +20,148 @@ public enum TtsPlayer
|
|||
{
|
||||
INSTANCE;
|
||||
|
||||
private static final String TAG = "TtsPlayer";
|
||||
private static final Locale DEFAULT_LOCALE = Locale.US;
|
||||
private static final float SPEECH_RATE = 1.2f;
|
||||
|
||||
// The both mTtts and mTtsLocale should be initialized before usage.
|
||||
private TextToSpeech mTts;
|
||||
private Locale mTtsLocale;
|
||||
private boolean mIsLocaleChanging;
|
||||
private boolean mInitializing;
|
||||
|
||||
private final static String TAG = "TtsPlayer";
|
||||
// TTS is locked down due to lack of supported languages
|
||||
private boolean mUnavailable;
|
||||
|
||||
TtsPlayer() {}
|
||||
|
||||
public void reinitIfLocaleChanged()
|
||||
private @Nullable LanguageData findSupportedLanguage(String internalCode, List<LanguageData> langs)
|
||||
{
|
||||
if (!isValid())
|
||||
return; // TtsPlayer was not inited yet.
|
||||
if (TextUtils.isEmpty(internalCode))
|
||||
return null;
|
||||
|
||||
final Locale locale = getDefaultLocale();
|
||||
if (!isLocaleEqual(locale))
|
||||
initTts(locale);
|
||||
for (LanguageData lang : langs)
|
||||
if (lang.matchesInternalCode(internalCode))
|
||||
return lang;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private Locale getDefaultLocale()
|
||||
private @Nullable LanguageData findSupportedLanguage(Locale locale, List<LanguageData> langs)
|
||||
{
|
||||
final Locale locale = Locale.getDefault();
|
||||
return locale == null ? DEFAULT_LOCALE : locale;
|
||||
if (locale == null)
|
||||
return null;
|
||||
|
||||
for (LanguageData lang : langs)
|
||||
if (lang.matchesLocale(locale))
|
||||
return lang;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean isLocaleEqual(Locale locale)
|
||||
private void setLanguageInternal(LanguageData lang)
|
||||
{
|
||||
return locale.getLanguage().equals(mTtsLocale.getLanguage()) &&
|
||||
locale.getCountry().equals(mTtsLocale.getCountry());
|
||||
mTts.setLanguage(lang.locale);
|
||||
nativeSetTurnNotificationsLocale(lang.internalCode);
|
||||
Config.setTtsLanguage(lang.internalCode);
|
||||
}
|
||||
|
||||
private boolean isLocaleAvailable(Locale locale)
|
||||
public void setLanguage(LanguageData lang)
|
||||
{
|
||||
final int avail = mTts.isLanguageAvailable(locale);
|
||||
return avail == TextToSpeech.LANG_AVAILABLE || avail == TextToSpeech.LANG_COUNTRY_AVAILABLE ||
|
||||
avail == TextToSpeech.LANG_COUNTRY_VAR_AVAILABLE;
|
||||
if (lang != null)
|
||||
setLanguageInternal(lang);
|
||||
}
|
||||
|
||||
private void initTts(final Locale locale)
|
||||
private LanguageData getDefaultLanguage(List<LanguageData> langs)
|
||||
{
|
||||
if (mIsLocaleChanging)
|
||||
return; // Preventing reiniting while creating TextToSpeech object. There's a small possibility a new locale is skipped.
|
||||
Locale defLocale = Locale.getDefault();
|
||||
if (defLocale == null)
|
||||
defLocale = DEFAULT_LOCALE;
|
||||
|
||||
if (mTts != null && mTtsLocale != null && mTtsLocale.equals(locale))
|
||||
return;
|
||||
|
||||
mTtsLocale = null;
|
||||
mIsLocaleChanging = true;
|
||||
|
||||
if (mTts != null)
|
||||
LanguageData lang = findSupportedLanguage(defLocale, langs);
|
||||
if (lang == null)
|
||||
{
|
||||
mTts.stop();
|
||||
mTts.shutdown();
|
||||
// No supported languages found, lock down TTS :(
|
||||
mUnavailable = true;
|
||||
Config.setTtsEnabled(false);
|
||||
}
|
||||
|
||||
mTts = new TextToSpeech(MwmApplication.get(), new TextToSpeech.OnInitListener()
|
||||
return lang;
|
||||
}
|
||||
|
||||
public LanguageData getSelectedLanguage(List<LanguageData> langs)
|
||||
{
|
||||
return findSupportedLanguage(Config.getTtsLanguage(), langs);
|
||||
}
|
||||
|
||||
public void init(Context context)
|
||||
{
|
||||
if (mTts != null || mInitializing || mUnavailable)
|
||||
return;
|
||||
|
||||
mInitializing = true;
|
||||
mTts = new TextToSpeech(context, new TextToSpeech.OnInitListener()
|
||||
{
|
||||
@Override
|
||||
public void onInit(int status)
|
||||
{
|
||||
// This method is called asynchronously.
|
||||
mIsLocaleChanging = false;
|
||||
if (status == TextToSpeech.ERROR)
|
||||
{
|
||||
Log.w(TAG, "Can't initialize TextToSpeech for locale " + locale.getLanguage() + " " + locale.getCountry());
|
||||
Log.e(TAG, "Failed to initialize TextToSpeach");
|
||||
mUnavailable = true;
|
||||
mInitializing = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (isLocaleAvailable(locale))
|
||||
{
|
||||
Log.i(TAG, "The locale " + locale.getLanguage() + " " + locale.getCountry() + " will be used for TTS.");
|
||||
mTtsLocale = locale;
|
||||
}
|
||||
else if (isLocaleAvailable(DEFAULT_LOCALE))
|
||||
{
|
||||
Log.w(TAG, "TTS is not available for locale " + locale.getLanguage() + " " + locale.getCountry() +
|
||||
". The default locale " + DEFAULT_LOCALE.getLanguage() + " " + DEFAULT_LOCALE.getCountry() + " will be used.");
|
||||
mTtsLocale = DEFAULT_LOCALE;
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.w(TAG, "TTS is not available for locale " + locale.getLanguage() + " " + locale.getCountry() +
|
||||
" and for the default locale " + DEFAULT_LOCALE.getLanguage() + " " + DEFAULT_LOCALE.getCountry() +
|
||||
". TTS will be switched off.");
|
||||
mTtsLocale = null;
|
||||
return;
|
||||
}
|
||||
List<LanguageData> langs = getAvailableLanguages(false);
|
||||
LanguageData defLang = getDefaultLanguage(langs);
|
||||
LanguageData lang = getSelectedLanguage(langs);
|
||||
if (lang == null)
|
||||
lang = defLang;
|
||||
|
||||
String localeTwine = Language.localeToTwineLanguage(mTtsLocale);
|
||||
if (TextUtils.isEmpty(localeTwine))
|
||||
if (lang != null)
|
||||
{
|
||||
Log.w(TAG, "Cann't get a twine language name for the locale " + locale.getLanguage() + " " + locale.getCountry() +
|
||||
". TTS will be switched off.");
|
||||
mTtsLocale = null;
|
||||
return;
|
||||
String curLangCode = Config.getTtsLanguage();
|
||||
if (defLang != null && !defLang.matchesInternalCode(curLangCode))
|
||||
{
|
||||
// Selected TTS locale does not match current defaults. And it was NOT set by user.
|
||||
// Assume that the current locale was equal to old default one.
|
||||
// So, let the new default locale be current.
|
||||
if (!Config.isTtsLanguageSetByUser())
|
||||
lang = findSupportedLanguage(defLang.internalCode, langs);
|
||||
}
|
||||
|
||||
setLanguage(lang);
|
||||
}
|
||||
|
||||
mTts.setSpeechRate(SPEECH_RATE);
|
||||
nativeSetTurnNotificationsLocale(localeTwine);
|
||||
mTts.setLanguage(mTtsLocale);
|
||||
Log.i(TAG, "setLocaleIfAvailable() onInit nativeSetTurnNotificationsLocale(" + localeTwine + ")");
|
||||
setEnabled(Config.isTtsEnabled());
|
||||
mInitializing = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private boolean isValid()
|
||||
public boolean isReady()
|
||||
{
|
||||
return !mIsLocaleChanging && mTts != null && mTtsLocale != null;
|
||||
return (mTts != null && !mUnavailable && !mInitializing);
|
||||
}
|
||||
|
||||
private void speak(String textToSpeak)
|
||||
{
|
||||
// @TODO(vbykoianko) removes these two toasts below when the test period is finished.
|
||||
Toast.makeText(MwmApplication.get(), textToSpeak, Toast.LENGTH_SHORT).show();
|
||||
if (mTts.speak(textToSpeak, TextToSpeech.QUEUE_ADD, null) == TextToSpeech.ERROR)
|
||||
{
|
||||
Log.e(TAG, "TextToSpeech returns TextToSpeech.ERROR.");
|
||||
Toast.makeText(MwmApplication.get(), "TTS error", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
//noinspection deprecation
|
||||
mTts.speak(textToSpeak, TextToSpeech.QUEUE_ADD, null);
|
||||
}
|
||||
|
||||
public void playTurnNotifications()
|
||||
{
|
||||
// It's necessary to call Framework.nativeGenerateTurnNotifications() even if TtsPlayer is invalid.
|
||||
final String[] turnNotifications = Framework.nativeGenerateTurnNotifications();
|
||||
|
||||
if (turnNotifications != null && isValid())
|
||||
|
||||
if (turnNotifications != null && isReady())
|
||||
for (String textToSpeak : turnNotifications)
|
||||
speak(textToSpeak);
|
||||
}
|
||||
|
||||
public void stop()
|
||||
{
|
||||
if(mTts != null)
|
||||
if (isReady())
|
||||
mTts.stop();
|
||||
}
|
||||
|
||||
|
@ -161,18 +170,40 @@ public enum TtsPlayer
|
|||
return nativeAreTurnNotificationsEnabled();
|
||||
}
|
||||
|
||||
// Note. After a call of enable(true) the flag enabled in cpp core will be set.
|
||||
// But later in onInit callback the initialization could fail.
|
||||
// In that case isValid() returns false and every call of playTurnNotifications returns in the beginning.
|
||||
public void enable(boolean enabled)
|
||||
public void setEnabled(boolean enabled)
|
||||
{
|
||||
if (enabled && !isValid())
|
||||
initTts(getDefaultLocale());
|
||||
nativeEnableTurnNotifications(enabled);
|
||||
}
|
||||
|
||||
public List<LanguageData> getAvailableLanguages(boolean includeDownloadable)
|
||||
{
|
||||
List<LanguageData> res = new ArrayList<>();
|
||||
if (mUnavailable || mTts == null)
|
||||
return res;
|
||||
|
||||
Resources resources = MwmApplication.get().getResources();
|
||||
String[] codes = resources.getStringArray(R.array.tts_languages_supported);
|
||||
String[] names = resources.getStringArray(R.array.tts_language_names);
|
||||
|
||||
for (int i = 0; i < codes.length; i++)
|
||||
{
|
||||
LanguageData lang = LanguageData.parse(codes[i], names[i]);
|
||||
int status = mTts.isLanguageAvailable(lang.locale);
|
||||
|
||||
int requiredStatus = (includeDownloadable ? TextToSpeech.LANG_MISSING_DATA
|
||||
: TextToSpeech.LANG_AVAILABLE);
|
||||
if (status >= requiredStatus)
|
||||
{
|
||||
lang.setStatus(status);
|
||||
res.add(lang);
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
private native static void nativeEnableTurnNotifications(boolean enable);
|
||||
private native static boolean nativeAreTurnNotificationsEnabled();
|
||||
private native static void nativeSetTurnNotificationsLocale(String locale);
|
||||
private native static void nativeSetTurnNotificationsLocale(String code);
|
||||
private native static String nativeGetTurnNotificationsLocale();
|
||||
}
|
||||
|
|
|
@ -13,6 +13,10 @@ public final class Config
|
|||
private static final String KEY_APP_LAST_SESSION_TIMESTAMP = "LastSessionTimestamp";
|
||||
private static final String KEY_APP_FIRST_INSTALL_FLAVOR = "FirstInstallFlavor";
|
||||
|
||||
private static final String KEY_TTS_ENABLED = "TtsEnabled";
|
||||
private static final String KEY_TTS_LANGUAGE = "TtsLanguage";
|
||||
private static final String KEY_TTS_LANGUAGE_SET_BY_USER = "TtsLanguageSetByUser";
|
||||
|
||||
private static final String KEY_PREF_ZOOM_BUTTONS = "ZoomButtonsEnabled";
|
||||
private static final String KEY_PREF_STATISTICS = "StatisticsEnabled";
|
||||
|
||||
|
@ -167,7 +171,37 @@ public final class Config
|
|||
incrementSessionNumber();
|
||||
}
|
||||
|
||||
public static boolean getShowZoomButtons()
|
||||
public static boolean isTtsEnabled()
|
||||
{
|
||||
return getBool(KEY_TTS_ENABLED, true);
|
||||
}
|
||||
|
||||
public static void setTtsEnabled(boolean enabled)
|
||||
{
|
||||
setBool(KEY_TTS_ENABLED, enabled);
|
||||
}
|
||||
|
||||
public static boolean isTtsLanguageSetByUser()
|
||||
{
|
||||
return getBool(KEY_TTS_LANGUAGE_SET_BY_USER);
|
||||
}
|
||||
|
||||
public static void setTtsLanguageSetByUser()
|
||||
{
|
||||
setBool(KEY_TTS_LANGUAGE_SET_BY_USER, true);
|
||||
}
|
||||
|
||||
public static String getTtsLanguage()
|
||||
{
|
||||
return getString(KEY_TTS_LANGUAGE);
|
||||
}
|
||||
|
||||
public static void setTtsLanguage(String language)
|
||||
{
|
||||
setString(KEY_TTS_LANGUAGE, language);
|
||||
}
|
||||
|
||||
public static boolean showZoomButtons()
|
||||
{
|
||||
return getBool(KEY_PREF_ZOOM_BUTTONS, true);
|
||||
}
|
||||
|
|
|
@ -1,18 +1,14 @@
|
|||
package com.mapswithme.util;
|
||||
|
||||
import android.content.Context;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.view.inputmethod.InputMethodSubtype;
|
||||
|
||||
import com.mapswithme.maps.MwmApplication;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
public class Language
|
||||
{
|
||||
private final static String TAG = "Language";
|
||||
// Locale.getLanguage() returns even 3-letter codes, not that we need in the C++ core,
|
||||
// so we use locale itself, like zh_CN
|
||||
public static String getDefaultLocale()
|
||||
|
@ -34,41 +30,4 @@ public class Language
|
|||
|
||||
return getDefaultLocale();
|
||||
}
|
||||
|
||||
// Converts Locale to twine language name.
|
||||
// If locale can be converted returns a twine language name. For example zh-Hans, ru, en and so on.
|
||||
// If not returns an empty string.
|
||||
public static String localeToTwineLanguage(Locale locale)
|
||||
{
|
||||
if (locale == null)
|
||||
{
|
||||
Log.e(TAG, "localeToTwineLanguage was called with null Locale.");
|
||||
return "";
|
||||
}
|
||||
|
||||
final String chinese = Locale.CHINESE.getLanguage();
|
||||
final String language = locale.getLanguage();
|
||||
final String country = locale.getCountry();
|
||||
|
||||
if (chinese == null || language == null || country == null)
|
||||
{
|
||||
Log.e(TAG, "Methods Locale.getLanguage or Locale.getCountry return null.");
|
||||
return "";
|
||||
}
|
||||
|
||||
if (chinese.equals(language))
|
||||
{
|
||||
if (country.equals("TW") || country.equals("MO") || country.equals("HK"))
|
||||
{
|
||||
return "zh-Hant"; // Chinese traditional
|
||||
}
|
||||
return "zh-Hans"; // Chinese simplified
|
||||
}
|
||||
if (TextUtils.isEmpty(language))
|
||||
{
|
||||
Log.e(TAG, "locale.getLanguage() returns null or empty string.");
|
||||
return "";
|
||||
}
|
||||
return language;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue