Back to project page K6nele.
The source code is released under:
Apache License
If you think the Android project K6nele listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.
/* * Copyright 2012-2013, Institute of Cybernetics at Tallinn University of Technology *// w w w . j av a 2 s .c om * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package ee.ioc.phon.android.speak; import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import java.util.List; import java.util.Locale; import android.app.PendingIntent; import android.content.ComponentName; import android.content.Context; import android.content.SharedPreferences; import android.os.Build; import android.os.Bundle; import android.preference.PreferenceManager; import ee.ioc.phon.netspeechapi.recsession.ChunkedWebRecSession; /** * <p>Builds a query for the speech recognizer server combing information from * various sources:</p> * * <ul> * <li>input extras</li> * <li>name of the calling app</li> * <li>stored preferences</li> * <li>app/grammar database</li> * </ul> * * <p>The following is some of the information that is sent to the server along with the audio.</p> * * <pre> * contentType * content type of the audio (e.g. "audio/x-flac;rate=16000") * serverUrl * URL of the recognizer server * grammarUrl * URL of the speech recognition grammar * grammarTargetLang * name of the target language (in case of GF grammars) * nbest * number of requested hypothesis * </pre> */ public class ChunkedWebRecSessionBuilder { public static final int MAX_RESULTS = 5; private final Context mContext; private URL mWsUrl; private URL mLmUrl; private int mNbest; private String mGrammarTargetLang; private String mLang; private boolean mPartialResults = false; private String mPhrase; private String mContentType; private String mUserAgentComment; private String mDeviceId; private String mCaller; public ChunkedWebRecSessionBuilder(Context context, Bundle extras, ComponentName callingActivity) throws MalformedURLException { mContext = context; if (extras == null) { extras = new Bundle(); } if (Log.DEBUG) Log.i(Utils.ppBundle(extras)); SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); mDeviceId = Utils.getUniqueId(prefs); PendingIntent pendingIntent = Utils.getPendingIntent(extras); if (callingActivity == null) { Caller caller1 = new Caller(pendingIntent, extras); mCaller = caller1.getActualCaller(); setUserAgentComment(caller1.toString()); } else { // TODO: integrate this into the caller-object mCaller = getCaller(callingActivity, pendingIntent); setUserAgentComment(mCaller); } // Calling the constructor modifies the database PackageNameRegistry wrapper = new PackageNameRegistry(context, mCaller); String urlService = prefs.getString(context.getString(R.string.keyServerHttp), context.getString(R.string.defaultServerHttp)); setFromExtras(extras, wrapper, urlService); mNbest = makeNbest(extras, callingActivity); } public void setUserAgentComment(String caller) { // TODO: rename "RecognizerIntentActivity" to "K6nele" mUserAgentComment = Utils.makeUserAgentComment("RecognizerIntentActivity", Utils.getVersionName(mContext), caller); } public void setContentType(String contentType) { mContentType = contentType; } public void setContentType(int sampleRate) { setContentType(makeContentType(sampleRate)); } public String getLang() { return mLang; } public String getDeviceId() { return mDeviceId; } public URL getServerUrl() { return mWsUrl; } public URL getGrammarUrl() { return mLmUrl; } public String getGrammarTargetLang() { return mGrammarTargetLang; } public String getCaller() { return mCaller; } public String getUserAgentComment() { return mUserAgentComment; } public boolean isPartialResults() { return mPartialResults; } public ChunkedWebRecSession build() { ChunkedWebRecSession recSession = new ChunkedWebRecSession(mWsUrl, mLmUrl, mGrammarTargetLang, mNbest); if (mPhrase != null) { recSession.setPhrase(mPhrase); } if (mLang != null) { recSession.setLang(mLang); } if (mUserAgentComment != null) { recSession.setUserAgentComment(mUserAgentComment); } if (mContentType != null) { recSession.setContentType(mContentType); } if (mDeviceId != null) { recSession.setDeviceId(mDeviceId); } if (mPartialResults) { recSession.setParam("partial", "true"); } return recSession; } public List<String> toStringArrayList() { List<String> list = new ArrayList<String>(); list.add(mWsUrl == null ? null : mWsUrl.toString()); list.add(mLmUrl == null ? null : mLmUrl.toString()); list.add(mContentType); list.add(mGrammarTargetLang); list.add(mLang); list.add(mNbest + ""); list.add(mPhrase); list.add(mDeviceId); list.add(mUserAgentComment); list.add(mPartialResults + ""); return list; } private void setFromExtras(Bundle extras, PackageNameRegistry wrapper, String urlServer) throws MalformedURLException { mLang = makeLang(extras); mPartialResults = extras.getBoolean(RecognizerIntent.EXTRA_PARTIAL_RESULTS); // K6nele-specific extras mPhrase = extras.getString(Extras.EXTRA_PHRASE); mGrammarTargetLang = Utils.chooseValue(wrapper.getGrammarLang(), extras.getString(Extras.EXTRA_GRAMMAR_TARGET_LANG)); // The server URL should never be null mWsUrl = new URL( Utils.chooseValue( wrapper.getServerUrl(), extras.getString(Extras.EXTRA_SERVER_URL), urlServer )); // If the user has not overridden the grammar then use the app's EXTRA. String urlAsString = Utils.chooseValue(wrapper.getGrammarUrl(), extras.getString(Extras.EXTRA_GRAMMAR_URL)); if (urlAsString != null && urlAsString.length() > 0) { mLmUrl = new URL(urlAsString); } } /** * <p>Returns the package name of the app that receives the transcription, * or <code>null</code> if the package name could not be resolved.</p> */ private String getCaller(ComponentName callingActivity, PendingIntent pendingIntent) { if (pendingIntent == null) { if (callingActivity != null) { return callingActivity.getPackageName(); } } else { return pendingIntent.getTargetPackage(); } return null; } private static String makeContentType(int sampleRate) { // little endian = 1234 // big endian = 4321 return "audio/x-raw-int,channels=1,signed=true,endianness=1234,depth=16,width=16,rate=" + sampleRate; } /** * <p>If {@code EXTRA_MAX_RESULTS} was set (i.e. it is larger than 0) then we * pass it on to the server.</p> * <p>If it was not set then we check the type of the language model (this is an obligatory input parameter). * If the language model is unset (e.g. K6nele was launched via its own launcher icon), or * the model is "web search" (this is the case with some web browsers), then we ask the server * for several results. (TODO: this could be user-configurable.) * Otherwise we ask for just a single result.</p> */ private static int makeNbest(Bundle extras, ComponentName callingActivity) { int maxResults = extras.getInt(RecognizerIntent.EXTRA_MAX_RESULTS); if (maxResults <= 0) { String model = extras.getString(RecognizerIntent.EXTRA_LANGUAGE_MODEL); if (model == null || model.equals(RecognizerIntent.LANGUAGE_MODEL_WEB_SEARCH)) { return MAX_RESULTS; } else { return 1; } } return maxResults; } /** * <p>We choose the input language, preferring the language specified in EXTRA_LANGUAGE, * if this is unspecified then we look into the bundle to see if "selectedLanguage" is set * (by an IME). If this is also unspecified then we return the current locale as required * by the Android specification: * {@link http://developer.android.com/reference/android/speech/RecognizerIntent.html#EXTRA_LANGUAGE}</p> * * <blockquote> * <p>Optional IETF language tag (as defined by BCP 47), for example "en-US". * This tag informs the recognizer to perform speech recognition in a * language different than the one set in the getDefault().</p> * </blockquote> */ private String makeLang(Bundle extras) { String lang = extras.getString(RecognizerIntent.EXTRA_LANGUAGE); if (lang != null) { return lang; } // If EXTRA_LANGUAGE is not set but the bundle contains "selectedLanguage" (as is the case with some IMEs) // then use a value from the latter. Object selectedLanguage = Utils.getBundleValue(extras, "selectedLanguage"); if (selectedLanguage != null) { return selectedLanguage.toString(); } SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(mContext); if (prefs.getBoolean(mContext.getString(R.string.keyRespectLocale), false)) { Locale locale = Locale.getDefault(); if (locale != null) { return locale.toString(); } } return null; } }