mirror of
https://github.com/M66B/FairEmail.git
synced 2026-04-03 15:46:34 +02:00
Added TTS
This commit is contained in:
@@ -167,6 +167,9 @@ public class AdapterRule extends RecyclerView.Adapter<AdapterRule.ViewHolder> {
|
||||
case EntityRule.TYPE_ANSWER:
|
||||
tvAction.setText(R.string.title_rule_answer);
|
||||
break;
|
||||
case EntityRule.TYPE_TTS:
|
||||
tvAction.setText(R.string.title_rule_tts);
|
||||
break;
|
||||
case EntityRule.TYPE_AUTOMATION:
|
||||
tvAction.setText(R.string.title_rule_automation);
|
||||
break;
|
||||
|
||||
@@ -98,6 +98,7 @@ public class EntityRule {
|
||||
static final int TYPE_KEYWORD = 11;
|
||||
static final int TYPE_HIDE = 12;
|
||||
static final int TYPE_IMPORTANCE = 13;
|
||||
static final int TYPE_TTS = 14;
|
||||
|
||||
static final String ACTION_AUTOMATION = BuildConfig.APPLICATION_ID + ".AUTOMATION";
|
||||
static final String EXTRA_RULE = "rule";
|
||||
@@ -323,6 +324,8 @@ public class EntityRule {
|
||||
return onActionCopy(context, message, jaction);
|
||||
case TYPE_ANSWER:
|
||||
return onActionAnswer(context, message, jaction);
|
||||
case TYPE_TTS:
|
||||
return onActionTts(context, message, jaction);
|
||||
case TYPE_AUTOMATION:
|
||||
return onActionAutomation(context, message, jaction);
|
||||
default:
|
||||
@@ -480,6 +483,24 @@ public class EntityRule {
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean onActionTts(Context context, EntityMessage message, JSONObject jargs) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(context.getString(R.string.title_rule_tts_prefix));
|
||||
|
||||
if (message.from != null && message.from.length > 0)
|
||||
sb.append(' ').append(context.getString(R.string.title_from))
|
||||
.append(' ').append(MessageHelper.formatAddressesShort(message.from));
|
||||
|
||||
if (!TextUtils.isEmpty(message.subject))
|
||||
sb.append(' ').append(context.getString(R.string.title_subject))
|
||||
.append(' ').append(message.subject);
|
||||
|
||||
EntityLog.log(context, "TTS queued language=" + message.language + " text=" + sb.toString());
|
||||
TTSHelper.speak(context, "rule:" + message.id, sb.toString(), message.language);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean onActionSnooze(Context context, EntityMessage message, JSONObject jargs) throws JSONException {
|
||||
int duration = jargs.getInt("duration");
|
||||
boolean schedule_end = jargs.optBoolean("schedule_end", false);
|
||||
|
||||
@@ -31,6 +31,7 @@ import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.provider.ContactsContract;
|
||||
import android.speech.tts.TextToSpeech;
|
||||
import android.text.TextUtils;
|
||||
import android.text.format.DateFormat;
|
||||
import android.view.LayoutInflater;
|
||||
@@ -133,6 +134,8 @@ public class FragmentRule extends FragmentBase {
|
||||
private Spinner spAnswer;
|
||||
private CheckBox cbCc;
|
||||
|
||||
private Button btnTts;
|
||||
|
||||
private TextView tvAutomation;
|
||||
|
||||
private BottomNavigationView bottom_navigation;
|
||||
@@ -146,6 +149,7 @@ public class FragmentRule extends FragmentBase {
|
||||
private Group grpMove;
|
||||
private Group grpMoveProp;
|
||||
private Group grpAnswer;
|
||||
private Group grpTts;
|
||||
private Group grpAutomation;
|
||||
|
||||
private ArrayAdapter<String> adapterDay;
|
||||
@@ -168,6 +172,7 @@ public class FragmentRule extends FragmentBase {
|
||||
private final static int REQUEST_DELETE = 4;
|
||||
private final static int REQUEST_SCHEDULE_START = 5;
|
||||
private final static int REQUEST_SCHEDULE_END = 6;
|
||||
private final static int REQUEST_TTS = 7;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
@@ -247,6 +252,7 @@ public class FragmentRule extends FragmentBase {
|
||||
spAnswer = view.findViewById(R.id.spAnswer);
|
||||
cbCc = view.findViewById(R.id.cbCc);
|
||||
|
||||
btnTts = view.findViewById(R.id.btnTts);
|
||||
tvAutomation = view.findViewById(R.id.tvAutomation);
|
||||
|
||||
bottom_navigation = view.findViewById(R.id.bottom_navigation);
|
||||
@@ -261,6 +267,7 @@ public class FragmentRule extends FragmentBase {
|
||||
grpMove = view.findViewById(R.id.grpMove);
|
||||
grpMoveProp = view.findViewById(R.id.grpMoveProp);
|
||||
grpAnswer = view.findViewById(R.id.grpAnswer);
|
||||
grpTts = view.findViewById(R.id.grpTts);
|
||||
grpAutomation = view.findViewById(R.id.grpAutomation);
|
||||
|
||||
ibSender.setOnClickListener(new View.OnClickListener() {
|
||||
@@ -391,6 +398,7 @@ public class FragmentRule extends FragmentBase {
|
||||
actions.add(new Action(EntityRule.TYPE_COPY, getString(R.string.title_rule_copy)));
|
||||
}
|
||||
actions.add(new Action(EntityRule.TYPE_ANSWER, getString(R.string.title_rule_answer)));
|
||||
actions.add(new Action(EntityRule.TYPE_TTS, getString(R.string.title_rule_tts)));
|
||||
actions.add(new Action(EntityRule.TYPE_AUTOMATION, getString(R.string.title_rule_automation)));
|
||||
adapterAction.addAll(actions);
|
||||
|
||||
@@ -454,6 +462,15 @@ public class FragmentRule extends FragmentBase {
|
||||
spIdent.setOnItemSelectedListener(onItemSelectedListener);
|
||||
spAnswer.setOnItemSelectedListener(onItemSelectedListener);
|
||||
|
||||
btnTts.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
Intent tts = new Intent();
|
||||
tts.setAction(TextToSpeech.Engine.ACTION_CHECK_TTS_DATA);
|
||||
startActivityForResult(tts, REQUEST_TTS);
|
||||
}
|
||||
});
|
||||
|
||||
tvAutomation.setText(getString(R.string.title_rule_automation_hint,
|
||||
EntityRule.ACTION_AUTOMATION,
|
||||
TextUtils.join(",", new String[]{
|
||||
@@ -491,6 +508,7 @@ public class FragmentRule extends FragmentBase {
|
||||
grpMove.setVisibility(View.GONE);
|
||||
grpMoveProp.setVisibility(View.GONE);
|
||||
grpAnswer.setVisibility(View.GONE);
|
||||
grpTts.setVisibility(View.GONE);
|
||||
grpAutomation.setVisibility(View.GONE);
|
||||
pbWait.setVisibility(View.VISIBLE);
|
||||
|
||||
@@ -634,6 +652,15 @@ public class FragmentRule extends FragmentBase {
|
||||
if (resultCode == RESULT_OK)
|
||||
onScheduleEnd(data.getBundleExtra("args"));
|
||||
break;
|
||||
case REQUEST_TTS:
|
||||
if (resultCode == TextToSpeech.Engine.CHECK_VOICE_DATA_PASS)
|
||||
ToastEx.makeText(getContext(), android.R.string.ok, Toast.LENGTH_LONG).show();
|
||||
else {
|
||||
Intent tts = new Intent();
|
||||
tts.setAction(TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA);
|
||||
startActivity(tts);
|
||||
}
|
||||
break;
|
||||
}
|
||||
} catch (Throwable ex) {
|
||||
Log.e(ex);
|
||||
@@ -881,6 +908,7 @@ public class FragmentRule extends FragmentBase {
|
||||
grpMove.setVisibility(type == EntityRule.TYPE_MOVE || type == EntityRule.TYPE_COPY ? View.VISIBLE : View.GONE);
|
||||
grpMoveProp.setVisibility(type == EntityRule.TYPE_MOVE ? View.VISIBLE : View.GONE);
|
||||
grpAnswer.setVisibility(type == EntityRule.TYPE_ANSWER ? View.VISIBLE : View.GONE);
|
||||
grpTts.setVisibility(type == EntityRule.TYPE_TTS ? View.VISIBLE : View.GONE);
|
||||
grpAutomation.setVisibility(type == EntityRule.TYPE_AUTOMATION ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
|
||||
|
||||
44
app/src/main/java/eu/faircode/email/TTSHelper.java
Normal file
44
app/src/main/java/eu/faircode/email/TTSHelper.java
Normal file
@@ -0,0 +1,44 @@
|
||||
package eu.faircode.email;
|
||||
|
||||
import android.content.Context;
|
||||
import android.speech.tts.TextToSpeech;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
public class TTSHelper {
|
||||
private static boolean initialized;
|
||||
private static TextToSpeech instance;
|
||||
|
||||
static void speak(Context context, final String utteranceId, final String text, final String language) {
|
||||
// https://developer.android.com/reference/android/speech/tts/TextToSpeech
|
||||
// https://android-developers.googleblog.com/2009/09/introduction-to-text-to-speech-in.html
|
||||
|
||||
final Runnable speak = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (language != null) {
|
||||
Locale loc = new Locale(language);
|
||||
if (instance.setLanguage(loc) < 0)
|
||||
EntityLog.log(context, "TTS unavailable language=" + loc);
|
||||
}
|
||||
|
||||
instance.speak(text, TextToSpeech.QUEUE_ADD, null, utteranceId);
|
||||
}
|
||||
};
|
||||
|
||||
if (initialized) {
|
||||
speak.run();
|
||||
return;
|
||||
}
|
||||
|
||||
instance = new TextToSpeech(context, new TextToSpeech.OnInitListener() {
|
||||
@Override
|
||||
public void onInit(int status) {
|
||||
initialized = (status == TextToSpeech.SUCCESS);
|
||||
Log.i("TTS status=" + status + " ok=" + initialized);
|
||||
if (initialized)
|
||||
speak.run();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user