TextToSpeech! Faça a sua aplicação falar!

Introdução

Não seria legal se o seu aplicativo falasse?

Isso é possível! O Android nos disponibilizou uma API na qual após informar uma String o dispositivo fala o texto informado.

Isso é feito através da classe:
TextToSpeech  da própria API do Android.

Para conseguir uma instância dessa classe devemos disparar uma Intent com a ação: TextToSpeech.Engine.ACTION_CHECK_TTS_DATA.

Essa Intent, vai checar se o dispositivo no qual o app esta rodando contém a engine de TTS que permite a nossa funcionalidade.

O resultado dessa Intent será tratado no método onActivityResult conforme o padrão do Android. Se for constatado que não existe no dispositivo essa engine, nos iremos disparar uma nova Intent agora solicitando a instalação da mesma.

Caso o dispositivo já venha com a engine instalada, apenas daremos início ao nosso processo de fazer o aplicativo falar.

Fazemos isso criando uma instância da classe TextToSpeech informando um Context e um OnInitListener no seu construtor.

O segundo parâmetro é uma interface que possui um método que será executado quando a engine estiver totalmente “carregada” e pronta para realizar a tarefa de “falar”.
Neste caso optamos por fazer a nossa Activity implementar essa OnInitListener para passa-la como parâmetro.

A implementação dessa interface implica na implementação do método onInit(int status), esse método será acionado logo após o objeto TextToSpeech ser completamente criado, e tem o objetivo de informar se ele foi criado com sucesso ou não.

Caso tenha sido criado com sucesso podemos configurar a língua na qual o audio será executado, fazemos isso através do método setLanguage também da classe TextSpeech.

Obs: É importante ressaltar que nem todas as línguas são suportadas por essa API (Inclusive a língua portuguesa). Por isso é interessante executar o método isLanguageAvailable para ver se você pode ou não utilizar determinado idimoa nessa estrutura.

A língua será representada pelo objeto Locale presente na linguagem Java. Após escolher a língua na qual o audio será executado, podemos enfim executa-lo através do método speak também da classe TextToSpeech.

O método speak recebe os seguintes parâmetros:

A String alvo, é essa informação que será falada.

A forma na qual o texto será executado.
Pode ser passado aqui duas constantes QUEUE_ADD ou QUEUE_FLUSH. O primeiro indica que a String entrará no final da fila de execuções.
O Segundo indica que a String passada substituirá os elementos que estão na fila atual, deixando os mesmos em uma outra fila.

E pronto, após a execução desse método a String passada será “falada” pelo seu dispositivo Android.

Exemplo prático

Logo abaixo segue um código que demonstra os conceitos abordados acima.

Veja que temos um layout com os seguintes componentes:

Um EdiText que receberá a String que será lida.

Um TextView que exibirá as informações resultantes do método isLanguageAvailable.

Um Spinner que exibirá algumas Locales para serem escolhidas, vale ressaltar que não necessariamente essas Locales serão suportadas pelo seu dispositivo, você saberá ao certo quando apertar o button e ver o resultado no nosso TextView de status.

O último componente é um Button que dará início a todo o processo.

Observe que no código utilizamos uma innerclass para exibir os dados no Spinner. Nessa innerclass teremos uma String que chamamos de label e um objeto genérico do tipo value, a String será exibida no nosso Spinner e o value se trata do valor que será retornado após a seleção de um elemento no Spinner (Não vou entrar em detalhes sobre a classe Spinner nesse post pois não é objetivo deste arquivo, mas se você não entendeu e gostaria de saber mais sobre a mesma, acompanhe este link )

Logo abaixo segue o Layout XML utilizado neste projeto:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" 
    android:orientation="vertical">

    <EditText
        android:id="@+id/editTextTexto"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" 
        android:hint="Digite o texto aqui"/>

    <TextView
        android:id="@+id/textViewStatusLocale"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceMedium" />
   
      <Spinner
        android:id="@+id/spinnerLanguage"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        />

    <Button
        android:id="@+id/buttonFale"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Fala Comigo"
        android:onClick="onClickSpeech" />

</LinearLayout>

Agora o código da Activity:

public class MainActivity extends Activity implements OnInitListener{

	private static final int INTENT_TEXT_SPEECH_CODE = 9;

