diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 06d819c..1cac71f 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -87,6 +87,14 @@
+
+
+
+
+
+
+
+
-
\ No newline at end of file
+
diff --git a/res/drawable/speech_bubbles.png b/res/drawable/speech_bubbles.png
new file mode 100644
index 0000000..143f45d
Binary files /dev/null and b/res/drawable/speech_bubbles.png differ
diff --git a/res/layout-sw600dp/activity_welcome.xml b/res/layout-sw600dp/activity_welcome.xml
new file mode 100644
index 0000000..4cac703
--- /dev/null
+++ b/res/layout-sw600dp/activity_welcome.xml
@@ -0,0 +1,67 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/res/layout/activity_production_experiment_datum_list.xml b/res/layout/activity_production_experiment_datum_list.xml
new file mode 100644
index 0000000..99731a1
--- /dev/null
+++ b/res/layout/activity_production_experiment_datum_list.xml
@@ -0,0 +1,13 @@
+
+
+
+
\ No newline at end of file
diff --git a/res/layout/activity_speech_recognition.xml b/res/layout/activity_speech_recognition.xml
new file mode 100644
index 0000000..c709cbe
--- /dev/null
+++ b/res/layout/activity_speech_recognition.xml
@@ -0,0 +1,7 @@
+
diff --git a/res/layout/activity_welcome.xml b/res/layout/activity_welcome.xml
new file mode 100644
index 0000000..f210dff
--- /dev/null
+++ b/res/layout/activity_welcome.xml
@@ -0,0 +1,54 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/res/layout/fragment_datum_detail.xml b/res/layout/fragment_datum_detail.xml
index 19ba77a..6052cef 100644
--- a/res/layout/fragment_datum_detail.xml
+++ b/res/layout/fragment_datum_detail.xml
@@ -6,25 +6,25 @@
+
+
diff --git a/res/layout/fragment_datum_detail_simple.xml b/res/layout/fragment_datum_detail_simple.xml
new file mode 100644
index 0000000..ecc6409
--- /dev/null
+++ b/res/layout/fragment_datum_detail_simple.xml
@@ -0,0 +1,90 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/res/layout/fragment_datum_speech_recognition_hypotheses.xml b/res/layout/fragment_datum_speech_recognition_hypotheses.xml
new file mode 100644
index 0000000..b11ee9b
--- /dev/null
+++ b/res/layout/fragment_datum_speech_recognition_hypotheses.xml
@@ -0,0 +1,217 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/res/menu/actions_datum_speech_recognition.xml b/res/menu/actions_datum_speech_recognition.xml
new file mode 100644
index 0000000..cd5cb7f
--- /dev/null
+++ b/res/menu/actions_datum_speech_recognition.xml
@@ -0,0 +1,15 @@
+
+
\ No newline at end of file
diff --git a/res/values-ka/strings.xml b/res/values-ka/strings.xml
index dda359f..883d9a0 100644
--- a/res/values-ka/strings.xml
+++ b/res/values-ka/strings.xml
@@ -2,6 +2,7 @@
ქართული ერთად
+ ქართული speech
ფრაზა
-
+
\ No newline at end of file
diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml
index 3827dbf..f8df0da 100644
--- a/res/values-ru/strings.xml
+++ b/res/values-ru/strings.xml
@@ -1,7 +1,8 @@
- Learn Georgian Together
- Phrase
+ ქართული ერთად
+ ქართული speech
+ ფრაზა
diff --git a/res/values/strings.xml b/res/values/strings.xml
index fc98d5a..f8df0da 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -2,6 +2,7 @@
ქართული ერთად
+ ქართული speech
ფრაზა
diff --git a/src/com/github/opensourcefieldlinguistics/fielddb/FieldDBApplication.java b/src/com/github/opensourcefieldlinguistics/fielddb/FieldDBApplication.java
index 2a1bf6f..8a1ccb7 100644
--- a/src/com/github/opensourcefieldlinguistics/fielddb/FieldDBApplication.java
+++ b/src/com/github/opensourcefieldlinguistics/fielddb/FieldDBApplication.java
@@ -8,6 +8,7 @@
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
+import java.util.Locale;
import org.acra.ACRA;
import org.acra.ACRAConfiguration;
@@ -16,16 +17,21 @@
import ca.ilanguage.oprime.database.User;
import ca.ilanguage.oprime.database.UserContentProvider.UserTable;
+import com.github.opensourcefieldlinguistics.fielddb.database.DatumContentProvider;
import com.github.opensourcefieldlinguistics.fielddb.database.FieldDBUserContentProvider;
+import com.github.opensourcefieldlinguistics.fielddb.database.DatumContentProvider.DatumTable;
import com.github.opensourcefieldlinguistics.fielddb.lessons.Config;
-import com.github.opensourcefieldlinguistics.fielddb.lessons.georgian.R;
+import com.github.opensourcefieldlinguistics.fielddb.speech.kartuli.BuildConfig;
+import com.github.opensourcefieldlinguistics.fielddb.speech.kartuli.R;
import com.github.opensourcefieldlinguistics.fielddb.service.DownloadDatumsService;
+import com.github.opensourcefieldlinguistics.fielddb.service.KartuliSMSCorpusService;
import com.github.opensourcefieldlinguistics.fielddb.service.RegisterUserService;
import android.app.Application;
import android.content.Context;
import android.content.CursorLoader;
import android.content.Intent;
+import android.content.res.Configuration;
import android.database.Cursor;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
@@ -39,8 +45,10 @@ public class FieldDBApplication extends Application {
@Override
public final void onCreate() {
super.onCreate();
+ String language = forceLocale(Config.DATA_IS_ABOUT_LANGUAGE_ISO);
+ Log.d(Config.TAG, "Forced the locale to " + language);
- (new File(Config.DEFAULT_OUTPUT_DIRECTORY)).mkdirs();
+ // (new File(Config.DEFAULT_OUTPUT_DIRECTORY)).mkdirs();
ACRAConfiguration config = ACRA.getNewDefaultConfig(this);
config.setFormUri(Config.ACRA_SERVER_URL);
@@ -90,27 +98,29 @@ public final void onCreate() {
ACRA.setConfig(config);
- ACRA.init(this);
+ if (!BuildConfig.DEBUG)
+ ACRA.init(this);
// Get the user from the db
- String[] userProjection = { UserTable.COLUMN_ID, UserTable.COLUMN_REV,
+ String[] userProjection = {UserTable.COLUMN_ID, UserTable.COLUMN_REV,
UserTable.COLUMN_USERNAME, UserTable.COLUMN_FIRSTNAME,
UserTable.COLUMN_LASTNAME, UserTable.COLUMN_EMAIL,
UserTable.COLUMN_GRAVATAR, UserTable.COLUMN_AFFILIATION,
UserTable.COLUMN_RESEARCH_INTEREST,
- UserTable.COLUMN_DESCRIPTION, UserTable.COLUMN_SUBTITLE };
+ UserTable.COLUMN_DESCRIPTION, UserTable.COLUMN_SUBTITLE};
CursorLoader cursorLoader = new CursorLoader(getApplicationContext(),
FieldDBUserContentProvider.CONTENT_URI, userProjection, null,
null, null);
Cursor cursor = cursorLoader.loadInBackground();
cursor.moveToFirst();
String _id = "";
+ String username = "default";
if (cursor.getCount() > 0) {
_id = cursor.getString(cursor
.getColumnIndexOrThrow(UserTable.COLUMN_ID));
String _rev = cursor.getString(cursor
.getColumnIndexOrThrow(UserTable.COLUMN_REV));
- String username = cursor.getString(cursor
+ username = cursor.getString(cursor
.getColumnIndexOrThrow(UserTable.COLUMN_USERNAME));
String firstname = cursor.getString(cursor
.getColumnIndexOrThrow(UserTable.COLUMN_FIRSTNAME));
@@ -132,13 +142,29 @@ public final void onCreate() {
mUser = new User(_id, _rev, username, firstname, lastname, email,
gravatar, affiliation, researchInterest, description,
subtitle, null, actualJSON);
- ACRA.getErrorReporter().putCustomData("username", username);
+ if (!BuildConfig.DEBUG)
+ ACRA.getErrorReporter().putCustomData("username", username);
+ Config.CURRENT_USERNAME = username;
} else {
Log.e(Config.TAG,
"There is no user... this is a problme the app wont work.");
- ACRA.getErrorReporter().putCustomData("username", "unknown");
+ if (!BuildConfig.DEBUG)
+ ACRA.getErrorReporter().putCustomData("username", "unknown");
+ }
+ /* Make the default corpus point to the user's own corpus */
+ Config.DEFAULT_CORPUS = Config.DEFAULT_CORPUS.replace("username",
+ username);
+ Config.CURRENT_USERNAME = username;
+ Config.DEFAULT_OUTPUT_DIRECTORY = "/sdcard/"
+ + Config.DATA_IS_ABOUT_LANGUAGE_NAME_ASCII + "-"
+ + Config.APP_TYPE + "/" + Config.DEFAULT_CORPUS;
+ (new File(Config.DEFAULT_OUTPUT_DIRECTORY)).mkdirs();
+
+ if (!BuildConfig.DEBUG) {
+ ACRA.getErrorReporter().putCustomData("dbname",
+ Config.DEFAULT_CORPUS);
}
- ACRA.getErrorReporter().putCustomData("dbname", Config.DEFAULT_CORPUS);
+
Log.d(Config.TAG, cursor.getString(cursor
.getColumnIndexOrThrow(UserTable.COLUMN_USERNAME)));
cursor.close();
@@ -152,11 +178,29 @@ public final void onCreate() {
.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo wifi = connManager
.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
- if (wifi.isConnected()) {
- Intent updateSamples = new Intent(getApplicationContext(),
- DownloadDatumsService.class);
- getApplicationContext().startService(updateSamples);
-
+ if (Config.APP_TYPE.equals("speechrecognition")) {
+ Log.d(Config.TAG,
+ "Not downloading samples, they are included in the training app");
+
+ String[] datumProjection = {UserTable.COLUMN_ID};
+ CursorLoader loader = new CursorLoader(getApplicationContext(),
+ DatumContentProvider.CONTENT_URI, datumProjection, null,
+ null, null);
+ Cursor datumCursor = loader.loadInBackground();
+ if (datumCursor.getCount() == 0) {
+ getContentResolver().insert(DatumContentProvider.CONTENT_URI,
+ DatumTable.sampleData());
+ Intent updateSMSSamples = new Intent(getApplicationContext(),
+ KartuliSMSCorpusService.class);
+ getApplicationContext().startService(updateSMSSamples);
+ }
+ datumCursor.close();
+ } else {
+ if (wifi.isConnected() || Config.D) {
+ Intent updateSamples = new Intent(getApplicationContext(),
+ DownloadDatumsService.class);
+ getApplicationContext().startService(updateSamples);
+ }
}
if (mUser.get_rev() == null || "".equals(mUser.get_rev())) {
Intent registerUser = new Intent(getApplicationContext(),
@@ -167,4 +211,38 @@ public final void onCreate() {
}
}
+
+ /**
+ * Forces the locale for the duration of the app to the language needed for
+ * that version of the Experiment. It accepts a variable in the form en or
+ * en-US containing just the language code, or the language code followed by
+ * a - and the co
+ *
+ * @param lang
+ * @return
+ */
+ public String forceLocale(String lang) {
+ if (lang.equals(Locale.getDefault().getLanguage())) {
+ return Locale.getDefault().getDisplayLanguage();
+ }
+ Configuration config = this.getBaseContext().getResources()
+ .getConfiguration();
+ Locale locale;
+ if (lang.contains("-")) {
+ String[] langCountrycode = lang.split("-");
+ locale = new Locale(langCountrycode[0], langCountrycode[1]);
+ } else {
+ locale = new Locale(lang);
+ }
+ Locale.setDefault(locale);
+ config.locale = locale;
+ this.getBaseContext()
+ .getResources()
+ .updateConfiguration(
+ config,
+ this.getBaseContext().getResources()
+ .getDisplayMetrics());
+
+ return Locale.getDefault().getDisplayLanguage();
+ }
}
diff --git a/src/com/github/opensourcefieldlinguistics/fielddb/database/AudioVideoContentProvider.java b/src/com/github/opensourcefieldlinguistics/fielddb/database/AudioVideoContentProvider.java
index e978dc4..c2d9074 100644
--- a/src/com/github/opensourcefieldlinguistics/fielddb/database/AudioVideoContentProvider.java
+++ b/src/com/github/opensourcefieldlinguistics/fielddb/database/AudioVideoContentProvider.java
@@ -27,6 +27,8 @@ public class AudioVideoContentProvider extends ContentProvider {
private static final int ITEM_ID = 20;
private static final String AUTHORITY = "com.github.opensourcefieldlinguistics.fielddb."
+ + Config.APP_TYPE.toLowerCase()
+ + "."
+ Config.DATA_IS_ABOUT_LANGUAGE_NAME_ASCII.toLowerCase()
+ "."
+ AudioVideoTable.TABLE_NAME;
@@ -89,15 +91,15 @@ public Cursor query(Uri uri, String[] projection, String selection,
int uriType = sURIMatcher.match(uri);
switch (uriType) {
- case ITEMS:
- break;
- case ITEM_ID:
- // Adding the ID to the original query
- queryBuilder.appendWhere(AudioVideoTable.COLUMN_FILENAME + "='"
- + uri.getLastPathSegment() + "'");
- break;
- default:
- throw new IllegalArgumentException("Unknown URI: " + uri);
+ case ITEMS :
+ break;
+ case ITEM_ID :
+ // Adding the ID to the original query
+ queryBuilder.appendWhere(AudioVideoTable.COLUMN_FILENAME + "='"
+ + uri.getLastPathSegment() + "'");
+ break;
+ default :
+ throw new IllegalArgumentException("Unknown URI: " + uri);
}
SQLiteDatabase db = database.getWritableDatabase();
@@ -117,23 +119,24 @@ public int update(Uri uri, ContentValues values, String selection,
SQLiteDatabase sqlDB = database.getWritableDatabase();
int rowsUpdated = 0;
switch (uriType) {
- case ITEMS:
- rowsUpdated = sqlDB.update(AudioVideoTable.TABLE_NAME, values,
- selection, selectionArgs);
- break;
- case ITEM_ID:
- String id = uri.getLastPathSegment();
- if (TextUtils.isEmpty(selection)) {
- rowsUpdated = sqlDB.update(AudioVideoTable.TABLE_NAME, values,
- AudioVideoTable.COLUMN_ID + "='" + id + "'", null);
- } else {
+ case ITEMS :
rowsUpdated = sqlDB.update(AudioVideoTable.TABLE_NAME, values,
- AudioVideoTable.COLUMN_ID + "='" + id + "' and "
- + selection, selectionArgs);
- }
- break;
- default:
- throw new IllegalArgumentException("Unknown Update URI: " + uri);
+ selection, selectionArgs);
+ break;
+ case ITEM_ID :
+ String id = uri.getLastPathSegment();
+ if (TextUtils.isEmpty(selection)) {
+ rowsUpdated = sqlDB.update(AudioVideoTable.TABLE_NAME,
+ values,
+ AudioVideoTable.COLUMN_ID + "='" + id + "'", null);
+ } else {
+ rowsUpdated = sqlDB.update(AudioVideoTable.TABLE_NAME,
+ values, AudioVideoTable.COLUMN_ID + "='" + id
+ + "' and " + selection, selectionArgs);
+ }
+ break;
+ default :
+ throw new IllegalArgumentException("Unknown Update URI: " + uri);
}
getContext().getContentResolver().notifyChange(uri, null);
return rowsUpdated;
@@ -222,8 +225,8 @@ public static class AudioVideoTable extends OPrimeTable {
public static final String COLUMN_URL = "url";
public static final String COLUMN_DESCRIPTION = "description";
- public static String[] version1Columns = { COLUMN_FILENAME, COLUMN_URL,
- COLUMN_DESCRIPTION };
+ public static String[] version1Columns = {COLUMN_FILENAME, COLUMN_URL,
+ COLUMN_DESCRIPTION};
public static String[] currentColumns = version1Columns;
diff --git a/src/com/github/opensourcefieldlinguistics/fielddb/database/DatumContentProvider.java b/src/com/github/opensourcefieldlinguistics/fielddb/database/DatumContentProvider.java
index 1f603f5..bb26c74 100644
--- a/src/com/github/opensourcefieldlinguistics/fielddb/database/DatumContentProvider.java
+++ b/src/com/github/opensourcefieldlinguistics/fielddb/database/DatumContentProvider.java
@@ -32,6 +32,8 @@ public class DatumContentProvider extends ContentProvider {
private static final int ITEM_ID = 20;
private static final String AUTHORITY = "com.github.opensourcefieldlinguistics.fielddb."
+ + Config.APP_TYPE.toLowerCase()
+ + "."
+ Config.DATA_IS_ABOUT_LANGUAGE_NAME_ASCII.toLowerCase()
+ "."
+ DatumTable.TABLE_NAME;
@@ -112,17 +114,19 @@ public Cursor query(Uri uri, String[] projection, String selection,
int uriType = sURIMatcher.match(uri);
switch (uriType) {
- case ITEMS:
-// queryBuilder.appendWhere(DatumTable.COLUMN_TRASHED + " LIKE 'deleted'");
- queryBuilder.appendWhere(DatumTable.COLUMN_TRASHED + " IS NULL");
- break;
- case ITEM_ID:
- // Adding the ID to the original query
- queryBuilder.appendWhere(DatumTable.COLUMN_ID + "='"
- + uri.getLastPathSegment() + "'");
- break;
- default:
- throw new IllegalArgumentException("Unknown URI: " + uri);
+ case ITEMS :
+ // queryBuilder.appendWhere(DatumTable.COLUMN_TRASHED +
+ // " LIKE 'deleted'");
+ queryBuilder
+ .appendWhere(DatumTable.COLUMN_TRASHED + " IS NULL");
+ break;
+ case ITEM_ID :
+ // Adding the ID to the original query
+ queryBuilder.appendWhere(DatumTable.COLUMN_ID + "='"
+ + uri.getLastPathSegment() + "'");
+ break;
+ default :
+ throw new IllegalArgumentException("Unknown URI: " + uri);
}
SQLiteDatabase db = database.getWritableDatabase();
@@ -142,24 +146,23 @@ public int update(Uri uri, ContentValues values, String selection,
SQLiteDatabase sqlDB = database.getWritableDatabase();
int rowsUpdated = 0;
switch (uriType) {
- case ITEMS:
- rowsUpdated = sqlDB.update(DatumTable.TABLE_NAME, values,
- selection, selectionArgs);
- break;
- case ITEM_ID:
- String id = uri.getLastPathSegment();
- if (TextUtils.isEmpty(selection)) {
+ case ITEMS :
rowsUpdated = sqlDB.update(DatumTable.TABLE_NAME, values,
- DatumTable.COLUMN_ID + "='" + id + "'", null);
- } else {
- rowsUpdated = sqlDB
- .update(DatumTable.TABLE_NAME, values,
- DatumTable.COLUMN_ID + "='" + id + "' and "
- + selection, selectionArgs);
- }
- break;
- default:
- throw new IllegalArgumentException("Unknown Update URI: " + uri);
+ selection, selectionArgs);
+ break;
+ case ITEM_ID :
+ String id = uri.getLastPathSegment();
+ if (TextUtils.isEmpty(selection)) {
+ rowsUpdated = sqlDB.update(DatumTable.TABLE_NAME, values,
+ DatumTable.COLUMN_ID + "='" + id + "'", null);
+ } else {
+ rowsUpdated = sqlDB.update(DatumTable.TABLE_NAME, values,
+ DatumTable.COLUMN_ID + "='" + id + "' and "
+ + selection, selectionArgs);
+ }
+ break;
+ default :
+ throw new IllegalArgumentException("Unknown Update URI: " + uri);
}
getContext().getContentResolver().notifyChange(uri, null);
return rowsUpdated;
@@ -186,7 +189,7 @@ public void onCreate(SQLiteDatabase db) {
NetworkInfo mWifi = connManager
.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
- if (mWifi.isConnected()) {
+ if (!Config.APP_TYPE.equals("speechrecognition") && mWifi.isConnected()) {
// if the user has a wifi connection we can download some
// real sample data
Intent downloadSamples = new Intent(getContext(),
@@ -194,8 +197,7 @@ public void onCreate(SQLiteDatabase db) {
getContext().startService(downloadSamples);
} else {
// Otherwise, insert offline data
- db.insert(DatumTable.TABLE_NAME, null,
- DatumTable.sampleData());
+ insert(null, DatumTable.sampleData());
}
} catch (SQLException e) {
@@ -277,24 +279,37 @@ public static class DatumTable extends OPrimeTable {
public static final String COLUMN_ENTERED_BY_USER = "enteredByUser";
public static final String COLUMN_MODIFIED_BY_USER = "modifiedByUser";
- public static String[] version1Columns = { COLUMN_UTTERANCE,
+ public static String[] version1Columns = {COLUMN_UTTERANCE,
COLUMN_MORPHEMES, COLUMN_GLOSS, COLUMN_TRANSLATION,
COLUMN_ORTHOGRAPHY, COLUMN_CONTEXT, COLUMN_IMAGE_FILES,
COLUMN_AUDIO_VIDEO_FILES, COLUMN_LOCATIONS, COLUMN_REMINDERS,
COLUMN_TAGS, COLUMN_COMMENTS, COLUMN_VALIDATION_STATUS,
- COLUMN_ENTERED_BY_USER, COLUMN_MODIFIED_BY_USER };
+ COLUMN_ENTERED_BY_USER, COLUMN_MODIFIED_BY_USER};
public static String[] currentColumns = version1Columns;
// Offline Sample data
- private static ContentValues sampleData() {
+ public static ContentValues sampleData() {
+ // ContentValues values = new ContentValues();
+ // values.put(COLUMN_ID, "sample12345");
+ // values.put(COLUMN_MORPHEMES, "e'sig");
+ // values.put(COLUMN_GLOSS, "clam");
+ // values.put(COLUMN_TRANSLATION, "Clam");
+ // values.put(COLUMN_ORTHOGRAPHY, "e'sig");
+ // values.put(COLUMN_CONTEXT, " ");
+ // return values;
+
ContentValues values = new ContentValues();
- values.put(COLUMN_ID, "sample12345");
- values.put(COLUMN_MORPHEMES, "e'sig");
- values.put(COLUMN_GLOSS, "clam");
- values.put(COLUMN_TRANSLATION, "Clam");
- values.put(COLUMN_ORTHOGRAPHY, "e'sig");
- values.put(COLUMN_CONTEXT, " ");
+ values.put(COLUMN_ID, "instructions");
+ values.put(
+ COLUMN_UTTERANCE,
+ "You need to read a few sentences to train the recognizer to your voice and your words.");
+ values.put(
+ COLUMN_ORTHOGRAPHY,
+ "შენ უნდა წაიკითხო რამოდენიმე წინადადება, რათა გადაამზადო აპლიკაცია შენს ხმაზე და შენს სიტყვებზე");
+ values.put(
+ COLUMN_CONTEXT,
+ "The Georgian language is very complex and very different from other languages which were used to build Speech Recognition systems. This means each person should have their own recognizer.");
return values;
}
diff --git a/src/com/github/opensourcefieldlinguistics/fielddb/database/FieldDBUserContentProvider.java b/src/com/github/opensourcefieldlinguistics/fielddb/database/FieldDBUserContentProvider.java
index 0998423..120c68b 100644
--- a/src/com/github/opensourcefieldlinguistics/fielddb/database/FieldDBUserContentProvider.java
+++ b/src/com/github/opensourcefieldlinguistics/fielddb/database/FieldDBUserContentProvider.java
@@ -10,10 +10,12 @@ public class FieldDBUserContentProvider extends UserContentProvider {
@Override
public boolean onCreate() {
+ UserTable.ANONYMOUS_PREFIX = Config.ANONYMOUS_USER_PREFIX;
if (Config.D) {
UserTable.ANONYMOUS_PREFIX = "testing" + UserTable.ANONYMOUS_PREFIX;
}
AUTHORITY = "com.github.opensourcefieldlinguistics.fielddb."
+ + Config.APP_TYPE.toLowerCase() + "."
+ Config.DATA_IS_ABOUT_LANGUAGE_NAME_ASCII.toLowerCase() + "."
+ UserTable.TABLE_NAME;
CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/" + BASE_PATH);
diff --git a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/Config.java b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/Config.java
index 0f1896c..42268fd 100644
--- a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/Config.java
+++ b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/Config.java
@@ -7,20 +7,30 @@ public class Config extends ca.ilanguage.oprime.Config {
public static final String ACRA_USER = PrivateConstants.ACRA_USER;
public static final String DATA_IS_ABOUT_LANGUAGE_ISO = "ka";
public static final String DATA_IS_ABOUT_LANGUAGE_NAME_ASCII = "kartuli";
-// public static final String DATA_IS_ABOUT_LANGUAGE_NAME = "ქართული";
+ public static final String APP_TYPE = "speechrecognition";
+ // public static final String DATA_IS_ABOUT_LANGUAGE_NAME = "ქართული";
- public static final String DEFAULT_CORPUS = "community-georgian";
+ public static String DEFAULT_CORPUS = "username-"
+ + DATA_IS_ABOUT_LANGUAGE_NAME_ASCII;
+ public static String CURRENT_USERNAME = "default";
public static final String DEFAULT_DATA_LOGIN = PrivateConstants.DEFAULT_DATA_SERVER_URL
+ "/_session";
public static final String DEFAULT_AUTH_LOGIN_URL = PrivateConstants.DEFAULT_AUTH_LOGIN_URL;
public static final String DEFAULT_DATA_SERVER_URL = PrivateConstants.DEFAULT_DATA_SERVER_URL;
- public static final String DEFAULT_OUTPUT_DIRECTORY = "/sdcard/"+DEFAULT_CORPUS;
+ public static String DEFAULT_OUTPUT_DIRECTORY = "/sdcard/"
+ + DATA_IS_ABOUT_LANGUAGE_NAME_ASCII + "-" + APP_TYPE + "/"
+ + DEFAULT_CORPUS;
public static final String DEFAULT_PUBLIC_USER_PASS = PrivateConstants.DEFAULT_PUBLIC_USER_PASS;
public static final String DEFAULT_PUBLIC_USERNAME = PrivateConstants.DEFAULT_PUBLIC_USERNAME;
+ public static final String DEFAULT_UPLOAD_TOKEN = PrivateConstants.DEFAULT_UPLOAD_TOKEN;
public static final String DEFAULT_REGISTER_USER_URL = PrivateConstants.DEFAULT_REGISTER_USER_URL;
+ public static final String DEFAULT_UPLOAD_AUDIO_VIDEO_URL = PrivateConstants.DEFAULT_UPLOAD_AUDIO_VIDEO_URL;
public static final String DEFAULT_SAMPLE_DATA_URL = PrivateConstants.DEFAULT_DATA_SERVER_URL
+ "/" + DEFAULT_CORPUS + "/_design/learnx/_view/byTag";
public static final String KEYSTORE_PASS = PrivateConstants.KEYSTORE_PASS;
public static final String USER_FRIENDLY_DATA_NAME = "ფრაზა";
+ public static final String ANONYMOUS_USER_PREFIX = "anonymous"
+ + DATA_IS_ABOUT_LANGUAGE_NAME_ASCII + APP_TYPE;
+
}
diff --git a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/PrivateConstantsSample.java b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/PrivateConstantsSample.java
index aad62a5..890d751 100644
--- a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/PrivateConstantsSample.java
+++ b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/PrivateConstantsSample.java
@@ -18,6 +18,7 @@ public class PrivateConstantsSample {
public static final String DEFAULT_PUBLIC_USER_PASS = "ausername";
public static final String DEFAULT_PUBLIC_USERNAME = "apassword";
public static final String DEFAULT_REGISTER_USER_URL = "http://10.0.2.2:3183/register";
+ public static final String DEFAULT_UPLOAD_AUDIO_VIDEO_URL = "http://10.0.2.2:3184/upload/extract/utterances";
/*
* Example on how to support self signed ssl certificates by creating a
diff --git a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumDetailActivity.java b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumDetailActivity.java
index f965bb3..5ea5793 100644
--- a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumDetailActivity.java
+++ b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumDetailActivity.java
@@ -1,6 +1,7 @@
package com.github.opensourcefieldlinguistics.fielddb.lessons.ui;
import com.github.opensourcefieldlinguistics.fielddb.lessons.georgian.R;
+import com.github.opensourcefieldlinguistics.fielddb.lessons.Config;
import android.content.Intent;
import android.os.Bundle;
@@ -51,17 +52,17 @@ protected void onCreate(Bundle savedInstanceState) {
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
- case android.R.id.home:
- // This ID represents the Home or Up button. In the case of this
- // activity, the Up button is shown. Use NavUtils to allow users
- // to navigate up one level in the application structure. For
- // more details, see the Navigation pattern on Android Design:
- //
- // http://developer.android.com/design/patterns/navigation.html#up-vs-back
- //
- NavUtils.navigateUpTo(this, new Intent(this,
- DatumListActivity.class));
- return true;
+ case android.R.id.home :
+ // This ID represents the Home or Up button. In the case of this
+ // activity, the Up button is shown. Use NavUtils to allow users
+ // to navigate up one level in the application structure. For
+ // more details, see the Navigation pattern on Android Design:
+ //
+ // http://developer.android.com/design/patterns/navigation.html#up-vs-back
+ //
+ NavUtils.navigateUpTo(this, new Intent(this,
+ DatumListActivity.class));
+ return true;
}
return super.onOptionsItemSelected(item);
}
diff --git a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumDetailFragment.java b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumDetailFragment.java
index 638f678..432e027 100644
--- a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumDetailFragment.java
+++ b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumDetailFragment.java
@@ -16,10 +16,13 @@
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
+import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Bundle;
+import android.os.Handler;
import android.support.v4.app.Fragment;
import android.support.v4.app.NavUtils;
+import android.support.v4.view.ViewPager;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
@@ -30,8 +33,10 @@
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
+import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.MediaController;
+import android.widget.TextView;
import android.widget.VideoView;
import ca.ilanguage.oprime.datacollection.AudioRecorder;
import ca.ilanguage.oprime.datacollection.TakePicture;
@@ -41,7 +46,9 @@
import com.github.opensourcefieldlinguistics.fielddb.database.DatumContentProvider;
import com.github.opensourcefieldlinguistics.fielddb.database.DatumContentProvider.DatumTable;
import com.github.opensourcefieldlinguistics.fielddb.lessons.Config;
-import com.github.opensourcefieldlinguistics.fielddb.lessons.georgian.R;
+import com.github.opensourcefieldlinguistics.fielddb.service.UploadAudioVideoService;
+import com.github.opensourcefieldlinguistics.fielddb.speech.kartuli.BuildConfig;
+import com.github.opensourcefieldlinguistics.fielddb.speech.kartuli.R;
import com.github.opensourcefieldlinguistics.fielddb.model.Datum;
/**
@@ -56,11 +63,13 @@ public class DatumDetailFragment extends Fragment {
*/
public static final String ARG_ITEM_ID = "item_id";
+ public static final String ARG_TOTAL_DATUM_IN_LIST = "total_datum_count_in_list";
+
/**
* The content this fragment is presenting.
*/
- private Datum mItem;
- private Uri mUri;
+ protected Datum mItem;
+ protected Uri mUri;
public boolean mTwoPane = false;
/**
@@ -70,13 +79,22 @@ public class DatumDetailFragment extends Fragment {
public DatumDetailFragment() {
}
- private String TAG = "FieldDB";
- private boolean mRecordingAudio = false;
- private VideoView mVideoView;
- private ImageView mImageView;
- private MediaController mMediaController;
+ protected boolean mRecordingAudio = false;
+ protected VideoView mVideoView;
+ protected ImageView mImageView;
+ protected MediaController mMediaController;
+ protected MediaPlayer mAudioPlayer;
protected DeviceDetails mDeviceDetails;
protected HashMap mDatumEditCounts;
+ protected ImageButton mSpeechRecognizerFeedback;
+ protected TextView mSpeechRecognizerInstructions;
+ protected boolean isPlaying = false;
+
+ protected ViewPager mDatumPager;
+
+ protected int mLastDatumIndex;
+
+ private String mAudioFileName;
@Override
public void onCreate(Bundle savedInstanceState) {
@@ -84,21 +102,23 @@ public void onCreate(Bundle savedInstanceState) {
setHasOptionsMenu(true);
if (this.mDeviceDetails == null) {
this.mDeviceDetails = new DeviceDetails(getActivity(), Config.D,
- this.TAG);
+ Config.TAG);
}
if (getArguments().containsKey(ARG_ITEM_ID)) {
String id = getArguments().getString(ARG_ITEM_ID);
+ this.mLastDatumIndex = getArguments().getInt(
+ ARG_TOTAL_DATUM_IN_LIST);
Log.d(Config.TAG, "Will get id " + id);
String selection = null;
String[] selectionArgs = null;
String sortOrder = null;
- String[] datumProjection = { DatumTable.COLUMN_ORTHOGRAPHY,
- DatumTable.COLUMN_MORPHEMES, DatumTable.COLUMN_GLOSS,
- DatumTable.COLUMN_TRANSLATION, DatumTable.COLUMN_CONTEXT,
- DatumTable.COLUMN_IMAGE_FILES,
- DatumTable.COLUMN_AUDIO_VIDEO_FILES };
+ String[] datumProjection = {DatumTable.COLUMN_ORTHOGRAPHY,
+ DatumTable.COLUMN_UTTERANCE, DatumTable.COLUMN_MORPHEMES,
+ DatumTable.COLUMN_GLOSS, DatumTable.COLUMN_TRANSLATION,
+ DatumTable.COLUMN_CONTEXT, DatumTable.COLUMN_IMAGE_FILES,
+ DatumTable.COLUMN_AUDIO_VIDEO_FILES, DatumTable.COLUMN_TAGS};
mUri = Uri.withAppendedPath(DatumContentProvider.CONTENT_URI, id);
CursorLoader cursorLoader = new CursorLoader(getActivity(), mUri,
datumProjection, selection, selectionArgs, sortOrder);
@@ -117,17 +137,24 @@ public void onCreate(Bundle savedInstanceState) {
.getColumnIndexOrThrow(DatumTable.COLUMN_TRANSLATION)),
cursor.getString(cursor
.getColumnIndexOrThrow(DatumTable.COLUMN_CONTEXT)));
+ datum.setId(id);
+ datum.setUtterance(cursor.getString(cursor
+ .getColumnIndexOrThrow(DatumTable.COLUMN_UTTERANCE)));
datum.addMediaFiles(cursor.getString(cursor
.getColumnIndexOrThrow(DatumTable.COLUMN_IMAGE_FILES)));
-
datum.addMediaFiles((cursor.getString(cursor
.getColumnIndexOrThrow(DatumTable.COLUMN_AUDIO_VIDEO_FILES))));
+
+ datum.setTagsFromSting(cursor.getString(cursor
+ .getColumnIndexOrThrow(DatumTable.COLUMN_TAGS)));
cursor.close();
mItem = datum;
this.recordUserEvent("loadDatum", mUri.getLastPathSegment());
- ACRA.getErrorReporter().putCustomData("urlString",
- mUri.toString());
+ if (!BuildConfig.DEBUG)
+ ACRA.getErrorReporter().putCustomData("urlString",
+ mUri.toString());
+
}
}
@@ -138,23 +165,33 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_datum_detail,
container, false);
+ if (Config.APP_TYPE.equals("speechrecognition")) {
+ rootView = inflater.inflate(R.layout.fragment_datum_detail_simple,
+ container, false);
+ }
if (mItem != null) {
+ this.prepareEditTextListeners(rootView);
+ this.prepareVideoAndImages(rootView);
+ this.prepareSpeechRecognitionButton(rootView);
+ }
- final EditText orthographyEditText = ((EditText) rootView
- .findViewById(R.id.orthography));
+ return rootView;
+ }
+
+ protected void prepareEditTextListeners(View rootView) {
+ final EditText orthographyEditText = ((EditText) rootView
+ .findViewById(R.id.orthography));
+ if (orthographyEditText != null) {
orthographyEditText.setText(mItem.getOrthography());
orthographyEditText.addTextChangedListener(new TextWatcher() {
-
@Override
public void afterTextChanged(Editable arg0) {
}
-
@Override
public void beforeTextChanged(CharSequence arg0, int arg1,
int arg2, int arg3) {
}
-
@Override
public void onTextChanged(CharSequence arg0, int arg1,
int arg2, int arg3) {
@@ -168,21 +205,21 @@ public void onTextChanged(CharSequence arg0, int arg1,
recordUserEvent("editDatum", "orthography");
}
});
+ }
+
+ final EditText morphemesEditText = ((EditText) rootView
+ .findViewById(R.id.morphemes));
+ if (morphemesEditText != null) {
- final EditText morphemesEditText = ((EditText) rootView
- .findViewById(R.id.morphemes));
morphemesEditText.setText(mItem.getMorphemes());
morphemesEditText.addTextChangedListener(new TextWatcher() {
-
@Override
public void afterTextChanged(Editable arg0) {
}
-
@Override
public void beforeTextChanged(CharSequence arg0, int arg1,
int arg2, int arg3) {
}
-
@Override
public void onTextChanged(CharSequence arg0, int arg1,
int arg2, int arg3) {
@@ -195,21 +232,20 @@ public void onTextChanged(CharSequence arg0, int arg1,
recordUserEvent("editDatum", "morphemes");
}
});
+ }
- final EditText glossEditText = ((EditText) rootView
- .findViewById(R.id.gloss));
+ final EditText glossEditText = ((EditText) rootView
+ .findViewById(R.id.gloss));
+ if (glossEditText != null) {
glossEditText.setText(mItem.getGloss());
glossEditText.addTextChangedListener(new TextWatcher() {
-
@Override
public void afterTextChanged(Editable arg0) {
}
-
@Override
public void beforeTextChanged(CharSequence arg0, int arg1,
int arg2, int arg3) {
}
-
@Override
public void onTextChanged(CharSequence arg0, int arg1,
int arg2, int arg3) {
@@ -222,12 +258,11 @@ public void onTextChanged(CharSequence arg0, int arg1,
recordUserEvent("editDatum", "gloss");
}
});
+ }
- ((EditText) rootView.findViewById(R.id.gloss)).setText(mItem
- .getGloss());
-
- final EditText translationEditText = ((EditText) rootView
- .findViewById(R.id.translation));
+ final EditText translationEditText = ((EditText) rootView
+ .findViewById(R.id.translation));
+ if (translationEditText != null) {
translationEditText.setText(mItem.getTranslation());
translationEditText.addTextChangedListener(new TextWatcher() {
@@ -253,11 +288,11 @@ public void onTextChanged(CharSequence arg0, int arg1,
recordUserEvent("editDatum", "translation");
}
});
- ((EditText) rootView.findViewById(R.id.translation)).setText(mItem
- .getTranslation());
+ }
- final EditText contextEditText = ((EditText) rootView
- .findViewById(R.id.context));
+ final EditText contextEditText = ((EditText) rootView
+ .findViewById(R.id.context));
+ if (contextEditText != null) {
contextEditText.setText(mItem.getContext());
contextEditText.addTextChangedListener(new TextWatcher() {
@@ -279,28 +314,84 @@ public void onTextChanged(CharSequence arg0, int arg1,
values.put(DatumTable.COLUMN_CONTEXT, currentText);
getActivity().getContentResolver().update(mUri, values,
null, null);
- recordUserEvent("editDatum", "translation");
+ recordUserEvent("editDatum", "context");
}
});
- ((EditText) rootView.findViewById(R.id.context)).setText(mItem
- .getContext());
- if (mImageView == null) {
- mImageView = (ImageView) rootView.findViewById(R.id.image_view);
- }
- if (mMediaController == null) {
- mMediaController = new MediaController(getActivity());
- mMediaController.setAnchorView((VideoView) rootView
- .findViewById(R.id.video_view));
- // mMediaController.setPadding(0, 0, 0, 200);
- }
- if (mVideoView == null) {
- mVideoView = (VideoView) rootView.findViewById(R.id.video_view);
+ }
+
+ final EditText tagsEditText = ((EditText) rootView
+ .findViewById(R.id.tags));
+ if (tagsEditText != null) {
+ tagsEditText.setText(mItem.getTagsString());
+ tagsEditText.addTextChangedListener(new TextWatcher() {
+
+ @Override
+ public void afterTextChanged(Editable arg0) {
+ }
+
+ @Override
+ public void beforeTextChanged(CharSequence arg0, int arg1,
+ int arg2, int arg3) {
+ }
+
+ @Override
+ public void onTextChanged(CharSequence arg0, int arg1,
+ int arg2, int arg3) {
+ String currentText = tagsEditText.getText().toString();
+ mItem.setTagsFromSting(currentText);
+ ContentValues values = new ContentValues();
+ values.put(DatumTable.COLUMN_TAGS, currentText);
+ getActivity().getContentResolver().update(mUri, values,
+ null, null);
+ recordUserEvent("editDatum", "tags");
+ }
+ });
+ }
+ }
+
+ protected void prepareVideoAndImages(View rootView) {
+ if (mImageView == null) {
+ mImageView = (ImageView) rootView.findViewById(R.id.image_view);
+ }
+ if (mMediaController == null) {
+ mMediaController = new MediaController(getActivity());
+ mMediaController.setAnchorView((VideoView) rootView
+ .findViewById(R.id.video_view));
+ // mMediaController.setPadding(0, 0, 0, 200);
+ }
+ if (mVideoView == null) {
+ mVideoView = (VideoView) rootView.findViewById(R.id.video_view);
+ if (mVideoView != null) {
mVideoView.setMediaController(mMediaController);
}
- this.loadVisuals(false);
}
+ this.loadVisuals(false);
+ }
- return rootView;
+ protected void prepareSpeechRecognitionButton(View rootView) {
+
+ mSpeechRecognizerFeedback = (ImageButton) rootView
+ .findViewById(R.id.speech_recognizer_feedback);
+ if (mSpeechRecognizerFeedback != null) {
+ mSpeechRecognizerFeedback
+ .setImageResource(R.drawable.speech_recognizer_listening);
+ mSpeechRecognizerFeedback
+ .setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ toggleAudioRecording(null);
+ }
+ });
+ }
+
+ mSpeechRecognizerInstructions = (TextView) rootView
+ .findViewById(R.id.speech_recognizer_instructions);
+ if (mSpeechRecognizerInstructions != null) {
+ mSpeechRecognizerInstructions.setText("");
+ }
+
+ this.mDatumPager = (ViewPager) getActivity().findViewById(
+ R.id.viewpager);
}
@Override
@@ -326,7 +417,7 @@ public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
* or changes, you must update the share intent by again calling
* mShareActionProvider.setShareIntent()
*/
- private Intent getDefaultIntent() {
+ protected Intent getDefaultIntent() {
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("image/*");
return intent;
@@ -336,72 +427,149 @@ private Intent getDefaultIntent() {
public boolean onOptionsItemSelected(MenuItem item) {
// handle item selection
switch (item.getItemId()) {
- case R.id.action_speak:
- if (!this.mRecordingAudio) {
- String audioFileName = Config.DEFAULT_OUTPUT_DIRECTORY + "/"
- + mItem.getBaseFilename()
- + Config.DEFAULT_AUDIO_EXTENSION;
- Intent intent;
- intent = new Intent(getActivity(), AudioRecorder.class);
- intent.putExtra(Config.EXTRA_RESULT_FILENAME, audioFileName);
- mItem.addAudioFile(audioFileName.replace(
- Config.DEFAULT_OUTPUT_DIRECTORY + "/", ""));
- getActivity().startService(intent);
- ContentValues values = new ContentValues();
- values.put(DatumTable.COLUMN_AUDIO_VIDEO_FILES,
- mItem.getMediaFilesAsCSV(mItem.getAudioVideoFiles()));
- getActivity().getContentResolver().update(mUri, values, null,
- null);
- Log.d(TAG, "Recording audio " + audioFileName);
- this.mRecordingAudio = true;
+ case R.id.action_speak :
+ return this.toggleAudioRecording(item);
+ case R.id.action_play :
+ return this.loadMainVideo(true);
+ case R.id.action_videos :
+ return this.captureVideo();
+ case R.id.action_images :
+ return this.captureImage();
+ case R.id.action_delete :
+ return this.delete();
+ default :
+ return super.onOptionsItemSelected(item);
+ }
+ }
+
+ public void onToggleAudioRecording(View view) {
+ this.toggleAudioRecording(null);
+ }
+
+ public boolean toggleAudioRecording(MenuItem item) {
+ if (!this.mRecordingAudio) {
+ String audioFileName = Config.DEFAULT_OUTPUT_DIRECTORY + "/"
+ + mItem.getBaseFilename() + Config.DEFAULT_AUDIO_EXTENSION;
+ this.mAudioFileName = audioFileName;
+ Intent intent;
+ intent = new Intent(getActivity(), AudioRecorder.class);
+ intent.putExtra(Config.EXTRA_RESULT_FILENAME, audioFileName);
+ mItem.addAudioFile(audioFileName.replace(
+ Config.DEFAULT_OUTPUT_DIRECTORY + "/", ""));
+ getActivity().startService(intent);
+ ContentValues values = new ContentValues();
+ values.put(DatumTable.COLUMN_AUDIO_VIDEO_FILES,
+ mItem.getMediaFilesAsCSV(mItem.getAudioVideoFiles()));
+ getActivity().getContentResolver().update(mUri, values, null, null);
+ Log.d(Config.TAG, "Recording audio " + audioFileName);
+ this.mRecordingAudio = true;
+ if (item != null) {
item.setIcon(R.drawable.ic_action_stop);
- this.recordUserEvent("captureAudio", audioFileName);
+ }
+ this.recordUserEvent("captureAudio", audioFileName);
+
+ if (mSpeechRecognizerFeedback != null) {
+ mSpeechRecognizerFeedback
+ .setImageResource(R.drawable.speech_recognizer_recognizing);
+ }
+
+ if (mSpeechRecognizerInstructions != null) {
+ mSpeechRecognizerInstructions.setText("Tap to end");
+ }
+
+ } else {
+ this.turnOffRecorder(item);
+ }
+ return true;
+ }
+ protected boolean turnOffRecorder(MenuItem item) {
+ if (mAudioFileName == null) {
+ return false;
+ }
+ Intent audio = new Intent(getActivity(), AudioRecorder.class);
+ getActivity().stopService(audio);
+ Handler mainHandler = new Handler(getActivity().getMainLooper());
+ Runnable launchUploadAudioService = new Runnable() {
+
+ @Override
+ public void run() {
+ if (getActivity() == null) {
+ return;
+ }
+ Intent uploadAudioFile = new Intent(getActivity(),
+ UploadAudioVideoService.class);
+ uploadAudioFile.setData(Uri.parse(mAudioFileName));
+ uploadAudioFile.putExtra(Config.EXTRA_PARTICIPANT_ID,
+ Config.CURRENT_USERNAME);
+ uploadAudioFile.putExtra(
+ Config.EXTRA_EXPERIMENT_TRIAL_INFORMATION,
+ mDeviceDetails.getCurrentDeviceDetails());
+ getActivity().startService(uploadAudioFile);
+ }
+ };
+ mainHandler.postDelayed(launchUploadAudioService, 1000);
+
+ this.mRecordingAudio = false;
+ if (item != null) {
+ item.setIcon(R.drawable.ic_action_mic);
+ }
+ this.recordUserEvent("stopAudio", this.mAudioFileName);
+
+ if (mSpeechRecognizerFeedback != null) {
+ mSpeechRecognizerFeedback
+ .setImageResource(R.drawable.speech_recognizer_waiting);
+ }
+ if (mSpeechRecognizerInstructions != null) {
+ mSpeechRecognizerInstructions.setText("Tap to speak again");
+ }
+ if (Config.APP_TYPE.equals("speechrecognition")) {
+ autoAdvanceAfterRecordingAudio();
+ }
+ return true;
+ }
+
+ protected boolean autoAdvanceAfterRecordingAudio() {
+ if (this.mDatumPager != null) {
+ int currentStimulusIndex = this.mDatumPager.getCurrentItem();
+ if (currentStimulusIndex == this.mLastDatumIndex) {
+ Intent openDataList = new Intent(getActivity(),
+ DatumListActivity.class);
+ startActivity(openDataList);
} else {
- Intent audio = new Intent(getActivity(), AudioRecorder.class);
- getActivity().stopService(audio);
- this.mRecordingAudio = false;
- item.setIcon(R.drawable.ic_action_mic);
- this.recordUserEvent("stopAudio", "");
+ this.mDatumPager.setCurrentItem(this.mDatumPager
+ .getCurrentItem() + 1);
}
- return true;
- case R.id.action_play:
- return this.loadMainVideo(true);
- case R.id.action_videos:
- return this.captureVideo();
- case R.id.action_images:
- return this.captureImage();
- case R.id.action_delete:
- return this.delete();
- default:
- return super.onOptionsItemSelected(item);
}
+ return true;
}
- private boolean delete() {
+ protected boolean delete() {
AlertDialog deleteConfirmationDialog = new AlertDialog.Builder(
getActivity())
- .setTitle("Are you sure?")
+ .setTitle(R.string.are_you_sure)
.setMessage(
- "Are you sure you want to put this "
- + Config.USER_FRIENDLY_DATA_NAME
- + " in the trash?")
+ getString(R.string.are_you_sure_put_in_trash).replace(
+ "datum", Config.USER_FRIENDLY_DATA_NAME))
+
.setPositiveButton(android.R.string.ok,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog,
int which) {
- getActivity().getContentResolver()
- .delete(mUri, null, null);
+ getActivity().getContentResolver().delete(mUri,
+ null, null);
dialog.dismiss();
-
- if(mTwoPane){
- getActivity().getSupportFragmentManager().popBackStack();
- }else{
- NavUtils.navigateUpTo(getActivity(), new Intent(getActivity(),
- DatumListActivity.class));
+
+ if (mTwoPane) {
+ getActivity().getSupportFragmentManager()
+ .popBackStack();
+ } else {
+ NavUtils.navigateUpTo(getActivity(),
+ new Intent(getActivity(),
+ DatumListActivity.class));
}
-
+
}
})
.setNegativeButton(android.R.string.cancel,
@@ -415,8 +583,7 @@ public void onClick(DialogInterface dialog,
deleteConfirmationDialog.show();
return true;
}
-
- private void loadVisuals(boolean playImmediately) {
+ protected void loadVisuals(boolean playImmediately) {
loadMainVideo(playImmediately);
}
@@ -429,61 +596,86 @@ public boolean loadMainVideo(boolean playNow) {
this.loadMainImage();
return false;
}
- mVideoView.setVideoPath(fileName);
- if (fileName.endsWith(Config.DEFAULT_AUDIO_EXTENSION)) {
- loadMainImage();
- } else {
- int sdk = android.os.Build.VERSION.SDK_INT;
- if (sdk >= 16) {
- mVideoView.setBackground(null);
+ if (mVideoView != null) {
+ mVideoView.setVideoPath(fileName);
+ if (fileName.endsWith(Config.DEFAULT_AUDIO_EXTENSION)) {
+ loadMainImage();
} else {
- Log.e(Config.TAG,
- "Couldnt set the video background. (this might be a kindle)");
- mImageView.setImageBitmap(null);
- mImageView.setVisibility(View.VISIBLE);
- mVideoView.setVisibility(View.GONE);
+ int sdk = android.os.Build.VERSION.SDK_INT;
+ if (sdk >= 16) {
+ mVideoView.setBackground(null);
+ } else {
+ Log.e(Config.TAG,
+ "Couldnt set the video background. (this might be a kindle)");
+ mImageView.setImageBitmap(null);
+ mImageView.setVisibility(View.VISIBLE);
+ mVideoView.setVisibility(View.GONE);
+ }
}
- }
- if (playNow) {
- this.recordUserEvent("loadMainVideo", fileName);
+ if (playNow) {
+ this.recordUserEvent("loadMainVideo", fileName);
- mVideoView.start();
- mMediaController.setPrevNextListeners(new View.OnClickListener() {
+ mVideoView.start();
+ mMediaController.setPrevNextListeners(
+ new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- String filename = mItem.getPrevNextMediaFile("audio",
- mItem.getAudioVideoFiles(), "next");
- if (filename != null) {
- mVideoView.stopPlayback();
- mVideoView.setVideoPath(Config.DEFAULT_OUTPUT_DIRECTORY
- + "/" + filename);
- mVideoView.start();
- }
- }
- }, new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ String filename = mItem.getPrevNextMediaFile(
+ "audio", mItem.getAudioVideoFiles(),
+ "next");
+ if (filename != null) {
+ mVideoView.stopPlayback();
+ mVideoView
+ .setVideoPath(Config.DEFAULT_OUTPUT_DIRECTORY
+ + "/" + filename);
+ mVideoView.start();
+ }
+ }
+ }, new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- String filename = mItem.getPrevNextMediaFile("audio",
- mItem.getAudioVideoFiles(), "prev");
- if (filename != null) {
- mVideoView.stopPlayback();
- mVideoView.setVideoPath(Config.DEFAULT_OUTPUT_DIRECTORY
- + "/" + filename);
- mVideoView.start();
- }
- }
- });
+ @Override
+ public void onClick(View v) {
+ String filename = mItem.getPrevNextMediaFile(
+ "audio", mItem.getAudioVideoFiles(),
+ "prev");
+ if (filename != null) {
+ mVideoView.stopPlayback();
+ mVideoView
+ .setVideoPath(Config.DEFAULT_OUTPUT_DIRECTORY
+ + "/" + filename);
+ mVideoView.start();
+ }
+ }
+ });
+ }
+ } else {
+ Log.d(Config.TAG, "Playing audio only (no video)");
+ mAudioPlayer = MediaPlayer.create(
+ getActivity(),
+ Uri.parse("file://" + Config.DEFAULT_OUTPUT_DIRECTORY + "/"
+ + fileName));
+ mAudioPlayer
+ .setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
+ @Override
+ public void onPrepared(MediaPlayer mp) {
+ mp.start();
+ }
+ });
}
return true;
}
- @SuppressLint("NewApi")
- private void loadMainImage() {
+ protected void loadMainImage() {
File image = new File(Config.DEFAULT_OUTPUT_DIRECTORY + "/"
+ mItem.getMainImageFile());
if (!image.exists()) {
+ if (mVideoView != null) {
+ mVideoView.setVisibility(View.GONE);
+ }
+ if (mImageView != null) {
+ mImageView.setVisibility(View.VISIBLE);
+ }
return;
}
Bitmap d = new BitmapDrawable(this.getResources(),
@@ -493,17 +685,17 @@ private void loadMainImage() {
}
int nh = (int) (d.getHeight() * (512.0 / d.getWidth()));
Bitmap scaled = Bitmap.createScaledBitmap(d, 512, nh, true);
- int sdk = android.os.Build.VERSION.SDK_INT;
- if (sdk >= 16) {
- mVideoView
- .setBackground(new BitmapDrawable(getResources(), scaled));
- } else {
- Log.e(Config.TAG,
- "Couldnt set the video background. (this might be a kindle)");
- mImageView.setImageBitmap(scaled);
- mImageView.setVisibility(View.VISIBLE);
- mVideoView.setVisibility(View.GONE);
- }
+ // int sdk = android.os.Build.VERSION.SDK_INT;
+ // if (falssdk >= 16) {
+ // mVideoView
+ // .setBackground(new BitmapDrawable(getResources(), scaled));
+ // } else {
+ // Log.e(Config.TAG,
+ // "Couldnt set the video background. (this might be a kindle)");
+ mImageView.setImageBitmap(scaled);
+ mImageView.setVisibility(View.VISIBLE);
+ mVideoView.setVisibility(View.GONE);
+ // }
}
@@ -514,52 +706,54 @@ public void onActivityResult(int requestCode, int resultCode, Intent data) {
// }
String resultFile;
switch (requestCode) {
- case Config.CODE_EXPERIMENT_COMPLETED:
- if (data != null && data.hasExtra(Config.EXTRA_RESULT_FILENAME)) {
- resultFile = data.getExtras().getString(
- Config.EXTRA_RESULT_FILENAME);
- if (resultFile != null) {
- // if (resultFile != null && new File(resultFile).exists())
- // {
- if (resultFile.endsWith(Config.DEFAULT_AUDIO_EXTENSION)) {
- mItem.addAudioFile(resultFile.replace(
- Config.DEFAULT_OUTPUT_DIRECTORY + "/", ""));
- } else {
- mItem.addVideoFile(resultFile.replace(
- Config.DEFAULT_OUTPUT_DIRECTORY + "/", ""));
+ case Config.CODE_EXPERIMENT_COMPLETED :
+ if (data != null && data.hasExtra(Config.EXTRA_RESULT_FILENAME)) {
+ resultFile = data.getExtras().getString(
+ Config.EXTRA_RESULT_FILENAME);
+ if (resultFile != null) {
+ // if (resultFile != null && new
+ // File(resultFile).exists())
+ // {
+ if (resultFile.endsWith(Config.DEFAULT_AUDIO_EXTENSION)) {
+ mItem.addAudioFile(resultFile.replace(
+ Config.DEFAULT_OUTPUT_DIRECTORY + "/", ""));
+ } else {
+ mItem.addVideoFile(resultFile.replace(
+ Config.DEFAULT_OUTPUT_DIRECTORY + "/", ""));
+ }
+ ContentValues values = new ContentValues();
+ values.put(DatumTable.COLUMN_AUDIO_VIDEO_FILES, mItem
+ .getMediaFilesAsCSV(mItem.getAudioVideoFiles()));
+ getActivity().getContentResolver().update(mUri, values,
+ null, null);
+ this.loadMainVideo(false);
}
- ContentValues values = new ContentValues();
- values.put(DatumTable.COLUMN_AUDIO_VIDEO_FILES, mItem
- .getMediaFilesAsCSV(mItem.getAudioVideoFiles()));
- getActivity().getContentResolver().update(mUri, values,
- null, null);
- this.loadMainVideo(false);
}
- }
- break;
- case Config.CODE_PICTURE_TAKEN:
- if (data != null && data.hasExtra(Config.EXTRA_RESULT_FILENAME)) {
- resultFile = data.getExtras().getString(
- Config.EXTRA_RESULT_FILENAME);
- if (resultFile != null) {
- // if (resultFile != null && new File(resultFile).exists())
- // {
- mItem.addImageFile(resultFile.replace(
- Config.DEFAULT_OUTPUT_DIRECTORY + "/", ""));
- ContentValues values = new ContentValues();
- values.put(DatumTable.COLUMN_IMAGE_FILES,
- mItem.getMediaFilesAsCSV(mItem.getImageFiles()));
- getActivity().getContentResolver().update(mUri, values,
- null, null);
- this.loadMainImage();
+ break;
+ case Config.CODE_PICTURE_TAKEN :
+ if (data != null && data.hasExtra(Config.EXTRA_RESULT_FILENAME)) {
+ resultFile = data.getExtras().getString(
+ Config.EXTRA_RESULT_FILENAME);
+ if (resultFile != null) {
+ // if (resultFile != null && new
+ // File(resultFile).exists())
+ // {
+ mItem.addImageFile(resultFile.replace(
+ Config.DEFAULT_OUTPUT_DIRECTORY + "/", ""));
+ ContentValues values = new ContentValues();
+ values.put(DatumTable.COLUMN_IMAGE_FILES,
+ mItem.getMediaFilesAsCSV(mItem.getImageFiles()));
+ getActivity().getContentResolver().update(mUri, values,
+ null, null);
+ this.loadMainImage();
+ }
}
- }
- break;
+ break;
}
super.onActivityResult(requestCode, requestCode, data);
}
- private boolean captureVideo() {
+ protected boolean captureVideo() {
String videoFileName = Config.DEFAULT_OUTPUT_DIRECTORY + "/"
+ mItem.getBaseFilename() + Config.DEFAULT_VIDEO_EXTENSION;
Intent intent = new Intent(getActivity(), VideoRecorder.class);
@@ -576,7 +770,7 @@ private boolean captureVideo() {
return true;
}
- private boolean captureImage() {
+ protected boolean captureImage() {
String imageFileName = Config.DEFAULT_OUTPUT_DIRECTORY + "/"
+ mItem.getBaseFilename() + Config.DEFAULT_IMAGE_EXTENSION;
Intent intent = new Intent(getActivity(), TakePicture.class);
@@ -601,12 +795,22 @@ public void onPause() {
it.remove(); // avoids a ConcurrentModificationException
}
edits = "[" + edits + "]";
+ if (Config.D) {
+ Log.d(Config.TAG, "edits: " + edits);
+ }
recordUserEvent("totalDatumEditsOnPause", edits);
}
+
+ if (mAudioPlayer != null) {
+ // if (mPrompt.isPlaying()) {
+ // mPrompt.stop();
+ // }
+ mAudioPlayer.release();
+ }
+
super.onPause();
}
-
- private void recordUserEvent(String eventType, String eventValue) {
+ protected void recordUserEvent(String eventType, String eventValue) {
if ("editDatum".equals(eventType)) {
if (this.mDatumEditCounts == null) {
this.mDatumEditCounts = new HashMap();
@@ -618,13 +822,15 @@ private void recordUserEvent(String eventType, String eventValue) {
this.mDatumEditCounts.put(eventValue, count);
return;
}
- ACRA.getErrorReporter().putCustomData("action",
- "{" + eventType + " : " + eventValue + "}");
- ACRA.getErrorReporter().putCustomData("androidTimestamp",
- System.currentTimeMillis() + "");
- ACRA.getErrorReporter().putCustomData("deviceDetails",
- this.mDeviceDetails.getCurrentDeviceDetails());
- ACRA.getErrorReporter().handleException(
- new Exception("*** User event " + eventType + " ***"));
+ if (!BuildConfig.DEBUG) {
+ ACRA.getErrorReporter().putCustomData("action",
+ "{\"" + eventType + "\" : \"" + eventValue + "\"}");
+ ACRA.getErrorReporter().putCustomData("androidTimestamp",
+ System.currentTimeMillis() + "");
+ ACRA.getErrorReporter().putCustomData("deviceDetails",
+ this.mDeviceDetails.getCurrentDeviceDetails());
+ ACRA.getErrorReporter().handleException(
+ new Exception("*** User event " + eventType + " ***"));
+ }
}
}
diff --git a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumFragmentPagerAdapter.java b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumFragmentPagerAdapter.java
new file mode 100644
index 0000000..9436fda
--- /dev/null
+++ b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumFragmentPagerAdapter.java
@@ -0,0 +1,91 @@
+package com.github.opensourcefieldlinguistics.fielddb.lessons.ui;
+
+import java.util.ArrayList;
+
+import ca.ilanguage.oprime.database.UserContentProvider.UserTable;
+
+import com.github.opensourcefieldlinguistics.fielddb.database.DatumContentProvider;
+import com.github.opensourcefieldlinguistics.fielddb.lessons.Config;
+
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.support.v4.app.FragmentManager;
+import android.support.v4.app.FragmentPagerAdapter;
+import android.util.Log;
+
+public class DatumFragmentPagerAdapter extends FragmentPagerAdapter {
+ private ArrayList mDatumsIds;
+ private ArrayList mFragments;
+
+ Uri mVisibleDatumUri;
+
+ public DatumFragmentPagerAdapter(FragmentManager fm) {
+ super(fm);
+ mFragments = new ArrayList();
+ }
+
+ public void swapCursor(Cursor cursor) {
+ this.mDatumsIds = new ArrayList();
+ this.mDatumsIds.add("instructions");
+ if (cursor != null && cursor.getCount() > 0) {
+ cursor.moveToFirst();
+ while (cursor.moveToNext()) {
+ String id = cursor.getString(cursor
+ .getColumnIndexOrThrow(UserTable.COLUMN_ID));
+ if (!"instructions".equals(id)) {
+ this.mDatumsIds.add(id);
+ }
+ }
+ cursor.close();
+ }
+ }
+ @Override
+ public Fragment getItem(int position) {
+ Log.d(Config.TAG, "Displaying datum in position " + position);
+ if (mFragments.size() > position) {
+ if (mFragments.get(position) != null) {
+ return mFragments.get(position);
+ }
+ }
+
+ String id = "instructions";
+ if (mDatumsIds.size() > position) {
+ id = mDatumsIds.get(position);
+ }
+ Bundle arguments = new Bundle();
+ DatumDetailFragment fragment = new DatumProductionExperimentFragment();
+ if (Config.APP_TYPE.equals("speechrecognition")) {
+// fragment = new DatumProductionExperimentFragment();
+ } else {
+ fragment = new DatumDetailFragment();
+ }
+ mVisibleDatumUri = Uri.parse(DatumContentProvider.CONTENT_URI + "/"
+ + id);
+ Log.d(Config.TAG, mVisibleDatumUri + "");
+ arguments.putParcelable(DatumContentProvider.CONTENT_ITEM_TYPE,
+ mVisibleDatumUri);
+ arguments.putString(DatumDetailFragment.ARG_ITEM_ID, id);
+ arguments.putInt(DatumDetailFragment.ARG_TOTAL_DATUM_IN_LIST,
+ mDatumsIds.size() - 1);
+
+ fragment.mTwoPane = false;
+ fragment.setArguments(arguments);
+ if (mFragments.size() == position ||mFragments.size() < position) {
+ mFragments.add(fragment);
+ } else {
+ mFragments.set(position, fragment);
+ }
+ return fragment;
+ }
+
+ @Override
+ public int getCount() {
+ if (mDatumsIds != null) {
+ return mDatumsIds.size();
+ }
+ return 0;
+ }
+
+}
diff --git a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumListActivity.java b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumListActivity.java
index b9f3858..dcb638d 100644
--- a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumListActivity.java
+++ b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumListActivity.java
@@ -1,9 +1,8 @@
package com.github.opensourcefieldlinguistics.fielddb.lessons.ui;
-import ca.ilanguage.oprime.Config;
-
import com.github.opensourcefieldlinguistics.fielddb.database.DatumContentProvider;
import com.github.opensourcefieldlinguistics.fielddb.lessons.georgian.R;
+import com.github.opensourcefieldlinguistics.fielddb.lessons.Config;
import android.content.Intent;
import android.net.Uri;
diff --git a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumListFragment.java b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumListFragment.java
index d0da3a4..2c3e5c3 100644
--- a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumListFragment.java
+++ b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumListFragment.java
@@ -27,6 +27,7 @@
import com.github.opensourcefieldlinguistics.fielddb.database.DatumContentProvider;
import com.github.opensourcefieldlinguistics.fielddb.lessons.Config;
import com.github.opensourcefieldlinguistics.fielddb.lessons.georgian.R;
+import com.github.opensourcefieldlinguistics.fielddb.lessons.georgian.BuildConfig;
/**
* A list fragment representing a list of Datums. This fragment also supports
@@ -250,7 +251,7 @@ private void fillData() {
android.R.layout.simple_list_item_activated_1, null, from, to,
0);
setListAdapter(adapter);
- ACRA.getErrorReporter().handleException(
+ if (!BuildConfig.DEBUG) ACRA.getErrorReporter().handleException(
new Exception("*** User load datum list ***"));
}
@@ -292,7 +293,7 @@ public boolean onOptionsItemSelected(MenuItem item) {
if (newDatum != null) {
mCallbacks.onItemSelected(newDatum.getLastPathSegment());
} else {
- ACRA.getErrorReporter().handleException(
+ if (!BuildConfig.DEBUG) ACRA.getErrorReporter().handleException(
new Exception(
"*** Error inserting a datum in DB ***"));
}
diff --git a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumProductionExperimentFragment.java b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumProductionExperimentFragment.java
new file mode 100644
index 0000000..49cb51f
--- /dev/null
+++ b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumProductionExperimentFragment.java
@@ -0,0 +1,191 @@
+package com.github.opensourcefieldlinguistics.fielddb.lessons.ui;
+
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.media.MediaPlayer;
+import android.os.Bundle;
+import android.os.Handler;
+import android.support.v4.app.DialogFragment;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+import android.widget.ImageView;
+import ca.ilanguage.oprime.Config;
+
+import com.github.opensourcefieldlinguistics.fielddb.speech.kartuli.R;
+
+public class DatumProductionExperimentFragment extends DatumDetailFragment {
+
+ protected int mAudioPromptResource;
+ protected boolean mIsInstructions = false;
+ protected long WAIT_TO_RECORD_AFTER_PROMPT_START = 400;
+
+ @Override
+ public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+ // no menu
+ }
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ View rootView = inflater.inflate(R.layout.fragment_production_stimulus,
+ container, false);
+
+ if (mItem != null) {
+ this.prepareSpeechRecognitionButton(rootView);
+ this.prepareVideoAndImages(rootView);
+
+ final TextView orthographyTextView = ((TextView) rootView
+ .findViewById(R.id.orthography));
+ orthographyTextView.setText(mItem.getOrthography());
+
+ final TextView contextTextView = ((TextView) rootView
+ .findViewById(R.id.context));
+ contextTextView.setText(mItem.getContext());
+
+ if (mImageView == null) {
+ mImageView = (ImageView) rootView.findViewById(R.id.image_view);
+ }
+ String tags = mItem.getTagsString();
+ if (tags.contains("WebSearch")) {
+ mImageView.setImageResource(R.drawable.search_selected);
+ } else if (tags.contains("LegalSearch")) {
+ mImageView.setImageResource(R.drawable.legal_search_selected);
+ } else if (tags.contains("SMS")) {
+ mImageView.setImageResource(R.drawable.sms_selected);
+ }
+
+ String id = mItem.getId();
+ Log.d(Config.TAG, "Prompt for this datum will be " + id);
+ if ("instructions".equals(id)) {
+ this.mIsInstructions = true;
+ mAudioPromptResource = R.raw.instructions;
+ mImageView.setImageResource(R.drawable.instructions);
+ mSpeechRecognizerFeedback.setVisibility(View.GONE);
+ mSpeechRecognizerInstructions.setText("Swipe to begin...");
+ playPromptContext();
+ } else {
+ mAudioPromptResource = R.raw.prompt;
+ }
+
+ }
+
+ return rootView;
+ }
+
+ @Override
+ public void setUserVisibleHint(boolean isVisibleToUser) {
+ super.setUserVisibleHint(isVisibleToUser);
+ if (this.isVisible() && !this.isPlaying) {
+ playPromptContext();
+ }
+ if (!this.isVisible()) {
+ turnOffRecorder(null);
+ }
+ }
+
+ protected void playPromptContext() {
+ isPlaying = true;
+
+ Log.d(Config.TAG, "Playing prompting context");
+ mAudioPlayer = MediaPlayer.create(getActivity(), mAudioPromptResource);
+ if (mAudioPlayer != null) {
+ mAudioPlayer
+ .setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
+
+ @Override
+ public void onCompletion(MediaPlayer mp) {
+ mp.release();
+ if (mIsInstructions) {
+ autoAdvanceAfterRecordingAudio();
+ }
+ }
+ });
+// mAudioPlayer
+// .setOnBufferingUpdateListener(new MediaPlayer.OnBufferingUpdateListener() {
+//
+// @Override
+// public void onBufferingUpdate(MediaPlayer arg0, int arg1) {
+// Log.d(Config.TAG, "Buffering " + arg1);
+// }
+// });
+ mAudioPlayer
+ .setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
+ @Override
+ public void onPrepared(MediaPlayer mp) {
+ mp.start();
+ }
+ });
+
+ if (mSpeechRecognizerInstructions != null && !mIsInstructions) {
+ mSpeechRecognizerInstructions.setText("Speak after beep");
+ }
+ }
+ /*
+ * begin recording almost immediately so that the user wont speak too
+ * early
+ */
+ Handler mainHandler = new Handler(getActivity().getMainLooper());
+ Runnable myRunnable = new Runnable() {
+
+ @Override
+ public void run() {
+ if (!mIsInstructions) {
+ toggleAudioRecording(null);
+ }
+ }
+ };
+ mainHandler.postDelayed(myRunnable, WAIT_TO_RECORD_AFTER_PROMPT_START);
+ }
+
+ protected boolean autoAdvanceAfterRecordingAudio() {
+ if (this.mDatumPager != null) {
+ int currentStimulusIndex = this.mDatumPager.getCurrentItem();
+ if (currentStimulusIndex == this.mLastDatumIndex) {
+
+ // Confirm dialog if they want to add their own sentences.
+ ContinueToAdvancedTraining continueDialog = new ContinueToAdvancedTraining();
+ continueDialog.show(getChildFragmentManager(), Config.TAG);
+
+ } else {
+ this.mDatumPager.setCurrentItem(this.mDatumPager
+ .getCurrentItem() + 1);
+ }
+ }
+ return true;
+ }
+
+ public static class ContinueToAdvancedTraining extends DialogFragment {
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+ builder.setMessage(R.string.dialog_continue_to_advanced_training)
+ .setPositiveButton(R.string.continue_word,
+ new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog,
+ int id) {
+ Intent openTrainer = new Intent(
+ getActivity(),
+ DatumListActivity.class);
+ startActivity(openTrainer);
+ }
+ })
+ .setNegativeButton(R.string.finished,
+ new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog,
+ int id) {
+ Intent openRecognizer = new Intent(
+ getActivity(),
+ SpeechRecognitionActivity.class);
+ startActivity(openRecognizer);
+ }
+ });
+ return builder.create();
+ }
+ }
+}
diff --git a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumSpeechRecognitionHypothesesFragment.java b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumSpeechRecognitionHypothesesFragment.java
new file mode 100644
index 0000000..37e01f5
--- /dev/null
+++ b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumSpeechRecognitionHypothesesFragment.java
@@ -0,0 +1,675 @@
+package com.github.opensourcefieldlinguistics.fielddb.lessons.ui;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+
+import android.app.Activity;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.os.Bundle;
+import android.os.Handler;
+import android.speech.RecognizerIntent;
+import android.text.Editable;
+import android.text.TextWatcher;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+import android.widget.AutoCompleteTextView;
+import android.widget.EditText;
+import android.widget.ImageButton;
+import android.widget.TableLayout;
+import android.widget.Toast;
+
+import com.github.opensourcefieldlinguistics.fielddb.FieldDBApplication;
+import com.github.opensourcefieldlinguistics.fielddb.database.DatumContentProvider.DatumTable;
+import com.github.opensourcefieldlinguistics.fielddb.lessons.Config;
+import com.github.opensourcefieldlinguistics.fielddb.speech.kartuli.R;
+
+public class DatumSpeechRecognitionHypothesesFragment
+ extends
+ DatumProductionExperimentFragment {
+
+ private boolean mHasRecognized;
+ private boolean mIsRecognizing;
+ private boolean mPerfectMatch;
+ private static final int RETURN_FROM_VOICE_RECOGNITION_REQUEST_CODE = 341;
+ EditText hypothesis1EditText;
+ EditText hypothesis2EditText;
+ EditText hypothesis3EditText;
+ EditText hypothesis4EditText;
+ EditText hypothesis5EditText;
+ TableLayout hypothesesArea;
+ protected long WAIT_TO_RECORD_AFTER_PROMPT_START = 100;
+
+ private static final String[] TAGS = new String[]{"WebSearch", "SMS",
+ "EMail"};
+
+
+ @Override
+ public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+ inflater.inflate(R.menu.actions_datum_speech_recognition, menu);
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ // handle item selection
+ switch (item.getItemId()) {
+ case R.id.action_speak :
+ playSpeechRecognitionPrompt();
+ return true;
+ case R.id.action_delete :
+ return this.delete();
+ default :
+ return super.onOptionsItemSelected(item);
+ }
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ View rootView = inflater.inflate(
+ R.layout.fragment_datum_speech_recognition_hypotheses,
+ container, false);
+
+ if (mItem != null) {
+ this.prepareEditTextListeners(rootView);
+ playSpeechRecognitionPrompt();
+ }
+
+ return rootView;
+ }
+
+ protected void showOrthographyOnly(View rootView) {
+ if (mHasRecognized == false) {
+ return;
+ }
+ TableLayout datumArea = (TableLayout) rootView
+ .findViewById(R.id.datumArea);
+ if (datumArea != null) {
+ datumArea.setVisibility(View.VISIBLE);
+ }
+
+ if (hypothesesArea != null) {
+ hypothesesArea.setVisibility(View.GONE);
+ }
+
+ final EditText contextEditText = ((EditText) rootView
+ .findViewById(R.id.context));
+ if (contextEditText != null) {
+ contextEditText.setText(mItem.getContext());
+ contextEditText.addTextChangedListener(new TextWatcher() {
+ @Override
+ public void afterTextChanged(Editable arg0) {
+ }
+ @Override
+ public void beforeTextChanged(CharSequence arg0, int arg1,
+ int arg2, int arg3) {
+ }
+ @Override
+ public void onTextChanged(CharSequence arg0, int arg1,
+ int arg2, int arg3) {
+ String currentText = contextEditText.getText().toString();
+ mItem.setContext(currentText);
+ ContentValues values = new ContentValues();
+ values.put(DatumTable.COLUMN_CONTEXT, currentText);
+ getActivity().getContentResolver().update(mUri, values,
+ null, null);
+ recordUserEvent("editDatum", "context");
+ }
+ });
+ }
+
+ final AutoCompleteTextView tagsEditText = ((AutoCompleteTextView) rootView
+ .findViewById(R.id.tags));
+ if (tagsEditText != null) {
+ ArrayAdapter tagsAdapter = new ArrayAdapter(
+ getActivity(), android.R.layout.simple_dropdown_item_1line,
+ TAGS);
+ tagsEditText.setAdapter(tagsAdapter);
+ tagsEditText.setText(mItem.getTagsString());
+ tagsEditText.addTextChangedListener(new TextWatcher() {
+ @Override
+ public void afterTextChanged(Editable arg0) {
+ }
+ @Override
+ public void beforeTextChanged(CharSequence arg0, int arg1,
+ int arg2, int arg3) {
+ }
+ @Override
+ public void onTextChanged(CharSequence arg0, int arg1,
+ int arg2, int arg3) {
+ String currentText = tagsEditText.getText().toString();
+ mItem.setTagsFromSting(currentText);
+ ContentValues values = new ContentValues();
+ values.put(DatumTable.COLUMN_TAGS, currentText);
+ getActivity().getContentResolver().update(mUri, values,
+ null, null);
+ recordUserEvent("editDatum", "tags");
+ }
+ });
+ }
+
+ final EditText orthographyEditText = ((EditText) rootView
+ .findViewById(R.id.orthography));
+ if (orthographyEditText != null) {
+ orthographyEditText.setText(mItem.getOrthography());
+ int textLength = mItem.getOrthography().length();
+ if (this.mPerfectMatch) {
+ orthographyEditText.setSelection(0, textLength);
+ } else {
+ orthographyEditText.setSelection(textLength, textLength);
+ }
+ orthographyEditText.addTextChangedListener(new TextWatcher() {
+ @Override
+ public void afterTextChanged(Editable arg0) {
+ }
+ @Override
+ public void beforeTextChanged(CharSequence arg0, int arg1,
+ int arg2, int arg3) {
+ }
+ @Override
+ public void onTextChanged(CharSequence arg0, int arg1,
+ int arg2, int arg3) {
+ String currentText = orthographyEditText.getText()
+ .toString();
+ mItem.setOrthography(currentText);
+ contextEditText.setVisibility(View.VISIBLE);
+ tagsEditText.setVisibility(View.VISIBLE);
+ ContentValues values = new ContentValues();
+ values.put(DatumTable.COLUMN_ORTHOGRAPHY, currentText);
+ getActivity().getContentResolver().update(mUri, values,
+ null, null);
+ recordUserEvent("editDatum", "orthography");
+ }
+ });
+ }
+ }
+
+ protected void prepareEditTextListeners(final View rootView) {
+ hypothesesArea = (TableLayout) rootView
+ .findViewById(R.id.hypothesesArea);
+
+ hypothesis1EditText = ((EditText) rootView
+ .findViewById(R.id.hypothesis1));
+ if (hypothesis1EditText != null) {
+ // hypothesis1EditText.setText(mItem.getOrthography());
+ hypothesis1EditText.addTextChangedListener(new TextWatcher() {
+ @Override
+ public void afterTextChanged(Editable arg0) {
+ }
+ @Override
+ public void beforeTextChanged(CharSequence arg0, int arg1,
+ int arg2, int arg3) {
+ }
+ @Override
+ public void onTextChanged(CharSequence arg0, int arg1,
+ int arg2, int arg3) {
+ if (mHasRecognized == false) {
+ return;
+ }
+ String currentText = hypothesis1EditText.getText()
+ .toString();
+ mItem.setOrthography(currentText);
+ showOrthographyOnly(rootView);
+ ContentValues values = new ContentValues();
+ values.put(DatumTable.COLUMN_ORTHOGRAPHY, currentText);
+ getActivity().getContentResolver().update(mUri, values,
+ null, null);
+ recordUserEvent("editDatum", "hypothesis1");
+ }
+ });
+ // hypothesis1EditText
+ // .setOnFocusChangeListener(new OnFocusChangeListener() {
+ // @Override
+ // public void onFocusChange(View v, boolean hasFocus) {
+ // if (!hasFocus) {
+ // return;
+ // }
+ // showOrthographyOnly(rootView);
+ // String currentText = hypothesis1EditText.getText()
+ // .toString();
+ // mItem.setOrthography(currentText);
+ // }
+ // });
+ }
+
+ final ImageButton removeHypothesis1Button = (ImageButton) rootView
+ .findViewById(R.id.removeHypothesis1);
+ if (removeHypothesis1Button != null) {
+ removeHypothesis1Button
+ .setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ removeHypothesis1Button.setVisibility(View.GONE);
+ hypothesis1EditText.setVisibility(View.GONE);
+ recordUserEvent("removeHypothesis",
+ "hypothesis1:::"
+ + hypothesis1EditText.getText()
+ .toString());
+
+ }
+ });
+ }
+
+ hypothesis2EditText = ((EditText) rootView
+ .findViewById(R.id.hypothesis2));
+ if (hypothesis2EditText != null) {
+ // hypothesis2EditText.setText(mItem.getOrthography());
+ hypothesis2EditText.addTextChangedListener(new TextWatcher() {
+ @Override
+ public void afterTextChanged(Editable arg0) {
+ }
+ @Override
+ public void beforeTextChanged(CharSequence arg0, int arg1,
+ int arg2, int arg3) {
+ }
+ @Override
+ public void onTextChanged(CharSequence arg0, int arg1,
+ int arg2, int arg3) {
+ if (mHasRecognized == false) {
+ return;
+ }
+ String currentText = hypothesis2EditText.getText()
+ .toString();
+ mItem.setOrthography(currentText);
+ showOrthographyOnly(rootView);
+ ContentValues values = new ContentValues();
+ values.put(DatumTable.COLUMN_ORTHOGRAPHY, currentText);
+ getActivity().getContentResolver().update(mUri, values,
+ null, null);
+ recordUserEvent("editDatum", "hypothesis2");
+ }
+ });
+ // hypothesis2EditText
+ // .setOnFocusChangeListener(new OnFocusChangeListener() {
+ // @Override
+ // public void onFocusChange(View v, boolean hasFocus) {
+ // if (!hasFocus) {
+ // return;
+ // }
+ // showOrthographyOnly(rootView);
+ // String currentText = hypothesis2EditText.getText()
+ // .toString();
+ // mItem.setOrthography(currentText);
+ // }
+ // });
+ }
+
+ final ImageButton removeHypothesis2Button = (ImageButton) rootView
+ .findViewById(R.id.removeHypothesis2);
+ if (removeHypothesis2Button != null) {
+ removeHypothesis2Button
+ .setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ removeHypothesis2Button.setVisibility(View.GONE);
+ hypothesis2EditText.setVisibility(View.GONE);
+ recordUserEvent("removeHypothesis",
+ "hypothesis2:::"
+ + hypothesis2EditText.getText()
+ .toString());
+
+ }
+ });
+ }
+
+ hypothesis3EditText = ((EditText) rootView
+ .findViewById(R.id.hypothesis3));
+ if (hypothesis3EditText != null) {
+ // hypothesis3EditText.setText(mItem.getOrthography());
+ hypothesis3EditText.addTextChangedListener(new TextWatcher() {
+ @Override
+ public void afterTextChanged(Editable arg0) {
+ }
+ @Override
+ public void beforeTextChanged(CharSequence arg0, int arg1,
+ int arg2, int arg3) {
+ }
+ @Override
+ public void onTextChanged(CharSequence arg0, int arg1,
+ int arg2, int arg3) {
+ if (mHasRecognized == false) {
+ return;
+ }
+ String currentText = hypothesis3EditText.getText()
+ .toString();
+ mItem.setOrthography(currentText);
+ showOrthographyOnly(rootView);
+ ContentValues values = new ContentValues();
+ values.put(DatumTable.COLUMN_ORTHOGRAPHY, currentText);
+ getActivity().getContentResolver().update(mUri, values,
+ null, null);
+ recordUserEvent("editDatum", "hypothesis3");
+ }
+ });
+ // hypothesis3EditText
+ // .setOnFocusChangeListener(new OnFocusChangeListener() {
+ // @Override
+ // public void onFocusChange(View v, boolean hasFocus) {
+ // if (!hasFocus) {
+ // return;
+ // }
+ // showOrthographyOnly(rootView);
+ // String currentText = hypothesis3EditText.getText()
+ // .toString();
+ // mItem.setOrthography(currentText);
+ // }
+ // });
+ }
+
+ final ImageButton removeHypothesis3Button = (ImageButton) rootView
+ .findViewById(R.id.removeHypothesis3);
+ if (removeHypothesis3Button != null) {
+ removeHypothesis3Button
+ .setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ removeHypothesis3Button.setVisibility(View.GONE);
+ hypothesis3EditText.setVisibility(View.GONE);
+ recordUserEvent("removeHypothesis",
+ "hypothesis3:::"
+ + hypothesis3EditText.getText()
+ .toString());
+
+ }
+ });
+ }
+
+ hypothesis4EditText = ((EditText) rootView
+ .findViewById(R.id.hypothesis4));
+ if (hypothesis4EditText != null) {
+ // hypothesis4EditText.setText(mItem.getOrthography());
+ hypothesis4EditText.addTextChangedListener(new TextWatcher() {
+ @Override
+ public void afterTextChanged(Editable arg0) {
+ }
+ @Override
+ public void beforeTextChanged(CharSequence arg0, int arg1,
+ int arg2, int arg3) {
+ }
+ @Override
+ public void onTextChanged(CharSequence arg0, int arg1,
+ int arg2, int arg3) {
+ if (mHasRecognized == false) {
+ return;
+ }
+ String currentText = hypothesis4EditText.getText()
+ .toString();
+ mItem.setOrthography(currentText);
+ showOrthographyOnly(rootView);
+ ContentValues values = new ContentValues();
+ values.put(DatumTable.COLUMN_ORTHOGRAPHY, currentText);
+ getActivity().getContentResolver().update(mUri, values,
+ null, null);
+ recordUserEvent("editDatum", "hypothesis4");
+ }
+ });
+ // hypothesis4EditText
+ // .setOnFocusChangeListener(new OnFocusChangeListener() {
+ // @Override
+ // public void onFocusChange(View v, boolean hasFocus) {
+ // if (!hasFocus) {
+ // return;
+ // }
+ // showOrthographyOnly(rootView);
+ // String currentText = hypothesis4EditText.getText()
+ // .toString();
+ // mItem.setOrthography(currentText);
+ // }
+ // });
+ }
+
+ final ImageButton removeHypothesis4Button = (ImageButton) rootView
+ .findViewById(R.id.removeHypothesis4);
+ if (removeHypothesis4Button != null) {
+ removeHypothesis4Button
+ .setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ removeHypothesis4Button.setVisibility(View.GONE);
+ hypothesis4EditText.setVisibility(View.GONE);
+ recordUserEvent("removeHypothesis",
+ "hypothesis4:::"
+ + hypothesis4EditText.getText()
+ .toString());
+
+ }
+ });
+ }
+
+ hypothesis5EditText = ((EditText) rootView
+ .findViewById(R.id.hypothesis5));
+ if (hypothesis5EditText != null) {
+ // hypothesis5EditText.setText(mItem.getOrthography());
+ hypothesis5EditText.addTextChangedListener(new TextWatcher() {
+ @Override
+ public void afterTextChanged(Editable arg0) {
+ }
+ @Override
+ public void beforeTextChanged(CharSequence arg0, int arg1,
+ int arg2, int arg3) {
+ }
+ @Override
+ public void onTextChanged(CharSequence arg0, int arg1,
+ int arg2, int arg3) {
+ if (mHasRecognized == false) {
+ return;
+ }
+ String currentText = hypothesis5EditText.getText()
+ .toString();
+ mItem.setOrthography(currentText);
+ showOrthographyOnly(rootView);
+ ContentValues values = new ContentValues();
+ values.put(DatumTable.COLUMN_ORTHOGRAPHY, currentText);
+ getActivity().getContentResolver().update(mUri, values,
+ null, null);
+ recordUserEvent("editDatum", "hypothesis5");
+ }
+ });
+ // hypothesis5EditText
+ // .setOnFocusChangeListener(new OnFocusChangeListener() {
+ // @Override
+ // public void onFocusChange(View v, boolean hasFocus) {
+ // if (!hasFocus) {
+ // return;
+ // }
+ // showOrthographyOnly(rootView);
+ // String currentText = hypothesis5EditText.getText()
+ // .toString();
+ // mItem.setOrthography(currentText);
+ // }
+ // });
+ }
+
+ final ImageButton removeHypothesis5Button = (ImageButton) rootView
+ .findViewById(R.id.removeHypothesis5);
+ if (removeHypothesis5Button != null) {
+ removeHypothesis5Button
+ .setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ removeHypothesis5Button.setVisibility(View.GONE);
+ hypothesis5EditText.setVisibility(View.GONE);
+ recordUserEvent("removeHypothesis",
+ "hypothesis5:::"
+ + hypothesis5EditText.getText()
+ .toString());
+
+ }
+ });
+ }
+
+ }
+ public void playSpeechRecognitionPrompt() {
+ this.mIsRecognizing = true;
+ this.mHasRecognized = false;
+ mAudioPromptResource = R.raw.im_listening;
+ playPromptContext();
+ Handler mainHandler = new Handler(getActivity().getMainLooper());
+ Runnable myRunnable = new Runnable() {
+ @Override
+ public void run() {
+ startVoiceRecognitionActivity();
+ }
+ };
+ mainHandler.postDelayed(myRunnable, 1000);/*
+ * make delay long to get some
+ * idea of what they will say
+ */
+ }
+
+ @Override
+ public void setUserVisibleHint(boolean isVisibleToUser) {
+ super.setUserVisibleHint(isVisibleToUser);
+ if (this.isVisible() && !this.mIsRecognizing) {
+ // playSpeechRecognitionPrompt();
+ }
+ }
+
+ /**
+ * Fire an intent to start the voice recognition activity.
+ */
+ private void startVoiceRecognitionActivity() {
+ recordUserEvent("recognizeSpeech", "");
+ if (isIntentAvailable(getActivity(),
+ RecognizerIntent.ACTION_RECOGNIZE_SPEECH)) {
+
+ recordUserEvent("recognizeSpeech", "defaultEngine:::"
+ + Locale.getDefault().getDisplayLanguage());
+
+ FieldDBApplication app = (FieldDBApplication) getActivity()
+ .getApplication();
+ app.forceLocale(Config.DATA_IS_ABOUT_LANGUAGE_ISO);
+
+ Toast.makeText(
+ getActivity(),
+ "Your voice model is not ready, using the default recognition for your system.",
+ Toast.LENGTH_LONG).show();
+
+ Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
+ intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL,
+ RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
+ intent.putExtra(RecognizerIntent.EXTRA_PROMPT,
+ getString(R.string.im_listening));
+ startActivityForResult(intent,
+ RETURN_FROM_VOICE_RECOGNITION_REQUEST_CODE);
+ } else {
+ Toast.makeText(
+ getActivity(),
+ "You have no speech recognition engine installed so we cannot provide the default recognizer for you. You must wait for your model to be downloaded.",
+ Toast.LENGTH_LONG).show();
+
+ recordUserEvent("recognizeSpeech", "noRecognizerIntent:::"
+ + Locale.getDefault().getDisplayLanguage());
+ Handler mainHandler = new Handler(getActivity().getMainLooper());
+ Runnable myRunnable = new Runnable() {
+ @Override
+ public void run() {
+ getActivity().finish();
+ }
+ };
+ mainHandler.postDelayed(myRunnable, 200);
+ }
+
+ }
+
+ /**
+ * Handle the results from the voice recognition activity.
+ */
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, Intent data) {
+ getActivity();
+ if (requestCode == RETURN_FROM_VOICE_RECOGNITION_REQUEST_CODE
+ && resultCode == Activity.RESULT_OK) {
+ turnOffRecorder(null);
+ hypothesesArea.setVisibility(View.VISIBLE);
+ /*
+ * Populate the wordsList with the String values the recognition
+ * engine thought it heard, and then Toast them to the user and say
+ * them out loud.
+ */
+ ArrayList matches = data
+ .getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
+
+ if (hypothesis1EditText != null) {
+ if (matches.size() > 0 && matches.get(0) != null) {
+ hypothesis1EditText.setText(matches.get(0));
+ } else {
+ // hypothesis1EditText.setVisibility(View.GONE);
+ }
+ // hypothesis1EditText.clearFocus();
+ }
+ if (hypothesis2EditText != null) {
+ if (matches.size() > 1 && matches.get(1) != null) {
+ hypothesis2EditText.setText(matches.get(1));
+ } else {
+ // hypothesis2EditText.setVisibility(View.GONE);
+ }
+ // hypothesis2EditText.clearFocus();
+ }
+ if (hypothesis3EditText != null) {
+ if (matches.size() > 2 && matches.get(2) != null) {
+ hypothesis3EditText.setText(matches.get(2));
+ } else {
+ // hypothesis3EditText.setVisibility(View.GONE);
+ }
+ // hypothesis3EditText.clearFocus();
+ }
+ if (hypothesis4EditText != null) {
+ if (matches.size() > 3 && matches.get(3) != null) {
+ hypothesis4EditText.setText(matches.get(3));
+ } else {
+ // hypothesis4EditText.setVisibility(View.GONE);
+ }
+ // hypothesis4EditText.clearFocus();
+ }
+ if (hypothesis5EditText != null) {
+ if (matches.size() > 4 && matches.get(4) != null) {
+ hypothesis5EditText.setText(matches.get(4));
+ } else {
+ // hypothesis5EditText.setVisibility(View.GONE);
+ }
+ // hypothesis5EditText.clearFocus();
+ }
+
+ if (matches.size() > 0) {
+ this.mHasRecognized = true;
+ } else {
+ /* make it possible for the user to create a datum anyway. */
+ this.mHasRecognized = true;
+ }
+
+ if (matches.size() == 1) {
+ // Trigger hypothesis 1 to be the orthography
+ hypothesis1EditText.setText(matches.get(0));
+ this.mPerfectMatch = true;
+
+ }
+ recordUserEvent("recognizedHypotheses", matches.toString());
+ }
+ super.onActivityResult(requestCode, resultCode, data);
+ }
+
+ @Override
+ public void onPause() {
+ turnOffRecorder(null);
+ super.onPause();
+ }
+
+ public static boolean isIntentAvailable(Context context, String action) {
+ final PackageManager packageManager = context.getPackageManager();
+ final Intent intent = new Intent(action);
+ List list = packageManager.queryIntentActivities(intent,
+ PackageManager.MATCH_DEFAULT_ONLY);
+ return list.size() > 0;
+ }
+
+}
diff --git a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/ListenAndRepeat.java b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/ListenAndRepeat.java
new file mode 100644
index 0000000..6684104
--- /dev/null
+++ b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/ListenAndRepeat.java
@@ -0,0 +1,136 @@
+package com.github.opensourcefieldlinguistics.fielddb.lessons.ui;
+
+import java.util.ArrayList;
+import java.util.Locale;
+
+import com.github.opensourcefieldlinguistics.fielddb.speech.kartuli.R;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.speech.RecognizerIntent;
+import android.speech.tts.TextToSpeech;
+import android.speech.tts.TextToSpeech.OnInitListener;
+import android.util.Log;
+import android.widget.Toast;
+
+/**
+ *
+ * Building on what we saw in MakeItTalk, now lets make it Listen. Here is some
+ * super simple code that uses the VoiceRecognition Intent to recognize what the
+ * user says, and then uses Text To Speech to tell the user what it might have
+ * heard.
+ *
+ *
+ */
+public class ListenAndRepeat extends Activity implements OnInitListener {
+ private static final String TAG = "MakeItListen";
+ private static final int RETURN_FROM_VOICE_RECOGNITION_REQUEST_CODE = 341;
+ /** Talk to the user */
+ private TextToSpeech mTts;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ mTts = new TextToSpeech(this, this);
+
+ }
+
+ protected void promptTheUserToTalk() {
+ mTts.speak(getString(R.string.im_listening), TextToSpeech.QUEUE_ADD,
+ null);
+ }
+
+ /**
+ * Fire an intent to start the voice recognition activity.
+ */
+ private void startVoiceRecognitionActivity() {
+ Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
+ intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL,
+ RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
+ intent.putExtra(RecognizerIntent.EXTRA_PROMPT,
+ getString(R.string.im_listening));
+ startActivityForResult(intent,
+ RETURN_FROM_VOICE_RECOGNITION_REQUEST_CODE);
+ }
+
+ /**
+ * Handle the results from the voice recognition activity.
+ */
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ if (requestCode == RETURN_FROM_VOICE_RECOGNITION_REQUEST_CODE
+ && resultCode == RESULT_OK) {
+ /*
+ * Populate the wordsList with the String values the recognition
+ * engine thought it heard, and then Toast them to the user and say
+ * them out loud.
+ */
+ ArrayList matches = data
+ .getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
+ for (int iMightHaveHeardThis = 0; iMightHaveHeardThis < matches
+ .size(); iMightHaveHeardThis++) {
+
+ /* Build a carrierPhrase if you want it to make some sense */
+ String carrierPhrase = getString(R.string.i_might_have_heard);
+ if (iMightHaveHeardThis > 0) {
+ carrierPhrase = getString(R.string.or_maybe);
+ }
+ carrierPhrase += " " + matches.get(iMightHaveHeardThis) + ".";
+
+ Toast.makeText(this, carrierPhrase, Toast.LENGTH_LONG).show();
+ mTts.speak(carrierPhrase, TextToSpeech.QUEUE_ADD, null);
+
+ /*
+ * Don't go on forever, it there are too many potential matches
+ * don't say them all
+ */
+ if (iMightHaveHeardThis == 2 && matches.size() > 2) {
+ mTts.speak(getString(R.string.there_were_others),
+ TextToSpeech.QUEUE_ADD, null);
+ break;
+ }
+ }
+ }
+ super.onActivityResult(requestCode, resultCode, data);
+ }
+
+ @Override
+ protected void onDestroy() {
+ if (mTts != null) {
+ mTts.stop();
+ mTts.shutdown();
+ }
+ super.onDestroy();
+ }
+
+ @Override
+ public void onInit(int status) {
+ if (status == TextToSpeech.SUCCESS) {
+ int result = mTts.setLanguage(Locale.getDefault());
+ if (result == TextToSpeech.LANG_MISSING_DATA
+ || result == TextToSpeech.LANG_NOT_SUPPORTED) {
+ Log.e(TAG, "Language is not available.");
+ Toast.makeText(
+ this,
+ "The "
+ + Locale.getDefault().getDisplayLanguage()
+ + " TextToSpeech isn't installed, you can go into the "
+ + "\nAndroid's settings in the "
+ + "\nVoice Input and Output menu to turn it on. ",
+ Toast.LENGTH_LONG).show();
+ } else {
+ // everything is working.
+ promptTheUserToTalk();
+ startVoiceRecognitionActivity();
+ }
+ } else {
+ Toast.makeText(
+ this,
+ "Sorry, I can't talk to you because "
+ + "I could not initialize TextToSpeech.",
+ Toast.LENGTH_LONG).show();
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/ProductionExperimentActivity.java b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/ProductionExperimentActivity.java
new file mode 100644
index 0000000..6abc195
--- /dev/null
+++ b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/ProductionExperimentActivity.java
@@ -0,0 +1,83 @@
+package com.github.opensourcefieldlinguistics.fielddb.lessons.ui;
+
+import ca.ilanguage.oprime.Config;
+import ca.ilanguage.oprime.datacollection.AudioRecorder;
+
+import com.github.opensourcefieldlinguistics.fielddb.database.DatumContentProvider;
+import com.github.opensourcefieldlinguistics.fielddb.database.DatumContentProvider.DatumTable;
+import com.github.opensourcefieldlinguistics.fielddb.speech.kartuli.R;
+
+import android.content.Intent;
+import android.database.Cursor;
+import android.os.Bundle;
+import android.support.v4.app.FragmentActivity;
+import android.support.v4.app.LoaderManager;
+import android.support.v4.content.CursorLoader;
+import android.support.v4.content.Loader;
+import android.support.v4.view.ViewPager;
+import android.util.Log;
+
+public class ProductionExperimentActivity extends FragmentActivity
+ implements
+ LoaderManager.LoaderCallbacks {
+
+ private DatumFragmentPagerAdapter mPagerAdapter;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ super.setContentView(R.layout.activity_production_experiment_datum_list);
+
+ this.initialisePaging();
+ }
+
+ @Override
+ public Loader onCreateLoader(int id, Bundle args) {
+ String[] projection = {DatumTable.COLUMN_ID};
+ String filterStr = "AutomaticallyRecognized";
+ String selection = DatumTable.COLUMN_VALIDATION_STATUS + " IS NULL OR "
+ + DatumTable.COLUMN_VALIDATION_STATUS + " NOT LIKE ? ";
+ String[] selectionArgs = new String[]{"%" + filterStr + "%"};
+
+ CursorLoader cursorLoader = new CursorLoader(this,
+ DatumContentProvider.CONTENT_URI, projection, selection,
+ selectionArgs, null);
+ Cursor cursor = cursorLoader.loadInBackground();
+ this.mPagerAdapter.swapCursor(cursor);
+
+ return cursorLoader;
+ }
+ @Override
+ public void onLoadFinished(Loader loader, Cursor data) {
+
+ Log.d(Config.TAG, "Finished loading the ids for swipe paging");
+ this.mPagerAdapter.swapCursor(data);
+ }
+
+ @Override
+ public void onLoaderReset(Loader loader) {
+ this.mPagerAdapter.swapCursor(null);
+ }
+
+ /**
+ * Initialise the fragments to be paged
+ */
+ private void initialisePaging() {
+
+ this.mPagerAdapter = new DatumFragmentPagerAdapter(
+ super.getSupportFragmentManager());
+ this.onCreateLoader(0, null);
+
+ ViewPager pager = (ViewPager) super.findViewById(R.id.viewpager);
+ pager.setAdapter(this.mPagerAdapter);
+ }
+
+ @Override
+ public void onBackPressed() {
+ Intent audio = new Intent(this, AudioRecorder.class);
+ this.stopService(audio);
+
+ super.onBackPressed();
+ }
+
+}
diff --git a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/SpeechRecognitionActivity.java b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/SpeechRecognitionActivity.java
new file mode 100644
index 0000000..b1fcc34
--- /dev/null
+++ b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/SpeechRecognitionActivity.java
@@ -0,0 +1,55 @@
+package com.github.opensourcefieldlinguistics.fielddb.lessons.ui;
+
+import org.acra.ACRA;
+
+import com.github.opensourcefieldlinguistics.fielddb.database.DatumContentProvider;
+import com.github.opensourcefieldlinguistics.fielddb.database.DatumContentProvider.DatumTable;
+import com.github.opensourcefieldlinguistics.fielddb.speech.kartuli.BuildConfig;
+import com.github.opensourcefieldlinguistics.fielddb.speech.kartuli.R;
+
+import android.content.ContentValues;
+import android.net.Uri;
+import android.os.Bundle;
+import android.support.v4.app.FragmentActivity;
+
+public class SpeechRecognitionActivity extends FragmentActivity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ super.setContentView(R.layout.activity_speech_recognition);
+
+ // savedInstanceState is non-null when there is fragment state
+ // saved from previous configurations of this activity
+ // (e.g. when rotating the screen from portrait to landscape).
+ // In this case, the fragment will automatically be re-added
+ // to its container so we don't need to manually add it.
+ // For more information, see the Fragments API guide at:
+ //
+ // http://developer.android.com/guide/components/fragments.html
+ //
+ if (savedInstanceState == null) {
+ // Create the detail fragment and add it to the activity
+ // using a fragment transaction.
+ ContentValues values = new ContentValues();
+ values.put(DatumTable.COLUMN_VALIDATION_STATUS,
+ "ToBeChecked,AutomaticallyRecognized");
+ Uri newDatum = this.getContentResolver().insert(
+ DatumContentProvider.CONTENT_URI, values);
+ if (newDatum == null) {
+ if (!BuildConfig.DEBUG)
+ ACRA.getErrorReporter()
+ .handleException(
+ new Exception(
+ "*** Error inserting a speech recognition datum in DB ***"));
+ }
+ Bundle arguments = new Bundle();
+ arguments.putString(DatumDetailFragment.ARG_ITEM_ID,
+ newDatum.getLastPathSegment());
+ DatumSpeechRecognitionHypothesesFragment fragment = new DatumSpeechRecognitionHypothesesFragment();
+ fragment.setArguments(arguments);
+ getSupportFragmentManager().beginTransaction()
+ .add(R.id.datum_detail_container, fragment).commit();
+ }
+ }
+}
diff --git a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/WelcomeActivity.java b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/WelcomeActivity.java
new file mode 100644
index 0000000..8cebf88
--- /dev/null
+++ b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/WelcomeActivity.java
@@ -0,0 +1,35 @@
+package com.github.opensourcefieldlinguistics.fielddb.lessons.ui;
+
+import com.github.opensourcefieldlinguistics.fielddb.speech.kartuli.R;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Bundle;
+import android.view.View;
+
+public class WelcomeActivity extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ super.setContentView(R.layout.activity_welcome);
+
+ }
+
+ public void onTrainClick(View view) {
+ Intent openTrainer = new Intent(this,
+ ProductionExperimentActivity.class);
+ startActivity(openTrainer);
+ }
+
+ public void onRecognizeClick(View view) {
+ Intent openRecognizer = new Intent(this, SpeechRecognitionActivity.class);
+ startActivity(openRecognizer);
+ }
+
+ public void goToWebSite(View view) {
+ Intent go = new Intent(Intent.ACTION_VIEW).setData(Uri
+ .parse("http://batumi.github.io"));
+ startActivity(go);
+ }
+}
diff --git a/src/com/github/opensourcefieldlinguistics/fielddb/model/Datum.java b/src/com/github/opensourcefieldlinguistics/fielddb/model/Datum.java
index f7a4915..205a97c 100644
--- a/src/com/github/opensourcefieldlinguistics/fielddb/model/Datum.java
+++ b/src/com/github/opensourcefieldlinguistics/fielddb/model/Datum.java
@@ -1,6 +1,7 @@
package com.github.opensourcefieldlinguistics.fielddb.model;
import java.util.ArrayList;
+import java.util.Arrays;
import android.util.Log;
@@ -23,6 +24,7 @@ public class Datum {
protected ArrayList related;
protected ArrayList reminders;
protected ArrayList tags;
+ protected ArrayList validationStati;
protected ArrayList coments;
protected String actualJSON;
@@ -33,7 +35,8 @@ public Datum(String id, String rev, DatumField utterance,
ArrayList audioVideoFiles,
ArrayList videoFiles, ArrayList locations,
ArrayList related, ArrayList reminders,
- ArrayList tags, ArrayList coments, String actualJSON) {
+ ArrayList tags, ArrayList validationStati,
+ ArrayList coments, String actualJSON) {
super();
this._id = id;
this._rev = rev;
@@ -49,6 +52,7 @@ public Datum(String id, String rev, DatumField utterance,
this.related = related;
this.reminders = reminders;
this.tags = tags;
+ this.validationStati = validationStati;
this.coments = coments;
this.actualJSON = actualJSON;
}
@@ -68,6 +72,7 @@ public Datum(String orthography) {
this.related = new ArrayList();
this.reminders = new ArrayList();
this.tags = new ArrayList();
+ this.validationStati = new ArrayList();
this.coments = new ArrayList();
this.actualJSON = "";
}
@@ -75,7 +80,7 @@ public Datum(String orthography) {
public Datum(String orthography, String morphemes, String gloss,
String translation) {
super();
- this._id = System.currentTimeMillis() + translation;
+ this._id = System.currentTimeMillis() + "";
this.utterance = new DatumField("utterance", orthography);
this.morphemes = new DatumField("morphemes", morphemes);
this.gloss = new DatumField("gloss", gloss);
@@ -88,6 +93,7 @@ public Datum(String orthography, String morphemes, String gloss,
this.related = new ArrayList();
this.reminders = new ArrayList();
this.tags = new ArrayList();
+ this.validationStati = new ArrayList();
this.coments = new ArrayList();
this.actualJSON = "";
}
@@ -95,7 +101,7 @@ public Datum(String orthography, String morphemes, String gloss,
public Datum(String orthography, String morphemes, String gloss,
String translation, String context) {
super();
- this._id = System.currentTimeMillis() + translation;
+ this._id = System.currentTimeMillis() + "";
this.utterance = new DatumField("utterance", orthography);
this.morphemes = new DatumField("morphemes", morphemes);
this.gloss = new DatumField("gloss", gloss);
@@ -108,6 +114,7 @@ public Datum(String orthography, String morphemes, String gloss,
this.related = new ArrayList();
this.reminders = new ArrayList();
this.tags = new ArrayList();
+ this.validationStati = new ArrayList();
this.coments = new ArrayList();
this.actualJSON = "";
}
@@ -127,6 +134,7 @@ public Datum() {
this.related = new ArrayList();
this.reminders = new ArrayList();
this.tags = new ArrayList();
+ this.validationStati = new ArrayList();
this.coments = new ArrayList();
this.actualJSON = "";
}
@@ -255,10 +263,53 @@ public ArrayList getTags() {
return tags;
}
+ public String getTagsString() {
+ String result = "";
+ for (String tag : this.tags) {
+ if (!"".equals(result)) {
+ result += ",";
+ }
+ result += tag;
+ }
+ return result;
+ }
+
+ public void setTagsFromSting(String tags) {
+ if (tags != null && !"".equals(tags)) {
+ this.tags = new ArrayList(Arrays.asList(tags.split(",")));
+ }
+ }
+
public void setTags(ArrayList tags) {
this.tags = tags;
}
+ public ArrayList getValidationStati() {
+ return validationStati;
+ }
+
+ public String getValidationStatiString() {
+ String result = "";
+ for (String validationStatus : this.validationStati) {
+ if (!"".equals(result)) {
+ result += ",";
+ }
+ result += validationStatus;
+ }
+ return result;
+ }
+
+ public void setValidationStatiFromSting(String validationStati) {
+ if (validationStati != null && !"".equals(validationStati)) {
+ this.validationStati = new ArrayList(
+ Arrays.asList(validationStati.split(",")));
+ }
+ }
+
+ public void setValidationStati(ArrayList validationStati) {
+ this.validationStati = validationStati;
+ }
+
public ArrayList getComents() {
return coments;
}
@@ -530,7 +581,7 @@ public String getBaseFilename() {
}
if (filenameBasedOnMorphemesOrWhateverIsAvailable == null
|| "".equals(filenameBasedOnMorphemesOrWhateverIsAvailable)) {
- filenameBasedOnMorphemesOrWhateverIsAvailable = "unknown";
+ filenameBasedOnMorphemesOrWhateverIsAvailable = "audio";
}
filenameBasedOnMorphemesOrWhateverIsAvailable = Config
.getSafeUri(filenameBasedOnMorphemesOrWhateverIsAvailable);
diff --git a/src/com/github/opensourcefieldlinguistics/fielddb/service/DownloadDatumsService.java b/src/com/github/opensourcefieldlinguistics/fielddb/service/DownloadDatumsService.java
index fbc78c3..a099985 100644
--- a/src/com/github/opensourcefieldlinguistics/fielddb/service/DownloadDatumsService.java
+++ b/src/com/github/opensourcefieldlinguistics/fielddb/service/DownloadDatumsService.java
@@ -19,7 +19,8 @@
import com.github.opensourcefieldlinguistics.fielddb.database.AudioVideoContentProvider.AudioVideoTable;
import com.github.opensourcefieldlinguistics.fielddb.database.DatumContentProvider.DatumTable;
import com.github.opensourcefieldlinguistics.fielddb.lessons.Config;
-import com.github.opensourcefieldlinguistics.fielddb.lessons.georgian.R;
+import com.github.opensourcefieldlinguistics.fielddb.speech.kartuli.BuildConfig;
+import com.github.opensourcefieldlinguistics.fielddb.speech.kartuli.R;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
@@ -46,6 +47,11 @@ public DownloadDatumsService() {
@Override
protected void onHandleIntent(Intent intent) {
+
+ if (Config.D) {
+ return;
+ }
+
this.D = Config.D;
this.statusMessage = "Downloading samples "
+ Config.USER_FRIENDLY_DATA_NAME;
@@ -62,17 +68,27 @@ protected void onHandleIntent(Intent intent) {
Log.d(Config.TAG, this.urlStringSampleDataDownload);
}
- ACRA.getErrorReporter().putCustomData("action",
- "downloadDatums:::" + datumTagToDownload);
- ACRA.getErrorReporter().putCustomData("urlString",
- this.urlStringSampleDataDownload);
+ if (!BuildConfig.DEBUG)
+ ACRA.getErrorReporter().putCustomData("action",
+ "downloadDatums:::" + datumTagToDownload);
+ if (!BuildConfig.DEBUG)
+ ACRA.getErrorReporter().putCustomData("urlString",
+ this.urlStringSampleDataDownload);
super.onHandleIntent(intent);
if (!"".equals(this.userFriendlyErrorMessage)) {
this.notifyUser(" " + this.userFriendlyErrorMessage, this.noti,
this.notificationId, true);
- ACRA.getErrorReporter().handleException(
- new Exception(this.userFriendlyErrorMessage));
+ if (!BuildConfig.DEBUG){
+ ACRA.getErrorReporter().putCustomData("action",
+ "downloadDatums:::" + datumTagToDownload);
+ ACRA.getErrorReporter().putCustomData("urlString",
+ this.urlStringSampleDataDownload);
+ ACRA.getErrorReporter().putCustomData("androidTimestamp",
+ System.currentTimeMillis() + "");
+ ACRA.getErrorReporter().handleException(
+ new Exception(this.userFriendlyErrorMessage));
+ }
return;
}
@@ -81,8 +97,16 @@ protected void onHandleIntent(Intent intent) {
if (!"".equals(this.userFriendlyErrorMessage)) {
this.notifyUser(" " + this.userFriendlyErrorMessage, this.noti,
this.notificationId, true);
- ACRA.getErrorReporter().handleException(
- new Exception(this.userFriendlyErrorMessage));
+ if (!BuildConfig.DEBUG){
+ ACRA.getErrorReporter().putCustomData("action",
+ "downloadDatums:::" + datumTagToDownload);
+ ACRA.getErrorReporter().putCustomData("urlString",
+ this.urlStringSampleDataDownload);
+ ACRA.getErrorReporter().putCustomData("androidTimestamp",
+ System.currentTimeMillis() + "");
+ ACRA.getErrorReporter().handleException(
+ new Exception(this.userFriendlyErrorMessage));
+ }
return;
}
@@ -90,8 +114,16 @@ protected void onHandleIntent(Intent intent) {
if (!"".equals(this.userFriendlyErrorMessage)) {
this.notifyUser(" " + this.userFriendlyErrorMessage, this.noti,
this.notificationId, true);
- ACRA.getErrorReporter().handleException(
- new Exception(this.userFriendlyErrorMessage));
+ if (!BuildConfig.DEBUG){
+ ACRA.getErrorReporter().putCustomData("action",
+ "downloadDatums:::" + datumTagToDownload);
+ ACRA.getErrorReporter().putCustomData("urlString",
+ this.urlStringSampleDataDownload);
+ ACRA.getErrorReporter().putCustomData("androidTimestamp",
+ System.currentTimeMillis() + "");
+ ACRA.getErrorReporter().handleException(
+ new Exception(this.userFriendlyErrorMessage));
+ }
return;
}
@@ -99,20 +131,32 @@ protected void onHandleIntent(Intent intent) {
if (!"".equals(this.userFriendlyErrorMessage)) {
this.notifyUser(" " + this.userFriendlyErrorMessage, this.noti,
this.notificationId, true);
- ACRA.getErrorReporter().handleException(
- new Exception(this.userFriendlyErrorMessage));
+ if (!BuildConfig.DEBUG){
+ ACRA.getErrorReporter().putCustomData("action",
+ "downloadDatums:::" + datumTagToDownload);
+ ACRA.getErrorReporter().putCustomData("urlString",
+ this.urlStringSampleDataDownload);
+ ACRA.getErrorReporter().putCustomData("androidTimestamp",
+ System.currentTimeMillis() + "");
+ ACRA.getErrorReporter().handleException(
+ new Exception(this.userFriendlyErrorMessage));
+ }
return;
}
/* Success: remove the notification */
((NotificationManager) getSystemService(NOTIFICATION_SERVICE))
.cancel(this.notificationId);
- ACRA.getErrorReporter().putCustomData("action",
- "downloadDatums:::" + datumTagToDownload);
- ACRA.getErrorReporter().putCustomData("urlString",
- this.urlStringSampleDataDownload);
- ACRA.getErrorReporter().handleException(
- new Exception("*** Downloaded data sucessfully ***"));
+ if (!BuildConfig.DEBUG) {
+ ACRA.getErrorReporter().putCustomData("action",
+ "downloadDatums:::" + datumTagToDownload);
+ ACRA.getErrorReporter().putCustomData("urlString",
+ this.urlStringSampleDataDownload);
+ ACRA.getErrorReporter().putCustomData("androidTimestamp",
+ System.currentTimeMillis() + "");
+ ACRA.getErrorReporter().handleException(
+ new Exception("*** Downloaded data sucessfully ***"));
+ }
}
public void getSampleData() {
@@ -162,7 +206,7 @@ public void processCouchDBMapResponse() {
JsonObject datumJson;
String id = "";
Uri uri;
- String[] datumProjection = { DatumTable.COLUMN_ID };
+ String[] datumProjection = {DatumTable.COLUMN_ID};
Cursor cursor;
String mediaFilesAsString = "";
ContentValues datumAsValues;
@@ -244,7 +288,7 @@ public void processCouchDBMapResponse() {
Log.d(Config.TAG,
"TODO download the image and audio files through a filter that makes them smaller... ");
}
- // ACRA.getErrorReporter().handleException(
+ // if (!BuildConfig.DEBUG) ACRA.getErrorReporter().handleException(
// new Exception("*** Download Data Completed ***"));
return;
}
@@ -323,13 +367,18 @@ public void downloadMediaFile(String mediaFileUrl) {
}
output.close();
this.statusMessage = "Downloaded " + filename;
- ACRA.getErrorReporter().putCustomData("action",
- "downloadMedia:::" + filename);
- ACRA.getErrorReporter()
- .putCustomData("urlString", mediaFileUrl);
- ACRA.getErrorReporter().handleException(
- new Exception(
- "*** Downloaded media file sucessfully ***"));
+ if (!BuildConfig.DEBUG) {
+ ACRA.getErrorReporter().putCustomData("action",
+ "downloadMedia:::" + filename);
+ ACRA.getErrorReporter().putCustomData("urlString",
+ mediaFileUrl);
+ ACRA.getErrorReporter().putCustomData("androidTimestamp",
+ System.currentTimeMillis() + "");
+ ACRA.getErrorReporter()
+ .handleException(
+ new Exception(
+ "*** Downloaded media file sucessfully ***"));
+ }
} else {
this.userFriendlyErrorMessage = "Server replied " + status;
}
@@ -345,7 +394,7 @@ public void downloadMediaFile(String mediaFileUrl) {
public Uri insertMediaFileInDB(String url) {
String filename = Uri.parse(url).getLastPathSegment();
- String[] audioVideoProjection = { AudioVideoTable.COLUMN_FILENAME };
+ String[] audioVideoProjection = {AudioVideoTable.COLUMN_FILENAME};
Uri uri = Uri.withAppendedPath(AudioVideoContentProvider.CONTENT_URI,
filename);
diff --git a/src/com/github/opensourcefieldlinguistics/fielddb/service/RegisterUserService.java b/src/com/github/opensourcefieldlinguistics/fielddb/service/RegisterUserService.java
index e0cc281..2186183 100644
--- a/src/com/github/opensourcefieldlinguistics/fielddb/service/RegisterUserService.java
+++ b/src/com/github/opensourcefieldlinguistics/fielddb/service/RegisterUserService.java
@@ -15,7 +15,8 @@
import com.github.opensourcefieldlinguistics.fielddb.database.FieldDBUserContentProvider;
import com.github.opensourcefieldlinguistics.fielddb.lessons.Config;
-import com.github.opensourcefieldlinguistics.fielddb.lessons.georgian.R;
+import com.github.opensourcefieldlinguistics.fielddb.speech.kartuli.BuildConfig;
+import com.github.opensourcefieldlinguistics.fielddb.speech.kartuli.R;
import com.google.gson.JsonObject;
import android.app.NotificationManager;
@@ -45,17 +46,20 @@ protected void onHandleIntent(Intent intent) {
if (Config.D) {
Log.d(Config.TAG, "Inside RegisterUserService intent");
}
- ACRA.getErrorReporter().putCustomData("action", "registerUser:::");
- ACRA.getErrorReporter().putCustomData("urlString",
- Config.DEFAULT_REGISTER_USER_URL);
+ if (!BuildConfig.DEBUG)
+ ACRA.getErrorReporter().putCustomData("action", "registerUser:::");
+ if (!BuildConfig.DEBUG)
+ ACRA.getErrorReporter().putCustomData("urlString",
+ Config.DEFAULT_REGISTER_USER_URL);
super.onHandleIntent(intent);
if (!"".equals(this.userFriendlyErrorMessage)) {
this.notifyUser(" " + this.userFriendlyErrorMessage, this.noti,
this.notificationId, true);
- ACRA.getErrorReporter().handleException(
- new Exception(this.userFriendlyErrorMessage));
+ if (!BuildConfig.DEBUG)
+ ACRA.getErrorReporter().handleException(
+ new Exception(this.userFriendlyErrorMessage));
return;
}
@@ -66,8 +70,9 @@ protected void onHandleIntent(Intent intent) {
if (!"".equals(this.userFriendlyErrorMessage)) {
this.notifyUser(" " + this.userFriendlyErrorMessage, this.noti,
this.notificationId, true);
- ACRA.getErrorReporter().handleException(
- new Exception(this.userFriendlyErrorMessage));
+ if (!BuildConfig.DEBUG)
+ ACRA.getErrorReporter().handleException(
+ new Exception(this.userFriendlyErrorMessage));
return;
}
@@ -75,8 +80,9 @@ protected void onHandleIntent(Intent intent) {
if (!"".equals(this.userFriendlyErrorMessage)) {
this.notifyUser(" " + this.userFriendlyErrorMessage, this.noti,
this.notificationId, true);
- ACRA.getErrorReporter().handleException(
- new Exception(this.userFriendlyErrorMessage));
+ if (!BuildConfig.DEBUG)
+ ACRA.getErrorReporter().handleException(
+ new Exception(this.userFriendlyErrorMessage));
return;
}
@@ -87,8 +93,9 @@ protected void onHandleIntent(Intent intent) {
/* Success: remove the notification */
((NotificationManager) getSystemService(NOTIFICATION_SERVICE))
.cancel(this.notificationId);
- ACRA.getErrorReporter().handleException(
- new Exception("*** Registered user ssucessfully ***"));
+ if (!BuildConfig.DEBUG)
+ ACRA.getErrorReporter().handleException(
+ new Exception("*** Registered user ssucessfully ***"));
}
public String loginUser(String username, String password, String loginUrl) {
@@ -138,20 +145,25 @@ public String loginUser(String username, String password, String loginUrl) {
}
public String registerUsers(Uri uri) {
- String[] userProjection = { UserTable.COLUMN_REV,
+ String[] userProjection = {UserTable.COLUMN_REV,
UserTable.COLUMN_USERNAME, UserTable.COLUMN_FIRSTNAME,
UserTable.COLUMN_LASTNAME, UserTable.COLUMN_EMAIL,
UserTable.COLUMN_GRAVATAR, UserTable.COLUMN_AFFILIATION,
UserTable.COLUMN_RESEARCH_INTEREST,
UserTable.COLUMN_DESCRIPTION, UserTable.COLUMN_SUBTITLE,
UserTable.COLUMN_GENERATED_PASSWORD,
- UserTable.COLUMN_APP_VERSIONS_WHEN_MODIFIED };
+ UserTable.COLUMN_APP_VERSIONS_WHEN_MODIFIED};
if (uri == null) {
uri = FieldDBUserContentProvider.CONTENT_URI;
}
CursorLoader cursorLoader = new CursorLoader(getApplicationContext(),
uri, userProjection, null, null, null);
Cursor cursor = cursorLoader.loadInBackground();
+ if (cursor == null) {
+ Log.e(Config.TAG,
+ "There is no user... this is not supposed to happen.");
+ return null;
+ }
cursor.moveToFirst();
if (cursor.getCount() == 0) {
Log.e(Config.TAG,
@@ -197,7 +209,8 @@ public String registerUsers(Uri uri) {
cursor.close();
this.statusMessage = "Registering user " + username;
- ACRA.getErrorReporter().putCustomData("registerUser", username);
+ if (!BuildConfig.DEBUG)
+ ACRA.getErrorReporter().putCustomData("registerUser", username);
String urlStringAuthenticationSession = Config.DEFAULT_REGISTER_USER_URL;
URL url;
HttpURLConnection urlConnection;
@@ -264,6 +277,10 @@ public String registerUsers(Uri uri) {
return null;
}
String JSONResponse = this.processResponse(url, urlConnection);
+ if (JSONResponse == null) {
+ this.userFriendlyErrorMessage = "Unknown error registering user";
+ return null;
+ }
if (JSONResponse.contains("name already exists")) {
JSONResponse = this.loginUser(username, generatedPassword,
Config.DEFAULT_AUTH_LOGIN_URL);
@@ -271,10 +288,6 @@ public String registerUsers(Uri uri) {
if (!"".equals(this.userFriendlyErrorMessage)) {
return null;
}
- if (JSONResponse == null) {
- this.userFriendlyErrorMessage = "Unknown error reading sample data from server";
- return null;
- }
return JSONResponse;
}
diff --git a/src/com/github/opensourcefieldlinguistics/fielddb/service/UploadAudioVideoService.java b/src/com/github/opensourcefieldlinguistics/fielddb/service/UploadAudioVideoService.java
new file mode 100644
index 0000000..c19419e
--- /dev/null
+++ b/src/com/github/opensourcefieldlinguistics/fielddb/service/UploadAudioVideoService.java
@@ -0,0 +1,317 @@
+package com.github.opensourcefieldlinguistics.fielddb.service;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.UnsupportedEncodingException;
+import java.nio.charset.Charset;
+import java.security.KeyStore;
+
+import org.acra.ACRA;
+import org.apache.http.HttpResponse;
+import org.apache.http.client.ClientProtocolException;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.conn.ClientConnectionManager;
+import org.apache.http.conn.scheme.PlainSocketFactory;
+import org.apache.http.conn.scheme.Scheme;
+import org.apache.http.conn.scheme.SchemeRegistry;
+import org.apache.http.conn.ssl.SSLSocketFactory;
+import org.apache.http.entity.mime.HttpMultipartMode;
+import org.apache.http.entity.mime.MultipartEntity;
+import org.apache.http.entity.mime.content.FileBody;
+import org.apache.http.entity.mime.content.StringBody;
+import org.apache.http.impl.client.DefaultHttpClient;
+import org.apache.http.impl.conn.SingleClientConnManager;
+import org.apache.http.protocol.BasicHttpContext;
+import org.apache.http.protocol.HttpContext;
+
+import ca.ilanguage.oprime.datacollection.NotifyingIntentService;
+
+import com.github.opensourcefieldlinguistics.fielddb.lessons.Config;
+import com.github.opensourcefieldlinguistics.fielddb.lessons.PrivateConstants;
+import com.github.opensourcefieldlinguistics.fielddb.speech.kartuli.BuildConfig;
+import com.github.opensourcefieldlinguistics.fielddb.speech.kartuli.R;
+import com.google.gson.JsonObject;
+
+import android.app.NotificationManager;
+import android.content.Context;
+import android.content.Intent;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
+import android.net.Uri;
+import android.util.Log;
+
+public class UploadAudioVideoService extends NotifyingIntentService {
+ protected String mDeviceDetails = "{}";
+ protected String mUsername = "default";
+ public UploadAudioVideoService(String name) {
+ super(name);
+ }
+
+ public UploadAudioVideoService() {
+ super("UploadAudioVideoService");
+ }
+
+ @Override
+ protected void onHandleIntent(Intent intent) {
+ if (Config.D) {
+ return;
+ }
+
+ /* only upload files when connected to wifi */
+ ConnectivityManager connManager = (ConnectivityManager) getApplicationContext()
+ .getSystemService(Context.CONNECTIVITY_SERVICE);
+ NetworkInfo wifi = connManager
+ .getNetworkInfo(ConnectivityManager.TYPE_WIFI);
+ if (!wifi.isConnected()) {
+ return;
+ }
+
+ /* only upload files with content */
+ if (intent.getData() == null) {
+ return;
+ }
+ Uri uri = intent.getData();
+ if (uri.getPath() == null) {
+ return;
+ }
+ File f = new File(uri.getPath());
+ if (!f.exists()) {
+ return;
+ }
+ if (f.length() < 5000) {
+ Log.d(Config.TAG, "Not uploading, " + uri.getLastPathSegment()
+ + " was too small " + f.length());
+ return;
+ }
+
+ this.D = Config.D;
+ this.statusMessage = "Uploading audio video";
+ this.tryAgain = intent;
+ this.keystoreResourceId = R.raw.sslkeystore;
+ if (Config.D) {
+ Log.d(Config.TAG, "Inside UploadAudioVideoService intent");
+ }
+ if (!BuildConfig.DEBUG)
+ ACRA.getErrorReporter().putCustomData("action",
+ "uploadAudioVideo:::");
+ if (!BuildConfig.DEBUG)
+ ACRA.getErrorReporter().putCustomData("urlString",
+ Config.DEFAULT_UPLOAD_AUDIO_VIDEO_URL);
+
+ super.onHandleIntent(intent);
+
+ if (!"".equals(this.userFriendlyErrorMessage)) {
+ this.notifyUser(" " + this.userFriendlyErrorMessage, this.noti,
+ this.notificationId, true);
+ if (!BuildConfig.DEBUG)
+ ACRA.getErrorReporter().handleException(
+ new Exception(this.userFriendlyErrorMessage));
+ return;
+ }
+
+ if (intent.hasExtra(Config.EXTRA_PARTICIPANT_ID)) {
+ mUsername = intent.getExtras().getString(
+ Config.EXTRA_PARTICIPANT_ID);
+ }
+ if (intent.hasExtra(Config.EXTRA_EXPERIMENT_TRIAL_INFORMATION)) {
+ mDeviceDetails = intent.getExtras().getString(
+ Config.EXTRA_EXPERIMENT_TRIAL_INFORMATION);
+ }
+
+ String JSONResponse = this.upload(intent.getData());
+ if (JSONResponse == null && "".equals(this.userFriendlyErrorMessage)) {
+ this.userFriendlyErrorMessage = "Server response was missing. Please report this.";
+ }
+ if (!"".equals(this.userFriendlyErrorMessage)) {
+ this.notifyUser(" " + this.userFriendlyErrorMessage, this.noti,
+ this.notificationId, true);
+ if (!BuildConfig.DEBUG)
+ ACRA.getErrorReporter().handleException(
+ new Exception(this.userFriendlyErrorMessage));
+ return;
+ }
+
+ processUploadResponse(intent.getData(), JSONResponse);
+ if (!"".equals(this.userFriendlyErrorMessage)) {
+ this.notifyUser(" " + this.userFriendlyErrorMessage, this.noti,
+ this.notificationId, true);
+ if (!BuildConfig.DEBUG)
+ ACRA.getErrorReporter().handleException(
+ new Exception(this.userFriendlyErrorMessage));
+ return;
+ }
+
+ /* all is well, get their cookie set */
+ // this.getCouchCookie(username, generatedPassword,
+ // Config.DEFAULT_DATA_LOGIN);
+
+ /* Success: remove the notification */
+ ((NotificationManager) getSystemService(NOTIFICATION_SERVICE))
+ .cancel(this.notificationId);
+ if (!BuildConfig.DEBUG)
+ ACRA.getErrorReporter().handleException(
+ new Exception("*** Uploaded audio sucessfully ***"));
+
+ }
+
+ public String upload(Uri uri) {
+ String filePath = uri.getPath();
+ this.statusMessage = "Uploading audio " + uri.getLastPathSegment();
+ if (!BuildConfig.DEBUG)
+ ACRA.getErrorReporter().putCustomData("uploadAudio",
+ uri.getLastPathSegment());
+ String urlStringAuthenticationSession = Config.DEFAULT_UPLOAD_AUDIO_VIDEO_URL;
+
+ /* Actually uploads the video */
+ HttpClient httpClient = new SecureHttpClient(getApplicationContext());
+ // HttpClient httpClient = new DefaultHttpClient();
+
+ HttpContext localContext = new BasicHttpContext();
+ String url = Config.DEFAULT_UPLOAD_AUDIO_VIDEO_URL;
+ HttpPost httpPost = new HttpPost(url);
+
+ MultipartEntity entity = new MultipartEntity(
+ HttpMultipartMode.BROWSER_COMPATIBLE, null,
+ Charset.forName("UTF-8"));
+
+ try {
+
+ entity.addPart("videoFile", new FileBody(new File(filePath)));
+
+ entity.addPart("token", new StringBody(Config.DEFAULT_UPLOAD_TOKEN,
+ "text/plain", Charset.forName("UTF-8")));
+
+ entity.addPart("username", new StringBody(mUsername, "text/plain",
+ Charset.forName("UTF-8")));
+
+ entity.addPart("dbname", new StringBody(Config.DEFAULT_CORPUS,
+ "text/plain", Charset.forName("UTF-8")));
+
+ entity.addPart("returnTextGrid", new StringBody("true",
+ "text/plain", Charset.forName("UTF-8")));
+
+ } catch (UnsupportedEncodingException e) {
+ Log.d(Config.TAG,
+ "Failed to add entity parts due to string encodinuserFriendlyMessageg UTF-8");
+ e.printStackTrace();
+ }
+
+ httpPost.setEntity(entity);
+ String userFriendlyErrorMessage = "";
+ String JSONResponse = "";
+
+ try {
+ HttpResponse response = httpClient.execute(httpPost, localContext);
+ BufferedReader reader = new BufferedReader(new InputStreamReader(
+ response.getEntity().getContent(), "UTF-8"));
+ String newLine;
+ do {
+ newLine = reader.readLine();
+ if (newLine != null) {
+ JSONResponse += newLine;
+ }
+ } while (newLine != null);
+
+ } catch (ClientProtocolException e1) {
+ this.userFriendlyErrorMessage = "Problem using POST, please report this error.";
+ e1.printStackTrace();
+ } catch (IOException e1) {
+ this.userFriendlyErrorMessage = "Problem opening upload connection to server, please report this error.";
+ e1.printStackTrace();
+ }
+
+ if ("".equals(JSONResponse)) {
+ this.userFriendlyErrorMessage = "Unknown error uploading data to server";
+ return null;
+ }
+
+ if (!"".equals(this.userFriendlyErrorMessage)) {
+ return null;
+ }
+ return JSONResponse;
+ }
+
+ public class SecureHttpClient extends DefaultHttpClient {
+
+ final Context context;
+
+ public SecureHttpClient(Context context) {
+ this.context = context;
+ }
+
+ @Override
+ protected ClientConnectionManager createClientConnectionManager() {
+ try {
+ // Get an instance of the Bouncy Castle KeyStore format
+ KeyStore trusted = KeyStore.getInstance("BKS");
+ // Get the raw resource, which contains the keystore with
+ // your trusted certificates (root and any intermediate certs)
+ InputStream in = getApplicationContext().getResources()
+ .openRawResource(R.raw.sslkeystore);
+ try {
+ // Initialize the keystore with the provided trusted
+ // certificates
+ // Also provide the password of the keystore
+ trusted.load(in,
+ PrivateConstants.KEYSTORE_PASS.toCharArray());
+ } finally {
+ in.close();
+ }
+ // Pass the keystore to the SSLSocketFactory. The factory is
+ // responsible
+ // for the verification of the server certificate.
+ SSLSocketFactory sf = new SSLSocketFactory(trusted);
+ // Hostname verification from certificate
+ // http://hc.apache.org/httpcomponents-client-ga/tutorial/html/connmgmt.html#d4e506
+ sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
+ // sf.setHostnameVerifier(SSLSocketFactory.STRICT_HOSTNAME_VERIFIER);
+
+ SchemeRegistry registry = new SchemeRegistry();
+ registry.register(new Scheme("http", PlainSocketFactory
+ .getSocketFactory(), 80));
+ // Register for port 443 our SSLSocketFactory with our keystore
+ // to the ConnectionManager
+ registry.register(new Scheme("https", sf, 443));
+ return new SingleClientConnManager(getParams(), registry);
+ } catch (Exception e) {
+ throw new AssertionError(e);
+ }
+ }
+ }
+
+ public int processUploadResponse(Uri uri, String jsonResponse) {
+ if (jsonResponse != null && this.D) {
+ Log.d(Config.TAG, jsonResponse);
+ }
+ JsonObject json = (JsonObject) NotifyingIntentService.jsonParser
+ .parse(jsonResponse);
+ if (json.has("userFriendlyErrors")) {
+ this.userFriendlyErrorMessage = json.get("userFriendlyErrors")
+ .getAsString();
+ return 0;
+ }
+ if (!json.has("files")) {
+ this.userFriendlyErrorMessage = "The server response is very strange, please report this.";
+ return 0;
+ } else {
+ String eventType = "uploadAudio";
+ String eventValue = jsonResponse;
+ if (!BuildConfig.DEBUG) {
+ ACRA.getErrorReporter().putCustomData("action",
+ "{" + eventType + " : " + eventValue + "}");
+ ACRA.getErrorReporter().putCustomData("androidTimestamp",
+ System.currentTimeMillis() + "");
+ ACRA.getErrorReporter().putCustomData("deviceDetails",
+ mDeviceDetails);
+ ACRA.getErrorReporter().handleException(
+ new Exception("*** User event " + eventType + " ***"));
+ }
+ }
+
+ return 0;
+ }
+}