Generalize auto-pickup and read-notifications-aloud features

This commit is contained in:
Arjan Schrijver 2024-04-12 23:02:39 +02:00 committed by José Rebelo
parent 717789dc48
commit 523d02ae7f
13 changed files with 203 additions and 194 deletions

View File

@ -19,6 +19,23 @@
along with this program. If not, see <https://www.gnu.org/licenses/>. */
package nodomain.freeyourgadget.gadgetbridge.activities.devicesettings;
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.*;
import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst.PREF_CONTROL_CENTER_SORTABLE;
import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst.PREF_DISPLAY_ITEMS;
import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst.PREF_DISPLAY_ITEMS_SORTABLE;
import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst.PREF_EXPOSE_HR_THIRDPARTY;
import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst.PREF_SHORTCUTS;
import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst.PREF_SHORTCUTS_SORTABLE;
import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst.PREF_WORKOUT_ACTIVITY_TYPES_SORTABLE;
import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.PREF_MI2_DATEFORMAT;
import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.PREF_MI2_ROTATE_WRIST_TO_SWITCH_INFO;
import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.PREF_NIGHT_MODE;
import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.PREF_NIGHT_MODE_END;
import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.PREF_NIGHT_MODE_OFF;
import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.PREF_NIGHT_MODE_SCHEDULED;
import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.PREF_NIGHT_MODE_START;
import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.PREF_SWIPE_UNLOCK;
import android.content.Context;
import android.content.Intent;
import android.media.AudioManager;
@ -43,10 +60,10 @@ import java.util.Set;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.activities.AbstractPreferenceFragment;
import nodomain.freeyourgadget.gadgetbridge.activities.CalBlacklistActivity;
import nodomain.freeyourgadget.gadgetbridge.activities.ConfigureContacts;
import nodomain.freeyourgadget.gadgetbridge.activities.ConfigureWorldClocks;
import nodomain.freeyourgadget.gadgetbridge.activities.AbstractPreferenceFragment;
import nodomain.freeyourgadget.gadgetbridge.activities.app_specific_notifications.AppSpecificNotificationSettingsActivity;
import nodomain.freeyourgadget.gadgetbridge.activities.loyaltycards.LoyaltyCardsSettingsActivity;
import nodomain.freeyourgadget.gadgetbridge.activities.loyaltycards.LoyaltyCardsSettingsConst;
@ -61,30 +78,6 @@ import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.model.CannedMessagesSpec;
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.*;
import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst.PREF_CONTROL_CENTER_SORTABLE;
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_DEVICE_ACTION_FELL_SLEEP_BROADCAST;
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_DEVICE_ACTION_FELL_SLEEP_SELECTIONS;
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_DEVICE_ACTION_SELECTION_BROADCAST;
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_DEVICE_ACTION_START_NON_WEAR_BROADCAST;
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_DEVICE_ACTION_START_NON_WEAR_SELECTIONS;
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_DEVICE_ACTION_WOKE_UP_BROADCAST;
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_DEVICE_ACTION_WOKE_UP_SELECTIONS;
import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst.PREF_DISPLAY_ITEMS;
import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst.PREF_DISPLAY_ITEMS_SORTABLE;
import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst.PREF_EXPOSE_HR_THIRDPARTY;
import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst.PREF_SHORTCUTS;
import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst.PREF_SHORTCUTS_SORTABLE;
import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst.PREF_WORKOUT_ACTIVITY_TYPES_SORTABLE;
import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.PREF_MI2_DATEFORMAT;
import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.PREF_MI2_ROTATE_WRIST_TO_SWITCH_INFO;
import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.PREF_NIGHT_MODE;
import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.PREF_NIGHT_MODE_END;
import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.PREF_NIGHT_MODE_OFF;
import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.PREF_NIGHT_MODE_SCHEDULED;
import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.PREF_NIGHT_MODE_START;
import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.PREF_SWIPE_UNLOCK;
public class DeviceSpecificSettingsFragment extends AbstractPreferenceFragment implements DeviceSpecificSettingsHandler {
private static final Logger LOG = LoggerFactory.getLogger(DeviceSpecificSettingsFragment.class);
@ -928,6 +921,7 @@ public class DeviceSpecificSettingsFragment extends AbstractPreferenceFragment i
setInputTypeFor(DeviceSettingsPreferenceConst.PREF_INACTIVITY_THRESHOLD, InputType.TYPE_CLASS_NUMBER);
setInputTypeFor(DeviceSettingsPreferenceConst.PREF_DEVICE_GPS_UPDATE_INTERVAL, InputType.TYPE_CLASS_NUMBER);
setInputTypeFor(DeviceSettingsPreferenceConst.PREF_BANGLEJS_TEXT_BITMAP_SIZE, InputType.TYPE_CLASS_NUMBER);
setInputTypeFor(DeviceSettingsPreferenceConst.PREF_AUTO_REPLY_INCOMING_CALL_DELAY, InputType.TYPE_CLASS_NUMBER);
new PasswordCapabilityImpl().registerPreferences(getContext(), coordinator.getPasswordCapability(), this);
new HeartRateCapability().registerPreferences(getContext(), coordinator.getHeartRateMeasurementIntervals(), this);

View File

@ -25,6 +25,7 @@ public enum DeviceSpecificSettingsScreen {
AUDIO("pref_screen_audio", R.xml.devicesettings_root_audio),
AUTHENTICATION("pref_screen_authentication", R.xml.devicesettings_root_authentication),
CALENDAR("pref_screen_calendar", R.xml.devicesettings_root_calendar),
CALLS_AND_NOTIFICATIONS("pref_screen_calls_and_notifications", R.xml.devicesettings_root_calls_and_notifications),
CONNECTION("pref_screen_connection", R.xml.devicesettings_root_connection),
DEVELOPER("pref_screen_developer", R.xml.devicesettings_root_developer),
DISPLAY("pref_screen_display", R.xml.devicesettings_root_display),

View File

@ -49,6 +49,8 @@ public class GalaxyBudsLiveDeviceCoordinator extends GalaxyBudsGenericCoordinato
final DeviceSpecificSettings deviceSpecificSettings = new DeviceSpecificSettings();
final List<Integer> audio = deviceSpecificSettings.addRootScreen(DeviceSpecificSettingsScreen.AUDIO);
audio.add(R.xml.devicesettings_galaxy_buds_live);
final List<Integer> callsAndNotif = deviceSpecificSettings.addRootScreen(DeviceSpecificSettingsScreen.CALLS_AND_NOTIFICATIONS);
callsAndNotif.add(R.xml.devicesettings_headphones);
return deviceSpecificSettings;
}

View File

@ -16,11 +16,11 @@
along with this program. If not, see <https://www.gnu.org/licenses/>. */
package nodomain.freeyourgadget.gadgetbridge.devices.galaxy_buds;
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_GALAXY_BUDS_2_NOISE_CONTROL;
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_GALAXY_BUDS_AMBIENT_VOLUME;
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_GALAXY_BUDS_PRO_ANC_LEVEL;
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_GALAXY_BUDS_PRO_BALANCE;
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_GALAXY_BUDS_PRO_NOISE_CONTROL;
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_GALAXY_BUDS_2_NOISE_CONTROL;
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_GALAXY_BUDS_TOUCH_LEFT;
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_GALAXY_BUDS_TOUCH_LEFT_SWITCH;
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_GALAXY_BUDS_TOUCH_RIGHT;

View File

@ -23,6 +23,7 @@ import androidx.annotation.NonNull;
import nodomain.freeyourgadget.gadgetbridge.GBException;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSpecificSettings;
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSpecificSettingsCustomizer;
import nodomain.freeyourgadget.gadgetbridge.devices.AbstractBLClassicDeviceCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.InstallHandler;
@ -74,10 +75,11 @@ public abstract class AbstractEarCoordinator extends AbstractBLClassicDeviceCoor
}
@Override
public int[] getSupportedDeviceSpecificSettings(GBDevice device) {
return new int[]{
R.xml.devicesettings_nothing_ear1
};
public DeviceSpecificSettings getDeviceSpecificSettings(final GBDevice device) {
final DeviceSpecificSettings deviceSpecificSettings = new DeviceSpecificSettings();
deviceSpecificSettings.addRootScreen(R.xml.devicesettings_nothing_ear1);
deviceSpecificSettings.addRootScreen(R.xml.devicesettings_headphones);
return deviceSpecificSettings;
}
@Override

View File

@ -17,9 +17,7 @@
package nodomain.freeyourgadget.gadgetbridge.devices.nothing;
import android.os.Parcel;
import android.text.InputType;
import androidx.preference.EditTextPreference;
import androidx.preference.ListPreference;
import androidx.preference.Preference;
@ -76,22 +74,6 @@ public class EarSettingsCustomizer implements DeviceSpecificSettingsCustomizer {
((ListPreference) audioModePref).setEntryValues(entryValues.toArray(new CharSequence[0]));
}
}
final Preference autoReplyPref = handler.findPreference(DeviceSettingsPreferenceConst.PREF_AUTO_REPLY_INCOMING_CALL);
final Preference autoReplyDelay = handler.findPreference(DeviceSettingsPreferenceConst.PREF_AUTO_REPLY_INCOMING_CALL_DELAY);
if (autoReplyPref != null && autoReplyDelay != null) {
autoReplyDelay.setEnabled(prefs.getBoolean(DeviceSettingsPreferenceConst.PREF_AUTO_REPLY_INCOMING_CALL, false));
autoReplyPref.setOnPreferenceChangeListener((preference, newValue) -> {
autoReplyDelay.setEnabled((Boolean) newValue);
return true;
});
((EditTextPreference) autoReplyDelay).setOnBindEditTextListener(editText -> editText.setInputType(InputType.TYPE_CLASS_NUMBER));
}
}
@Override