	private TextToSpeech textSpeech = null;
	private Spinner spinnerLanguage;
	private TextView textViewStatusLocale;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		spinnerLanguage = (Spinner) findViewById(R.id.spinnerLanguage);
		textViewStatusLocale = (TextView) findViewById(R.id.textViewStatusLocale);
	
		List<SpinnerDataObject<Locale>> locales = getLocales();
		ArrayAdapter<SpinnerDataObject<Locale>> adapter = new ArrayAdapter<SpinnerDataObject<Locale>>(this, android.R.layout.simple_list_item_1, locales);
		spinnerLanguage.setAdapter(adapter);
	} 
	
	
	@SuppressWarnings({ "unchecked", "rawtypes" })
	private  List<SpinnerDataObject<Locale>> getLocales() {
	   List<SpinnerDataObject<Locale>> locales = new ArrayList<MainActivity.SpinnerDataObject<Locale>>();
		Locale localeBR = new Locale("pt","br");
		locales.add(new SpinnerDataObject("Brasil", localeBR));
		locales.add(new SpinnerDataObject("Canadá", Locale.CANADA));
		locales.add(new SpinnerDataObject("EUA", Locale.US));
		Locale localeES = new Locale("es","ES");
		locales.add(new SpinnerDataObject("Espanha", localeES));
		return locales;
		
	}

	public void onClickSpeech(View view) {
		Intent checkIntent = new Intent();
		checkIntent.setAction(TextToSpeech.Engine.ACTION_CHECK_TTS_DATA);
		startActivityForResult(checkIntent, INTENT_TEXT_SPEECH_CODE);
	}

	@Override
	public void onInit(int status) {
		if(status == TextToSpeech.SUCCESS) {
			SpinnerDataObject<Locale> registroSelecionado  = (SpinnerDataObject<Locale>) spinnerLanguage.getSelectedItem();
			Locale localeSelected = registroSelecionado.getValue();
			
		
			int available =	textSpeech.isLanguageAvailable(localeSelected) ;
			atualizarStatusDisponibilidadeLocaleSelecionado(available);
			textSpeech.setLanguage(localeSelected);

			String textoQueSeraFalado = ((EditText)findViewById(R.id.editTextTexto)).getText().toString();

			textSpeech.speak(textoQueSeraFalado, TextToSpeech.QUEUE_FLUSH, null);
		}
	}
	
	private void atualizarStatusDisponibilidadeLocaleSelecionado(int available) {
		switch (available) {
	
		case TextToSpeech.LANG_AVAILABLE:
			textViewStatusLocale.setText("Locale suportada, mas não por país ou variante!");
			break;
			
		case TextToSpeech.LANG_COUNTRY_AVAILABLE:
			textViewStatusLocale.setText("Locale suportada pela Localidade, mas não por país ou variante!");
			break;
			
		case TextToSpeech.LANG_COUNTRY_VAR_AVAILABLE:
			textViewStatusLocale.setText("Locale suportada !");
			break;
			
		case TextToSpeech.LANG_MISSING_DATA:
			textViewStatusLocale.setText("Locale com dados faltando !");
			break;
			
		case TextToSpeech.LANG_NOT_SUPPORTED:
			textViewStatusLocale.setText("Locale nao suportada !");
			break;

		default:
			break;
		}
	}

	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		if (requestCode == INTENT_TEXT_SPEECH_CODE) {
			if (resultCode == TextToSpeech.Engine.CHECK_VOICE_DATA_PASS) {
				Log.i("", "success, create the TTS instance"); 
				textSpeech = new TextToSpeech(this, this);
			} else {
				Log.i("", "missing data, install it");
				Intent installIntent = new Intent();
				installIntent.setAction(TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA);
				startActivity(installIntent);
			}
		}

	}	
	
	
	private class SpinnerDataObject<T> {
		
		private String label;
		private T value;
		
		
		public SpinnerDataObject(String label, T value) {
			super();
			this.label = label;
			this.value = value;
		}
		
		
		public String getLabel() {
			return label;
		}
		public void setLabel(String label) {
			this.label = label;
		}
		public T getValue() {
			return value;
		}
		public void setValue(T value) {
			this.value = value;
		}

		private MainActivity getOuterType() {
			return MainActivity.this;
		}
		
		@Override
		public String toString() {
			return label;
		}
		
	}

}


