Browse through more Android tutorials. If you'd like to see a tutorial on any particular topic, do leave a comment in the wishlist page. We frequently post new tutorials along with app releases. You may subscribe to our newsletter to get all updates in your inbox.
Now you can get the latest Java source bundled with each app update. Install the app from Google Play and go to Settings > Extras.
* Become a 10x programmer! →

«  Create a notepad/to-do list app Create a SMS app  »

Create an App Widget in Android with Text-to-Speech (TTS)

DownloadDownload
By

Keywords: AppWidgetProvider RemoteViews AppWidgetManager BroadcastReceiver Widget Configuration Activity AlarmManager TextToSpeech Service PreferenceActivity OnPreferenceChangeListener

Contents

4 « Prev Page

10. Android Text-to-Speech (TTS) using Service

Text-to-Speech functionality enables an Android device to "speak" with help of TTS engine and language specific data. Android provides an easy way of querying the platform for availability of these language files using an Intent.



	private static final int TTS_CHECK_CODE = 101;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		//... usual stuff
		
		Intent checkIntent = new Intent();
		checkIntent.setAction(TextToSpeech.Engine.ACTION_CHECK_TTS_DATA);
		startActivityForResult(checkIntent, TTS_CHECK_CODE);		
	}

	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
	    if (requestCode == TTS_CHECK_CODE) {
	        if (resultCode == TextToSpeech.Engine.CHECK_VOICE_DATA_PASS) {
	            // success, create the TTS instance
	        	
	        } else {
	            // missing data, install it
	            Intent installIntent = new Intent();
	            installIntent.setAction(TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA);
	            startActivity(installIntent);
	        }
	    }
	}	
					
If TTS data is missing then in onActivityResult callback we launch an activity that directs user to the Play Store for downloading and installing the data.
If data is already present then we can create the TTS instance and configure it.

You can read more about using TTS from Android developers blogspot.

Since we are going to use a Service for Text-to-Speech implementation so we will initialize TTS inside the service.
First, register the service in manifest.
        <service android:name=".SpeechService" >
        </service>
						
Next, create SpeechService class as follows.
	public class SpeechService extends Service implements TextToSpeech.OnInitListener {
		
		public static final String EXTRA_WORD = "word";
		public static final String EXTRA_MEANING = "meaning";
		
		private TextToSpeech tts;
		private String word, meaning;
		private boolean isInit;
		private Handler handler;
		
		@Override
		public void onCreate() {
			super.onCreate();
			tts = new TextToSpeech(getApplicationContext(), this);
			handler = new Handler();
		}

		@Override
		public int onStartCommand(Intent intent, int flags, int startId) {
			handler.removeCallbacksAndMessages(null);
			
			word = intent.getStringExtra(SpeechService.EXTRA_WORD);
			meaning = intent.getStringExtra(SpeechService.EXTRA_MEANING);
			
			if (isInit) {
				speak();
			}
			
			handler.postDelayed(new Runnable() {
				
				@Override
				public void run() {
					stopSelf();
				}
			}, 15*1000);
			
			return SpeechService.START_NOT_STICKY;
		}

		@Override
		public void onDestroy() {
			if (tts != null) {
				tts.stop();
				tts.shutdown();
			}
			super.onDestroy();
		}

		@Override
		public void onInit(int status) {
			if (status == TextToSpeech.SUCCESS) {
				int result = tts.setLanguage(Locale.US);
				if (result != TextToSpeech.LANG_MISSING_DATA && result != TextToSpeech.LANG_NOT_SUPPORTED) {
					speak();
					isInit = true;
				}
			}		
		}
		
		private void speak() {
			if (tts != null) {
				tts.speak(word, TextToSpeech.QUEUE_FLUSH, null);
				tts.speak(meaning, TextToSpeech.QUEUE_ADD, null);
			}
		}

		@Override
		public IBinder onBind(Intent arg0) {
			return null;
		}

	}
					
TextToSpeech constructor requires a listener which would receive callback once TTS is ready. So we make SpeechService implement OnInitListener interface and override onInit() method where we configure TTS (e.g. set language) and use it to speak.
Finally, we stop speech service after some time by using a Handler. It is good practice to shut down TTS in onDestroy() method to release resources held by TTS engine.

Now that our speech service is ready, we'll integrate it with our widget.
Modify VocabWidget class as follows.
	public static final String ACTION_SPEAKER = "com.appsrox.dailyvocab.action.SPEAKER";
	
	static void updateAppWidget(Context context, AppWidgetManager appWidgetManager, int appWidgetId) {
		
		//...

		// Construct the RemoteViews object
		RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.vocab_widget);
		
		views.setTextViewText(R.id.txtWord, word);
		views.setTextViewText(R.id.txtMeaning, meaning);
		
		boolean isTTS = prefs.getBoolean(SettingsActivity.TTS_PREF, false);
		if (isTTS) {
			views.setOnClickPendingIntent(R.id.btnSpeaker, getPendingSelfIntent(context, ACTION_SPEAKER, word, meaning));
			views.setViewVisibility(R.id.btnSpeaker, View.VISIBLE);
		} else {
			views.setViewVisibility(R.id.btnSpeaker, View.GONE);
		}
		
		//...
		
	}
	
    private static PendingIntent getPendingSelfIntent(Context context, String action, String... content) {
        Intent intent = new Intent(context, VocabWidget.class);
        intent.setAction(action);
        if (content != null && content.length == 2) {
        	intent.putExtra(SpeechService.EXTRA_WORD, content[0]);
        	intent.putExtra(SpeechService.EXTRA_MEANING, content[1]);
        }
        return PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
    }
    
    @Override
    public void onReceive(Context context, Intent intent) {
        if (ACTION_SPEAKER.equals(intent.getAction())) {
        	Intent speechIntent = new Intent(context, SpeechService.class);
        	speechIntent.putExtra(SpeechService.EXTRA_WORD, intent.getStringExtra(SpeechService.EXTRA_WORD));
        	speechIntent.putExtra(SpeechService.EXTRA_MEANING, intent.getStringExtra(SpeechService.EXTRA_MEANING));
        	context.startService(speechIntent);
        	
        } else if (ACTION_UPDATE.equals(intent.getAction())) {
        	onUpdate(context);
        	
        } else super.onReceive(context, intent);
    }	
					
We check whether TTS is enabled or not before displaying speaker button on the widget. Clicking this button by user results in starting our SpeechService with the text passed as extras. The service gets automatically stopped as discussed before.
Share the love:  

Next Page » 4

App Gen
App Name:
Project Name:
Package:
Screens:
Splash
Login
Help
Main
List  Grid  Pager
Detail
Settings
Options:
Action Bar
Navigation Drawer
Dummy Data
Generate
Free Apps