summaryrefslogtreecommitdiffstats
path: root/src/com/android/settings/VoiceInputOutputSettings.java
diff options
context:
space:
mode:
authorMike LeBeau <mlebeau@android.com>2010-02-11 22:57:12 -0800
committerMike LeBeau <mlebeau@android.com>2010-02-12 13:45:04 -0800
commit766a19b27883c478ec263eb93dc5cc820b00b7af (patch)
tree855ffadf2df322090c2c041910da6ff6867cacbc /src/com/android/settings/VoiceInputOutputSettings.java
parenteadeebd1df04405e71d5a7b4dfba08d6d6afcc27 (diff)
downloadpackages_apps_Settings-766a19b27883c478ec263eb93dc5cc820b00b7af.zip
packages_apps_Settings-766a19b27883c478ec263eb93dc5cc820b00b7af.tar.gz
packages_apps_Settings-766a19b27883c478ec263eb93dc5cc820b00b7af.tar.bz2
Dynamically populate a list of available recognition services in voice settings,
only showing the option to choose if there is more than one to choose from. Use the new settingsActivity meta-data to target the appropriate settings activity for the chosen recognizer.
Diffstat (limited to 'src/com/android/settings/VoiceInputOutputSettings.java')
-rw-r--r--src/com/android/settings/VoiceInputOutputSettings.java181
1 files changed, 159 insertions, 22 deletions
diff --git a/src/com/android/settings/VoiceInputOutputSettings.java b/src/com/android/settings/VoiceInputOutputSettings.java
index 7586bd0..62c909f 100644
--- a/src/com/android/settings/VoiceInputOutputSettings.java
+++ b/src/com/android/settings/VoiceInputOutputSettings.java
@@ -16,55 +16,192 @@
package com.android.settings;
-import android.content.Context;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import android.content.ComponentName;
import android.content.Intent;
import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
+import android.content.res.TypedArray;
+import android.content.res.XmlResourceParser;
import android.os.Bundle;
+import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.PreferenceActivity;
+import android.preference.PreferenceCategory;
import android.preference.PreferenceGroup;
+import android.preference.PreferenceScreen;
+import android.preference.Preference.OnPreferenceChangeListener;
+import android.provider.Settings;
+import android.speech.RecognitionService;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.util.Xml;
+import java.io.IOException;
+import java.util.HashMap;
import java.util.List;
/**
* Settings screen for voice input/output.
*/
-public class VoiceInputOutputSettings extends PreferenceActivity {
+public class VoiceInputOutputSettings extends PreferenceActivity
+ implements OnPreferenceChangeListener {
+
+ private static final String TAG = "VoiceInputOutputSettings";
private static final String KEY_PARENT = "parent";
- private static final String KEY_VOICE_SEARCH_SETTINGS = "voice_search_settings";
- private static final String KEY_KEYBOARD_SETTINGS = "keyboard_settings";
+ private static final String KEY_VOICE_INPUT_CATEGORY = "voice_input_category";
+ private static final String KEY_RECOGNIZER = "recognizer";
+ private static final String KEY_RECOGNIZER_SETTINGS = "recognizer_settings";
+
+ private PreferenceGroup mParent;
+ private PreferenceCategory mVoiceInputCategory;
+ private ListPreference mRecognizerPref;
+ private PreferenceScreen mSettingsPref;
+
+ private HashMap<String, ResolveInfo> mAvailableRecognizersMap;
@Override
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
addPreferencesFromResource(R.xml.voice_input_output_settings);
+
+ mParent = (PreferenceGroup) findPreference(KEY_PARENT);
+ mVoiceInputCategory = (PreferenceCategory) mParent.findPreference(KEY_VOICE_INPUT_CATEGORY);
+ mRecognizerPref = (ListPreference) mParent.findPreference(KEY_RECOGNIZER);
+ mRecognizerPref.setOnPreferenceChangeListener(this);
+ mSettingsPref = (PreferenceScreen) mParent.findPreference(KEY_RECOGNIZER_SETTINGS);
+
+ mAvailableRecognizersMap = new HashMap<String, ResolveInfo>();
- removePreferenceIfNecessary(KEY_VOICE_SEARCH_SETTINGS);
- removePreferenceIfNecessary(KEY_KEYBOARD_SETTINGS);
+ populateOrRemoveRecognizerPreference();
}
-
- /**
- * Removes a preference if there is no activity to handle its intent.
- */
- private void removePreferenceIfNecessary(String preferenceKey) {
- PreferenceGroup parent = (PreferenceGroup) findPreference(KEY_PARENT);
+
+ private void populateOrRemoveRecognizerPreference() {
+ List<ResolveInfo> availableRecognitionServices = getPackageManager().queryIntentServices(
+ new Intent(RecognitionService.SERVICE_INTERFACE), PackageManager.GET_META_DATA);
+ int numAvailable = availableRecognitionServices.size();
- Preference preference = parent.findPreference(preferenceKey);
- if (preference == null) {
- return;
+ if (numAvailable == 0) {
+ // No recognizer available - remove all related preferences.
+ removePreference(mVoiceInputCategory);
+ removePreference(mRecognizerPref);
+ removePreference(mSettingsPref);
+ } else if (numAvailable == 1) {
+ // Only one recognizer available, so don't show the list of choices.
+ removePreference(mRecognizerPref);
+ } else {
+ // Multiple recognizers available, so show the full list of choices.
+ populateRecognizerPreference(availableRecognitionServices);
+ }
+ }
+
+ private void removePreference(Preference pref) {
+ if (pref != null) {
+ mParent.removePreference(pref);
}
+ }
+
+ private void populateRecognizerPreference(List<ResolveInfo> recognizers) {
+ int size = recognizers.size();
+ CharSequence[] entries = new CharSequence[size];
+ CharSequence[] values = new CharSequence[size];
+
+ // Get the current value from the secure setting.
+ String currentSetting = Settings.Secure.getString(
+ getContentResolver(), Settings.Secure.VOICE_RECOGNITION_SERVICE);
+
+ // Iterate through all the available recognizers and load up their info to show
+ // in the preference. Also build up a map of recognizer component names to their
+ // ResolveInfos - we'll need that a little later.
+ for (int i = 0; i < size; i++) {
+ ResolveInfo resolveInfo = recognizers.get(i);
+ String recognizerComponent =
+ new ComponentName(resolveInfo.serviceInfo.packageName,
+ resolveInfo.serviceInfo.name).flattenToString();
+
+ mAvailableRecognizersMap.put(recognizerComponent, resolveInfo);
- Intent intent = preference.getIntent();
- if (intent != null) {
- PackageManager pm = getPackageManager();
- if (!pm.queryIntentActivities(intent, 0).isEmpty()) {
- return;
+ entries[i] = resolveInfo.loadLabel(getPackageManager());
+ values[i] = recognizerComponent;
+ }
+
+ mRecognizerPref.setEntries(entries);
+ mRecognizerPref.setEntryValues(values);
+
+ mRecognizerPref.setDefaultValue(currentSetting);
+ mRecognizerPref.setValue(currentSetting);
+
+ updateSettingsLink(currentSetting);
+ }
+
+ private void updateSettingsLink(String currentSetting) {
+ ResolveInfo currentRecognizer = mAvailableRecognizersMap.get(currentSetting);
+ ServiceInfo si = currentRecognizer.serviceInfo;
+ XmlResourceParser parser = null;
+ String settingsActivity = null;
+ try {
+ parser = si.loadXmlMetaData(getPackageManager(), RecognitionService.SERVICE_META_DATA);
+ if (parser == null) {
+ throw new XmlPullParserException("No " + RecognitionService.SERVICE_META_DATA +
+ " meta-data for " + si.packageName);
}
+
+ AttributeSet attrs = Xml.asAttributeSet(parser);
+
+ int type;
+ while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
+ && type != XmlPullParser.START_TAG) {
+ }
+
+ String nodeName = parser.getName();
+ if (!"recognition-service".equals(nodeName)) {
+ throw new XmlPullParserException(
+ "Meta-data does not start with recognition-service tag");
+ }
+
+ TypedArray array = getResources().obtainAttributes(attrs,
+ com.android.internal.R.styleable.RecognitionService);
+ settingsActivity = array.getString(
+ com.android.internal.R.styleable.RecognitionService_settingsActivity);
+ array.recycle();
+ } catch (XmlPullParserException e) {
+ Log.e(TAG, "error parsing recognition service meta-data", e);
+ } catch (IOException e) {
+ Log.e(TAG, "error parsing recognition service meta-data", e);
+ } finally {
+ if (parser != null) parser.close();
}
- // Did not find a matching activity, so remove the preference.
- parent.removePreference(preference);
+ if (settingsActivity == null) {
+ // No settings preference available - hide the preference.
+ Log.w(TAG, "no recognizer settings available for " + si.packageName);
+ mSettingsPref.setIntent(null);
+ mParent.removePreference(mSettingsPref);
+ } else {
+ Intent i = new Intent(Intent.ACTION_MAIN);
+ i.setComponent(new ComponentName(si.packageName, settingsActivity));
+ mSettingsPref.setIntent(i);
+ }
+ }
+
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ if (preference == mRecognizerPref) {
+ String setting = (String) newValue;
+
+ // Put the new value back into secure settings.
+ Settings.Secure.putString(
+ getContentResolver(),
+ Settings.Secure.VOICE_RECOGNITION_SERVICE,
+ setting);
+
+ // Update the settings item so it points to the right settings.
+ updateSettingsLink(setting);
+ }
+ return true;
}
}