Skip to content

Commit

Permalink
Add contexts support in services
Browse files Browse the repository at this point in the history
  • Loading branch information
Danil Skachkov committed Oct 24, 2014
1 parent b762dcf commit 9ffdb51
Show file tree
Hide file tree
Showing 7 changed files with 133 additions and 10 deletions.
24 changes: 22 additions & 2 deletions ailib/src/main/java/ai/api/AIDataService.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import com.google.gson.JsonSyntaxException;

import ai.api.http.HttpClient;
import ai.api.model.AIContext;
import ai.api.model.AIRequest;
import ai.api.model.AIResponse;

Expand All @@ -43,6 +44,7 @@
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Calendar;
import java.util.List;

/**
* Do simple requests to the AI Service
Expand Down Expand Up @@ -112,6 +114,19 @@ public AIResponse request(final AIRequest request) throws AIServiceException {
Log.e(TAG, "Malformed url should not be raised", e);
throw new AIServiceException("Wrong configuration. Please, connect to AI Service support", e);
} catch (final IOException e) {

if (connection != null) {
try {
final String errorString = IOUtils.toString(connection.getErrorStream(), Charsets.UTF_8);
Log.d(TAG, "" + errorString);
if (!TextUtils.isEmpty(errorString)) {
final AIResponse errorResponse = gson.fromJson(errorString, AIResponse.class);
return errorResponse;
}
} catch (final IOException ex) {
}
}

Log.e(TAG, "Can't make request to the Speaktoit AI service. Please, check connection settings and API access token.", e);
throw new AIServiceException("Can't make request to the AI service. Please, check connection settings and API access token.", e);
} catch (final JsonSyntaxException je) {
Expand All @@ -130,7 +145,7 @@ public AIResponse request(final AIRequest request) throws AIServiceException {
* @return response object from service
* @throws AIServiceException
*/
public AIResponse voiceRequest(final InputStream voiceStream) throws AIServiceException {
public AIResponse voiceRequest(final InputStream voiceStream, final List<AIContext> aiContexts) throws AIServiceException {
final Gson gson = GsonFactory.getGson();

HttpURLConnection connection = null;
Expand All @@ -146,6 +161,10 @@ public AIResponse voiceRequest(final InputStream voiceStream) throws AIServiceEx
request.setAgentId(config.getAgentId());
request.setTimezone(Calendar.getInstance().getTimeZone().getID());

if (context != null) {
request.setContexts(aiContexts);
}

final String queryData = gson.toJson(request);

connection = (HttpURLConnection) url.openConnection();
Expand Down Expand Up @@ -182,7 +201,8 @@ public AIResponse voiceRequest(final InputStream voiceStream) throws AIServiceEx
final String errorString = httpClient.getErrorString();
Log.d(TAG, "" + errorString);
if (!TextUtils.isEmpty(errorString)) {

final AIResponse errorResponse = gson.fromJson(errorString, AIResponse.class);
return errorResponse;
}
}

Expand Down
8 changes: 8 additions & 0 deletions ailib/src/main/java/ai/api/AIService.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@

import android.content.Context;

import java.util.List;

import ai.api.model.AIContext;
import ai.api.model.AIError;
import ai.api.model.AIResponse;

Expand Down Expand Up @@ -62,6 +65,11 @@ protected AIService(final AIConfiguration config, final Context context) {
*/
public abstract void startListening();

/**
* Starts listening process. Request to the AI service will be done with specified contexts.
*/
public abstract void startListening(List<AIContext> contexts);

/**
* Stop listening and start request to the AI service with current recognition results
*/
Expand Down
17 changes: 16 additions & 1 deletion ailib/src/main/java/ai/api/GoogleRecognitionServiceImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,15 @@
import android.speech.SpeechRecognizer;
import android.util.Log;

import ai.api.model.AIContext;
import ai.api.model.AIError;
import ai.api.model.AIRequest;
import ai.api.model.AIResponse;
import ai.api.util.RecognizerChecker;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class GoogleRecognitionServiceImpl extends AIService {
Expand All @@ -63,6 +65,8 @@ public class GoogleRecognitionServiceImpl extends AIService {
errorMessages.put(9, "Insufficient permissions.");
}

private List<AIContext> contexts;

protected GoogleRecognitionServiceImpl(final Context context, final AIConfiguration config) {
super(config, context);

Expand Down Expand Up @@ -119,7 +123,14 @@ protected void onPostExecute(final AIResponse response) {

@Override
public void startListening() {
startListening(null);
}

@Override
public void startListening(final List<AIContext> contexts) {
if (!recognitionActive) {
this.contexts = contexts;

final Intent sttIntent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
sttIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL,
RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
Expand All @@ -135,7 +146,6 @@ public void startListening() {
} else {
Log.w(TAG, "Trying to start recognition while another recognition active");
}

}

@Override
Expand Down Expand Up @@ -242,6 +252,11 @@ public void onResults(final Bundle results) {
} else {
aiRequest.setQuery(recognitionResults.get(0));
}

if (contexts != null) {
aiRequest.setContexts(contexts);
}

GoogleRecognitionServiceImpl.this.sendRequest(aiRequest);
}
}
Expand Down
21 changes: 18 additions & 3 deletions ailib/src/main/java/ai/api/SpeaktoitRecognitionServiceImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,16 @@
import android.os.AsyncTask;
import android.util.Log;

import ai.api.model.AIContext;
import ai.api.model.AIError;
import ai.api.model.AIResponse;
import ai.api.util.VoiceActivityDetector;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;

public class SpeaktoitRecognitionServiceImpl extends AIService {

Expand Down Expand Up @@ -96,6 +97,11 @@ public void run() {

@Override
public void startListening() {
startListening(null);
}

@Override
public void startListening(final List<AIContext> contexts) {
Log.v(TAG, "startListening");
synchronized (mediaRecorderLock) {
if (!isRecording) {
Expand All @@ -106,7 +112,7 @@ public void startListening() {

onListeningStarted();

new RequestTask(new RecorderWrapper(mediaRecorder)).execute();
new RequestTask(new RecorderWrapper(mediaRecorder), contexts).execute();
} else {
Log.w(TAG, "Trying start listening when it already active");
}
Expand Down Expand Up @@ -194,16 +200,25 @@ public int read(final byte[] buffer, final int byteOffset, final int byteCount)
private class RequestTask extends AsyncTask<Void, Void, AIResponse> {

private final RecorderWrapper recorderWrapper;
private final List<AIContext> contexts;

private AIError aiError;


private RequestTask(final RecorderWrapper recorderWrapper) {
this.recorderWrapper = recorderWrapper;
contexts = null;
}

private RequestTask(final RecorderWrapper recorderWrapper, final List<AIContext> contexts) {
this.recorderWrapper = recorderWrapper;
this.contexts = contexts;
}

@Override
protected AIResponse doInBackground(final Void... params) {
try {
final AIResponse aiResponse = aiDataService.voiceRequest(recorderWrapper);
final AIResponse aiResponse = aiDataService.voiceRequest(recorderWrapper, contexts);
return aiResponse;
} catch (final AIServiceException e) {
aiError = new AIError("Wrong answer from server " + e.toString());
Expand Down
44 changes: 43 additions & 1 deletion ailib/src/test/java/ai/api/test/ProtocolTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ public void AIServiceSpeaktoitVoiceRequestTest() {
final InputStream inputStream = getClass().getClassLoader().getResourceAsStream("log.raw");

try {
final AIResponse aiResponse = aiDataService.voiceRequest(inputStream);
final AIResponse aiResponse = aiDataService.voiceRequest(inputStream, null);
assertNotNull(aiResponse);
assertFalse(aiResponse.isError());
assertFalse(TextUtils.isEmpty(aiResponse.getId()));
Expand Down Expand Up @@ -124,6 +124,8 @@ public void ContextTest() {
String action;

try {
cleanContexts(aiDataService);

aiResponse = makeRequest(aiDataService, aiRequest);
action = aiResponse.getResult().getAction();
assertEquals("greeting", action);
Expand All @@ -132,20 +134,38 @@ public void ContextTest() {
aiResponse = makeRequest(aiDataService, aiRequest);
action = aiResponse.getResult().getAction();
assertEquals("firstGreeting", action);
assertArrayContains("firstContext", aiResponse.getResult().getMetadata().getInputContexts());
//assertArrayContains("firstContext", aiResponse.getResult().getMetadata().getContexts());

aiRequest.setResetContexts(true);
aiRequest.setContexts(null);
aiRequest.addContext(new AIContext("secondContext"));
aiResponse = makeRequest(aiDataService, aiRequest);
action = aiResponse.getResult().getAction();
assertEquals("secondGreeting", action);
assertArrayNotContains("firstContext", aiResponse.getResult().getMetadata().getInputContexts());
assertArrayContains("secondContext", aiResponse.getResult().getMetadata().getInputContexts());
//assertArrayNotContains("firstContext", aiResponse.getResult().getMetadata().getContexts());
//assertArrayContains("secondContext", aiResponse.getResult().getMetadata().getContexts());

cleanContexts(aiDataService);

} catch (final AIServiceException e) {
e.printStackTrace();
assertTrue(e.getMessage(), false);
}
}

/**
* Cleanup contexts to prevent Tests correlation
*/
private void cleanContexts(final AIDataService aiDataService) throws AIServiceException {
final AIRequest cleanRequest = new AIRequest();
cleanRequest.setResetContexts(true);
final AIResponse response = aiDataService.request(cleanRequest);
assertFalse(response.isError());
}

private AIResponse makeRequest(final AIDataService aiDataService, final AIRequest aiRequest) throws AIServiceException {
final AIResponse aiResponse = aiDataService.request(aiRequest);
assertNotNull(aiResponse);
Expand All @@ -154,4 +174,26 @@ private AIResponse makeRequest(final AIDataService aiDataService, final AIReques
assertNotNull(aiResponse.getResult());
return aiResponse;
}

private void assertArrayContains(final String expected, final String[] array) {
assertNotNull(array);
boolean exist = false;
for (int i = 0; i < array.length; i++) {
if (array[i].equalsIgnoreCase(expected)) {
exist = true;
}
}
assertTrue(exist);
}

private void assertArrayNotContains(final String expected, final String[] array) {
assertNotNull(array);
boolean exist = false;
for (int i = 0; i < array.length; i++) {
if (array[i].equalsIgnoreCase(expected)) {
exist = true;
}
}
assertFalse(exist);
}
}
21 changes: 18 additions & 3 deletions apiAISampleApp/src/main/java/ai/api/sample/MainActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.text.TextUtils;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
Expand All @@ -34,17 +35,18 @@
import com.google.gson.Gson;
import com.google.gson.JsonElement;

import java.util.Locale;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import ai.api.AIConfiguration;
import ai.api.AIListener;
import ai.api.AIService;
import ai.api.GsonFactory;
import ai.api.model.AIContext;
import ai.api.model.AIError;
import ai.api.model.AIResponse;


public class MainActivity extends ActionBarActivity implements AIListener {

public static final String TAG = MainActivity.class.getName();
Expand All @@ -58,6 +60,7 @@ public class MainActivity extends ActionBarActivity implements AIListener {
private ImageView recIndicator;
private TextView resultTextView;
private Gson gson;
private TextView contextTextView;

@Override
protected void onCreate(final Bundle savedInstanceState) {
Expand All @@ -70,6 +73,7 @@ protected void onCreate(final Bundle savedInstanceState) {
recIndicator.setVisibility(View.INVISIBLE);

resultTextView = (TextView) findViewById(R.id.resultTextView);
contextTextView = (TextView) findViewById(R.id.contextTextView);

gson = GsonFactory.getGson();

Expand Down Expand Up @@ -129,7 +133,18 @@ public boolean onOptionsItemSelected(final MenuItem item) {
}

public void buttonListenOnClick(final View view) {
aiService.startListening();
final String contextString = String.valueOf(contextTextView.getText());
if (!TextUtils.isEmpty(contextString)) {

final AIContext aiContext = new AIContext(contextString);
final List<AIContext> contexts = new ArrayList<AIContext>();
contexts.add(aiContext);
aiService.startListening(contexts);

} else {
aiService.startListening();
}

}

public void buttonStopListenOnClick(final View view) {
Expand Down
8 changes: 8 additions & 0 deletions apiAISampleApp/src/main/res/layout/activity_main.xml
Original file line number Diff line number Diff line change
Expand Up @@ -65,5 +65,13 @@
android:textAppearance="?android:attr/textAppearanceMedium"
android:id="@+id/resultTextView" />

<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/contextTextView"
android:hint="add Context here"
android:textAppearance="?android:attr/textAppearanceMedium"
/>

</LinearLayout>
</RelativeLayout>

0 comments on commit 9ffdb51

Please sign in to comment.