View File

@ -0,0 +1,135 @@
/* Copyright (C) 2024 Arjan Schrijver, Daniele Gobbetti
This file is part of Gadgetbridge.
Gadgetbridge is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Gadgetbridge is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
package nodomain.freeyourgadget.gadgetbridge.service;
import android.content.SharedPreferences;
import android.os.Handler;
import android.os.Looper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst;
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventCallControl;
import nodomain.freeyourgadget.gadgetbridge.model.CallSpec;
import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec;
import nodomain.freeyourgadget.gadgetbridge.service.serial.AbstractSerialDeviceSupport;
import nodomain.freeyourgadget.gadgetbridge.util.GBTextToSpeech;
public abstract class AbstractHeadphoneDeviceSupport extends AbstractSerialDeviceSupport {
private static final Logger LOG = LoggerFactory.getLogger(AbstractHeadphoneDeviceSupport.class);
private GBTextToSpeech gbTextToSpeech;
@Override
public void onSetCallState(CallSpec callSpec) {
SharedPreferences prefs = GBApplication.getDeviceSpecificSharedPrefs(getDevice().getAddress());
if (!prefs.getBoolean(DeviceSettingsPreferenceConst.PREF_AUTO_REPLY_INCOMING_CALL, false))
return;
final int delayMillis = Integer.parseInt(prefs.getString(DeviceSettingsPreferenceConst.PREF_AUTO_REPLY_INCOMING_CALL_DELAY, "15")) * 1000;
if (CallSpec.CALL_INCOMING != callSpec.command)
return;
if (!gbTextToSpeech.isConnected()) { // schedule the automatic reply here, if the speech to text is not connected. Else it's done by the callback, and the timeout starts after the name or number have been spoken
Looper mainLooper = Looper.getMainLooper();
LOG.debug("Incoming call, scheduling auto answer in {} seconds.", delayMillis / 1000);
new Handler(mainLooper).postDelayed(() -> {
GBDeviceEventCallControl callCmd = new GBDeviceEventCallControl();
callCmd.event = GBDeviceEventCallControl.Event.ACCEPT;
evaluateGBDeviceEvent(callCmd);
}, delayMillis); //15s
return;
}
String speechText = callSpec.name;
if (callSpec.name.equals(callSpec.number)) {
StringBuilder numberSpeller = new StringBuilder();
for (char c : callSpec.number.toCharArray()) {
numberSpeller.append(c).append(" ");
}
speechText = numberSpeller.toString();
}
gbTextToSpeech.speak(speechText);
}
@Override
public void onNotification(NotificationSpec notificationSpec) {
SharedPreferences prefs = GBApplication.getDeviceSpecificSharedPrefs(getDevice().getAddress());
if (!prefs.getBoolean(DeviceSettingsPreferenceConst.PREF_SPEAK_NOTIFICATIONS_ALOUD, false))
return;
if (gbTextToSpeech.isConnected()) {
String notificationSpeller = new StringBuilder()
.append(notificationSpec.sourceName == null ? "" : notificationSpec.sourceName).append(". ")
.append(notificationSpec.title == null ? "" : notificationSpec.title).append(": ")
.append(notificationSpec.body == null ? "" : notificationSpec.body).toString();
gbTextToSpeech.speakNotification(notificationSpeller);
}
}
@Override
public boolean connect() {
getDeviceIOThread().start();
gbTextToSpeech = new GBTextToSpeech(getContext(), new UtteranceProgressListener());
return true;
}
@Override
public void dispose() {
gbTextToSpeech.shutdown();
super.dispose();
}
private class UtteranceProgressListener extends android.speech.tts.UtteranceProgressListener {
@Override
public void onStart(String utteranceId) {
// LOG.debug("UtteranceProgressListener onStart.");
}
@Override
public void onDone(String utteranceId) {
// LOG.debug("UtteranceProgressListener onDone.");
if (utteranceId.equals("call")) {
SharedPreferences prefs = GBApplication.getDeviceSpecificSharedPrefs(getDevice().getAddress());
final int delayMillis = Integer.parseInt(prefs.getString(DeviceSettingsPreferenceConst.PREF_AUTO_REPLY_INCOMING_CALL_DELAY, "15")) * 1000;
Looper mainLooper = Looper.getMainLooper();
new Handler(mainLooper).postDelayed(() -> {
GBDeviceEventCallControl callCmd = new GBDeviceEventCallControl();
callCmd.event = GBDeviceEventCallControl.Event.ACCEPT;
evaluateGBDeviceEvent(callCmd);
}, delayMillis); //15s
}
}
@Override
public void onError(String utteranceId) {
LOG.error("UtteranceProgressListener returned error.");
}
}
}

View File

@ -16,23 +16,16 @@
along with this program. If not, see <https://www.gnu.org/licenses/>. */
package nodomain.freeyourgadget.gadgetbridge.service.devices.galaxy_buds;
import android.net.Uri;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.UUID;
import nodomain.freeyourgadget.gadgetbridge.model.Alarm;
import nodomain.freeyourgadget.gadgetbridge.service.serial.AbstractSerialDeviceSupport;
import nodomain.freeyourgadget.gadgetbridge.service.AbstractHeadphoneDeviceSupport;
import nodomain.freeyourgadget.gadgetbridge.service.serial.GBDeviceIoThread;
import nodomain.freeyourgadget.gadgetbridge.service.serial.GBDeviceProtocol;
public class GalaxyBudsDeviceSupport extends AbstractSerialDeviceSupport {
public class GalaxyBudsDeviceSupport extends AbstractHeadphoneDeviceSupport {
private static final Logger LOG = LoggerFactory.getLogger(GalaxyBudsDeviceSupport.class);
@Override
public void onSendConfiguration(String config) {
super.onSendConfiguration(config);
@ -43,12 +36,6 @@ public class GalaxyBudsDeviceSupport extends AbstractSerialDeviceSupport {
super.onTestNewFunction();
}
@Override
public boolean connect() {
getDeviceIOThread().start();
return true;
}
@Override
public synchronized GalaxyBudsIOThread getDeviceIOThread() {
return (GalaxyBudsIOThread) super.getDeviceIOThread();

View File

@ -16,82 +16,15 @@
along with this program. If not, see <https://www.gnu.org/licenses/>. */
package nodomain.freeyourgadget.gadgetbridge.service.devices.nothing;
import android.content.SharedPreferences;
import android.os.Handler;
import android.os.Looper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst;
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventCallControl;
import nodomain.freeyourgadget.gadgetbridge.model.CallSpec;
import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec;
import nodomain.freeyourgadget.gadgetbridge.service.serial.AbstractSerialDeviceSupport;
import nodomain.freeyourgadget.gadgetbridge.service.AbstractHeadphoneDeviceSupport;
import nodomain.freeyourgadget.gadgetbridge.service.serial.GBDeviceIoThread;
import nodomain.freeyourgadget.gadgetbridge.service.serial.GBDeviceProtocol;
import nodomain.freeyourgadget.gadgetbridge.util.GBTextToSpeech;
public class Ear1Support extends AbstractSerialDeviceSupport {
public class Ear1Support extends AbstractHeadphoneDeviceSupport {
private static final Logger LOG = LoggerFactory.getLogger(Ear1Support.class);
private GBTextToSpeech gbTextToSpeech;
@Override
public void onSetCallState(CallSpec callSpec) {
SharedPreferences prefs = GBApplication.getDeviceSpecificSharedPrefs(getDevice().getAddress());
if (!prefs.getBoolean(DeviceSettingsPreferenceConst.PREF_AUTO_REPLY_INCOMING_CALL, false))
return;
final int delayMillis = Integer.parseInt(prefs.getString(DeviceSettingsPreferenceConst.PREF_AUTO_REPLY_INCOMING_CALL_DELAY, "15")) * 1000;
if (CallSpec.CALL_INCOMING != callSpec.command)
return;
if (!gbTextToSpeech.isConnected()) { // schedule the automatic reply here, if the speech to text is not connected. Else it's done by the callback, and the timeout starts after the name or number have been spoken
Looper mainLooper = Looper.getMainLooper();
LOG.debug("Incoming call, scheduling auto answer in {} seconds.", delayMillis / 1000);
new Handler(mainLooper).postDelayed(() -> {
GBDeviceEventCallControl callCmd = new GBDeviceEventCallControl();
callCmd.event = GBDeviceEventCallControl.Event.ACCEPT;
evaluateGBDeviceEvent(callCmd);
}, delayMillis); //15s
return;
}
String speechText = callSpec.name;
if (callSpec.name.equals(callSpec.number)) {
StringBuilder numberSpeller = new StringBuilder();
for (char c : callSpec.number.toCharArray()) {
numberSpeller.append(c).append(" ");
}
speechText = numberSpeller.toString();
}
gbTextToSpeech.speak(speechText);
}
@Override
public void onNotification(NotificationSpec notificationSpec) {
SharedPreferences prefs = GBApplication.getDeviceSpecificSharedPrefs(getDevice().getAddress());
if (!prefs.getBoolean(DeviceSettingsPreferenceConst.PREF_SPEAK_NOTIFICATIONS_ALOUD, false))
return;
if (gbTextToSpeech.isConnected()) {
String notificationSpeller = new StringBuilder()
.append(notificationSpec.sourceName == null ? "" : notificationSpec.sourceName).append(". ")
.append(notificationSpec.title == null ? "" : notificationSpec.title).append(": ")
.append(notificationSpec.body == null ? "" : notificationSpec.body).toString();
gbTextToSpeech.speakNotification(notificationSpeller);
}
}
@Override
public void onSendConfiguration(String config) {
@ -103,13 +36,6 @@ public class Ear1Support extends AbstractSerialDeviceSupport {
//getDeviceIOThread().write(((NothingProtocol) getDeviceProtocol()).encodeBatteryStatusReq());
}
@Override
public boolean connect() {
getDeviceIOThread().start();
gbTextToSpeech = new GBTextToSpeech(getContext(), new UtteranceProgressListener());
return true;
}
@Override
public synchronized NothingIOThread getDeviceIOThread() {
return (NothingIOThread) super.getDeviceIOThread();
@ -129,39 +55,4 @@ public class Ear1Support extends AbstractSerialDeviceSupport {
return new NothingIOThread(getDevice(), getContext(), (NothingProtocol) getDeviceProtocol(),
Ear1Support.this, getBluetoothAdapter());
}
@Override
public void dispose() {
gbTextToSpeech.shutdown();
super.dispose();
}
private class UtteranceProgressListener extends android.speech.tts.UtteranceProgressListener {
@Override
public void onStart(String utteranceId) {
// LOG.debug("UtteranceProgressListener onStart.");
}
@Override
public void onDone(String utteranceId) {
// LOG.debug("UtteranceProgressListener onDone.");
if (utteranceId.equals("call")) {
SharedPreferences prefs = GBApplication.getDeviceSpecificSharedPrefs(getDevice().getAddress());
final int delayMillis = Integer.parseInt(prefs.getString(DeviceSettingsPreferenceConst.PREF_AUTO_REPLY_INCOMING_CALL_DELAY, "15")) * 1000;
Looper mainLooper = Looper.getMainLooper();
new Handler(mainLooper).postDelayed(() -> {
GBDeviceEventCallControl callCmd = new GBDeviceEventCallControl();
callCmd.event = GBDeviceEventCallControl.Event.ACCEPT;
evaluateGBDeviceEvent(callCmd);
}, delayMillis); //15s
}
}
@Override
public void onError(String utteranceId) {
LOG.error("UtteranceProgressListener returned error.");
}
}
}

View File

@ -2789,4 +2789,5 @@
<string name="pref_auto_reply_calls_delay_title">Automatic Answer Delay</string>
<string name="pref_speak_notifications_aloud_summary">Notifications will be read aloud through the headphones</string>
<string name="pref_speak_notifications_aloud_title">Speak Notifications Aloud</string>
<string name="pref_header_calls_and_notifications">Calls and notifications</string>
</resources>

View File

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<SwitchPreferenceCompat
android:defaultValue="false"
android:icon="@drawable/ic_phone"
android:key="pref_auto_reply_phonecall"
android:summary="@string/pref_auto_reply_calls_summary"
android:title="@string/pref_auto_reply_calls_title"/>
<EditTextPreference
android:icon="@drawable/ic_timer"
android:digits="123"
android:dependency="pref_auto_reply_phonecall"
android:inputType="numberDecimal"
android:key="pref_auto_reply_phonecall_delay"
android:summary="@string/pref_auto_reply_calls_delay_summary"
android:title="@string/pref_auto_reply_calls_delay_title"
app:defaultValue="15" />
<SwitchPreferenceCompat
android:defaultValue="false"
android:icon="@drawable/ic_voice"
android:key="pref_speak_notifications_aloud"
android:summary="@string/pref_speak_notifications_aloud_summary"
android:title="@string/pref_speak_notifications_aloud_title" />
</androidx.preference.PreferenceScreen>

View File

@ -15,24 +15,4 @@
android:key="pref_nothing_audiomode"
android:summary="%s"
android:title="@string/nothing_prefs_audiomode_title" />
<SwitchPreferenceCompat
android:defaultValue="false"
android:icon="@drawable/ic_phone"
android:key="pref_auto_reply_phonecall"
android:summary="@string/pref_auto_reply_calls_summary"
android:title="@string/pref_auto_reply_calls_title"/>
<EditTextPreference
android:digits="123"
android:enabled="false"
android:inputType="numberDecimal"
android:key="pref_auto_reply_phonecall_delay"
android:summary="@string/pref_auto_reply_calls_delay_summary"
android:title="@string/pref_auto_reply_calls_delay_title"
app:defaultValue="15" />
<SwitchPreferenceCompat
android:defaultValue="false"
android:icon="@drawable/ic_voice"
android:key="pref_speak_notifications_aloud"
android:summary="@string/pref_speak_notifications_aloud_summary"
android:title="@string/pref_speak_notifications_aloud_title" />
</androidx.preference.PreferenceScreen>

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceScreen
android:icon="@drawable/ic_notifications"
android:key="pref_screen_calls_and_notifications"
android:persistent="false"
android:title="@string/pref_header_calls_and_notifications">
</PreferenceScreen>
</androidx.preference.PreferenceScreen>