Espero ter fornecido informações interessantes sobre esta funcionalidade super interessante.

Abraço e até a próxima!

Anúncios

  1. #1 by luciene on Outubro 21, 2014 - 1:24 pm

    como implementar a aplicação falar em português (pt-br)? tem algum exemplo?

    • #2 by Levi Costa on Julho 22, 2017 - 12:49 am

      textToSpeech.setLanguage(Locale.ROOT); E pronto, está em português.

  2. #3 by Elton Sarmanho on Dezembro 11, 2013 - 10:17 pm

    Poderia me dizer com mais detalhes sobre esse trecho:
    Intent installIntent = new Intent();
    installIntent.setAction(TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA);
    startActivity(installIntent);

    • #4 by Leonardo Casasanta on Dezembro 12, 2013 - 2:35 am

      Ola Elton,

      A funcionalidade de TextToSpeech faz uso de uma engine, chamada de TTS(TextToSpeech).
      Em alguns dispositivos essa engine pode não vir instalada já de fabrica, então, quando o app identificar que não tem o TTS instalado nos vamos enviar uma Intent para que a instalação ocorra e o usuário possa desfrutar dessa funcionalidade.

      Vou tentar melhorar esse trecho no artigo.

      Abraço.

  3. #5 by Lucas Manoel on Junho 24, 2013 - 2:57 pm

    Cara eu tentei testar seu projeto aqui, importei tudinho, mas ele dá um erro na sua linha 54 “EditText cannot be resolved to a type”. Será que você tem uma ideia do que possa ser e como resolver?

    • #6 by Leonardo Casasanta on Junho 24, 2013 - 6:06 pm

      Ola Lucas,

      Tente utilizar uma versão mais atual do Android neste seu projeto.
      Clique com o botão direito no seu projeto e vai em propriedades, no menu lateral esquerdo selecione o item Android, em seguida no Project Build Target use uma versão do Android mais nova, talvez seja isso.

      Outra dica, veja se seu eclipse esta configurado para dar build automático. Clique na aba project no menu superior do eclipse ao lado do Run e veja se o build automatically esta selecionado, também é interessante selecionar a opção clean.

  4. #7 by Paulo Ronaldo on Março 30, 2013 - 10:30 pm

    Olá, Gostaria de saber se é possivel implementar o TTS em um Service por exemplo, para que varias Activits possam passar um texto como parametro para a aplicação falar.

    Tentei encontrar material a respeito mas não achei. como sou novinho no assunto estou tendo dificuldades.

    Obrigado Ronaldo

    • #8 by Leonardo Casasanta on Março 31, 2013 - 4:50 pm

      Ola Paulo, é possível sim. Veja esta thread http://stackoverflow.com/questions/3860711/start-android-tts-from-broadcast-receiver-or-service.
      Você pode também, criar uma Activity abstrata que possua esta funcionalidade e fazer as outras Activitys herdarem dela. Assim, nos pontos que você desejar de cada activity é soh chamar o método “falar” da classe mãe.

      • #9 by Paulo Ronaldo on Março 31, 2013 - 6:09 pm

        Fantastico Leonardo, funcionou direitinho!

        Eu já tava mesmo seguindo o caminho do Service, contudo ainda não conhecia a função BroadCastReceiver.

        Ficou show.

        Obrigado e Parabens.

  5. #10 by Paulo Lima Jr on Março 27, 2013 - 4:54 pm

    Excelente material. mas gostaria de saber se tenho que colocar alguma coisa no manifest.xml

    tem como colocar o exemplo para download ??

    Obrigado

    Paulo Lima

    • #11 by Paulo Lima Jr on Março 27, 2013 - 6:06 pm

      já funcionou ! valeu.

  1. Recognize Speech Android! Fale com o seu dispositivo. | Android On Board

Deixe uma Resposta

Preencha os seus detalhes abaixo ou clique num ícone para iniciar sessão:

Logótipo da WordPress.com

Está a comentar usando a sua conta WordPress.com Terminar Sessão / Alterar )

Imagem do Twitter

Está a comentar usando a sua conta Twitter Terminar Sessão / Alterar )

Facebook photo

Está a comentar usando a sua conta Facebook Terminar Sessão / Alterar )

Google+ photo

Está a comentar usando a sua conta Google+ Terminar Sessão / Alterar )

Connecting to %s

%d bloggers like this: