From f7f66429a3d6057a98b9c5c9cb77b6d2c80e5573 Mon Sep 17 00:00:00 2001 From: Beqa Gozalishvili Date: Mon, 17 Oct 2022 16:53:53 +0400 Subject: [PATCH] Add directBoot support. Fixes #917 --- ChangeLog.md | 3 ++ android/AndroidManifest.xml | 4 +- .../com/reecedunn/espeak/CheckVoiceData.java | 8 ++-- .../reecedunn/espeak/DownloadVoiceData.java | 6 ++- .../src/com/reecedunn/espeak/EspeakApp.java | 41 +++++++++++++++++++ .../src/com/reecedunn/espeak/TtsService.java | 12 ++++-- .../reecedunn/espeak/TtsSettingsActivity.java | 18 +++++--- .../espeak/preference/SeekBarPreference.java | 4 ++ .../SpeakPunctuationPreference.java | 4 ++ .../preference/VoiceVariantPreference.java | 4 ++ 10 files changed, 89 insertions(+), 15 deletions(-) create mode 100644 android/src/com/reecedunn/espeak/EspeakApp.java diff --git a/ChangeLog.md b/ChangeLog.md index 5371d9ec..fb4f7c84 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -9,6 +9,9 @@ The espeak-ng project is a fork of the espeak project. ### 1.52 (In Development) +android: +* Added directBoot support -- beqabeqa473 + updated languages: * ba (Bashkir) -- Andiv06 * be (Belarusian) -- Andiv06, bespsm, Alaksiej Stankievič diff --git a/android/AndroidManifest.xml b/android/AndroidManifest.xml index c2a0ad99..9445005d 100644 --- a/android/AndroidManifest.xml +++ b/android/AndroidManifest.xml @@ -9,12 +9,14 @@ android:required="false" /> + android:label="@string/app_name" + android:directBootAware="true"> diff --git a/android/src/com/reecedunn/espeak/CheckVoiceData.java b/android/src/com/reecedunn/espeak/CheckVoiceData.java index 379f337a..70b17e5f 100644 --- a/android/src/com/reecedunn/espeak/CheckVoiceData.java +++ b/android/src/com/reecedunn/espeak/CheckVoiceData.java @@ -1,4 +1,5 @@ /* + * Copyright (C) 2022 Beka Gozalishvili * Copyright (C) 2012-2013 Reece H. Dunn * Copyright (C) 2009 The Android Open Source Project * @@ -83,11 +84,12 @@ public class CheckVoiceData extends Activity { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + Context storageContext = EspeakApp.getStorageContext(); ArrayList availableLanguages = new ArrayList(); ArrayList unavailableLanguages = new ArrayList(); - boolean haveBaseResources = hasBaseResources(this); - if (!haveBaseResources || canUpgradeResources(this)) { + boolean haveBaseResources = hasBaseResources(storageContext); + if (!haveBaseResources || canUpgradeResources(storageContext)) { if (!haveBaseResources) { unavailableLanguages.add(Locale.ENGLISH.toString()); } @@ -95,7 +97,7 @@ public class CheckVoiceData extends Activity { return; } - final SpeechSynthesis engine = new SpeechSynthesis(this, mSynthReadyCallback); + final SpeechSynthesis engine = new SpeechSynthesis(storageContext, mSynthReadyCallback); final List voices = engine.getAvailableVoices(); for (Voice voice : voices) { diff --git a/android/src/com/reecedunn/espeak/DownloadVoiceData.java b/android/src/com/reecedunn/espeak/DownloadVoiceData.java index 54183902..e5481495 100644 --- a/android/src/com/reecedunn/espeak/DownloadVoiceData.java +++ b/android/src/com/reecedunn/espeak/DownloadVoiceData.java @@ -1,4 +1,5 @@ /* + * Copyright (C) 2022 Beka Gozalishvili * Copyright (C) 2012-2013 Reece H. Dunn * Copyright (C) 2009 The Android Open Source Project * @@ -45,10 +46,11 @@ public class DownloadVoiceData extends Activity { setContentView(R.layout.download_voice_data); 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 protected void onPostExecute(Integer result) { switch (result) { diff --git a/android/src/com/reecedunn/espeak/EspeakApp.java b/android/src/com/reecedunn/espeak/EspeakApp.java new file mode 100644 index 00000000..ef7e93fe --- /dev/null +++ b/android/src/com/reecedunn/espeak/EspeakApp.java @@ -0,0 +1,41 @@ +/* + * 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; + } +} diff --git a/android/src/com/reecedunn/espeak/TtsService.java b/android/src/com/reecedunn/espeak/TtsService.java index ad10cc72..63b10716 100644 --- a/android/src/com/reecedunn/espeak/TtsService.java +++ b/android/src/com/reecedunn/espeak/TtsService.java @@ -1,4 +1,5 @@ /* + * Copyright (C) 2022 Beka Gozalishvili * Copyright (C) 2012-2015 Reece H. Dunn * Copyright (C) 2011 Google Inc. * @@ -61,6 +62,7 @@ public class TtsService extends TextToSpeechService { public static final String ESPEAK_INITIALIZED = "com.reecedunn.espeak.ESPEAK_INITIALIZED"; private static final String TAG = TtsService.class.getSimpleName(); + private static Context storageContext; private static final boolean DEBUG = false; private SpeechSynthesis mEngine; @@ -73,6 +75,8 @@ public class TtsService extends TextToSpeechService { @Override public void onCreate() { + storageContext = EspeakApp.getStorageContext(); + storageContext.moveSharedPreferencesFrom(this, this.getPackageName() + "_preferences"); initializeTtsEngine(); super.onCreate(); } @@ -94,7 +98,7 @@ public class TtsService extends TextToSpeechService { mEngine = null; } - mEngine = new SpeechSynthesis(this, mSynthCallback); + mEngine = new SpeechSynthesis(storageContext, mSynthCallback); mAvailableVoices.clear(); for (Voice voice : mEngine.getAvailableVoices()) { mAvailableVoices.put(voice.name, voice); @@ -118,7 +122,7 @@ public class TtsService extends TextToSpeechService { } private Pair findVoice(String language, String country, String variant) { - if (!CheckVoiceData.hasBaseResources(this) || CheckVoiceData.canUpgradeResources(this)) { + if (!CheckVoiceData.hasBaseResources(storageContext) || CheckVoiceData.canUpgradeResources(storageContext)) { if (mOnLanguagesDownloaded == null) { mOnLanguagesDownloaded = new BroadcastReceiver() { @Override @@ -131,7 +135,7 @@ public class TtsService extends TextToSpeechService { 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); startActivity(intent); @@ -303,7 +307,7 @@ public class TtsService extends TextToSpeechService { mCallback = callback; 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.Rate.setValue(settings.getRate(), request.getSpeechRate()); mEngine.Pitch.setValue(settings.getPitch(), request.getPitch()); diff --git a/android/src/com/reecedunn/espeak/TtsSettingsActivity.java b/android/src/com/reecedunn/espeak/TtsSettingsActivity.java index 1691faac..b5bfe674 100644 --- a/android/src/com/reecedunn/espeak/TtsSettingsActivity.java +++ b/android/src/com/reecedunn/espeak/TtsSettingsActivity.java @@ -1,4 +1,5 @@ /* + * Copyright (C) 2022 Beka Gozalishvili * Copyright (C) 2013 Reece H. Dunn * Copyright (C) 2011 The Android Open Source Project * @@ -35,14 +36,21 @@ import com.reecedunn.espeak.preference.SpeakPunctuationPreference; import com.reecedunn.espeak.preference.VoiceVariantPreference; public class TtsSettingsActivity extends PreferenceActivity { + + private static Context storageContext; + @Override @SuppressWarnings("deprecation") protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + PreferenceManager preferenceManager = getPreferenceManager(); + preferenceManager.setStorageDeviceProtected (); + // 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(); String pitch = prefs.getString(VoiceSettings.PREF_PITCH, null); @@ -56,7 +64,7 @@ public class TtsSettingsActivity extends PreferenceActivity { String rate = prefs.getString(VoiceSettings.PREF_RATE, null); if (rate == null) { // Try the old eyes-free setting: - SpeechSynthesis engine = new SpeechSynthesis(this, null); + SpeechSynthesis engine = new SpeechSynthesis(storageContext, null); int defaultValue = engine.Rate.getDefaultValue(); int maxValue = engine.Rate.getMaxValue(); @@ -164,7 +172,7 @@ public class TtsSettingsActivity extends PreferenceActivity { pref.setMax(parameter.getMaxValue()); pref.setDefaultValue(defaultValue); - final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); + final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(storageContext); final String prefString = prefs.getString(key, null); if (prefString == null) { pref.setProgress(defaultValue); @@ -181,8 +189,8 @@ public class TtsSettingsActivity extends PreferenceActivity { * summary with the current entry value. */ 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(createVoiceVariantPreference(context, settings, R.string.espeak_variant)); diff --git a/android/src/com/reecedunn/espeak/preference/SeekBarPreference.java b/android/src/com/reecedunn/espeak/preference/SeekBarPreference.java index f2823b04..3ccf0c74 100644 --- a/android/src/com/reecedunn/espeak/preference/SeekBarPreference.java +++ b/android/src/com/reecedunn/espeak/preference/SeekBarPreference.java @@ -1,4 +1,5 @@ /* + * Copyright (C) 2022 Beka Gozalishvili * Copyright (C) 2013 Reece H. Dunn * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -20,6 +21,7 @@ import android.content.Context; import android.content.DialogInterface; import android.content.SharedPreferences; import android.preference.DialogPreference; +import android.preference.PreferenceManager; import android.util.AttributeSet; import android.view.View; import android.widget.Button; @@ -113,6 +115,8 @@ public class SeekBarPreference extends DialogPreference implements SeekBar.OnSee String text = Integer.toString(mProgress); callChangeListener(text); if (shouldCommit()) { + PreferenceManager preferenceManager = getPreferenceManager(); + preferenceManager.setStorageDeviceProtected (); SharedPreferences.Editor editor = getEditor(); editor.putString(getKey(), text); editor.commit(); diff --git a/android/src/com/reecedunn/espeak/preference/SpeakPunctuationPreference.java b/android/src/com/reecedunn/espeak/preference/SpeakPunctuationPreference.java index 2cc6707d..5bca5ddc 100644 --- a/android/src/com/reecedunn/espeak/preference/SpeakPunctuationPreference.java +++ b/android/src/com/reecedunn/espeak/preference/SpeakPunctuationPreference.java @@ -1,4 +1,5 @@ /* + * Copyright (C) 2022 Beka Gozalishvili * Copyright (C) 2013 Reece H. Dunn * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -20,6 +21,7 @@ import android.content.Context; import android.content.DialogInterface; import android.content.SharedPreferences; import android.preference.DialogPreference; +import android.preference.PreferenceManager; import android.text.Editable; import android.util.AttributeSet; import android.view.View; @@ -128,6 +130,8 @@ public class SpeakPunctuationPreference extends DialogPreference { onDataChanged(level, characters); if (shouldCommit()) { + PreferenceManager preferenceManager = getPreferenceManager(); + preferenceManager.setStorageDeviceProtected(); SharedPreferences.Editor editor = getEditor(); if (editor != null) { editor.putString(VoiceSettings.PREF_PUNCTUATION_CHARACTERS, characters); diff --git a/android/src/com/reecedunn/espeak/preference/VoiceVariantPreference.java b/android/src/com/reecedunn/espeak/preference/VoiceVariantPreference.java index 9a56e7ef..b304be68 100644 --- a/android/src/com/reecedunn/espeak/preference/VoiceVariantPreference.java +++ b/android/src/com/reecedunn/espeak/preference/VoiceVariantPreference.java @@ -1,4 +1,5 @@ /* + * Copyright (C) 2022 Beka Gozalishvili * Copyright (C) 2013 Reece H. Dunn * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -21,6 +22,7 @@ import android.content.Context; import android.content.DialogInterface; import android.content.SharedPreferences; import android.preference.DialogPreference; +import android.preference.PreferenceManager; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.View; @@ -328,6 +330,8 @@ public class VoiceVariantPreference extends DialogPreference { case DialogInterface.BUTTON_POSITIVE: onDataChanged(); if (shouldCommit()) { + PreferenceManager preferenceManager = getPreferenceManager(); + preferenceManager.setStorageDeviceProtected(); SharedPreferences.Editor editor = getEditor(); if (editor != null) { VoiceVariant variant = variants[mCategoryIndex][mVariantIndex].getVariant();