Wednesday, January 28, 2015

The fastest route between voice search and your app

A very cool feature you can add to your Android app is integrating with Google's voice search.

When enabled, your users will be able to say to their phone:

  "Ok Google, search for flights from NY to LA on MyCoolTravelApp"

The good news is this integration is very simple, and Eva is a perfect match to parse any text provided by the user.

3 small steps are necessary:

1. To AndroidManifest.xml  change the your Activity entry with:

            android:launchMode="singleTask"    >
           <action android:name=""/>
           <category android:name="android.intent.category.DEFAULT"/>

2. To your search activity - add:

protected void onNewIntent(Intent intent) {

3. at the end of onResume method add:

Intent intent = getIntent();
if ("".equals(intent.getAction())) {
         // search from Google Voice Search:
         // similar to clearing session and then handling voice-recognition results
         // When starting a new session you'd want to clear the chat screen
         String searchString = intent.getStringExtra(SearchManager.QUERY);|
         // Add the user chat and initiate an eva search
        eva.searchWithText(searchString, null, false);
        // clear the intent - it shouldn't run again when resuming
       onNewIntent(new Intent());

  1. If your search activity is not the top level activity in your app you may wish to setup a back stack - see the relevant Android documentation.
  2. The Google Voice integration will not work until you publish your app to the Play store with the updated AndroidManifest.
    To test it can send the intent via adb, for example:
    adb shell am start -a -e query Flights from NY to LA <app package name here>

Tuesday, January 27, 2015

Using Eva's Android SDK

This post will describe how to integrate Eva in an Android Project.

SDK Structure
The SDK comes with three directories:

  • EvaAPIs: The Eva SDK 
  • android_demo:  A minimal demo that allows sending text to Eva and displays the response on the screen.
  • android_search: A larger sample application which demonstrates Eva’s usage for searching for hotels. The application can search and book hotels using Expedia API. It has a Google map display, however to use it you must use your own API keys (Expedia, Google maps, Vayant).

Download or clone the SDK from:

How to use the SDK

  1. Import the EvaAPIs project to your Eclipse workspace as an existing Android Project.
  2. Add EvaAPIs as a library to your own project -
    1. Right click your project, choose “properties”. 
    2. Click “Android” in the left side menu.
    3. Add a reference to the EvaAPIs project.
  3.  Add required permissions to your AndroidManifest:

    Required permissions:

    If you want to use the voice based search you also need:
At this point you can start using Evature SDK -

A minimal integration is very simple:
  1. extend EvaBaseActivity
  2. override the onEvaReply listener callback to handle Eva reply
  3. call "searchWithText" or "searchWithVoice" methods to send user input to Eva.

Class Reference


Reply object for Eva, populated into java classes.
Documentation for it can be found  at:


Base activity for activities that use the Eva SDK. 

Many Android frameworks and libraries require you to extend your main activity from a base class (eg. RoboGuice, ActionbarSherlock, more…) . This is problematic since Java does not allow multiple inheritance and so only one such library can be used. Eva SDK is compatible with such libraries - you can use Eva without extending the base class but it requires more “wiring” and isn’t recommended if not required. See the section below on using Eva without extending from a base class.  

public methods:

void speak(String sayIt, [boolean flush])
Uses TTS to say a string.  Eva will delay the speech until the TTS (Text to speech) engine is ready, so calling speak(“hello”)  in onCreate of the activity may be delayed by a few seconds.
If the flush parameter is true (defualt) then calling a second speak while a first is still playing will stop the first speech.   eg. use speak(“”) to stop the speech.

void searchWithVoice(Object cookie, boolean editLastUtterance)
Eva will start a recording of user. When silence is detected (after a period of non-silence) the recording is automatically stopped.
The user speech will be used as input text by Eva to generate the result.
It is essential to stop TTS before starting a recording - call speak(“”)
It is essential to let the user know he is being recorded -
We strongly recommend to play a short “beep” before starting the recording, and also show a visual mark that a recording is ongoing. If you add a visual mark you should override speechResultOK and speechResultError (see below) to disable the visual mark when the recording completes.
See “visual feedback of ongoing recording” below for optional visual feedback provided by Eva.

  • editLastUtterance:  tell Eva the current input replaces the previous one. 
  • cookie: The cookie parameter will be returned untouched with the search result callback, this can be used to store data known when the search is triggered and which useful when the result arrives. Pass null if not needed.

void searchWithText(String text  , Object cookie, boolean editLastUtterance)
Send a query to Eva with text instead of voice. The result will trigger a callback onEvaReply  (see below).
  • text: Text to query for 
  • cookie, editLastUtterance: see above.

void replyToDialog(int replyIndex, Object cookie)
When confronted with a multiple choice question in an Eva Reply, the answer chosen by the user should be sent using this function.

boolean isNewSession()
Returns true if the current state is of a new session.

void resetSession()
Start a new session.

void cancelSearch()
Stop an ongoing search - no callback will be activated.

The class includes different getters and setters for configuration of Eva - for example:
apiKey, siteCode - the credentials to use Eva.
locale -  see
language - auto translated input_text and EvaReply, and also change the TTS language.
context - see

Method Overrides:

public void onEvaReply(EvaApiReply reply, Object cookie)  
Override this method to get the EvaReply from a voice or text search. Cookie is the object that was passed to the search request which triggered this reply.

public void newSessionStarted(boolean selfTriggered)
Called when a new session has started. If the parameter is true this is in response to a  resetSession call, otherwise it means Eva’s logic decided that the previous request started a new session.

this method is called when a valid response is returned. The first parameter is the response string that can be passed to EvaApiReply constructor. 

called when there is an error (such as connection timeout) and the parameter is the error message. The default behaviour is to show the message in a Toast.

Advanced use cases

Using Eva without extending a base class

Many Android frameworks and libraries require you to extend your main activity from a base class (eg. RoboGuice, ActionbarSherlock, more…). This is problematic since Java does not allow multiple inheritance and so only one such library can be used. 

To overcome this problem you can use Eva without extending a base class. To do so follow the following steps:

Create a com.evaapis.EvaSearchReplyListener.
Create a field of type EvaComponent  - the constructor requires two parameters:  Activity and EvaSearchReplyListener.
In your activity’s onCreate, onResume, onPause, onActivityResult, onDestroy methods call the matching methods on the EvaComponent field.  
At this point you can use the methods described above for EvaBaseActivity - but activate them on the EvaComponent object or EvaSpeechComponent.

Visual feedback of ongoing recording

While the recording is ongoing, you can poll Eva for data such as current volume or even a buffer of the previous samples. This data can be visualized on the screen, for example brighter background color on higher volume. 

Data for visualization can be queried from the class SpeechAudioStreamer which can be retrieved from the EvaSpeechComponent using 
Polling the recorder state and updating GUI can be done using android.os.Handler class. 
For example:

updateLevel = new Handler()  {
   public void handleMessage(Message msg) {
      SpeechAudioStreamer  speechAudioStreamer = speechSearch.getSpeechAudioStreamer();
      //   can read audio state from speechAudioStreamer here and update GUI based on it
      sendEmptyMessageDelayed(0, 50); // poll the statistics every 50ms
// send initial message to start the polling
updateLevel.sendEmptyMessageDelayed(0, 50);
// start the recording

Eva provides a widget to visualize the wave-form of the recording, the class SoundView. To update it run:

soundView.setSoundData(  speechAudioStreamer.getSoundLevelBuffer(),

Using Eva's iOS SDK

This Blog post will describe how to install and use Eva SDK for iOS.

Project Setup and Installation

Download & Install the SDK

  1. Download the SDK:
    git clone

    or download the file:
  2. Make sure you are using the latest version of Xcode and targeting iOS6.0 or higher.
  3. Drag Eva.framework folder to your Xcode project folder target (Make sure the “Copy items to destination’s group folder is checked).

  4.  Click on the Targets -> Your app name -> and then “build phases” tab, and then expand “Link binary with libraries”
  5. Add the following libraries:

Code Integration

UI Views Integration

1. Go to your “AppDelegate.m” file, and add this line:

#import <Eva/Eva.h>

And add the following lines to  didFinishLaunchingWithOptions:

-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
     [[Eva sharedInstance] setAPIkey:@"YOUR-API-KEY" withSiteCode:@"YOUR-SITE-CODE"];

2. Go to “YourViewController.h” (Where you want to integrate Eva) and import Eva also:

#import <Eva/Eva.h>

Add EvaDelegate to the Controller delegates, File should look like that:

#import <Eva/Eva.h>
@interface YourViewController : UIViewController < EvaDelegate>{

3. Now, set the delegate in viewWillAppear:

    [Eva sharedInstance].delegate = self; // Setting the delegate to this view //
    // The delegate initiation is here for it to be set-up every time this view is called //

Do steps 2 to 3 to every view you want to integrate Eva.

Using Eva and Handling the Results

1. Implement the two delegates (a must):

#pragma mark - Eva Delegate
- (void)evaDidReceiveData:(NSData *)dataFromServer{
     NSString* dataStr = [[NSString alloc] initWithData:dataFromServer encoding:NSASCIIStringEncoding];
    NSLog(@"Received data from Eva %@", dataStr);

- (void)evaDidFailWithError:(NSError *)error{
    NSLog(@"Got error from Eva");

2. To start recording a new session call:

[[Eva sharedInstance] startRecord:TRUE];

If you want to continue the previous session should you call:

[[Eva sharedInstance] startRecord:FALSE];

This would keep the previous session number.

3.  When you want to stop the record, please call:

[[Eva sharedInstance] stopRecord];

Record would stop automatically, eg when silent is detected.
Expect to get a delegate call just after that.

4.  Instead of quering Eva using a recording, you can send text to Eva. Do so using

- (BOOL)queryWithText:(NSString *)text startNewSession:(BOOL)newSession 

5.  All configurable parameters are optional. Those can be set, For example:

[[Eva sharedInstance] setHome:@"paris"];
[[Eva sharedInstance] setVersion: @"v1.0"];
(it is recommended to do all those settings in the AppDelegate.m file just before the setApiKey:withSiteCode function )

6.  You can add additional properties to the Eva request using Eva’s optional_- those will not be used but will be recorded in Eva’s logs. This can be useful for debugging. For example:

[Eva sharedInstance].optional_dictionary = @{@“app_version" : @“2"}; 

Playing Audio Files

Eva SDK supports playing audio files before and/or after the recording. 
To enable sounds you should call one of the four methods below:

1. -(BOOL)setStartRecordAudioFile:(NSURL *)filePath
   The file passed will play when StartRecord is called.

2. -(BOOL)setRequestedEndRecordAudioFile:(NSURL *)filePath
   This file will play when stopRecord is called.

3. -(BOOL)setVADEndRecordAudioFile:(NSURL *)filePath
   This file will play when VAD (Voice Activity Detection) decides the recording  has ended.

4. -(BOOL)setCanceledRecordAudioFile:(NSURL *)filePath
      This file will play when cancelRecord is called.

Setting audio files is optional - the default is to have no sounds activated. You should call these function only once when the application loads. To disable sounds you can call the functions with the filePath parameter set to NULL.

These functions will return FALSE in case of error (eg. file not found, wrong file format, etc…). The error description will appear in the log. 

Eva does not setup the AVAudioSession parameters for you.
If, for example, you wish the audio files to play using the device speaker and not the ear-piece you should run the following snippet (only once, when the application loads).

Setting AudioSession

NSLog(@"Setting Audio Session");
AVAudioSession *session = [AVAudioSession sharedInstance];
NSError *error;
[session setCategory:AVAudioSessionCategoryPlayAndRecord withOptions:AVAudioSessionCategoryOptionDefaultToSpeaker error:&error];
if (error != nil) {
     NSLog(@"Failed to setCategory %@", error);
[session setActive:YES error:&error];
if (error != nil) {
     NSLog(@"Failed setActive %@", error);

Advanced API Parameters

1. If you want to implement mic activity level inside your app, On either the Single View Project section or Multiple Views Project section, you should call:

[[Eva sharedInstance] setAPIkey:@"YOUR-API_KEY" withSiteCode:@"YOUR-SITE-CODE" withMicLevel:TRUE];

Instead of:

[[Eva sharedInstance] setAPIkey:@"YOUR-API_KEY" withSiteCode:@"YOUR-SITE-CODE"]; 

2. In case you set withMicLevel to TRUE you must implement:
-(void)evaMicLevelCallbackAverage: (float)averagePower andPeak: (float)peakPower;
averagePower and peakPower are in decibels, evaMicLevelCallbackAverage:andPeak would be called for each mic buffer of samples. Check out EvaTest project for animation example.

3. It is recommended to know that Eva finished all setup before starting using it:

- (void)evaRecorderIsReady;
Called when initiation process is complete after setting the API keys.

4. In case you want to change default timeout for recording you can use:

[[Eva sharedInstance] setAPIkey:apiKeyString withSiteCode:siteCodeString withMicLevel:TRUE withRecordingTimeout:8.0f]; 

This is exactly same as on paragraph 1, but you can change 8 sec timeout to any value you wish in seconds, Pay attention to send a float value.


The SDK comes with a demo project called EvaTest.
While its not the prettiest app there is, it shows how easy it is to integrate with Eva.

The interesting parts are in MainViewController.m  -

  1. initialization of Eva API keys, sounds files and AudioSession in viewDidLoad
  2. evaMicLevelCallbackAverage - used to animate a progress bar.
  3. evaDidReceiveData - minimal parsing of the json response.
  4. The difference between continuing a session and starting a new one in the respective button handlers.
  5. The difference between stop and cancel recording in the respective button handlers.

Monday, January 12, 2015




extreme understanding, performance, skill, etc. displayed by an artificial intelligence agent
skill in handling a difficult or highly sensitive situation; adroit and artful management:
"She displayed exceptional evature".

user:  I want to find my flight but I'm having trouble booking it can you book it for me
eva:  Where would you like to fly to?
user:  we're flying from Boston to Tampa
eva:  When would you like to depart from Boston Massachusetts to Tampa Florida?
user:  December
eva:  On what date in December would you like to depart from your current location to Tampa Florida?
user:  we're flying from Boston Massachusetts to Tampa Florida on December 1
eva:  When would you like to return from Tampa Florida to Boston Massachusetts?
user:  one way trip
eva:  One way flights from Boston Massachusetts to Tampa Florida, departing December 1st, for 2 adults.

user:  Days Inn Richland Washington
eva:  When would you like to check-in at the Days Inn Richland United States?
user:  January 12th thru the 14th
eva:  Days Inn Richland United States, arriving January 12th for 2 nights.

user:  Delta Airlines
eva:  Where would you like to fly to?
user:  from Jacksonville Beach Florida
eva:  What city would you like to fly to?
user:  Tirana Albania
eva:  When would you like to depart from Jacksonville Beach Florida to Tirana Albania?
user:  January 20th
eva:  When would you like to return from Tirana Albania to Jacksonville Beach Florida?
user:  January 30
eva:  Return flights from Jacksonville Beach Florida to Tirana Albania, departing January 20th, arriving back January 30th, with Delta.

user:  find an economy car in Bloomington Minnesota
eva:  When would you like to pick up the car from Bloomington Minnesota?
user:  today
eva:  When would you like to return the car in Bloomington Minnesota?
user:  tomorrow
eva:  Rent an economy car in Bloomington Minnesota, on January 11th, return it on January 12th.