package ee.ioc.phon.android.speak; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.content.res.Resources; import android.content.res.TypedArray; import android.os.Bundle; import android.speech.RecognizerIntent; import android.speech.SpeechRecognizer; import android.text.TextUtils; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Set; import ee.ioc.phon.android.speak.model.CallerInfo; import ee.ioc.phon.android.speak.utils.Utils; import ee.ioc.phon.android.speechutils.Extras; import ee.ioc.phon.android.speechutils.RecognitionServiceManager; import ee.ioc.phon.android.speechutils.utils.IntentUtils; import ee.ioc.phon.android.speechutils.utils.PreferenceUtils; public class ServiceLanguageChooser { private final Context mContext; private final SharedPreferences mPrefs; private final List<String> mCombosAsList; private final CallerInfo mCallerInfo; private final int mKeyCurrentCombo; private int mIndex; private SpeechRecognizer mSpeechRecognizer; private Intent mIntent; private String mLanguage = null; private ComponentName mRecognizerComponentName = null; public ServiceLanguageChooser(Context context, SharedPreferences prefs, int keys, CallerInfo callerInfo) { mContext = context; mPrefs = prefs; mCallerInfo = callerInfo; // If SERVICE_COMPONENT is defined, we do not use the combos selected in the settings. String comboOverride = null; Bundle extras = callerInfo.getExtras(); if (extras.containsKey(Extras.EXTRA_SERVICE_COMPONENT)) { comboOverride = extras.getString(Extras.EXTRA_SERVICE_COMPONENT); if (extras.containsKey(RecognizerIntent.EXTRA_LANGUAGE)) { comboOverride = RecognitionServiceManager.createComboString(comboOverride, extras.getString(RecognizerIntent.EXTRA_LANGUAGE)); } } if (comboOverride == null) { Resources res = context.getResources(); TypedArray keysAsTypedArray = res.obtainTypedArray(keys); int keyCombo = keysAsTypedArray.getResourceId(0, 0); mKeyCurrentCombo = keysAsTypedArray.getResourceId(1, 0); int defaultCombos = keysAsTypedArray.getResourceId(2, 0); keysAsTypedArray.recycle(); Set<String> mCombos = PreferenceUtils.getPrefStringSet(prefs, res, keyCombo); if (mCombos == null || mCombos.isEmpty()) { // If the user has chosen an empty set of combos mCombosAsList = PreferenceUtils.getStringListFromStringArray(res, defaultCombos); } else { mCombosAsList = new ArrayList<>(mCombos); } String currentCombo = PreferenceUtils.getPrefString(prefs, res, mKeyCurrentCombo); mIndex = mCombosAsList.indexOf(currentCombo); // If the current combo was not found among the choices then select the first combo. if (mIndex == -1) { mIndex = 0; PreferenceUtils.putPrefString(prefs, res, mKeyCurrentCombo, mCombosAsList.get(0)); } } else { mCombosAsList = Collections.singletonList(comboOverride); mIndex = 0; mKeyCurrentCombo = -1; } update(); } public SpeechRecognizer getSpeechRecognizer() { return mSpeechRecognizer; } public int size() { return mCombosAsList.size(); } public Intent getIntent() { return mIntent; } /** * Switch to the "next" combo and set it as default. * Only done if there are more than 1 combos, meaning that defining SERVICE_COMPONENT (which * creates a single-element combo list) does not change the default combo. */ public void next() { if (size() > 1) { if (++mIndex >= size()) { mIndex = 0; } PreferenceUtils.putPrefString(mPrefs, mContext.getResources(), mKeyCurrentCombo, mCombosAsList.get(mIndex)); } update(); } public String getCombo() { return mCombosAsList.get(mIndex); } public String getLanguage() { return mLanguage; } public ComponentName getService() { return mRecognizerComponentName; } private void update() { String language = null; String[] splits = TextUtils.split(getCombo(), ";"); mRecognizerComponentName = ComponentName.unflattenFromString(splits[0]); if (splits.length > 1) { language = splits[1]; } // If the stored combo name does not refer to an existing service on the device then we use // the default service. This can happen if services get removed or renamed. if (mRecognizerComponentName == null || !IntentUtils.isRecognitionAvailable(mContext, mRecognizerComponentName)) { mSpeechRecognizer = SpeechRecognizer.createSpeechRecognizer(mContext); } else { mSpeechRecognizer = SpeechRecognizer.createSpeechRecognizer(mContext, mRecognizerComponentName); } // TODO: support other actions mIntent = Utils.getRecognizerIntent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH, mCallerInfo, language); mLanguage = language; } }