Android Open Source - K6nele Chunked Web Rec Session Builder






From Project

Back to project page K6nele.

License

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.

Java Source Code

/*
 * 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;
  }
}




Java Source Code List

ee.ioc.phon.android.speak.AboutActivity.java
ee.ioc.phon.android.speak.AppListActivity.java
ee.ioc.phon.android.speak.AppListCursorAdapter.java
ee.ioc.phon.android.speak.AudioCue.java
ee.ioc.phon.android.speak.AudioPauser.java
ee.ioc.phon.android.speak.Caller.java
ee.ioc.phon.android.speak.ChunkedWebRecSessionBuilder.java
ee.ioc.phon.android.speak.Constants.java
ee.ioc.phon.android.speak.DetailsActivity.java
ee.ioc.phon.android.speak.ExecutableString.java
ee.ioc.phon.android.speak.Executable.java
ee.ioc.phon.android.speak.Extras.java
ee.ioc.phon.android.speak.GetLanguageDetailsReceiver.java
ee.ioc.phon.android.speak.GrammarListActivity.java
ee.ioc.phon.android.speak.Log.java
ee.ioc.phon.android.speak.MicButton.java
ee.ioc.phon.android.speak.OnSwipeTouchListener.java
ee.ioc.phon.android.speak.PackageNameRegistry.java
ee.ioc.phon.android.speak.PreferencesRecognitionServiceHttp.java
ee.ioc.phon.android.speak.PreferencesRecognitionServiceWs.java
ee.ioc.phon.android.speak.Preferences.java
ee.ioc.phon.android.speak.RawAudioRecorder.java
ee.ioc.phon.android.speak.RecognizerIntentActivity.java
ee.ioc.phon.android.speak.RecognizerIntentListActivity.java
ee.ioc.phon.android.speak.RecognizerIntentService.java
ee.ioc.phon.android.speak.RecognizerIntent.java
ee.ioc.phon.android.speak.ServerListActivity.java
ee.ioc.phon.android.speak.SpeechRecognitionService.java
ee.ioc.phon.android.speak.Utils.java
ee.ioc.phon.android.speak.VoiceImeService.java
ee.ioc.phon.android.speak.VoiceImeView.java
ee.ioc.phon.android.speak.WebSocketRecognizer.java
ee.ioc.phon.android.speak.WebSocketResponse.java
ee.ioc.phon.android.speak.demo.AbstractRecognizerDemoActivity.java
ee.ioc.phon.android.speak.demo.ExtrasDemo.java
ee.ioc.phon.android.speak.demo.RepeaterDemo.java
ee.ioc.phon.android.speak.demo.SimpleDemo.java
ee.ioc.phon.android.speak.demo.VoiceSearchDemo.java
ee.ioc.phon.android.speak.provider.App.java
ee.ioc.phon.android.speak.provider.AppsContentProvider.java
ee.ioc.phon.android.speak.provider.BaseColumnsImpl.java
ee.ioc.phon.android.speak.provider.FileContentProvider.java
ee.ioc.phon.android.speak.provider.Grammar.java
ee.ioc.phon.android.speak.provider.Server.java