Create an App Widget in Android with Text-to-Speech (TTS)
DownloadKeywords: AppWidgetProvider RemoteViews AppWidgetManager BroadcastReceiver Widget Configuration Activity AlarmManager TextToSpeech Service PreferenceActivity OnPreferenceChangeListener
Contents- Overview
- Create a new Android project
- Create Vocab App Widget
- Android manifest
- The Widget Provider class
- The Widget layout
- Using AlarmManager to update App Widget
- The Widget Configuration activity
- The Widget Configuration layout
- Android Text-to-Speech (TTS) using Service
- Create a Settings screen
- What's next?
8. The Widget Configuration activity
We can (optionally) specify a configuration screen to be displayed to the user when the widget is added to the Home screen. We had opted for a configuration screen in the wizard so ADT has generated a default activity and layout.public class VocabWidgetConfigureActivity extends Activity { int mAppWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID; Spinner mRefreshIntervalSpn; public VocabWidgetConfigureActivity() { super(); } @Override public void onCreate(Bundle icicle) { super.onCreate(icicle); // Set the result to CANCELED. This will cause the widget host to cancel // out of the widget placement if the user presses the back button. setResult(RESULT_CANCELED); setContentView(R.layout.vocab_widget_configure); mRefreshIntervalSpn = (Spinner) findViewById(R.id.refresh_interval_spinner); findViewById(R.id.add_button).setOnClickListener(mOnClickListener); // Find the widget id from the intent. Intent intent = getIntent(); Bundle extras = intent.getExtras(); if (extras != null) { mAppWidgetId = extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID); } // If this activity was started with an intent without an app widget ID, // finish with an error. if (mAppWidgetId == AppWidgetManager.INVALID_APPWIDGET_ID) { finish(); return; } mRefreshIntervalSpn.setSelection(getSelectedPosition(loadIntervalPref(this, mAppWidgetId))); } private int getSelectedPosition(String interval) { String[] values = getResources().getStringArray(R.array.refresh_interval_values); for (int i=0; i<values.length; i++) { if (values[i].equals(interval)) return i; } return 0; } View.OnClickListener mOnClickListener = new View.OnClickListener() { public void onClick(View v) { final Context context = VocabWidgetConfigureActivity.this; // When the button is clicked, store the string locally String[] values = getResources().getStringArray(R.array.refresh_interval_values); String widgetText = values[mRefreshIntervalSpn.getSelectedItemPosition()]; saveIntervalPref(context, mAppWidgetId, widgetText); // Make sure we pass back the original appWidgetId Intent resultValue = new Intent(); resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId); setResult(RESULT_OK, resultValue); finish(); } }; // Write the prefix to the SharedPreferences object for this widget static void saveIntervalPref(Context context, int appWidgetId, String text) { SharedPreferences.Editor prefs = PreferenceManager.getDefaultSharedPreferences(context).edit(); prefs.putString(SettingsActivity.INTERVAL_PREF, text); prefs.commit(); } // Read the prefix from the SharedPreferences object for this widget. // If there is no preference saved, get the default from a resource static String loadIntervalPref(Context context, int appWidgetId) { SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); String interval = prefs.getString(SettingsActivity.INTERVAL_PREF, SettingsActivity.DEFAULT_INTERVAL); return interval; } }The configuration activity is launched by the App Widget host so we need to pass back RESULT_OK with appWidgetId so that the widget gets added.
The code is straight-forward and due to simplicity of the screen we have set a Dialog theme for the activity in the manifest.
<activity android:name=".VocabWidgetConfigureActivity" android:theme="@style/AppTheme.Dialog" > <intent-filter> <action android:name="android.appwidget.action.APPWIDGET_CONFIGURE" /> </intent-filter> </activity>Here is the styles for AppTheme.Dialog theme. Add the following snippet to res/values/styles.xml
<style name="AppTheme.Dialog" parent="android:Theme.Light"> <item name="android:windowNoTitle">true</item> <item name="android:windowFrame">@null</item> <item name="android:windowIsFloating">true</item> <item name="android:windowContentOverlay">@null</item> <item name="android:windowBackground">@android:color/white</item> <item name="android:maxWidth">600dp</item> <item name="android:windowAnimationStyle">@android:style/Animation.Dialog</item> </style>And the following snippet to res/values-v11/styles.xml
<style name="AppTheme.Dialog" parent="android:Theme.Holo.Light.Dialog"> <item name="android:windowNoTitle">true</item> <item name="android:windowCloseOnTouchOutside">true</item> </style>
9. The Widget Configuration layout
Modify vocab_widget.xml in res/layout as follows.<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:padding="16dp" android:gravity="center_horizontal" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="8dp" android:textStyle="bold" android:text="@string/configure" /> <Spinner android:id="@+id/refresh_interval_spinner" android:layout_width="wrap_content" android:layout_height="wrap_content" android:entries="@array/refresh_interval_titles" android:entryValues="@array/refresh_interval_values" /> <Button android:id="@+id/add_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="8dp" android:text="@string/add_widget" /> </LinearLayout>The entries and values for refresh interval spinner is defined as string arrays in res/values/strings.xml resource file.
<string-array name="refresh_interval_titles"> <item>15 minutes</item> <item>30 minutes</item> <item>1 hour</item> <item>3 hours</item> <item>6 hours</item> </string-array> <string-array name="refresh_interval_values"> <item>15</item> <item>30</item> <item>60</item> <item>180</item> <item>360</item> </string-array>Next, we'll see how to add Text-to-speech (TTS) functionality in an Android app.