| ### 1.52 (In Development) | ### 1.52 (In Development) | ||||
| android: | |||||
| * Added directBoot support -- beqabeqa473 | |||||
| updated languages: | updated languages: | ||||
| * ba (Bashkir) -- Andiv06 | * ba (Bashkir) -- Andiv06 | ||||
| * be (Belarusian) -- Andiv06, bespsm, Alaksiej Stankievič | * be (Belarusian) -- Andiv06, bespsm, Alaksiej Stankievič |
| android:required="false" /> | android:required="false" /> | ||||
| <application | <application | ||||
| android:name="com.reecedunn.espeak.EspeakApp" | |||||
| android:icon="@drawable/icon" | android:icon="@drawable/icon" | ||||
| android:theme="@style/AppTheme" | android:theme="@style/AppTheme" | ||||
| android:label="@string/app_name" > | android:label="@string/app_name" > | ||||
| <service | <service | ||||
| android:name=".TtsService" | android:name=".TtsService" | ||||
| android:label="@string/app_name" > | |||||
| android:label="@string/app_name" | |||||
| android:directBootAware="true"> | |||||
| <intent-filter> | <intent-filter> | ||||
| <action android:name="android.intent.action.TTS_SERVICE" /> | <action android:name="android.intent.action.TTS_SERVICE" /> | ||||
| /* | /* | ||||
| * Copyright (C) 2022 Beka Gozalishvili | |||||
| * Copyright (C) 2012-2013 Reece H. Dunn | * Copyright (C) 2012-2013 Reece H. Dunn | ||||
| * Copyright (C) 2009 The Android Open Source Project | * Copyright (C) 2009 The Android Open Source Project | ||||
| * | * | ||||
| protected void onCreate(Bundle savedInstanceState) { | protected void onCreate(Bundle savedInstanceState) { | ||||
| super.onCreate(savedInstanceState); | super.onCreate(savedInstanceState); | ||||
| Context storageContext = EspeakApp.getStorageContext(); | |||||
| ArrayList<String> availableLanguages = new ArrayList<String>(); | ArrayList<String> availableLanguages = new ArrayList<String>(); | ||||
| ArrayList<String> unavailableLanguages = new ArrayList<String>(); | ArrayList<String> unavailableLanguages = new ArrayList<String>(); | ||||
| boolean haveBaseResources = hasBaseResources(this); | |||||
| if (!haveBaseResources || canUpgradeResources(this)) { | |||||
| boolean haveBaseResources = hasBaseResources(storageContext); | |||||
| if (!haveBaseResources || canUpgradeResources(storageContext)) { | |||||
| if (!haveBaseResources) { | if (!haveBaseResources) { | ||||
| unavailableLanguages.add(Locale.ENGLISH.toString()); | unavailableLanguages.add(Locale.ENGLISH.toString()); | ||||
| } | } | ||||
| return; | return; | ||||
| } | } | ||||
| final SpeechSynthesis engine = new SpeechSynthesis(this, mSynthReadyCallback); | |||||
| final SpeechSynthesis engine = new SpeechSynthesis(storageContext, mSynthReadyCallback); | |||||
| final List<Voice> voices = engine.getAvailableVoices(); | final List<Voice> voices = engine.getAvailableVoices(); | ||||
| for (Voice voice : voices) { | for (Voice voice : voices) { |
| /* | /* | ||||
| * Copyright (C) 2022 Beka Gozalishvili | |||||
| * Copyright (C) 2012-2013 Reece H. Dunn | * Copyright (C) 2012-2013 Reece H. Dunn | ||||
| * Copyright (C) 2009 The Android Open Source Project | * Copyright (C) 2009 The Android Open Source Project | ||||
| * | * | ||||
| setContentView(R.layout.download_voice_data); | setContentView(R.layout.download_voice_data); | ||||
| mProgress = (ProgressBar)findViewById(R.id.progress); | mProgress = (ProgressBar)findViewById(R.id.progress); | ||||
| Context storageContext = EspeakApp.getStorageContext(); | |||||
| final File dataPath = CheckVoiceData.getDataPath(this).getParentFile(); | |||||
| final File dataPath = CheckVoiceData.getDataPath(storageContext).getParentFile(); | |||||
| mAsyncExtract = new AsyncExtract(this, R.raw.espeakdata, dataPath, mProgress) { | |||||
| mAsyncExtract = new AsyncExtract(storageContext, R.raw.espeakdata, dataPath, mProgress) { | |||||
| @Override | @Override | ||||
| protected void onPostExecute(Integer result) { | protected void onPostExecute(Integer result) { | ||||
| switch (result) { | switch (result) { |
| /* | |||||
| * Copyright (C) 2022 Beka Gozalishvili | |||||
| * | |||||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||||
| * you may not use this file except in compliance with the License. | |||||
| * You may obtain a copy of the License at | |||||
| * | |||||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||||
| * | |||||
| * Unless required by applicable law or agreed to in writing, software | |||||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
| * See the License for the specific language governing permissions and | |||||
| * limitations under the License. | |||||
| */ | |||||
| package com.reecedunn.espeak; | |||||
| import android.app.Application; | |||||
| import android.content.Context; | |||||
| import android.os.Build; | |||||
| public class EspeakApp extends Application { | |||||
| private static Context storageContext; | |||||
| public void onCreate() { | |||||
| super.onCreate(); | |||||
| Context appContext = getApplicationContext(); | |||||
| if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { | |||||
| EspeakApp.storageContext = appContext.createDeviceProtectedStorageContext(); | |||||
| } | |||||
| else { | |||||
| EspeakApp.storageContext = appContext; | |||||
| } | |||||
| } | |||||
| public static Context getStorageContext() { | |||||
| return EspeakApp.storageContext; | |||||
| } | |||||
| } |
| /* | /* | ||||
| * Copyright (C) 2022 Beka Gozalishvili | |||||
| * Copyright (C) 2012-2015 Reece H. Dunn | * Copyright (C) 2012-2015 Reece H. Dunn | ||||
| * Copyright (C) 2011 Google Inc. | * Copyright (C) 2011 Google Inc. | ||||
| * | * | ||||
| public static final String ESPEAK_INITIALIZED = "com.reecedunn.espeak.ESPEAK_INITIALIZED"; | public static final String ESPEAK_INITIALIZED = "com.reecedunn.espeak.ESPEAK_INITIALIZED"; | ||||
| private static final String TAG = TtsService.class.getSimpleName(); | private static final String TAG = TtsService.class.getSimpleName(); | ||||
| private static Context storageContext; | |||||
| private static final boolean DEBUG = false; | private static final boolean DEBUG = false; | ||||
| private SpeechSynthesis mEngine; | private SpeechSynthesis mEngine; | ||||
| @Override | @Override | ||||
| public void onCreate() { | public void onCreate() { | ||||
| storageContext = EspeakApp.getStorageContext(); | |||||
| storageContext.moveSharedPreferencesFrom(this, this.getPackageName() + "_preferences"); | |||||
| initializeTtsEngine(); | initializeTtsEngine(); | ||||
| super.onCreate(); | super.onCreate(); | ||||
| } | } | ||||
| mEngine = null; | mEngine = null; | ||||
| } | } | ||||
| mEngine = new SpeechSynthesis(this, mSynthCallback); | |||||
| mEngine = new SpeechSynthesis(storageContext, mSynthCallback); | |||||
| mAvailableVoices.clear(); | mAvailableVoices.clear(); | ||||
| for (Voice voice : mEngine.getAvailableVoices()) { | for (Voice voice : mEngine.getAvailableVoices()) { | ||||
| mAvailableVoices.put(voice.name, voice); | mAvailableVoices.put(voice.name, voice); | ||||
| } | } | ||||
| private Pair<Voice, Integer> findVoice(String language, String country, String variant) { | private Pair<Voice, Integer> findVoice(String language, String country, String variant) { | ||||
| if (!CheckVoiceData.hasBaseResources(this) || CheckVoiceData.canUpgradeResources(this)) { | |||||
| if (!CheckVoiceData.hasBaseResources(storageContext) || CheckVoiceData.canUpgradeResources(storageContext)) { | |||||
| if (mOnLanguagesDownloaded == null) { | if (mOnLanguagesDownloaded == null) { | ||||
| mOnLanguagesDownloaded = new BroadcastReceiver() { | mOnLanguagesDownloaded = new BroadcastReceiver() { | ||||
| @Override | @Override | ||||
| registerReceiver(mOnLanguagesDownloaded, filter); | registerReceiver(mOnLanguagesDownloaded, filter); | ||||
| } | } | ||||
| final Intent intent = new Intent(this, DownloadVoiceData.class); | |||||
| final Intent intent = new Intent(storageContext, DownloadVoiceData.class); | |||||
| intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); | intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); | ||||
| startActivity(intent); | startActivity(intent); | ||||
| mCallback = callback; | mCallback = callback; | ||||
| mCallback.start(mEngine.getSampleRate(), mEngine.getAudioFormat(), mEngine.getChannelCount()); | mCallback.start(mEngine.getSampleRate(), mEngine.getAudioFormat(), mEngine.getChannelCount()); | ||||
| final VoiceSettings settings = new VoiceSettings(PreferenceManager.getDefaultSharedPreferences(this), mEngine); | |||||
| final VoiceSettings settings = new VoiceSettings(PreferenceManager.getDefaultSharedPreferences(storageContext), mEngine); | |||||
| mEngine.setVoice(mMatchingVoice, settings.getVoiceVariant()); | mEngine.setVoice(mMatchingVoice, settings.getVoiceVariant()); | ||||
| mEngine.Rate.setValue(settings.getRate(), request.getSpeechRate()); | mEngine.Rate.setValue(settings.getRate(), request.getSpeechRate()); | ||||
| mEngine.Pitch.setValue(settings.getPitch(), request.getPitch()); | mEngine.Pitch.setValue(settings.getPitch(), request.getPitch()); |
| /* | /* | ||||
| * Copyright (C) 2022 Beka Gozalishvili | |||||
| * Copyright (C) 2013 Reece H. Dunn | * Copyright (C) 2013 Reece H. Dunn | ||||
| * Copyright (C) 2011 The Android Open Source Project | * Copyright (C) 2011 The Android Open Source Project | ||||
| * | * | ||||
| import com.reecedunn.espeak.preference.VoiceVariantPreference; | import com.reecedunn.espeak.preference.VoiceVariantPreference; | ||||
| public class TtsSettingsActivity extends PreferenceActivity { | public class TtsSettingsActivity extends PreferenceActivity { | ||||
| private static Context storageContext; | |||||
| @Override | @Override | ||||
| @SuppressWarnings("deprecation") | @SuppressWarnings("deprecation") | ||||
| protected void onCreate(Bundle savedInstanceState) { | protected void onCreate(Bundle savedInstanceState) { | ||||
| super.onCreate(savedInstanceState); | super.onCreate(savedInstanceState); | ||||
| PreferenceManager preferenceManager = getPreferenceManager(); | |||||
| preferenceManager.setStorageDeviceProtected (); | |||||
| // Migrate old eyes-free settings to the new settings: | // Migrate old eyes-free settings to the new settings: | ||||
| final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); | |||||
| storageContext = EspeakApp.getStorageContext(); | |||||
| final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(storageContext); | |||||
| final SharedPreferences.Editor editor = prefs.edit(); | final SharedPreferences.Editor editor = prefs.edit(); | ||||
| String pitch = prefs.getString(VoiceSettings.PREF_PITCH, null); | String pitch = prefs.getString(VoiceSettings.PREF_PITCH, null); | ||||
| String rate = prefs.getString(VoiceSettings.PREF_RATE, null); | String rate = prefs.getString(VoiceSettings.PREF_RATE, null); | ||||
| if (rate == null) { | if (rate == null) { | ||||
| // Try the old eyes-free setting: | // Try the old eyes-free setting: | ||||
| SpeechSynthesis engine = new SpeechSynthesis(this, null); | |||||
| SpeechSynthesis engine = new SpeechSynthesis(storageContext, null); | |||||
| int defaultValue = engine.Rate.getDefaultValue(); | int defaultValue = engine.Rate.getDefaultValue(); | ||||
| int maxValue = engine.Rate.getMaxValue(); | int maxValue = engine.Rate.getMaxValue(); | ||||
| pref.setMax(parameter.getMaxValue()); | pref.setMax(parameter.getMaxValue()); | ||||
| pref.setDefaultValue(defaultValue); | pref.setDefaultValue(defaultValue); | ||||
| final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); | |||||
| final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(storageContext); | |||||
| final String prefString = prefs.getString(key, null); | final String prefString = prefs.getString(key, null); | ||||
| if (prefString == null) { | if (prefString == null) { | ||||
| pref.setProgress(defaultValue); | pref.setProgress(defaultValue); | ||||
| * summary with the current entry value. | * summary with the current entry value. | ||||
| */ | */ | ||||
| private static void createPreferences(Context context, PreferenceGroup group) { | private static void createPreferences(Context context, PreferenceGroup group) { | ||||
| SpeechSynthesis engine = new SpeechSynthesis(context, null); | |||||
| VoiceSettings settings = new VoiceSettings(PreferenceManager.getDefaultSharedPreferences(context), engine); | |||||
| SpeechSynthesis engine = new SpeechSynthesis(storageContext, null); | |||||
| VoiceSettings settings = new VoiceSettings(PreferenceManager.getDefaultSharedPreferences(storageContext), engine); | |||||
| group.addPreference(createImportVoicePreference(context)); | group.addPreference(createImportVoicePreference(context)); | ||||
| group.addPreference(createVoiceVariantPreference(context, settings, R.string.espeak_variant)); | group.addPreference(createVoiceVariantPreference(context, settings, R.string.espeak_variant)); |
| /* | /* | ||||
| * Copyright (C) 2022 Beka Gozalishvili | |||||
| * Copyright (C) 2013 Reece H. Dunn | * Copyright (C) 2013 Reece H. Dunn | ||||
| * | * | ||||
| * Licensed under the Apache License, Version 2.0 (the "License"); | * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
| import android.content.DialogInterface; | import android.content.DialogInterface; | ||||
| import android.content.SharedPreferences; | import android.content.SharedPreferences; | ||||
| import android.preference.DialogPreference; | import android.preference.DialogPreference; | ||||
| import android.preference.PreferenceManager; | |||||
| import android.util.AttributeSet; | import android.util.AttributeSet; | ||||
| import android.view.View; | import android.view.View; | ||||
| import android.widget.Button; | import android.widget.Button; | ||||
| String text = Integer.toString(mProgress); | String text = Integer.toString(mProgress); | ||||
| callChangeListener(text); | callChangeListener(text); | ||||
| if (shouldCommit()) { | if (shouldCommit()) { | ||||
| PreferenceManager preferenceManager = getPreferenceManager(); | |||||
| preferenceManager.setStorageDeviceProtected (); | |||||
| SharedPreferences.Editor editor = getEditor(); | SharedPreferences.Editor editor = getEditor(); | ||||
| editor.putString(getKey(), text); | editor.putString(getKey(), text); | ||||
| editor.commit(); | editor.commit(); |
| /* | /* | ||||
| * Copyright (C) 2022 Beka Gozalishvili | |||||
| * Copyright (C) 2013 Reece H. Dunn | * Copyright (C) 2013 Reece H. Dunn | ||||
| * | * | ||||
| * Licensed under the Apache License, Version 2.0 (the "License"); | * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
| import android.content.DialogInterface; | import android.content.DialogInterface; | ||||
| import android.content.SharedPreferences; | import android.content.SharedPreferences; | ||||
| import android.preference.DialogPreference; | import android.preference.DialogPreference; | ||||
| import android.preference.PreferenceManager; | |||||
| import android.text.Editable; | import android.text.Editable; | ||||
| import android.util.AttributeSet; | import android.util.AttributeSet; | ||||
| import android.view.View; | import android.view.View; | ||||
| onDataChanged(level, characters); | onDataChanged(level, characters); | ||||
| if (shouldCommit()) { | if (shouldCommit()) { | ||||
| PreferenceManager preferenceManager = getPreferenceManager(); | |||||
| preferenceManager.setStorageDeviceProtected(); | |||||
| SharedPreferences.Editor editor = getEditor(); | SharedPreferences.Editor editor = getEditor(); | ||||
| if (editor != null) { | if (editor != null) { | ||||
| editor.putString(VoiceSettings.PREF_PUNCTUATION_CHARACTERS, characters); | editor.putString(VoiceSettings.PREF_PUNCTUATION_CHARACTERS, characters); |
| /* | /* | ||||
| * Copyright (C) 2022 Beka Gozalishvili | |||||
| * Copyright (C) 2013 Reece H. Dunn | * Copyright (C) 2013 Reece H. Dunn | ||||
| * | * | ||||
| * Licensed under the Apache License, Version 2.0 (the "License"); | * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
| import android.content.DialogInterface; | import android.content.DialogInterface; | ||||
| import android.content.SharedPreferences; | import android.content.SharedPreferences; | ||||
| import android.preference.DialogPreference; | import android.preference.DialogPreference; | ||||
| import android.preference.PreferenceManager; | |||||
| import android.util.AttributeSet; | import android.util.AttributeSet; | ||||
| import android.view.LayoutInflater; | import android.view.LayoutInflater; | ||||
| import android.view.View; | import android.view.View; | ||||
| case DialogInterface.BUTTON_POSITIVE: | case DialogInterface.BUTTON_POSITIVE: | ||||
| onDataChanged(); | onDataChanged(); | ||||
| if (shouldCommit()) { | if (shouldCommit()) { | ||||
| PreferenceManager preferenceManager = getPreferenceManager(); | |||||
| preferenceManager.setStorageDeviceProtected(); | |||||
| SharedPreferences.Editor editor = getEditor(); | SharedPreferences.Editor editor = getEditor(); | ||||
| if (editor != null) { | if (editor != null) { | ||||
| VoiceVariant variant = variants[mCategoryIndex][mVariantIndex].getVariant(); | VoiceVariant variant = variants[mCategoryIndex][mVariantIndex].getVariant(); |