diff --git a/.gitignore b/.gitignore
index 25cbd61..f54fe31 100644
--- a/.gitignore
+++ b/.gitignore
@@ -95,3 +95,5 @@ hs_err_pid*
/captures
**/*.iml
*.class
+
+mozillaspeechlibrary/.cxx/
diff --git a/app/build.gradle b/app/build.gradle
index 50882dd..1efbe91 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -1,14 +1,14 @@
apply plugin: 'com.android.application'
android {
- compileSdkVersion 27
+ compileSdkVersion 28
defaultConfig {
applicationId "com.mozilla.speechmodule"
minSdkVersion 24
- targetSdkVersion 27
+ targetSdkVersion 28
versionCode 1
versionName "1.0"
- testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
+ testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
ndk {
abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86_64'
}
@@ -31,12 +31,13 @@ android {
dependencies {
implementation project(':mozillaspeechlibrary')
+ implementation 'com.loopj.android:android-async-http:1.4.9'
implementation fileTree(include: ['*.jar'], dir: 'libs')
- implementation 'com.android.support:appcompat-v7:27.1.1'
- implementation 'com.android.support.constraint:constraint-layout:1.1.2'
+ implementation 'androidx.annotation:annotation:1.1.0'
+ implementation 'androidx.constraintlayout:constraintlayout:2.0.0-beta4'
implementation 'com.jjoe64:graphview:4.2.2'
implementation 'net.lingala.zip4j:zip4j:1.3.2'
testImplementation 'junit:junit:4.12'
- androidTestImplementation 'com.android.support.test:runner:1.0.2'
- androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
+ androidTestImplementation 'androidx.test:runner:1.2.0'
+ androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
}
diff --git a/app/src/androidTest/java/com/mozilla/speechmodule/ExampleInstrumentedTest.java b/app/src/androidTest/java/com/mozilla/speechmodule/ExampleInstrumentedTest.java
index 4cee819..029ceaa 100644
--- a/app/src/androidTest/java/com/mozilla/speechmodule/ExampleInstrumentedTest.java
+++ b/app/src/androidTest/java/com/mozilla/speechmodule/ExampleInstrumentedTest.java
@@ -1,8 +1,8 @@
package com.mozilla.speechmodule;
import android.content.Context;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.runner.AndroidJUnit4;
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
diff --git a/app/src/main/java/com/mozilla/speechapp/MainActivity.java b/app/src/main/java/com/mozilla/speechapp/MainActivity.java
index 8225956..49b497b 100644
--- a/app/src/main/java/com/mozilla/speechapp/MainActivity.java
+++ b/app/src/main/java/com/mozilla/speechapp/MainActivity.java
@@ -2,7 +2,6 @@
import android.Manifest;
-import android.app.Activity;
import android.app.DownloadManager;
import android.content.pm.PackageManager;
@@ -13,9 +12,9 @@
import android.database.Cursor;
-import android.support.annotation.NonNull;
-import android.support.v4.app.ActivityCompat;
-import android.support.v7.app.AppCompatActivity;
+import androidx.annotation.NonNull;
+import androidx.core.app.ActivityCompat;
+import androidx.appcompat.app.AppCompatActivity;
import android.net.Uri;
@@ -25,7 +24,6 @@
import android.util.Log;
import android.view.View;
-import android.view.WindowManager;
import android.widget.Button;
import android.widget.CompoundButton;
@@ -46,10 +44,10 @@
import net.lingala.zip4j.core.ZipFile;
-import static android.support.constraint.Constraints.TAG;
-
public class MainActivity extends AppCompatActivity implements ISpeechRecognitionListener, CompoundButton.OnCheckedChangeListener {
+ private static final String TAG = MainActivity.class.getSimpleName();
+
private static long sDownloadId;
private static DownloadManager sDownloadManager;
@@ -103,7 +101,7 @@ private void initialize() {
mMozillaSpeechService.setLanguage(txtLanguage.getText().toString());
mMozillaSpeechService.setProductTag(txtProdutTag.getText().toString());
mMozillaSpeechService.setModelPath(getExternalFilesDir("models").getAbsolutePath());
- if (mMozillaSpeechService.ensureModelInstalled()) {
+ if (!useDeepSpeech.isChecked() || mMozillaSpeechService.ensureModelInstalled()) {
mMozillaSpeechService.start(getApplicationContext());
} else {
maybeDownloadOrExtractModel(getExternalFilesDir("models").getAbsolutePath(), mMozillaSpeechService.getLanguageDir());
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
index c2f20e7..8a89533 100644
--- a/app/src/main/res/layout/activity_main.xml
+++ b/app/src/main/res/layout/activity_main.xml
@@ -1,49 +1,52 @@
-
+
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toTopOf="parent">
-
+
-
+
-
+
-
+
-
+
diff --git a/build.gradle b/build.gradle
index 9f7353b..2552fde 100644
--- a/build.gradle
+++ b/build.gradle
@@ -19,6 +19,9 @@ allprojects {
repositories {
google()
jcenter()
+ maven {
+ url "https://maven.mozilla.org/maven2"
+ }
}
}
diff --git a/gradle.properties b/gradle.properties
index d430d14..a66c3eb 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -13,8 +13,8 @@ org.gradle.jvmargs=-Xmx1536m
# org.gradle.parallel=true
-VERSION_NAME=1.0.10
-VERSION_CODE=10010
+VERSION_NAME=1.0.11
+VERSION_CODE=10011
GROUP=com.github.mozilla
POM_DESCRIPTION=This is an Android library containing an API to Mozilla's speech recognition services
@@ -26,4 +26,6 @@ POM_LICENCE_NAME=The Apache Software License, Version 2.0
POM_LICENCE_URL=http://www.apache.org/licenses/LICENSE-2.0.txt
POM_LICENCE_DIST=repo
POM_DEVELOPER_ID=anatal@gmail.com
-POM_DEVELOPER_NAME=Andre Natal
\ No newline at end of file
+POM_DEVELOPER_NAME=Andre Natal
+android.useAndroidX=true
+android.enableJetifier=true
\ No newline at end of file
diff --git a/mozillaspeechlibrary/build.gradle b/mozillaspeechlibrary/build.gradle
index d7fa9e2..106c07a 100644
--- a/mozillaspeechlibrary/build.gradle
+++ b/mozillaspeechlibrary/build.gradle
@@ -3,16 +3,16 @@ apply from: 'maven-push.gradle'
def versionMajor = 1
def versionMinor = 0
-def versionPatch = 10
+def versionPatch = 11
android {
- compileSdkVersion 25
+ compileSdkVersion 28
defaultConfig {
minSdkVersion 24
- targetSdkVersion 25
+ targetSdkVersion 28
versionCode versionMajor * 10000 + versionMinor * 100 + versionPatch
versionName "${versionMajor}.${versionMinor}.${versionPatch}"
- testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
+ testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles 'proguard-consumer-rules.pro'
ndk {
@@ -34,8 +34,8 @@ android {
}
compileOptions {
- sourceCompatibility = 1.7
- targetCompatibility = 1.7
+ sourceCompatibility = 1.8
+ targetCompatibility = 1.8
}
lintOptions {
@@ -45,13 +45,17 @@ android {
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
- implementation 'com.loopj.android:android-async-http:1.4.9'
implementation 'org.mozilla.deepspeech:libdeepspeech:0.6.1@aar'
+ implementation 'org.gagravarr:vorbis-java-core:0.8'
+ implementation 'com.github.axet:opus:1.0.2'
+ implementation 'com.github.axet:jssrc:1.0.2-2'
+ implementation 'org.apache.commons:commons-math3:3.6.1'
+ implementation 'androidx.annotation:annotation:1.1.0'
+
+ compileOnly 'com.loopj.android:android-async-http:1.4.9'
+ compileOnly "org.mozilla.geckoview:geckoview-nightly-x86_64:75.0.20200213035745"
+
testImplementation 'junit:junit:4.12'
- androidTestImplementation 'com.android.support.test:runner:1.0.2'
- androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
- api 'org.gagravarr:vorbis-java-core:0.8'
- api 'com.github.axet:opus:1.0.2'
- api 'com.github.axet:jssrc:1.0.2-2'
- api 'org.apache.commons:commons-math3:3.6.1'
+ androidTestImplementation 'androidx.test:runner:1.2.0'
+ androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
}
diff --git a/mozillaspeechlibrary/src/androidTest/java/com/mozilla/speechlibrary/ExampleInstrumentedTest.java b/mozillaspeechlibrary/src/androidTest/java/com/mozilla/speechlibrary/ExampleInstrumentedTest.java
index b002bb1..da4aeba 100644
--- a/mozillaspeechlibrary/src/androidTest/java/com/mozilla/speechlibrary/ExampleInstrumentedTest.java
+++ b/mozillaspeechlibrary/src/androidTest/java/com/mozilla/speechlibrary/ExampleInstrumentedTest.java
@@ -1,8 +1,8 @@
package com.mozilla.speechlibrary;
import android.content.Context;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.runner.AndroidJUnit4;
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
diff --git a/mozillaspeechlibrary/src/main/java/com/mozilla/speechlibrary/MozillaSpeechService.java b/mozillaspeechlibrary/src/main/java/com/mozilla/speechlibrary/MozillaSpeechService.java
index e510409..c19704f 100644
--- a/mozillaspeechlibrary/src/main/java/com/mozilla/speechlibrary/MozillaSpeechService.java
+++ b/mozillaspeechlibrary/src/main/java/com/mozilla/speechlibrary/MozillaSpeechService.java
@@ -1,9 +1,14 @@
package com.mozilla.speechlibrary;
-import android.app.Activity;
import android.content.Context;
import android.util.Log;
+import androidx.annotation.NonNull;
+
+import com.mozilla.speechlibrary.networking.NetworkSettings;
+
+import org.mozilla.geckoview.GeckoWebExecutor;
+
import java.util.ArrayList;
public class MozillaSpeechService {
@@ -12,11 +17,11 @@ public class MozillaSpeechService {
private final int SAMPLERATE = 16000;
private final int CHANNELS = 1;
private ArrayList mListeners;
- private Context mContext;
private boolean isIdle = true;
- NetworkSettings mNetworkSettings;
+ private NetworkSettings mNetworkSettings;
private boolean useDeepSpeech = false;
private String mModelPath;
+ private GeckoWebExecutor mExecutor;
public enum SpeechState
{
@@ -27,7 +32,6 @@ public enum SpeechState
private static final MozillaSpeechService ourInstance = new MozillaSpeechService();
private NetworkSpeechRecognition mNetworkSpeechRecognition;
private LocalSpeechRecognition mLocalSpeechRecognition;
- private SpeechState mState;
private Vad mVad;
public static MozillaSpeechService getInstance() {
@@ -46,7 +50,6 @@ public void start(Context aContext) {
notifyListeners(SpeechState.ERROR, "Recognition already In progress");
} else {
int retVal = mVad.start();
- this.mContext = aContext;
if (retVal < 0) {
notifyListeners(SpeechState.ERROR, "Error Initializing VAD " + String.valueOf(retVal));
} else {
@@ -77,12 +80,11 @@ public void addListener(ISpeechRecognitionListener aListener) {
mListeners.add(aListener);
}
- protected void notifyListeners(MozillaSpeechService.SpeechState aState, Object aPayload) {
+ public void notifyListeners(MozillaSpeechService.SpeechState aState, Object aPayload) {
if (aState == SpeechState.STT_RESULT || aState == SpeechState.ERROR
|| aState == SpeechState.NO_VOICE || aState == SpeechState.CANCELED) {
isIdle = true;
}
- mState = aState;
for (ISpeechRecognitionListener listener : mListeners) {
listener.onSpeechStatusChanged(aState, aPayload);
}
@@ -144,4 +146,14 @@ public void setProductTag(String tag) {
this.mNetworkSettings.mProductTag = tag;
}
+ public void setGeckoWebExecutor(@NonNull GeckoWebExecutor executor) {
+ mExecutor = executor;
+ }
+
+ GeckoWebExecutor getGeckoWebExecutor() {
+ // We used to be able to get the GeckoRuntime instance through GeckoRuntime.getInstance but
+ // it has been made private so now we need to provide the GeckoWebExecutor from outside
+ return mExecutor;
+ }
+
}
diff --git a/mozillaspeechlibrary/src/main/java/com/mozilla/speechlibrary/NetworkSpeechRecognition.java b/mozillaspeechlibrary/src/main/java/com/mozilla/speechlibrary/NetworkSpeechRecognition.java
index 01b0bcc..94231e6 100644
--- a/mozillaspeechlibrary/src/main/java/com/mozilla/speechlibrary/NetworkSpeechRecognition.java
+++ b/mozillaspeechlibrary/src/main/java/com/mozilla/speechlibrary/NetworkSpeechRecognition.java
@@ -3,11 +3,19 @@
import android.content.Context;
import android.media.AudioRecord;
import android.os.Process;
+
import com.github.axet.audiolibrary.encoders.Encoder;
import com.github.axet.audiolibrary.encoders.EncoderInfo;
import com.github.axet.audiolibrary.encoders.Factory;
import com.github.axet.audiolibrary.encoders.FormatOPUS;
import com.github.axet.audiolibrary.encoders.Sound;
+import com.mozilla.speechlibrary.networking.CustomNetworking;
+import com.mozilla.speechlibrary.networking.GeckoNetworking;
+import com.mozilla.speechlibrary.networking.NetworkSettings;
+import com.mozilla.speechlibrary.networking.Networking;
+
+import org.mozilla.geckoview.GeckoWebExecutor;
+
import java.io.ByteArrayOutputStream;
import java.util.Arrays;
@@ -28,15 +36,17 @@ class NetworkSpeechRecognition implements Runnable {
MozillaSpeechService mService;
Networking network;
NetworkSettings mNetworkSettings;
+ GeckoWebExecutor mExecutor;
protected NetworkSpeechRecognition(int aSampleRate, int aChannels, Vad aVad, Context aContext,
- MozillaSpeechService aService, NetworkSettings mNetworkSettings) {
+ MozillaSpeechService aService, NetworkSettings mNetworkSettings) {
this.mVad = aVad;
this.mContext = aContext;
this.mSampleRate = aSampleRate;
this.mChannels = aChannels;
this.mService = aService;
this.mNetworkSettings = mNetworkSettings;
+ this.mExecutor = aService.getGeckoWebExecutor();
}
public void run() {
@@ -53,8 +63,18 @@ public void run() {
long dtantes = System.currentTimeMillis();
long dtantesmili = System.currentTimeMillis();
boolean raisenovoice = false;
- network = new Networking(mService);
- network.mContext = this.mContext;
+
+ try {
+ Class.forName("org.mozilla.geckoview.GeckoWebExecutor");
+ if (mExecutor == null) {
+ throw new IllegalStateException("GeckoWebExecutor not set, call setGeckoWebExecutor first.");
+ }
+ network = new GeckoNetworking(mContext, mService, mExecutor);
+
+ } catch (ClassNotFoundException exception) {
+ network = new CustomNetworking(mContext, mService);
+ }
+
AudioRecord recorder = Sound.getAudioRecord(mChannels, mSampleRate);
EncoderInfo ef = new EncoderInfo(1, mSampleRate, 16);
Encoder e = Factory.getEncoder(mContext, FormatOPUS.EXT, ef, baos);
diff --git a/mozillaspeechlibrary/src/main/java/com/mozilla/speechlibrary/Networking.java b/mozillaspeechlibrary/src/main/java/com/mozilla/speechlibrary/Networking.java
deleted file mode 100644
index 90e3ed1..0000000
--- a/mozillaspeechlibrary/src/main/java/com/mozilla/speechlibrary/Networking.java
+++ /dev/null
@@ -1,105 +0,0 @@
-package com.mozilla.speechlibrary;
-
-import android.content.Context;
-import android.os.Looper;
-import android.util.Log;
-import com.loopj.android.http.AsyncHttpResponseHandler;
-import com.loopj.android.http.SyncHttpClient;
-import org.json.JSONArray;
-import org.json.JSONObject;
-import cz.msebera.android.httpclient.Header;
-import cz.msebera.android.httpclient.entity.ByteArrayEntity;
-import java.io.ByteArrayOutputStream;
-import static com.mozilla.speechlibrary.MozillaSpeechService.TAG;
-
-public class Networking {
-
- final String STT_ENDPOINT = "https://speaktome-2.services.mozilla.com/";
- MozillaSpeechService mSpeechService;
- public boolean cancelled;
- protected Context mContext;
-
- public Networking(MozillaSpeechService aSpeechService) {
- this.mSpeechService = aSpeechService;
- }
-
- protected void doSTT(final ByteArrayOutputStream baos, NetworkSettings mNetworkSettings) {
-
- if (cancelled) {
- mSpeechService.notifyListeners(MozillaSpeechService.SpeechState.CANCELED, null);
- return;
- }
-
- try {
- Looper.prepare();
- ByteArrayEntity byteArrayEntity = new ByteArrayEntity(baos.toByteArray());
- SyncHttpClient client = new SyncHttpClient();
- client.addHeader("Accept-Language-STT", mNetworkSettings.mLanguage);
- client.addHeader("Store-Transcription", mNetworkSettings.mStoreTranscriptions ? "1": "0" );
- client.addHeader("Store-Sample", mNetworkSettings.mStoreSamples ? "1": "0");
- client.addHeader("Product-Tag", mNetworkSettings.mProductTag);
-
- client.post(mContext, STT_ENDPOINT, byteArrayEntity, "audio/3gpp",
- new AsyncHttpResponseHandler() {
-
- @Override
- public void onStart() {
- // called before request is started
- mSpeechService.notifyListeners(MozillaSpeechService.SpeechState.DECODING, null);
- }
-
- @Override
- public void onSuccess(int statusCode, Header[] headers, byte[] response) {
- // Implement cancelation
- if (cancelled) {
- return;
- }
-
- // called when response HTTP status is "200 OK"
- String json = new String(response);
- try {
- JSONObject reader = new JSONObject(json);
- JSONArray results = reader.getJSONArray("data");
- final String transcription = results.getJSONObject(0).getString("text");
- final String confidence = results.getJSONObject(0).getString("confidence");
- STTResult sttResult = new STTResult(transcription, Float.parseFloat(confidence));
- mSpeechService.notifyListeners(MozillaSpeechService.SpeechState.STT_RESULT, sttResult);
- } catch (Exception exc) {
- String error = String.format("Error parsing results: %s", exc.getMessage());
- mSpeechService.notifyListeners(MozillaSpeechService.SpeechState.ERROR, error);
- }
- }
-
- @Override
- public void onFailure(int statusCode, Header[] headers, byte[] errorResponse, Throwable e) {
- // called when response HTTP status is "4XX" (eg. 401, 403, 404)
- String error = String.format("Network Error: %s (%s)", errorResponse == null ? "General Error" : new String(errorResponse), String.valueOf(statusCode));
- mSpeechService.notifyListeners(MozillaSpeechService.SpeechState.ERROR, error);
- }
-
- @Override
- public void onRetry(int retryNo) {
- // called when request is retried
- String error = String.format("Network Error: Retrying %s", String.valueOf(retryNo));
- mSpeechService.notifyListeners(MozillaSpeechService.SpeechState.ERROR, error);
- }
- }
- );
- }
- catch(Exception e)
- {
- e.printStackTrace();
- }
- }
-
- public void cancel() {
- cancelled = true;
- }
-}
-
-class NetworkSettings {
- boolean mStoreSamples = true;
- boolean mStoreTranscriptions = true;
- String mLanguage;
- String mProductTag = "moz-android-speech-lib";
-}
\ No newline at end of file
diff --git a/mozillaspeechlibrary/src/main/java/com/mozilla/speechlibrary/networking/CustomNetworking.java b/mozillaspeechlibrary/src/main/java/com/mozilla/speechlibrary/networking/CustomNetworking.java
new file mode 100644
index 0000000..6bbdd49
--- /dev/null
+++ b/mozillaspeechlibrary/src/main/java/com/mozilla/speechlibrary/networking/CustomNetworking.java
@@ -0,0 +1,92 @@
+package com.mozilla.speechlibrary.networking;
+
+import android.content.Context;
+import android.os.Looper;
+
+import com.loopj.android.http.AsyncHttpResponseHandler;
+import com.loopj.android.http.SyncHttpClient;
+import com.mozilla.speechlibrary.MozillaSpeechService;
+import com.mozilla.speechlibrary.STTResult;
+
+import org.json.JSONArray;
+import org.json.JSONObject;
+
+import java.io.ByteArrayOutputStream;
+
+import cz.msebera.android.httpclient.Header;
+import cz.msebera.android.httpclient.entity.ByteArrayEntity;
+
+public class CustomNetworking extends Networking {
+
+ public CustomNetworking(Context aContext, MozillaSpeechService aSpeechService) {
+ super(aContext, aSpeechService);
+ }
+
+ @Override
+ public void doSTT(final ByteArrayOutputStream baos, NetworkSettings mNetworkSettings) {
+ if (cancelled) {
+ mSpeechService.notifyListeners(MozillaSpeechService.SpeechState.CANCELED, null);
+ return;
+ }
+
+ try {
+ Looper.prepare();
+ ByteArrayEntity byteArrayEntity = new ByteArrayEntity(baos.toByteArray());
+ SyncHttpClient client = new SyncHttpClient();
+ client.addHeader("Accept-Language-STT", mNetworkSettings.mLanguage);
+ client.addHeader("Store-Transcription", mNetworkSettings.mStoreTranscriptions ? "1": "0" );
+ client.addHeader("Store-Sample", mNetworkSettings.mStoreSamples ? "1": "0");
+ client.addHeader("Product-Tag", mNetworkSettings.mProductTag);
+
+ client.post(mContext, STT_ENDPOINT, byteArrayEntity, "audio/3gpp",
+ new AsyncHttpResponseHandler() {
+
+ @Override
+ public void onStart() {
+ // called before request is started
+ mSpeechService.notifyListeners(MozillaSpeechService.SpeechState.DECODING, null);
+ }
+
+ @Override
+ public void onSuccess(int statusCode, Header[] headers, byte[] response) {
+ // Implement cancelation
+ if (cancelled) {
+ return;
+ }
+
+ // called when response HTTP status is "200 OK"
+ String json = new String(response);
+ try {
+ JSONObject reader = new JSONObject(json);
+ JSONArray results = reader.getJSONArray("data");
+ final String transcription = results.getJSONObject(0).getString("text");
+ final String confidence = results.getJSONObject(0).getString("confidence");
+ STTResult sttResult = new STTResult(transcription, Float.parseFloat(confidence));
+ mSpeechService.notifyListeners(MozillaSpeechService.SpeechState.STT_RESULT, sttResult);
+ } catch (Exception exc) {
+ String error = String.format("Error parsing results: %s", exc.getMessage());
+ mSpeechService.notifyListeners(MozillaSpeechService.SpeechState.ERROR, error);
+ }
+ }
+
+ @Override
+ public void onFailure(int statusCode, Header[] headers, byte[] errorResponse, Throwable e) {
+ // called when response HTTP status is "4XX" (eg. 401, 403, 404)
+ String error = String.format("Network Error: %s (%s)", errorResponse == null ? "General Error" : new String(errorResponse), String.valueOf(statusCode));
+ mSpeechService.notifyListeners(MozillaSpeechService.SpeechState.ERROR, error);
+ }
+
+ @Override
+ public void onRetry(int retryNo) {
+ // called when request is retried
+ String error = String.format("Network Error: Retrying %s", String.valueOf(retryNo));
+ mSpeechService.notifyListeners(MozillaSpeechService.SpeechState.ERROR, error);
+ }
+ }
+ );
+
+ } catch(Exception e) {
+ mSpeechService.notifyListeners(MozillaSpeechService.SpeechState.ERROR, e.getMessage());
+ }
+ }
+}
\ No newline at end of file
diff --git a/mozillaspeechlibrary/src/main/java/com/mozilla/speechlibrary/networking/GeckoNetworking.java b/mozillaspeechlibrary/src/main/java/com/mozilla/speechlibrary/networking/GeckoNetworking.java
new file mode 100644
index 0000000..06bf71e
--- /dev/null
+++ b/mozillaspeechlibrary/src/main/java/com/mozilla/speechlibrary/networking/GeckoNetworking.java
@@ -0,0 +1,100 @@
+package com.mozilla.speechlibrary.networking;
+
+import android.content.Context;
+import android.os.Handler;
+import android.os.Looper;
+
+import androidx.annotation.NonNull;
+
+import com.mozilla.speechlibrary.MozillaSpeechService;
+import com.mozilla.speechlibrary.STTResult;
+
+import org.json.JSONArray;
+import org.json.JSONObject;
+import org.mozilla.geckoview.GeckoWebExecutor;
+import org.mozilla.geckoview.WebRequest;
+
+import java.io.ByteArrayOutputStream;
+import java.nio.ByteBuffer;
+import java.nio.charset.StandardCharsets;
+
+public class GeckoNetworking extends Networking {
+
+ private Handler mHandler;
+ private GeckoWebExecutor mExecutor;
+
+ public GeckoNetworking(Context aContext, MozillaSpeechService aSpeechService, @NonNull GeckoWebExecutor executor) {
+ super(aContext, aSpeechService);
+
+ mHandler = new Handler(Looper.getMainLooper());
+ mExecutor = executor;
+ }
+
+ @Override
+ public void doSTT(final ByteArrayOutputStream baos, final NetworkSettings mNetworkSettings) {
+ if (cancelled) {
+ mSpeechService.notifyListeners(MozillaSpeechService.SpeechState.CANCELED, null);
+ return;
+ }
+
+ mHandler.post(() -> {
+ byte[] byteArray = baos.toByteArray();
+ ByteBuffer input = ByteBuffer.allocateDirect(byteArray.length);
+ input.put(byteArray);
+ WebRequest request = new WebRequest.Builder(STT_ENDPOINT)
+ .body(input)
+ .method("POST")
+ .addHeader("Accept-Language-STT", mNetworkSettings.mLanguage)
+ .addHeader("Store-Transcription", mNetworkSettings.mStoreTranscriptions ? "1": "0" )
+ .addHeader("Store-Sample", mNetworkSettings.mStoreSamples ? "1": "0")
+ .addHeader("Product-Tag", mNetworkSettings.mProductTag)
+ .addHeader("Content-Type", "audio/3gpp")
+ .build();
+
+ mSpeechService.notifyListeners(MozillaSpeechService.SpeechState.DECODING, null);
+ mExecutor.fetch(request).then(webResponse -> {
+ String body;
+ if (webResponse != null) {
+ if (webResponse.body != null) {
+ ByteArrayOutputStream buffer = new ByteArrayOutputStream();
+ int nRead;
+ byte[] data = new byte[16384];
+ while ((nRead = webResponse.body.read(data, 0, data.length)) != -1) {
+ buffer.write(data, 0, nRead);
+ }
+ body = new String(buffer.toByteArray(), StandardCharsets.UTF_8);
+
+ if (webResponse.statusCode == 200) {
+ JSONObject reader = new JSONObject(body);
+ JSONArray results = reader.getJSONArray("data");
+ final String transcription = results.getJSONObject(0).getString("text");
+ final String confidence = results.getJSONObject(0).getString("confidence");
+ STTResult sttResult = new STTResult(transcription, Float.parseFloat(confidence));
+ mSpeechService.notifyListeners(MozillaSpeechService.SpeechState.STT_RESULT, sttResult);
+
+ } else {
+ // called when response HTTP status is not "200"
+ String error = String.format("Network Error: %s", webResponse.statusCode);
+ mSpeechService.notifyListeners(MozillaSpeechService.SpeechState.ERROR, error);
+ }
+
+ } else {
+ // WebResponse body is null
+ mSpeechService.notifyListeners(MozillaSpeechService.SpeechState.ERROR, "Response error null");
+ }
+
+ } else {
+ // WebResponse is null
+ mSpeechService.notifyListeners(MozillaSpeechService.SpeechState.ERROR, "Unknown network Error");
+ }
+
+ return null;
+
+ }).exceptionally(throwable -> {
+ // Exception happened
+ mSpeechService.notifyListeners(MozillaSpeechService.SpeechState.ERROR, String.format("An exception happened during the request: %s", throwable.getMessage()));
+ return null;
+ });
+ });
+ }
+}
\ No newline at end of file
diff --git a/mozillaspeechlibrary/src/main/java/com/mozilla/speechlibrary/networking/NetworkSettings.java b/mozillaspeechlibrary/src/main/java/com/mozilla/speechlibrary/networking/NetworkSettings.java
new file mode 100644
index 0000000..41ea40e
--- /dev/null
+++ b/mozillaspeechlibrary/src/main/java/com/mozilla/speechlibrary/networking/NetworkSettings.java
@@ -0,0 +1,8 @@
+package com.mozilla.speechlibrary.networking;
+
+public class NetworkSettings {
+ public boolean mStoreSamples = true;
+ public boolean mStoreTranscriptions = true;
+ public String mLanguage;
+ public String mProductTag = "moz-android-speech-lib";
+}
diff --git a/mozillaspeechlibrary/src/main/java/com/mozilla/speechlibrary/networking/Networking.java b/mozillaspeechlibrary/src/main/java/com/mozilla/speechlibrary/networking/Networking.java
new file mode 100644
index 0000000..d06740c
--- /dev/null
+++ b/mozillaspeechlibrary/src/main/java/com/mozilla/speechlibrary/networking/Networking.java
@@ -0,0 +1,27 @@
+package com.mozilla.speechlibrary.networking;
+
+import android.content.Context;
+
+import com.mozilla.speechlibrary.MozillaSpeechService;
+
+import java.io.ByteArrayOutputStream;
+
+public abstract class Networking {
+
+ String STT_ENDPOINT = "https://speaktome-2.services.mozilla.com/";
+
+ MozillaSpeechService mSpeechService;
+ boolean cancelled;
+ Context mContext;
+
+ Networking(Context aContext, MozillaSpeechService aSpeechService) {
+ mContext = aContext;
+ mSpeechService = aSpeechService;
+ }
+
+ public abstract void doSTT(final ByteArrayOutputStream baos, NetworkSettings mNetworkSettings);
+
+ public void cancel() {
+ cancelled = true;
+ }
+}