So I have been trying to change the TTS language inside a fragment but it isn't working but same code works fine inside MainActivity. I don't understand why. I have checked other solutions but none worked for me. I have tried different solution , solution but even this isn't working.
public class HomeFragment extends Fragment implements TextToSpeech.OnInitListener{
private static final int TTS_DATA_CHECK = 1;
private TextToSpeech engine;
private SettingsViewModel settingsViewModel;
private EditText textMsg;
private Button button;
public View onCreateView(@NonNull LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
engine = new TextToSpeech(getContext(),this);
settingsViewModel = new ViewModelProvider(getActivity()).get(SettingsViewModel.class);
return inflater.inflate(R.layout.fragment_home, container, false);
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
textMsg = view.findViewById(R.id.textMsg);
button = view.findViewById(R.id.playButton);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
engine.speak(textMsg.getText().toString(), TextToSpeech.QUEUE_FLUSH, null,null);
}
});
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
settingsViewModel.getLanguage().observe(getViewLifecycleOwner(), new Observer<String>() {
@Override
public void onChanged(String s) {
Log.d("LANGUAGE_SELECTED",s);
switch (s){
case "ENGLISH":
engine.setLanguage(Locale.ENGLISH);
break;
case "FRENCH":
engine.setLanguage(Locale.FRENCH);
break;
}
}
});
}
@Override
public void onInit(int status) {
if(status==TextToSpeech.SUCCESS){
int result = engine.setLanguage(Locale.ENGLISH);
if(result == TextToSpeech.LANG_MISSING_DATA
|| result== TextToSpeech.LANG_NOT_SUPPORTED){
Toast.makeText(getContext(),"Not supported",Toast.LENGTH_LONG).show();
}
}else{
Toast.makeText(getContext(),"TTS is missing",Toast.LENGTH_LONG).show();
}
}
}
First you need to initialize TTS in main activity like this -
public class MainActivity extends AppCompatActivity implements TextToSpeech.OnInitListener {
private static final int TTS_DATA_CHECK = 101;
static TextToSpeech engine;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
engine = new TextToSpeech(this,this);
}
@Override
public final void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 101)
{
if (resultCode != TextToSpeech.Engine.CHECK_VOICE_DATA_PASS)
{
final Intent tnt = new Intent(TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA);
startActivity(tnt);
}
}
}
@Override
public void onInit(int status) {
if(status==TextToSpeech.SUCCESS){
if(TTS_DATA_CHECK == TextToSpeech.LANG_MISSING_DATA
|| TTS_DATA_CHECK== TextToSpeech.LANG_NOT_SUPPORTED){
Toast.makeText(this,"Not supported",Toast.LENGTH_LONG).show();
}
}
}
static public TextToSpeech getInstance() {
return engine;
}
}
Then you have to call the TTS instance inside Fragment like this. Note that, MainActivity is the parent activity of the given Fragment.
Now replace the following code in your Fragment with this code -
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
Log.d("VMA","OnActivityCreated");
settingsViewModel.getLanguage().observe(getViewLifecycleOwner(), new Observer<String>() {
@Override
public void onChanged(String s) {
Log.d("VMA","LANGUAGE_SELECTED " + s);
switch (s){
case "FRENCH":
MainActivity.getInstance().setLanguage(Locale.FRENCH);
break;
case "ENGLISH":
MainActivity.getInstance().setLanguage(Locale.ENGLISH);
break;
}
}
});
}
Also, you can remove the rest of the TTS code from Fragment. You don't that anymore.