Search code examples
javaandroidandroid-studiolocaletext-to-speech

How can I get TTS to say in different languages in an app?


I am a beginner and this is my first app. I cannot get tts to speak in different language even after using setLanguage() on it. It is always speaking in English. Any help would be appreciated. Here is my MainActivity:

package com.example.android.sayhi;

import android.os.Build;
import android.os.Bundle;
import android.speech.tts.TextToSpeech;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.TextView;

import java.util.Locale;

public class MainActivity extends AppCompatActivity {

    TextToSpeech t;
    String option;
    Locale language;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Spinner dropdown = (Spinner)findViewById(R.id.spinner);
        String[] items = new String[]{Locale.FRENCH.getDisplayLanguage(),Locale.UK.getDisplayLanguage(), Locale.US.getDisplayLanguage()};
        ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_dropdown_item, items);
        dropdown.setAdapter(adapter);

      dropdown.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
          @Override
          public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
              option =  adapterView.getItemAtPosition(i).toString();


          }

          @Override
          public void onNothingSelected(AdapterView<?> adapterView) {
option = adapterView.getItemAtPosition(0).toString();
          }


      });
        language = new Locale(option);
        t = new TextToSpeech(getApplicationContext(), new TextToSpeech.OnInitListener() {
            @Override
            public void onInit(int status) {
                if (status != TextToSpeech.ERROR) {
                    t.setLanguage(language);
                    t.setSpeechRate((float)0.8);


                }
            }
        });




    }


    public void show(View view) {
        EditText textField = (EditText) findViewById(R.id.text);
        String field = textField.getText().toString();


        TextView viewField = (TextView) findViewById(R.id.textView);
        viewField.setText(field);

        if (Build.VERSION.RELEASE.startsWith("5")) {
          t.speak(field, TextToSpeech.QUEUE_FLUSH, null, null);
        }
        else {
            t.speak(field, TextToSpeech.QUEUE_FLUSH, null);
        }

    }

    public void onPause() {
        if (t != null) {
            t.stop();

        }
        super.onPause();
    }

    @Override
    protected void onResume() {
        super.onResume();

    }

Here is my XML file:

<?xml version="1.0" encoding="utf-8"?>

<ScrollView

    android:layout_height="fill_parent"
    android:layout_width="fill_parent"
    xmlns:android="http://schemas.android.com/apk/res/android">


<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.android.sayhi.MainActivity">


    <EditText
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/text"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="40dp"
        android:width="300dp"/>

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Say it!"
        android:id="@+id/button"
        android:layout_below="@+id/text"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="38dp"
        android:onClick="show"/>

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:text="Write it up!"
        android:id="@+id/textView"
        android:layout_below="@+id/button"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="105dp"
        android:gravity="center_horizontal" />

    <Spinner
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/spinner"
        android:layout_below="@+id/button"
        android:layout_alignParentRight="true"
        android:layout_alignParentEnd="true"
        android:background="@android:drawable/btn_dropdown"/>

</RelativeLayout>
</ScrollView>

Any help would be appreciated! Thanks.


Solution

  • You are instantiating the Text to Speech object in your onCreate() method and attempting to set the language inside onInit().

    Your variable option will be null at this point (as nothing has yet been selected), so creating the locale with a null value will fail, hence the language will not be set.

    When items are selected from your drop-down list, option is populated, but nothing further happens to it. It does not continue 'outside' of the listener back into the onCreate() method.

    Inside your drop-down listener, add the following:

        option =  adapterView.getItemAtPosition(xxx).toString();
        language = new Locale(option);
    
        if (t != null) {
            int result = t.setLanguage(language)
            // Check the result to see if it was successful
        } else {
            // the tts object was null?
        }
    

    That should fix the issue.

    Alternatively, as you will be using the above code twice, it's good practice to create your own method for it.

    private void setLanguage(final String option) {
    
        language = new Locale(option);
    
        if (t != null) {
        int result = t.setLanguage(language)
        // Check the result to see if it was successful
        } else {
        // the tts object was null?
        }
    
    }
    

    Then you could simply call:

    setLanguage(adapterView.getItemAtPosition(xxx).toString());
    

    Whenever you create variables and assign values, as a beginner, always log the value, so you can see it for yourself. It will give you an early clue that something is wrong if it is null or not the value you intended.