From 2d46898add03001063edfc404eb17d6a742f609a Mon Sep 17 00:00:00 2001 From: cesine Date: Thu, 12 Jun 2014 10:44:27 +0400 Subject: [PATCH 01/30] making default db the username's db fixes https://github.com/OpenSourceFieldlinguistics/FieldDB/issues/1531 --- .../fielddb/FieldDBApplication.java | 29 ++++++++++++------- .../fielddb/lessons/Config.java | 14 ++++++--- 2 files changed, 29 insertions(+), 14 deletions(-) diff --git a/src/com/github/opensourcefieldlinguistics/fielddb/FieldDBApplication.java b/src/com/github/opensourcefieldlinguistics/fielddb/FieldDBApplication.java index 2a1bf6f..0f5fc08 100644 --- a/src/com/github/opensourcefieldlinguistics/fielddb/FieldDBApplication.java +++ b/src/com/github/opensourcefieldlinguistics/fielddb/FieldDBApplication.java @@ -18,7 +18,7 @@ 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.R; import com.github.opensourcefieldlinguistics.fielddb.service.DownloadDatumsService; import com.github.opensourcefieldlinguistics.fielddb.service.RegisterUserService; @@ -93,24 +93,25 @@ public final void onCreate() { 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)); @@ -138,7 +139,11 @@ public final void onCreate() { "There is no user... this is a problme the app wont work."); ACRA.getErrorReporter().putCustomData("username", "unknown"); } - ACRA.getErrorReporter().putCustomData("dbname", Config.DEFAULT_CORPUS); + /* Make the default corpus point to the user's own corpus */ + Config.DEFAULT_CORPUS = Config.DEFAULT_CORPUS.replace("username", + username); + ACRA.getErrorReporter().putCustomData("dbname", + Config.DEFAULT_CORPUS.replace("username", username)); Log.d(Config.TAG, cursor.getString(cursor .getColumnIndexOrThrow(UserTable.COLUMN_USERNAME))); cursor.close(); @@ -152,11 +157,15 @@ 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("speechrec")) { + Log.d(Config.TAG, + "Not downloading samples, they are included in the training app"); + } 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(), diff --git a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/Config.java b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/Config.java index 0f1896c..bc91f81 100644 --- a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/Config.java +++ b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/Config.java @@ -1,20 +1,23 @@ package com.github.opensourcefieldlinguistics.fielddb.lessons; public class Config extends ca.ilanguage.oprime.Config { - public static final boolean D = false; + public static final boolean D = true; public static final String ACRA_PASS = PrivateConstants.ACRA_PASS; public static final String ACRA_SERVER_URL = PrivateConstants.ACRA_SERVER_URL; 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 = "speechrec"; + // 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 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 final String DEFAULT_OUTPUT_DIRECTORY = "/sdcard/" + + 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_REGISTER_USER_URL = PrivateConstants.DEFAULT_REGISTER_USER_URL; @@ -23,4 +26,7 @@ public class Config extends ca.ilanguage.oprime.Config { 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; + } From 2722f052edf61ffea0f58ca699da16a7535610d4 Mon Sep 17 00:00:00 2001 From: cesine Date: Thu, 12 Jun 2014 10:45:19 +0400 Subject: [PATCH 02/30] adding support for speech recognition training app --- res/values-ka/strings.xml | 3 +- res/values-ru/strings.xml | 5 +- res/values/strings.xml | 1 + .../database/AudioVideoContentProvider.java | 57 +++++++++-------- .../database/DatumContentProvider.java | 63 ++++++++++--------- .../database/FieldDBUserContentProvider.java | 2 + .../service/DownloadDatumsService.java | 2 +- .../fielddb/service/RegisterUserService.java | 14 ++--- 8 files changed, 79 insertions(+), 68 deletions(-) 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/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..fd050fa 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; @@ -277,12 +280,12 @@ 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; 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/service/DownloadDatumsService.java b/src/com/github/opensourcefieldlinguistics/fielddb/service/DownloadDatumsService.java index fbc78c3..c01c075 100644 --- a/src/com/github/opensourcefieldlinguistics/fielddb/service/DownloadDatumsService.java +++ b/src/com/github/opensourcefieldlinguistics/fielddb/service/DownloadDatumsService.java @@ -19,7 +19,7 @@ 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.R; import com.google.gson.JsonArray; import com.google.gson.JsonObject; diff --git a/src/com/github/opensourcefieldlinguistics/fielddb/service/RegisterUserService.java b/src/com/github/opensourcefieldlinguistics/fielddb/service/RegisterUserService.java index e0cc281..abbbacc 100644 --- a/src/com/github/opensourcefieldlinguistics/fielddb/service/RegisterUserService.java +++ b/src/com/github/opensourcefieldlinguistics/fielddb/service/RegisterUserService.java @@ -15,7 +15,7 @@ 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.R; import com.google.gson.JsonObject; import android.app.NotificationManager; @@ -138,14 +138,14 @@ 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; } @@ -264,6 +264,10 @@ public String registerUsers(Uri uri) { return null; } String JSONResponse = this.processResponse(url, urlConnection); + if (JSONResponse == null) { + this.userFriendlyErrorMessage = "Unknown error reading sample data from server"; + return null; + } if (JSONResponse.contains("name already exists")) { JSONResponse = this.loginUser(username, generatedPassword, Config.DEFAULT_AUTH_LOGIN_URL); @@ -271,10 +275,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; } From e5ec28dc45bede24e0919522308a2f219b25a6be Mon Sep 17 00:00:00 2001 From: cesine Date: Thu, 12 Jun 2014 14:43:13 +0400 Subject: [PATCH 03/30] created a production experiment datum fragment which just presents the stimulus, plays a prompt and records the result fixes https://github.com/OpenSourceFieldlinguistics/FieldDB/issues/1532 --- .../fielddb/FieldDBApplication.java | 4 ++ .../lessons/ui/DatumDetailActivity.java | 26 ++++++----- .../lessons/ui/DatumDetailFragment.java | 28 +++++------ .../fielddb/lessons/ui/DatumListActivity.java | 6 ++- .../ui/DatumProductionExperimentFragment.java | 46 +++++++++++++++++++ .../fielddb/model/Datum.java | 16 +++++++ 6 files changed, 99 insertions(+), 27 deletions(-) create mode 100644 src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumProductionExperimentFragment.java diff --git a/src/com/github/opensourcefieldlinguistics/fielddb/FieldDBApplication.java b/src/com/github/opensourcefieldlinguistics/fielddb/FieldDBApplication.java index 0f5fc08..51b26d7 100644 --- a/src/com/github/opensourcefieldlinguistics/fielddb/FieldDBApplication.java +++ b/src/com/github/opensourcefieldlinguistics/fielddb/FieldDBApplication.java @@ -20,6 +20,7 @@ import com.github.opensourcefieldlinguistics.fielddb.lessons.Config; 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; @@ -160,6 +161,9 @@ public final void onCreate() { if (Config.APP_TYPE.equals("speechrec")) { Log.d(Config.TAG, "Not downloading samples, they are included in the training app"); + Intent updateSamples = new Intent(getApplicationContext(), + KartuliSMSCorpusService.class); + getApplicationContext().startService(updateSamples); } else { if (wifi.isConnected() || Config.D) { Intent updateSamples = new Intent(getApplicationContext(), diff --git a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumDetailActivity.java b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumDetailActivity.java index f965bb3..630522e 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; @@ -42,6 +43,9 @@ protected void onCreate(Bundle savedInstanceState) { arguments.putString(DatumDetailFragment.ARG_ITEM_ID, getIntent() .getStringExtra(DatumDetailFragment.ARG_ITEM_ID)); DatumDetailFragment fragment = new DatumDetailFragment(); + if (Config.APP_TYPE.equals("speechrec")) { + fragment = new DatumProductionExperimentFragment(); + } fragment.setArguments(arguments); getSupportFragmentManager().beginTransaction() .add(R.id.datum_detail_container, fragment).commit(); @@ -51,17 +55,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..c1e23d5 100644 --- a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumDetailFragment.java +++ b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumDetailFragment.java @@ -59,8 +59,8 @@ public class DatumDetailFragment extends Fragment { /** * The content this fragment is presenting. */ - private Datum mItem; - private Uri mUri; + protected Datum mItem; + protected Uri mUri; public boolean mTwoPane = false; /** @@ -70,11 +70,11 @@ 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 String TAG = "FieldDB"; + protected boolean mRecordingAudio = false; + protected VideoView mVideoView; + protected ImageView mImageView; + protected MediaController mMediaController; protected DeviceDetails mDeviceDetails; protected HashMap mDatumEditCounts; @@ -326,7 +326,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; @@ -378,7 +378,7 @@ public boolean onOptionsItemSelected(MenuItem item) { } } - private boolean delete() { + protected boolean delete() { AlertDialog deleteConfirmationDialog = new AlertDialog.Builder( getActivity()) .setTitle("Are you sure?") @@ -416,7 +416,7 @@ public void onClick(DialogInterface dialog, return true; } - private void loadVisuals(boolean playImmediately) { + protected void loadVisuals(boolean playImmediately) { loadMainVideo(playImmediately); } @@ -480,7 +480,7 @@ public void onClick(View v) { } @SuppressLint("NewApi") - private void loadMainImage() { + protected void loadMainImage() { File image = new File(Config.DEFAULT_OUTPUT_DIRECTORY + "/" + mItem.getMainImageFile()); if (!image.exists()) { @@ -559,7 +559,7 @@ public void onActivityResult(int requestCode, int resultCode, Intent data) { 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 +576,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); @@ -606,7 +606,7 @@ public void onPause() { 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(); diff --git a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumListActivity.java b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumListActivity.java index b9f3858..1416bb9 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; @@ -77,6 +76,9 @@ public void onItemSelected(String id) { // adding or replacing the detail fragment using a // fragment transaction. DatumDetailFragment fragment = new DatumDetailFragment(); + if (Config.APP_TYPE.equals("speechrec")) { + fragment = new DatumProductionExperimentFragment(); + } fragment.mTwoPane = mTwoPane; fragment.setArguments(arguments); FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); 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..fae04c5 --- /dev/null +++ b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumProductionExperimentFragment.java @@ -0,0 +1,46 @@ +package com.github.opensourcefieldlinguistics.fielddb.lessons.ui; + +import android.os.Bundle; +import android.util.Log; +import android.view.LayoutInflater; +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 { + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View rootView = inflater.inflate(R.layout.fragment_production_stimulus, + container, false); + + if (mItem != null) { + + 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); + } + mImageView.setImageResource(R.drawable.search_default); + + this.playPromptContext(); + } + + return rootView; + } + + protected void playPromptContext() { + Log.d(Config.TAG, "Playing prompting context"); + } +} diff --git a/src/com/github/opensourcefieldlinguistics/fielddb/model/Datum.java b/src/com/github/opensourcefieldlinguistics/fielddb/model/Datum.java index f7a4915..3c377a6 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; @@ -255,6 +256,21 @@ 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) { + this.tags = new ArrayList(Arrays.asList(tags.split(","))); + } + public void setTags(ArrayList tags) { this.tags = tags; } From f3de322e0953c01e4643fc6f14d61e70bda8712e Mon Sep 17 00:00:00 2001 From: cesine Date: Thu, 12 Jun 2014 15:19:25 +0400 Subject: [PATCH 04/30] displaying different background images based on tags (for category based flash cards) https://github.com/OpenSourceFieldlinguistics/FieldDB/issues/1532 --- AndroidManifest.xml | 8 +- .../fielddb/FieldDBApplication.java | 16 +- .../lessons/ui/DatumDetailFragment.java | 186 +++++++++--------- .../ui/DatumProductionExperimentFragment.java | 9 +- .../fielddb/model/Datum.java | 4 +- 5 files changed, 129 insertions(+), 94 deletions(-) diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 06d819c..80daef6 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -87,6 +87,12 @@ + + + + + + - \ No newline at end of file + diff --git a/src/com/github/opensourcefieldlinguistics/fielddb/FieldDBApplication.java b/src/com/github/opensourcefieldlinguistics/fielddb/FieldDBApplication.java index 51b26d7..90fec72 100644 --- a/src/com/github/opensourcefieldlinguistics/fielddb/FieldDBApplication.java +++ b/src/com/github/opensourcefieldlinguistics/fielddb/FieldDBApplication.java @@ -20,7 +20,9 @@ import com.github.opensourcefieldlinguistics.fielddb.lessons.Config; import com.github.opensourcefieldlinguistics.fielddb.speech.kartuli.R; import com.github.opensourcefieldlinguistics.fielddb.service.DownloadDatumsService; +import com.github.opensourcefieldlinguistics.fielddb.service.KartuliLegalSearchCorpusService; import com.github.opensourcefieldlinguistics.fielddb.service.KartuliSMSCorpusService; +import com.github.opensourcefieldlinguistics.fielddb.service.KartuliWebSearchCorpusService; import com.github.opensourcefieldlinguistics.fielddb.service.RegisterUserService; import android.app.Application; @@ -161,9 +163,19 @@ public final void onCreate() { if (Config.APP_TYPE.equals("speechrec")) { Log.d(Config.TAG, "Not downloading samples, they are included in the training app"); - Intent updateSamples = new Intent(getApplicationContext(), + + Intent updateSMSSamples = new Intent(getApplicationContext(), KartuliSMSCorpusService.class); - getApplicationContext().startService(updateSamples); + getApplicationContext().startService(updateSMSSamples); + + Intent updateWebSearchSamples = new Intent(getApplicationContext(), + KartuliWebSearchCorpusService.class); + getApplicationContext().startService(updateWebSearchSamples); + + Intent updateLegalSearchSamples = new Intent(getApplicationContext(), + KartuliLegalSearchCorpusService.class); + getApplicationContext().startService(updateLegalSearchSamples); + } else { if (wifi.isConnected() || Config.D) { Intent updateSamples = new Intent(getApplicationContext(), diff --git a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumDetailFragment.java b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumDetailFragment.java index c1e23d5..1510b68 100644 --- a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumDetailFragment.java +++ b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumDetailFragment.java @@ -94,11 +94,12 @@ public void onCreate(Bundle savedInstanceState) { String[] selectionArgs = null; String sortOrder = null; - String[] datumProjection = { DatumTable.COLUMN_ORTHOGRAPHY, + 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 }; + 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); @@ -119,9 +120,11 @@ public void onCreate(Bundle savedInstanceState) { .getColumnIndexOrThrow(DatumTable.COLUMN_CONTEXT))); 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; @@ -336,45 +339,46 @@ protected 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; - item.setIcon(R.drawable.ic_action_stop); - this.recordUserEvent("captureAudio", audioFileName); - - } else { - Intent audio = new Intent(getActivity(), AudioRecorder.class); - getActivity().stopService(audio); - this.mRecordingAudio = false; - item.setIcon(R.drawable.ic_action_mic); - this.recordUserEvent("stopAudio", ""); - } - 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); + 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; + item.setIcon(R.drawable.ic_action_stop); + this.recordUserEvent("captureAudio", audioFileName); + + } else { + Intent audio = new Intent(getActivity(), + AudioRecorder.class); + getActivity().stopService(audio); + this.mRecordingAudio = false; + item.setIcon(R.drawable.ic_action_mic); + this.recordUserEvent("stopAudio", ""); + } + 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); } } @@ -391,17 +395,19 @@ protected boolean delete() { @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, @@ -514,47 +520,49 @@ 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); } diff --git a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumProductionExperimentFragment.java b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumProductionExperimentFragment.java index fae04c5..61afc63 100644 --- a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumProductionExperimentFragment.java +++ b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumProductionExperimentFragment.java @@ -32,7 +32,14 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, if (mImageView == null) { mImageView = (ImageView) rootView.findViewById(R.id.image_view); } - mImageView.setImageResource(R.drawable.search_default); + 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); + } this.playPromptContext(); } diff --git a/src/com/github/opensourcefieldlinguistics/fielddb/model/Datum.java b/src/com/github/opensourcefieldlinguistics/fielddb/model/Datum.java index 3c377a6..505e4bb 100644 --- a/src/com/github/opensourcefieldlinguistics/fielddb/model/Datum.java +++ b/src/com/github/opensourcefieldlinguistics/fielddb/model/Datum.java @@ -268,7 +268,9 @@ public String getTagsString() { } public void setTagsFromSting(String tags) { - this.tags = new ArrayList(Arrays.asList(tags.split(","))); + if(tags != null && !"".equals(tags)){ + this.tags = new ArrayList(Arrays.asList(tags.split(","))); + } } public void setTags(ArrayList tags) { From c8c1aeb7540a3783ff6d13c802f748dabc679d50 Mon Sep 17 00:00:00 2001 From: cesine Date: Thu, 12 Jun 2014 18:33:23 +0400 Subject: [PATCH 05/30] added a list pager which makes it possible to swipe between datum fixes https://github.com/OpenSourceFieldlinguistics/FieldDB/issues/1533 --- ...ivity_production_experiment_datum_list.xml | 13 +++ .../lessons/ui/DatumFragmentPagerAdapter.java | 79 +++++++++++++++++++ ...onExperimentViewPagerFragmentActivity.java | 67 ++++++++++++++++ 3 files changed, 159 insertions(+) create mode 100644 res/layout/activity_production_experiment_datum_list.xml create mode 100644 src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumFragmentPagerAdapter.java create mode 100644 src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/ProductionExperimentViewPagerFragmentActivity.java 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/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..70e71ed --- /dev/null +++ b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumFragmentPagerAdapter.java @@ -0,0 +1,79 @@ +package com.github.opensourcefieldlinguistics.fielddb.lessons.ui; + +import java.util.ArrayList; +import java.util.List; + +import ca.ilanguage.oprime.database.UserContentProvider.UserTable; + +import com.github.opensourcefieldlinguistics.fielddb.database.DatumContentProvider; +import com.github.opensourcefieldlinguistics.fielddb.database.DatumContentProvider.DatumTable; +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; + +public class DatumFragmentPagerAdapter extends FragmentPagerAdapter { + private String[] datumsIds; + private ArrayList mFragments; + + Uri mVisibleDatumUri; + Cursor mCursor; + + public DatumFragmentPagerAdapter(FragmentManager fm) { + super(fm); + mFragments = new ArrayList(); + } + + public void swapCursor(Cursor cursor) { + this.mCursor = cursor; + } + + @Override + public Fragment getItem(int position) { + if (mFragments.size() > position) { + if (mFragments.get(position) != null) { + return mFragments.get(position); + } + } + + String id = "sms1"; + if (mCursor.getCount() > position) { + mCursor.moveToPosition(position); + id = mCursor.getString(mCursor + .getColumnIndexOrThrow(UserTable.COLUMN_ID)); + } + Bundle arguments = new Bundle(); + DatumProductionExperimentFragment fragment = new DatumProductionExperimentFragment(); + if (Config.APP_TYPE.equals("speechrec")) { + fragment = new DatumProductionExperimentFragment(); + } else { + // fragment = new DatumDetailFragment(); + } + mVisibleDatumUri = Uri.parse(DatumContentProvider.CONTENT_URI + "/" + + id); + arguments.putParcelable(DatumContentProvider.CONTENT_ITEM_TYPE, + mVisibleDatumUri); + arguments.putString(DatumDetailFragment.ARG_ITEM_ID, id); + + fragment.mTwoPane = false; + fragment.setArguments(arguments); + if (mFragments.size() == position) { + mFragments.add(fragment); + } else { + mFragments.set(position, fragment); + } + return fragment; + } + + @Override + public int getCount() { + if (mCursor != null) { + return mCursor.getCount(); + } + return 0; + } +} diff --git a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/ProductionExperimentViewPagerFragmentActivity.java b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/ProductionExperimentViewPagerFragmentActivity.java new file mode 100644 index 0000000..e8b4288 --- /dev/null +++ b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/ProductionExperimentViewPagerFragmentActivity.java @@ -0,0 +1,67 @@ +package com.github.opensourcefieldlinguistics.fielddb.lessons.ui; + +import ca.ilanguage.oprime.Config; + +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.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 ProductionExperimentViewPagerFragmentActivity + 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}; + CursorLoader cursorLoader = new CursorLoader(this, + DatumContentProvider.CONTENT_URI, projection, null, null, 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); + } + +} From 997bfe891a02fd9aea8169fb54b81dc3b84ddd9d Mon Sep 17 00:00:00 2001 From: cesine Date: Fri, 13 Jun 2014 11:22:41 +0400 Subject: [PATCH 06/30] scrollabel flash cards a bit more memory optimized and turning of acra if not in release build config and using the first datum as instructions and making images show in the image view not hte video view... fixes https://github.com/OpenSourceFieldlinguistics/FieldDB/issues/1537 fixes https://github.com/OpenSourceFieldlinguistics/FieldDB/issues/1536 fixes https://github.com/OpenSourceFieldlinguistics/FieldDB/issues/1535 --- .../fielddb/FieldDBApplication.java | 10 +- .../database/DatumContentProvider.java | 34 +- .../lessons/ui/DatumDetailFragment.java | 367 +++++++++++------- .../lessons/ui/DatumFragmentPagerAdapter.java | 27 +- .../fielddb/lessons/ui/DatumListFragment.java | 5 +- .../ui/DatumProductionExperimentFragment.java | 67 +++- .../service/DownloadDatumsService.java | 33 +- .../fielddb/service/RegisterUserService.java | 15 +- 8 files changed, 378 insertions(+), 180 deletions(-) diff --git a/src/com/github/opensourcefieldlinguistics/fielddb/FieldDBApplication.java b/src/com/github/opensourcefieldlinguistics/fielddb/FieldDBApplication.java index 90fec72..2d36300 100644 --- a/src/com/github/opensourcefieldlinguistics/fielddb/FieldDBApplication.java +++ b/src/com/github/opensourcefieldlinguistics/fielddb/FieldDBApplication.java @@ -18,6 +18,7 @@ import com.github.opensourcefieldlinguistics.fielddb.database.FieldDBUserContentProvider; import com.github.opensourcefieldlinguistics.fielddb.lessons.Config; +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.KartuliLegalSearchCorpusService; @@ -93,7 +94,8 @@ 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, @@ -136,16 +138,16 @@ 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); } 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); - ACRA.getErrorReporter().putCustomData("dbname", + if (!BuildConfig.DEBUG) ACRA.getErrorReporter().putCustomData("dbname", Config.DEFAULT_CORPUS.replace("username", username)); Log.d(Config.TAG, cursor.getString(cursor .getColumnIndexOrThrow(UserTable.COLUMN_USERNAME))); diff --git a/src/com/github/opensourcefieldlinguistics/fielddb/database/DatumContentProvider.java b/src/com/github/opensourcefieldlinguistics/fielddb/database/DatumContentProvider.java index fd050fa..c676792 100644 --- a/src/com/github/opensourcefieldlinguistics/fielddb/database/DatumContentProvider.java +++ b/src/com/github/opensourcefieldlinguistics/fielddb/database/DatumContentProvider.java @@ -291,13 +291,35 @@ public static class DatumTable extends OPrimeTable { // Offline Sample data private 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_MORPHEMES, + "You need to read a few sentences to train the recognizer to your voice and your words."); + values.put( + COLUMN_GLOSS, + "You need to read a few sentences to train the recognizer to your voice and your words."); + values.put( + COLUMN_TRANSLATION, + "You need to read a few sentences to train the recognizer to your voice and your words."); + values.put( + COLUMN_ORTHOGRAPHY, + "You need to read a few sentences to train the recognizer to your voice and your words."); + values.put( + COLUMN_CONTEXT, + "Recognition in the Georgian language is too complex to do with yout being speaker specific."); return values; } diff --git a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumDetailFragment.java b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumDetailFragment.java index 1510b68..ab43606 100644 --- a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumDetailFragment.java +++ b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumDetailFragment.java @@ -1,6 +1,7 @@ package com.github.opensourcefieldlinguistics.fielddb.lessons.ui; import java.io.File; +import java.io.IOException; import java.util.HashMap; import java.util.Iterator; import java.util.Map; @@ -16,6 +17,7 @@ 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.support.v4.app.Fragment; @@ -30,8 +32,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 +45,8 @@ 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.speech.kartuli.BuildConfig; +import com.github.opensourcefieldlinguistics.fielddb.speech.kartuli.R; import com.github.opensourcefieldlinguistics.fielddb.model.Datum; /** @@ -75,8 +80,12 @@ public DatumDetailFragment() { protected VideoView mVideoView; protected ImageView mImageView; protected MediaController mMediaController; + MediaPlayer mAudioPlayer; protected DeviceDetails mDeviceDetails; protected HashMap mDatumEditCounts; + protected ImageButton mSpeechRecognizerFeedback; + protected TextView mSpeechRecognizerInstructions; + protected boolean isPlaying = false; @Override public void onCreate(Bundle savedInstanceState) { @@ -98,8 +107,7 @@ public void onCreate(Bundle savedInstanceState) { DatumTable.COLUMN_MORPHEMES, DatumTable.COLUMN_GLOSS, DatumTable.COLUMN_TRANSLATION, DatumTable.COLUMN_CONTEXT, DatumTable.COLUMN_IMAGE_FILES, - DatumTable.COLUMN_AUDIO_VIDEO_FILES, - DatumTable.COLUMN_TAGS}; + 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); @@ -122,15 +130,17 @@ public void onCreate(Bundle savedInstanceState) { .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()); + } } @@ -143,21 +153,27 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, container, false); if (mItem != null) { + this.prepareEditTextListeners(rootView); + this.prepareVideoAndImages(rootView); + this.prepareSpeechRecognitionButton(rootView); + } + + return rootView; + } - final EditText orthographyEditText = ((EditText) rootView - .findViewById(R.id.orthography)); + 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) { @@ -171,21 +187,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) { @@ -198,21 +214,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) { @@ -225,12 +240,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() { @@ -256,11 +270,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() { @@ -285,25 +299,50 @@ public void onTextChanged(CharSequence arg0, int arg1, recordUserEvent("editDatum", "translation"); } }); - ((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); + } + } + + 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); + } + + 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(""); } - return rootView; } @Override @@ -340,35 +379,7 @@ 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; - item.setIcon(R.drawable.ic_action_stop); - this.recordUserEvent("captureAudio", audioFileName); - - } else { - Intent audio = new Intent(getActivity(), - AudioRecorder.class); - getActivity().stopService(audio); - this.mRecordingAudio = false; - item.setIcon(R.drawable.ic_action_mic); - this.recordUserEvent("stopAudio", ""); - } - return true; + return this.toggleAudioRecording(item); case R.id.action_play : return this.loadMainVideo(true); case R.id.action_videos : @@ -382,6 +393,61 @@ public boolean onOptionsItemSelected(MenuItem 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; + 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; + if (item != null) { + item.setIcon(R.drawable.ic_action_stop); + } + this.recordUserEvent("captureAudio", audioFileName); + + if (mSpeechRecognizerFeedback != null) { + mSpeechRecognizerFeedback + .setImageResource(R.drawable.speech_recognizer_recognizing); + } + + if (mSpeechRecognizerInstructions != null) { + mSpeechRecognizerInstructions.setText("Tap to end"); + } + + } else { + Intent audio = new Intent(getActivity(), AudioRecorder.class); + getActivity().stopService(audio); + this.mRecordingAudio = false; + if (item != null) { + item.setIcon(R.drawable.ic_action_mic); + } + this.recordUserEvent("stopAudio", ""); + + if (mSpeechRecognizerFeedback != null) { + mSpeechRecognizerFeedback + .setImageResource(R.drawable.speech_recognizer_waiting); + } + + if (mSpeechRecognizerInstructions != null) { + mSpeechRecognizerInstructions.setText("Tap to speak"); + } + } + return true; + } + protected boolean delete() { AlertDialog deleteConfirmationDialog = new AlertDialog.Builder( getActivity()) @@ -435,57 +501,76 @@ 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") protected void loadMainImage() { File image = new File(Config.DEFAULT_OUTPUT_DIRECTORY + "/" + mItem.getMainImageFile()); @@ -499,17 +584,17 @@ protected 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); + // } } @@ -611,6 +696,14 @@ public void onPause() { edits = "[" + edits + "]"; recordUserEvent("totalDatumEditsOnPause", edits); } + + if (mAudioPlayer != null) { + // if (mPrompt.isPlaying()) { + // mPrompt.stop(); + // } + mAudioPlayer.release(); + } + super.onPause(); } @@ -626,13 +719,17 @@ protected 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 + "}"); + if (!BuildConfig.DEBUG) + ACRA.getErrorReporter().putCustomData("androidTimestamp", + System.currentTimeMillis() + ""); + if (!BuildConfig.DEBUG) + ACRA.getErrorReporter().putCustomData("deviceDetails", + this.mDeviceDetails.getCurrentDeviceDetails()); + if (!BuildConfig.DEBUG) + 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 index 70e71ed..99cbf2c 100644 --- a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumFragmentPagerAdapter.java +++ b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumFragmentPagerAdapter.java @@ -1,12 +1,10 @@ package com.github.opensourcefieldlinguistics.fielddb.lessons.ui; import java.util.ArrayList; -import java.util.List; import ca.ilanguage.oprime.database.UserContentProvider.UserTable; import com.github.opensourcefieldlinguistics.fielddb.database.DatumContentProvider; -import com.github.opensourcefieldlinguistics.fielddb.database.DatumContentProvider.DatumTable; import com.github.opensourcefieldlinguistics.fielddb.lessons.Config; import android.database.Cursor; @@ -17,11 +15,10 @@ import android.support.v4.app.FragmentPagerAdapter; public class DatumFragmentPagerAdapter extends FragmentPagerAdapter { - private String[] datumsIds; + private ArrayList mDatumsIds; private ArrayList mFragments; Uri mVisibleDatumUri; - Cursor mCursor; public DatumFragmentPagerAdapter(FragmentManager fm) { super(fm); @@ -29,9 +26,16 @@ public DatumFragmentPagerAdapter(FragmentManager fm) { } public void swapCursor(Cursor cursor) { - this.mCursor = cursor; + this.mDatumsIds = new ArrayList(); + if (cursor != null && cursor.getCount() > 0) { + cursor.moveToFirst(); + while (cursor.moveToNext()) { + this.mDatumsIds.add(cursor.getString(cursor + .getColumnIndexOrThrow(UserTable.COLUMN_ID))); + } + cursor.close(); + } } - @Override public Fragment getItem(int position) { if (mFragments.size() > position) { @@ -41,10 +45,8 @@ public Fragment getItem(int position) { } String id = "sms1"; - if (mCursor.getCount() > position) { - mCursor.moveToPosition(position); - id = mCursor.getString(mCursor - .getColumnIndexOrThrow(UserTable.COLUMN_ID)); + if (mDatumsIds.size() > position) { + id = mDatumsIds.get(position); } Bundle arguments = new Bundle(); DatumProductionExperimentFragment fragment = new DatumProductionExperimentFragment(); @@ -71,9 +73,10 @@ public Fragment getItem(int position) { @Override public int getCount() { - if (mCursor != null) { - return mCursor.getCount(); + if (mDatumsIds != null) { + return mDatumsIds.size(); } return 0; } + } 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 index 61afc63..eef1891 100644 --- a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumProductionExperimentFragment.java +++ b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumProductionExperimentFragment.java @@ -1,6 +1,8 @@ package com.github.opensourcefieldlinguistics.fielddb.lessons.ui; +import android.media.MediaPlayer; import android.os.Bundle; +import android.os.Handler; import android.util.Log; import android.view.LayoutInflater; import android.view.View; @@ -13,6 +15,8 @@ public class DatumProductionExperimentFragment extends DatumDetailFragment { + private int mAudioPromptResource; + @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { @@ -20,6 +24,8 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, container, false); if (mItem != null) { + this.prepareSpeechRecognitionButton(rootView); + this.prepareVideoAndImages(rootView); final TextView orthographyTextView = ((TextView) rootView .findViewById(R.id.orthography)); @@ -41,13 +47,72 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, mImageView.setImageResource(R.drawable.sms_selected); } - this.playPromptContext(); + if ("instructions".equals(mItem.getId())) { + mAudioPromptResource = R.raw.instructions; + } else { + mAudioPromptResource = R.raw.prompt; + } + } return rootView; } + @Override + public void setUserVisibleHint(boolean isVisibleToUser) { + super.setUserVisibleHint(isVisibleToUser); + if (this.isVisible() && !this.isPlaying) { + playPromptContext(); + } + } + + public void onToggleAudioRecording(View view) { + this.toggleAudioRecording(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) { + Handler mainHandler = new Handler(getActivity() + .getMainLooper()); + Runnable myRunnable = new Runnable() { + @Override + public void run() { + toggleAudioRecording(null); + } + }; + mainHandler.post(myRunnable); + mp.release(); + } + }); + 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) { + mSpeechRecognizerInstructions.setText("Speak now"); + } + } } + } diff --git a/src/com/github/opensourcefieldlinguistics/fielddb/service/DownloadDatumsService.java b/src/com/github/opensourcefieldlinguistics/fielddb/service/DownloadDatumsService.java index c01c075..161eee8 100644 --- a/src/com/github/opensourcefieldlinguistics/fielddb/service/DownloadDatumsService.java +++ b/src/com/github/opensourcefieldlinguistics/fielddb/service/DownloadDatumsService.java @@ -19,6 +19,7 @@ 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.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; @@ -55,6 +61,7 @@ protected void onHandleIntent(Intent intent) { Log.d(Config.TAG, "Inside DownloadDatumsService intent"); } + this.datumTagToDownload = "SampleData"; this.urlStringSampleDataDownload = Config.DEFAULT_SAMPLE_DATA_URL + "?key=%22" + datumTagToDownload + "%22"; @@ -62,16 +69,16 @@ protected void onHandleIntent(Intent intent) { Log.d(Config.TAG, this.urlStringSampleDataDownload); } - ACRA.getErrorReporter().putCustomData("action", + if (!BuildConfig.DEBUG) ACRA.getErrorReporter().putCustomData("action", "downloadDatums:::" + datumTagToDownload); - ACRA.getErrorReporter().putCustomData("urlString", + 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( + if (!BuildConfig.DEBUG) ACRA.getErrorReporter().handleException( new Exception(this.userFriendlyErrorMessage)); return; } @@ -81,7 +88,7 @@ protected void onHandleIntent(Intent intent) { if (!"".equals(this.userFriendlyErrorMessage)) { this.notifyUser(" " + this.userFriendlyErrorMessage, this.noti, this.notificationId, true); - ACRA.getErrorReporter().handleException( + if (!BuildConfig.DEBUG) ACRA.getErrorReporter().handleException( new Exception(this.userFriendlyErrorMessage)); return; } @@ -90,7 +97,7 @@ protected void onHandleIntent(Intent intent) { if (!"".equals(this.userFriendlyErrorMessage)) { this.notifyUser(" " + this.userFriendlyErrorMessage, this.noti, this.notificationId, true); - ACRA.getErrorReporter().handleException( + if (!BuildConfig.DEBUG) ACRA.getErrorReporter().handleException( new Exception(this.userFriendlyErrorMessage)); return; } @@ -99,7 +106,7 @@ protected void onHandleIntent(Intent intent) { if (!"".equals(this.userFriendlyErrorMessage)) { this.notifyUser(" " + this.userFriendlyErrorMessage, this.noti, this.notificationId, true); - ACRA.getErrorReporter().handleException( + if (!BuildConfig.DEBUG) ACRA.getErrorReporter().handleException( new Exception(this.userFriendlyErrorMessage)); return; } @@ -107,11 +114,11 @@ protected void onHandleIntent(Intent intent) { /* Success: remove the notification */ ((NotificationManager) getSystemService(NOTIFICATION_SERVICE)) .cancel(this.notificationId); - ACRA.getErrorReporter().putCustomData("action", + if (!BuildConfig.DEBUG) ACRA.getErrorReporter().putCustomData("action", "downloadDatums:::" + datumTagToDownload); - ACRA.getErrorReporter().putCustomData("urlString", + if (!BuildConfig.DEBUG) ACRA.getErrorReporter().putCustomData("urlString", this.urlStringSampleDataDownload); - ACRA.getErrorReporter().handleException( + if (!BuildConfig.DEBUG) ACRA.getErrorReporter().handleException( new Exception("*** Downloaded data sucessfully ***")); } @@ -244,7 +251,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,11 +330,11 @@ public void downloadMediaFile(String mediaFileUrl) { } output.close(); this.statusMessage = "Downloaded " + filename; - ACRA.getErrorReporter().putCustomData("action", + if (!BuildConfig.DEBUG) ACRA.getErrorReporter().putCustomData("action", "downloadMedia:::" + filename); - ACRA.getErrorReporter() + if (!BuildConfig.DEBUG) ACRA.getErrorReporter() .putCustomData("urlString", mediaFileUrl); - ACRA.getErrorReporter().handleException( + if (!BuildConfig.DEBUG) ACRA.getErrorReporter().handleException( new Exception( "*** Downloaded media file sucessfully ***")); } else { diff --git a/src/com/github/opensourcefieldlinguistics/fielddb/service/RegisterUserService.java b/src/com/github/opensourcefieldlinguistics/fielddb/service/RegisterUserService.java index abbbacc..3ffa143 100644 --- a/src/com/github/opensourcefieldlinguistics/fielddb/service/RegisterUserService.java +++ b/src/com/github/opensourcefieldlinguistics/fielddb/service/RegisterUserService.java @@ -15,6 +15,7 @@ import com.github.opensourcefieldlinguistics.fielddb.database.FieldDBUserContentProvider; import com.github.opensourcefieldlinguistics.fielddb.lessons.Config; +import com.github.opensourcefieldlinguistics.fielddb.speech.kartuli.BuildConfig; import com.github.opensourcefieldlinguistics.fielddb.speech.kartuli.R; import com.google.gson.JsonObject; @@ -45,8 +46,8 @@ protected void onHandleIntent(Intent intent) { if (Config.D) { Log.d(Config.TAG, "Inside RegisterUserService intent"); } - ACRA.getErrorReporter().putCustomData("action", "registerUser:::"); - ACRA.getErrorReporter().putCustomData("urlString", + if (!BuildConfig.DEBUG) ACRA.getErrorReporter().putCustomData("action", "registerUser:::"); + if (!BuildConfig.DEBUG) ACRA.getErrorReporter().putCustomData("urlString", Config.DEFAULT_REGISTER_USER_URL); super.onHandleIntent(intent); @@ -54,7 +55,7 @@ protected void onHandleIntent(Intent intent) { if (!"".equals(this.userFriendlyErrorMessage)) { this.notifyUser(" " + this.userFriendlyErrorMessage, this.noti, this.notificationId, true); - ACRA.getErrorReporter().handleException( + if (!BuildConfig.DEBUG) ACRA.getErrorReporter().handleException( new Exception(this.userFriendlyErrorMessage)); return; } @@ -66,7 +67,7 @@ protected void onHandleIntent(Intent intent) { if (!"".equals(this.userFriendlyErrorMessage)) { this.notifyUser(" " + this.userFriendlyErrorMessage, this.noti, this.notificationId, true); - ACRA.getErrorReporter().handleException( + if (!BuildConfig.DEBUG) ACRA.getErrorReporter().handleException( new Exception(this.userFriendlyErrorMessage)); return; } @@ -75,7 +76,7 @@ protected void onHandleIntent(Intent intent) { if (!"".equals(this.userFriendlyErrorMessage)) { this.notifyUser(" " + this.userFriendlyErrorMessage, this.noti, this.notificationId, true); - ACRA.getErrorReporter().handleException( + if (!BuildConfig.DEBUG) ACRA.getErrorReporter().handleException( new Exception(this.userFriendlyErrorMessage)); return; } @@ -87,7 +88,7 @@ protected void onHandleIntent(Intent intent) { /* Success: remove the notification */ ((NotificationManager) getSystemService(NOTIFICATION_SERVICE)) .cancel(this.notificationId); - ACRA.getErrorReporter().handleException( + if (!BuildConfig.DEBUG) ACRA.getErrorReporter().handleException( new Exception("*** Registered user ssucessfully ***")); } @@ -197,7 +198,7 @@ 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; From 621854cd7b99897cd1ec6e04a5e2e7d2c1d26297 Mon Sep 17 00:00:00 2001 From: cesine Date: Fri, 13 Jun 2014 16:17:10 +0400 Subject: [PATCH 07/30] creating corpus directories in an app directory and playing instructions first is working --- res/layout/activity_welcome.xml | 54 +++++++ .../fielddb/FieldDBApplication.java | 53 ++++--- .../database/DatumContentProvider.java | 18 +-- .../fielddb/lessons/Config.java | 3 +- .../lessons/ui/DatumDetailFragment.java | 1 + .../lessons/ui/DatumFragmentPagerAdapter.java | 13 +- .../ui/DatumProductionExperimentFragment.java | 26 +++- .../fielddb/lessons/ui/ListenAndRepeat.java | 136 ++++++++++++++++++ .../fielddb/lessons/ui/WelcomeActivity.java | 35 +++++ .../fielddb/model/Datum.java | 4 +- 10 files changed, 296 insertions(+), 47 deletions(-) create mode 100644 res/layout/activity_welcome.xml create mode 100644 src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/ListenAndRepeat.java create mode 100644 src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/WelcomeActivity.java 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/src/com/github/opensourcefieldlinguistics/fielddb/FieldDBApplication.java b/src/com/github/opensourcefieldlinguistics/fielddb/FieldDBApplication.java index 2d36300..6d0d4d3 100644 --- a/src/com/github/opensourcefieldlinguistics/fielddb/FieldDBApplication.java +++ b/src/com/github/opensourcefieldlinguistics/fielddb/FieldDBApplication.java @@ -16,14 +16,14 @@ 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.speech.kartuli.BuildConfig; import com.github.opensourcefieldlinguistics.fielddb.speech.kartuli.R; import com.github.opensourcefieldlinguistics.fielddb.service.DownloadDatumsService; -import com.github.opensourcefieldlinguistics.fielddb.service.KartuliLegalSearchCorpusService; import com.github.opensourcefieldlinguistics.fielddb.service.KartuliSMSCorpusService; -import com.github.opensourcefieldlinguistics.fielddb.service.KartuliWebSearchCorpusService; import com.github.opensourcefieldlinguistics.fielddb.service.RegisterUserService; import android.app.Application; @@ -44,7 +44,7 @@ public class FieldDBApplication extends Application { public final void onCreate() { super.onCreate(); - (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); @@ -94,8 +94,8 @@ public final void onCreate() { ACRA.setConfig(config); - if (!BuildConfig.DEBUG) - ACRA.init(this); + if (!BuildConfig.DEBUG) + ACRA.init(this); // Get the user from the db String[] userProjection = {UserTable.COLUMN_ID, UserTable.COLUMN_REV, @@ -138,17 +138,25 @@ public final void onCreate() { mUser = new User(_id, _rev, username, firstname, lastname, email, gravatar, affiliation, researchInterest, description, subtitle, null, actualJSON); - if (!BuildConfig.DEBUG) ACRA.getErrorReporter().putCustomData("username", username); + if (!BuildConfig.DEBUG) + ACRA.getErrorReporter().putCustomData("username", username); } else { Log.e(Config.TAG, "There is no user... this is a problme the app wont work."); - if (!BuildConfig.DEBUG) 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); - if (!BuildConfig.DEBUG) ACRA.getErrorReporter().putCustomData("dbname", - Config.DEFAULT_CORPUS.replace("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.replace("username", username)); Log.d(Config.TAG, cursor.getString(cursor .getColumnIndexOrThrow(UserTable.COLUMN_USERNAME))); cursor.close(); @@ -165,19 +173,20 @@ public final void onCreate() { if (Config.APP_TYPE.equals("speechrec")) { Log.d(Config.TAG, "Not downloading samples, they are included in the training app"); - - Intent updateSMSSamples = new Intent(getApplicationContext(), - KartuliSMSCorpusService.class); - getApplicationContext().startService(updateSMSSamples); - - Intent updateWebSearchSamples = new Intent(getApplicationContext(), - KartuliWebSearchCorpusService.class); - getApplicationContext().startService(updateWebSearchSamples); - - Intent updateLegalSearchSamples = new Intent(getApplicationContext(), - KartuliLegalSearchCorpusService.class); - getApplicationContext().startService(updateLegalSearchSamples); - + + 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(), diff --git a/src/com/github/opensourcefieldlinguistics/fielddb/database/DatumContentProvider.java b/src/com/github/opensourcefieldlinguistics/fielddb/database/DatumContentProvider.java index c676792..0a4250f 100644 --- a/src/com/github/opensourcefieldlinguistics/fielddb/database/DatumContentProvider.java +++ b/src/com/github/opensourcefieldlinguistics/fielddb/database/DatumContentProvider.java @@ -197,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) { @@ -290,7 +289,7 @@ public static class DatumTable extends OPrimeTable { 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"); @@ -305,21 +304,12 @@ private static ContentValues sampleData() { values.put( COLUMN_UTTERANCE, "You need to read a few sentences to train the recognizer to your voice and your words."); - values.put( - COLUMN_MORPHEMES, - "You need to read a few sentences to train the recognizer to your voice and your words."); - values.put( - COLUMN_GLOSS, - "You need to read a few sentences to train the recognizer to your voice and your words."); - values.put( - COLUMN_TRANSLATION, - "You need to read a few sentences to train the recognizer to your voice and your words."); values.put( COLUMN_ORTHOGRAPHY, - "You need to read a few sentences to train the recognizer to your voice and your words."); + "შენ უნდა წაიკითხო რამოდენიმე წინადადება, რათა გადაამზადო აპლიკაცია შენს ხმაზე და შენს სიტყვებზე"); values.put( COLUMN_CONTEXT, - "Recognition in the Georgian language is too complex to do with yout being speaker specific."); + "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/lessons/Config.java b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/Config.java index bc91f81..a3170d1 100644 --- a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/Config.java +++ b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/Config.java @@ -16,7 +16,8 @@ public class Config extends ca.ilanguage.oprime.Config { + "/_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/" + 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; diff --git a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumDetailFragment.java b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumDetailFragment.java index ab43606..2128caa 100644 --- a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumDetailFragment.java +++ b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumDetailFragment.java @@ -126,6 +126,7 @@ public void onCreate(Bundle savedInstanceState) { .getColumnIndexOrThrow(DatumTable.COLUMN_TRANSLATION)), cursor.getString(cursor .getColumnIndexOrThrow(DatumTable.COLUMN_CONTEXT))); + datum.setId(id); datum.addMediaFiles(cursor.getString(cursor .getColumnIndexOrThrow(DatumTable.COLUMN_IMAGE_FILES))); datum.addMediaFiles((cursor.getString(cursor diff --git a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumFragmentPagerAdapter.java b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumFragmentPagerAdapter.java index 99cbf2c..fa9aa5e 100644 --- a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumFragmentPagerAdapter.java +++ b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumFragmentPagerAdapter.java @@ -13,6 +13,7 @@ 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; @@ -27,24 +28,29 @@ public DatumFragmentPagerAdapter(FragmentManager fm) { public void swapCursor(Cursor cursor) { this.mDatumsIds = new ArrayList(); + this.mDatumsIds.add("instructions"); if (cursor != null && cursor.getCount() > 0) { cursor.moveToFirst(); while (cursor.moveToNext()) { - this.mDatumsIds.add(cursor.getString(cursor - .getColumnIndexOrThrow(UserTable.COLUMN_ID))); + 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 = "sms1"; + String id = "instructions"; if (mDatumsIds.size() > position) { id = mDatumsIds.get(position); } @@ -57,6 +63,7 @@ public Fragment getItem(int position) { } 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); diff --git a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumProductionExperimentFragment.java b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumProductionExperimentFragment.java index eef1891..f1db851 100644 --- a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumProductionExperimentFragment.java +++ b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumProductionExperimentFragment.java @@ -5,6 +5,8 @@ import android.os.Handler; 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; @@ -16,7 +18,11 @@ public class DatumProductionExperimentFragment extends DatumDetailFragment { private int mAudioPromptResource; - + private boolean isInstructions = false; + @Override + public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { + //no menu + } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { @@ -45,10 +51,18 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, mImageView.setImageResource(R.drawable.legal_search_selected); } else if (tags.contains("SMS")) { mImageView.setImageResource(R.drawable.sms_selected); + } else { + mImageView.setImageResource(R.drawable.instructions); } - - if ("instructions".equals(mItem.getId())) { + String id = mItem.getId(); + Log.d(Config.TAG, "Prompt for this datum will be " + id); + if ("instructions".equals(id)) { + this.isInstructions = 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; } @@ -86,7 +100,9 @@ public void onCompletion(MediaPlayer mp) { Runnable myRunnable = new Runnable() { @Override public void run() { - toggleAudioRecording(null); + if(!isInstructions){ + toggleAudioRecording(null); + } } }; mainHandler.post(myRunnable); @@ -109,7 +125,7 @@ public void onPrepared(MediaPlayer mp) { } }); - if (mSpeechRecognizerInstructions != null) { + if (mSpeechRecognizerInstructions != null && !isInstructions ) { mSpeechRecognizerInstructions.setText("Speak now"); } } 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/WelcomeActivity.java b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/WelcomeActivity.java new file mode 100644 index 0000000..af6d9c7 --- /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, + ProductionExperimentViewPagerFragmentActivity.class); + startActivity(openTrainer); + } + + public void onRecognizeClick(View view) { + Intent openRecognizer = new Intent(this, ListenAndRepeat.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 505e4bb..7bd3ac7 100644 --- a/src/com/github/opensourcefieldlinguistics/fielddb/model/Datum.java +++ b/src/com/github/opensourcefieldlinguistics/fielddb/model/Datum.java @@ -76,7 +76,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); @@ -96,7 +96,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); From 9f991fed9b66b1da4ce404e5daa420ac2e85c0f9 Mon Sep 17 00:00:00 2001 From: cesine Date: Fri, 13 Jun 2014 18:05:52 +0400 Subject: [PATCH 08/30] auto advancing between stimuli/cards fixes https://github.com/OpenSourceFieldlinguistics/FieldDB/issues/1538 --- .../lessons/ui/DatumDetailFragment.java | 42 ++++++++++++++++--- .../lessons/ui/DatumFragmentPagerAdapter.java | 2 + .../ui/DatumProductionExperimentFragment.java | 38 ++++++++++------- ...onExperimentViewPagerFragmentActivity.java | 1 + 4 files changed, 62 insertions(+), 21 deletions(-) diff --git a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumDetailFragment.java b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumDetailFragment.java index 2128caa..a5e0511 100644 --- a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumDetailFragment.java +++ b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumDetailFragment.java @@ -22,6 +22,7 @@ import android.os.Bundle; 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; @@ -61,6 +62,8 @@ 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. */ @@ -80,13 +83,17 @@ public DatumDetailFragment() { protected VideoView mVideoView; protected ImageView mImageView; protected MediaController mMediaController; - MediaPlayer mAudioPlayer; + protected MediaPlayer mAudioPlayer; protected DeviceDetails mDeviceDetails; protected HashMap mDatumEditCounts; protected ImageButton mSpeechRecognizerFeedback; protected TextView mSpeechRecognizerInstructions; protected boolean isPlaying = false; + protected ViewPager mDatumPager; + + private int mLastDatumIndex; + @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -98,15 +105,17 @@ public void onCreate(Bundle savedInstanceState) { 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_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, @@ -127,6 +136,8 @@ public void onCreate(Bundle savedInstanceState) { 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 @@ -344,6 +355,8 @@ public void onClick(View v) { mSpeechRecognizerInstructions.setText(""); } + this.mDatumPager = (ViewPager) getActivity().findViewById( + R.id.viewpager); } @Override @@ -443,7 +456,26 @@ public boolean toggleAudioRecording(MenuItem item) { } if (mSpeechRecognizerInstructions != null) { - mSpeechRecognizerInstructions.setText("Tap to speak"); + mSpeechRecognizerInstructions.setText("Tap to speak again"); + } + if (Config.APP_TYPE.equals("speechrec")) { + autoAdvanceAfterRecordingAudio(); + } + + } + return true; + } + + protected boolean autoAdvanceAfterRecordingAudio() { + if (this.mDatumPager != null) { + int currentStimulusIndex = this.mDatumPager.getCurrentItem(); + if (currentStimulusIndex == this.mLastDatumIndex) { + Intent openTrainer = new Intent(getActivity(), + DatumListActivity.class); + startActivity(openTrainer); + } else { + this.mDatumPager.setCurrentItem(this.mDatumPager + .getCurrentItem() + 1); } } return true; diff --git a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumFragmentPagerAdapter.java b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumFragmentPagerAdapter.java index fa9aa5e..6cb087c 100644 --- a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumFragmentPagerAdapter.java +++ b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumFragmentPagerAdapter.java @@ -67,6 +67,8 @@ public Fragment getItem(int position) { 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); diff --git a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumProductionExperimentFragment.java b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumProductionExperimentFragment.java index f1db851..948a9f2 100644 --- a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumProductionExperimentFragment.java +++ b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumProductionExperimentFragment.java @@ -18,10 +18,12 @@ public class DatumProductionExperimentFragment extends DatumDetailFragment { private int mAudioPromptResource; - private boolean isInstructions = false; + private boolean mIsInstructions = false; + private long WAIT_TO_RECORD_AFTER_PROMPT_START = 300; + @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { - //no menu + // no menu } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, @@ -57,7 +59,7 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, String id = mItem.getId(); Log.d(Config.TAG, "Prompt for this datum will be " + id); if ("instructions".equals(id)) { - this.isInstructions = true; + this.mIsInstructions = true; mAudioPromptResource = R.raw.instructions; mImageView.setImageResource(R.drawable.instructions); mSpeechRecognizerFeedback.setVisibility(View.GONE); @@ -95,17 +97,6 @@ protected void playPromptContext() { @Override public void onCompletion(MediaPlayer mp) { - Handler mainHandler = new Handler(getActivity() - .getMainLooper()); - Runnable myRunnable = new Runnable() { - @Override - public void run() { - if(!isInstructions){ - toggleAudioRecording(null); - } - } - }; - mainHandler.post(myRunnable); mp.release(); } }); @@ -125,10 +116,25 @@ public void onPrepared(MediaPlayer mp) { } }); - if (mSpeechRecognizerInstructions != null && !isInstructions ) { - mSpeechRecognizerInstructions.setText("Speak now"); + 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); } } diff --git a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/ProductionExperimentViewPagerFragmentActivity.java b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/ProductionExperimentViewPagerFragmentActivity.java index e8b4288..f73771d 100644 --- a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/ProductionExperimentViewPagerFragmentActivity.java +++ b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/ProductionExperimentViewPagerFragmentActivity.java @@ -18,6 +18,7 @@ public class ProductionExperimentViewPagerFragmentActivity extends FragmentActivity implements LoaderManager.LoaderCallbacks { + private DatumFragmentPagerAdapter mPagerAdapter; @Override From cd1f0047c6412c7970204085a5456ce5aa662b4a Mon Sep 17 00:00:00 2001 From: cesine Date: Fri, 13 Jun 2014 18:49:58 +0400 Subject: [PATCH 09/30] added a confirm dialog if users want to add their own words --- .../lessons/ui/DatumDetailFragment.java | 12 ++-- .../ui/DatumProductionExperimentFragment.java | 60 +++++++++++++++++-- 2 files changed, 61 insertions(+), 11 deletions(-) diff --git a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumDetailFragment.java b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumDetailFragment.java index a5e0511..b112808 100644 --- a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumDetailFragment.java +++ b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumDetailFragment.java @@ -1,7 +1,6 @@ package com.github.opensourcefieldlinguistics.fielddb.lessons.ui; import java.io.File; -import java.io.IOException; import java.util.HashMap; import java.util.Iterator; import java.util.Map; @@ -78,7 +77,6 @@ public class DatumDetailFragment extends Fragment { public DatumDetailFragment() { } - protected String TAG = "FieldDB"; protected boolean mRecordingAudio = false; protected VideoView mVideoView; protected ImageView mImageView; @@ -92,7 +90,7 @@ public DatumDetailFragment() { protected ViewPager mDatumPager; - private int mLastDatumIndex; + protected int mLastDatumIndex; @Override public void onCreate(Bundle savedInstanceState) { @@ -100,7 +98,7 @@ 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)) { @@ -425,7 +423,7 @@ public boolean toggleAudioRecording(MenuItem item) { values.put(DatumTable.COLUMN_AUDIO_VIDEO_FILES, mItem.getMediaFilesAsCSV(mItem.getAudioVideoFiles())); getActivity().getContentResolver().update(mUri, values, null, null); - Log.d(TAG, "Recording audio " + audioFileName); + Log.d(Config.TAG, "Recording audio " + audioFileName); this.mRecordingAudio = true; if (item != null) { item.setIcon(R.drawable.ic_action_stop); @@ -470,9 +468,9 @@ protected boolean autoAdvanceAfterRecordingAudio() { if (this.mDatumPager != null) { int currentStimulusIndex = this.mDatumPager.getCurrentItem(); if (currentStimulusIndex == this.mLastDatumIndex) { - Intent openTrainer = new Intent(getActivity(), + Intent openDataList = new Intent(getActivity(), DatumListActivity.class); - startActivity(openTrainer); + startActivity(openDataList); } else { this.mDatumPager.setCurrentItem(this.mDatumPager .getCurrentItem() + 1); diff --git a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumProductionExperimentFragment.java b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumProductionExperimentFragment.java index 948a9f2..173cdaf 100644 --- a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumProductionExperimentFragment.java +++ b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumProductionExperimentFragment.java @@ -1,8 +1,13 @@ 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; @@ -19,7 +24,7 @@ public class DatumProductionExperimentFragment extends DatumDetailFragment { private int mAudioPromptResource; private boolean mIsInstructions = false; - private long WAIT_TO_RECORD_AFTER_PROMPT_START = 300; + private long WAIT_TO_RECORD_AFTER_PROMPT_START = 400; @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { @@ -53,9 +58,8 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, mImageView.setImageResource(R.drawable.legal_search_selected); } else if (tags.contains("SMS")) { mImageView.setImageResource(R.drawable.sms_selected); - } else { - mImageView.setImageResource(R.drawable.instructions); - } + } + String id = mItem.getId(); Log.d(Config.TAG, "Prompt for this datum will be " + id); if ("instructions".equals(id)) { @@ -98,6 +102,9 @@ protected void playPromptContext() { @Override public void onCompletion(MediaPlayer mp) { mp.release(); + if (mIsInstructions) { + autoAdvanceAfterRecordingAudio(); + } } }); mAudioPlayer @@ -137,4 +144,49 @@ public void run() { 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(), + ListenAndRepeat.class); + startActivity(openRecognizer); + } + }); + return builder.create(); + } + } } From ac5849069989c7a25793890d723b2c1a12a75b7a Mon Sep 17 00:00:00 2001 From: cesine Date: Fri, 13 Jun 2014 19:57:20 +0400 Subject: [PATCH 10/30] adding a high res version of the speech bubbles for backgroun dimage --- res/drawable/speech_bubbles.png | Bin 0 -> 15085 bytes res/layout/fragment_datum_detail.xml | 15 +++++++++++++-- 2 files changed, 13 insertions(+), 2 deletions(-) create mode 100644 res/drawable/speech_bubbles.png diff --git a/res/drawable/speech_bubbles.png b/res/drawable/speech_bubbles.png new file mode 100644 index 0000000000000000000000000000000000000000..143f45df0e2dd0a1da73c40de34c1d557ba2c89b GIT binary patch literal 15085 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 + + From c5808152d71bf469d61f6407581be14db163957a Mon Sep 17 00:00:00 2001 From: cesine Date: Fri, 13 Jun 2014 19:58:13 +0400 Subject: [PATCH 11/30] aded a simple datum view for non-linguists fixes https://github.com/OpenSourceFieldlinguistics/FieldDB/issues/1539 --- res/layout/fragment_datum_detail_simple.xml | 90 +++++++++++++++++++ .../lessons/ui/DatumDetailFragment.java | 41 ++++++++- 2 files changed, 130 insertions(+), 1 deletion(-) create mode 100644 res/layout/fragment_datum_detail_simple.xml diff --git a/res/layout/fragment_datum_detail_simple.xml b/res/layout/fragment_datum_detail_simple.xml new file mode 100644 index 0000000..562bbf3 --- /dev/null +++ b/res/layout/fragment_datum_detail_simple.xml @@ -0,0 +1,90 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumDetailFragment.java b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumDetailFragment.java index b112808..dc6d68d 100644 --- a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumDetailFragment.java +++ b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumDetailFragment.java @@ -161,6 +161,10 @@ 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("speechrec")) { + rootView = inflater.inflate(R.layout.fragment_datum_detail_simple, + container, false); + } if (mItem != null) { this.prepareEditTextListeners(rootView); @@ -306,7 +310,36 @@ 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"); + } + }); + } + + 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"); } }); } @@ -606,6 +639,12 @@ 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(), From ef0fcf6bfd35fdee730228fb2ccc9fb4f255e694 Mon Sep 17 00:00:00 2001 From: cesine Date: Fri, 13 Jun 2014 19:58:53 +0400 Subject: [PATCH 12/30] putting default datum list back to using the datum views not a view pager --- .../fielddb/lessons/ui/DatumDetailActivity.java | 3 --- .../fielddb/lessons/ui/DatumFragmentPagerAdapter.java | 8 ++++---- .../fielddb/lessons/ui/DatumListActivity.java | 3 --- 3 files changed, 4 insertions(+), 10 deletions(-) diff --git a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumDetailActivity.java b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumDetailActivity.java index 630522e..5ea5793 100644 --- a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumDetailActivity.java +++ b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumDetailActivity.java @@ -43,9 +43,6 @@ protected void onCreate(Bundle savedInstanceState) { arguments.putString(DatumDetailFragment.ARG_ITEM_ID, getIntent() .getStringExtra(DatumDetailFragment.ARG_ITEM_ID)); DatumDetailFragment fragment = new DatumDetailFragment(); - if (Config.APP_TYPE.equals("speechrec")) { - fragment = new DatumProductionExperimentFragment(); - } fragment.setArguments(arguments); getSupportFragmentManager().beginTransaction() .add(R.id.datum_detail_container, fragment).commit(); diff --git a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumFragmentPagerAdapter.java b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumFragmentPagerAdapter.java index 6cb087c..aed3e0a 100644 --- a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumFragmentPagerAdapter.java +++ b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumFragmentPagerAdapter.java @@ -55,11 +55,11 @@ public Fragment getItem(int position) { id = mDatumsIds.get(position); } Bundle arguments = new Bundle(); - DatumProductionExperimentFragment fragment = new DatumProductionExperimentFragment(); + DatumDetailFragment fragment = new DatumProductionExperimentFragment(); if (Config.APP_TYPE.equals("speechrec")) { - fragment = new DatumProductionExperimentFragment(); +// fragment = new DatumProductionExperimentFragment(); } else { - // fragment = new DatumDetailFragment(); + fragment = new DatumDetailFragment(); } mVisibleDatumUri = Uri.parse(DatumContentProvider.CONTENT_URI + "/" + id); @@ -72,7 +72,7 @@ public Fragment getItem(int position) { fragment.mTwoPane = false; fragment.setArguments(arguments); - if (mFragments.size() == position) { + if (mFragments.size() == position ||mFragments.size() < position) { mFragments.add(fragment); } else { mFragments.set(position, fragment); diff --git a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumListActivity.java b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumListActivity.java index 1416bb9..dcb638d 100644 --- a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumListActivity.java +++ b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumListActivity.java @@ -76,9 +76,6 @@ public void onItemSelected(String id) { // adding or replacing the detail fragment using a // fragment transaction. DatumDetailFragment fragment = new DatumDetailFragment(); - if (Config.APP_TYPE.equals("speechrec")) { - fragment = new DatumProductionExperimentFragment(); - } fragment.mTwoPane = mTwoPane; fragment.setArguments(arguments); FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); From 66edfbf70164f5394cbd16de9a8f22c4e89b051f Mon Sep 17 00:00:00 2001 From: cesine Date: Fri, 13 Jun 2014 22:54:36 +0400 Subject: [PATCH 13/30] added audio upload for https://github.com/OpenSourceFieldlinguistics/FieldDB/issues/1437 --- AndroidManifest.xml | 2 + .../fielddb/FieldDBApplication.java | 2 + .../fielddb/lessons/Config.java | 3 + .../lessons/PrivateConstantsSample.java | 1 + .../lessons/ui/DatumDetailFragment.java | 23 ++ .../service/UploadAudioVideoService.java | 220 ++++++++++++++++++ 6 files changed, 251 insertions(+) create mode 100644 src/com/github/opensourcefieldlinguistics/fielddb/service/UploadAudioVideoService.java diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 80daef6..1cac71f 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -87,6 +87,8 @@ + + diff --git a/src/com/github/opensourcefieldlinguistics/fielddb/FieldDBApplication.java b/src/com/github/opensourcefieldlinguistics/fielddb/FieldDBApplication.java index 6d0d4d3..2ffd9a3 100644 --- a/src/com/github/opensourcefieldlinguistics/fielddb/FieldDBApplication.java +++ b/src/com/github/opensourcefieldlinguistics/fielddb/FieldDBApplication.java @@ -140,6 +140,7 @@ public final void onCreate() { subtitle, null, actualJSON); 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."); @@ -149,6 +150,7 @@ public final void onCreate() { /* 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; diff --git a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/Config.java b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/Config.java index a3170d1..106c458 100644 --- a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/Config.java +++ b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/Config.java @@ -12,6 +12,7 @@ public class Config extends ca.ilanguage.oprime.Config { 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; @@ -21,7 +22,9 @@ public class Config extends ca.ilanguage.oprime.Config { + 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"; 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/DatumDetailFragment.java b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumDetailFragment.java index dc6d68d..0aad0b2 100644 --- a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumDetailFragment.java +++ b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumDetailFragment.java @@ -19,6 +19,7 @@ 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; @@ -43,8 +44,11 @@ import ca.ilanguage.oprime.model.DeviceDetails; 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.service.RegisterUserService; +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; @@ -92,6 +96,8 @@ public DatumDetailFragment() { protected int mLastDatumIndex; + private String mAudioFileName; + @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -446,6 +452,7 @@ 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); @@ -475,6 +482,22 @@ public boolean toggleAudioRecording(MenuItem item) { } else { Intent audio = new Intent(getActivity(), AudioRecorder.class); getActivity().stopService(audio); + + Handler mainHandler = new Handler(getActivity().getMainLooper()); + Runnable launchUploadAudioService = new Runnable() { + + @Override + public void run() { + Intent uploadAudioFile = new Intent(getActivity(), + UploadAudioVideoService.class); + uploadAudioFile.setData(Uri.parse(mAudioFileName)); + uploadAudioFile.putExtra(Config.EXTRA_PARTICIPANT_ID, + Config.CURRENT_USERNAME); + getActivity().startService(uploadAudioFile); + } + }; + mainHandler.postDelayed(launchUploadAudioService, 1000); + this.mRecordingAudio = false; if (item != null) { item.setIcon(R.drawable.ic_action_mic); 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..42f55cf --- /dev/null +++ b/src/com/github/opensourcefieldlinguistics/fielddb/service/UploadAudioVideoService.java @@ -0,0 +1,220 @@ +package com.github.opensourcefieldlinguistics.fielddb.service; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; + +import org.acra.ACRA; +import org.apache.http.HttpEntity; +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.entity.mime.HttpMultipartMode; +import org.apache.http.entity.mime.MultipartEntityBuilder; +import org.apache.http.entity.mime.content.FileBody; +import org.apache.http.impl.client.DefaultHttpClient; + +import ca.ilanguage.oprime.datacollection.NotifyingIntentService; + +import com.github.opensourcefieldlinguistics.fielddb.lessons.Config; +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 username = "default"; + public UploadAudioVideoService(String name) { + super(name); + } + + public UploadAudioVideoService() { + super("UploadAudioVideoService"); + } + + @Override + protected void onHandleIntent(Intent intent) { + + /* 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)) { + username = intent.getExtras() + .getString(Config.EXTRA_PARTICIPANT_ID); + } + + 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("*** Uploadinged user ssucessfully ***")); + } + + public String upload(Uri uri) { + String filePath = uri.getPath(); + this.statusMessage = "Uploading audio " + uri.getLastPathSegment(); + if (!BuildConfig.DEBUG) + ACRA.getErrorReporter().putCustomData("registerUser", + uri.getLastPathSegment()); + String urlStringAuthenticationSession = Config.DEFAULT_UPLOAD_AUDIO_VIDEO_URL; + + // http://stackoverflow.com/questions/18964288/upload-a-file-through-an-http-form-via-multipartentitybuilder-with-a-progress + HttpClient client = new DefaultHttpClient(); + HttpPost post = new HttpPost(urlStringAuthenticationSession); + MultipartEntityBuilder builder = MultipartEntityBuilder.create(); + builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE); + builder.addPart("file", new FileBody(new File(filePath))); + builder.addTextBody("userName", username); + builder.addTextBody("token", Config.DEFAULT_UPLOAD_TOKEN); + builder.addTextBody("dbname", Config.DEFAULT_CORPUS); + builder.addTextBody("returnTextGrid", "true"); + + post.setEntity(builder.build()); + HttpResponse response; + String JSONResponse = ""; + try { + response = client.execute(post); + HttpEntity entity = response.getEntity(); + int status = response.getStatusLine().getStatusCode(); + if (status >= 500) { + this.userFriendlyErrorMessage = "Server error, please report this error."; + } else if (status >= 400) { + this.userFriendlyErrorMessage = "Something was wrong with this file. It could not be processed."; + } else { + JSONResponse = ""; + 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); + + } + entity.consumeContent(); + client.getConnectionManager().shutdown(); + } 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 reading sample data from server"; + return null; + } + + if (!"".equals(this.userFriendlyErrorMessage)) { + return null; + } + return JSONResponse; + } + public int processUploadResponse(Uri uri, String jsonResponse) { + JsonObject json = (JsonObject) NotifyingIntentService.jsonParser + .parse(jsonResponse); + if (json.has("userFriendlyErrors")) { + this.userFriendlyErrorMessage = json.get("userFriendlyErrors") + .getAsString(); + return 0; + } + if (!json.has("user")) { + this.userFriendlyErrorMessage = "The server response is very strange, please report this."; + return 0; + } + + return 0; + } +} From bb7e9bfaf5757fa1ebdd86060e9792772a69ec1e Mon Sep 17 00:00:00 2001 From: cesine Date: Fri, 13 Jun 2014 22:56:09 +0400 Subject: [PATCH 14/30] checking if the cursor is null --- .../fielddb/service/RegisterUserService.java | 36 ++++++++++++------- 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/src/com/github/opensourcefieldlinguistics/fielddb/service/RegisterUserService.java b/src/com/github/opensourcefieldlinguistics/fielddb/service/RegisterUserService.java index 3ffa143..64f5186 100644 --- a/src/com/github/opensourcefieldlinguistics/fielddb/service/RegisterUserService.java +++ b/src/com/github/opensourcefieldlinguistics/fielddb/service/RegisterUserService.java @@ -46,17 +46,20 @@ protected void onHandleIntent(Intent intent) { if (Config.D) { Log.d(Config.TAG, "Inside RegisterUserService intent"); } - if (!BuildConfig.DEBUG) ACRA.getErrorReporter().putCustomData("action", "registerUser:::"); - if (!BuildConfig.DEBUG) 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); - if (!BuildConfig.DEBUG) ACRA.getErrorReporter().handleException( - new Exception(this.userFriendlyErrorMessage)); + if (!BuildConfig.DEBUG) + ACRA.getErrorReporter().handleException( + new Exception(this.userFriendlyErrorMessage)); return; } @@ -67,8 +70,9 @@ protected void onHandleIntent(Intent intent) { if (!"".equals(this.userFriendlyErrorMessage)) { this.notifyUser(" " + this.userFriendlyErrorMessage, this.noti, this.notificationId, true); - if (!BuildConfig.DEBUG) ACRA.getErrorReporter().handleException( - new Exception(this.userFriendlyErrorMessage)); + if (!BuildConfig.DEBUG) + ACRA.getErrorReporter().handleException( + new Exception(this.userFriendlyErrorMessage)); return; } @@ -76,8 +80,9 @@ protected void onHandleIntent(Intent intent) { if (!"".equals(this.userFriendlyErrorMessage)) { this.notifyUser(" " + this.userFriendlyErrorMessage, this.noti, this.notificationId, true); - if (!BuildConfig.DEBUG) ACRA.getErrorReporter().handleException( - new Exception(this.userFriendlyErrorMessage)); + if (!BuildConfig.DEBUG) + ACRA.getErrorReporter().handleException( + new Exception(this.userFriendlyErrorMessage)); return; } @@ -88,8 +93,9 @@ protected void onHandleIntent(Intent intent) { /* Success: remove the notification */ ((NotificationManager) getSystemService(NOTIFICATION_SERVICE)) .cancel(this.notificationId); - if (!BuildConfig.DEBUG) 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) { @@ -153,6 +159,11 @@ public String registerUsers(Uri 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, @@ -198,7 +209,8 @@ public String registerUsers(Uri uri) { cursor.close(); this.statusMessage = "Registering user " + username; - if (!BuildConfig.DEBUG) ACRA.getErrorReporter().putCustomData("registerUser", username); + if (!BuildConfig.DEBUG) + ACRA.getErrorReporter().putCustomData("registerUser", username); String urlStringAuthenticationSession = Config.DEFAULT_REGISTER_USER_URL; URL url; HttpURLConnection urlConnection; From 2052c3ff8c58efa967a2e2022bc1cdb54b2ec56a Mon Sep 17 00:00:00 2001 From: cesine Date: Fri, 13 Jun 2014 23:48:13 +0400 Subject: [PATCH 15/30] adding bouncy castle but not upload not working yet --- .../service/UploadAudioVideoService.java | 151 +++++++++++++----- 1 file changed, 112 insertions(+), 39 deletions(-) diff --git a/src/com/github/opensourcefieldlinguistics/fielddb/service/UploadAudioVideoService.java b/src/com/github/opensourcefieldlinguistics/fielddb/service/UploadAudioVideoService.java index 42f55cf..1e19de7 100644 --- a/src/com/github/opensourcefieldlinguistics/fielddb/service/UploadAudioVideoService.java +++ b/src/com/github/opensourcefieldlinguistics/fielddb/service/UploadAudioVideoService.java @@ -3,22 +3,35 @@ 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.HttpEntity; 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.MultipartEntityBuilder; +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; @@ -145,45 +158,56 @@ public String upload(Uri uri) { uri.getLastPathSegment()); String urlStringAuthenticationSession = Config.DEFAULT_UPLOAD_AUDIO_VIDEO_URL; - // http://stackoverflow.com/questions/18964288/upload-a-file-through-an-http-form-via-multipartentitybuilder-with-a-progress - HttpClient client = new DefaultHttpClient(); - HttpPost post = new HttpPost(urlStringAuthenticationSession); - MultipartEntityBuilder builder = MultipartEntityBuilder.create(); - builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE); - builder.addPart("file", new FileBody(new File(filePath))); - builder.addTextBody("userName", username); - builder.addTextBody("token", Config.DEFAULT_UPLOAD_TOKEN); - builder.addTextBody("dbname", Config.DEFAULT_CORPUS); - builder.addTextBody("returnTextGrid", "true"); - - post.setEntity(builder.build()); - HttpResponse response; + /* 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("file", 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(username, "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 { - response = client.execute(post); - HttpEntity entity = response.getEntity(); - int status = response.getStatusLine().getStatusCode(); - if (status >= 500) { - this.userFriendlyErrorMessage = "Server error, please report this error."; - } else if (status >= 400) { - this.userFriendlyErrorMessage = "Something was wrong with this file. It could not be processed."; - } else { - JSONResponse = ""; - 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); + 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); - } - entity.consumeContent(); - client.getConnectionManager().shutdown(); } catch (ClientProtocolException e1) { this.userFriendlyErrorMessage = "Problem using POST, please report this error."; e1.printStackTrace(); @@ -193,7 +217,7 @@ public String upload(Uri uri) { } if ("".equals(JSONResponse)) { - this.userFriendlyErrorMessage = "Unknown error reading sample data from server"; + this.userFriendlyErrorMessage = "Unknown error uploading data to server"; return null; } @@ -202,6 +226,55 @@ public String upload(Uri uri) { } 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) { JsonObject json = (JsonObject) NotifyingIntentService.jsonParser .parse(jsonResponse); From 6f47e879530a270ea9b4d743fe933fd8d0e33981 Mon Sep 17 00:00:00 2001 From: cesine Date: Sat, 14 Jun 2014 11:48:37 +0400 Subject: [PATCH 16/30] uplaod is working including device details in the activity log for speech recognition information --- .../lessons/ui/DatumDetailFragment.java | 11 +++-- .../fielddb/service/RegisterUserService.java | 2 +- .../service/UploadAudioVideoService.java | 41 ++++++++++++++----- 3 files changed, 37 insertions(+), 17 deletions(-) diff --git a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumDetailFragment.java b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumDetailFragment.java index 0aad0b2..e0ae4dc 100644 --- a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumDetailFragment.java +++ b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumDetailFragment.java @@ -44,10 +44,8 @@ import ca.ilanguage.oprime.model.DeviceDetails; 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.service.RegisterUserService; import com.github.opensourcefieldlinguistics.fielddb.service.UploadAudioVideoService; import com.github.opensourcefieldlinguistics.fielddb.speech.kartuli.BuildConfig; import com.github.opensourcefieldlinguistics.fielddb.speech.kartuli.R; @@ -493,6 +491,9 @@ public void run() { 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); } }; @@ -812,17 +813,15 @@ protected void recordUserEvent(String eventType, String eventValue) { this.mDatumEditCounts.put(eventValue, count); return; } - if (!BuildConfig.DEBUG) + if (!BuildConfig.DEBUG) { ACRA.getErrorReporter().putCustomData("action", "{" + eventType + " : " + eventValue + "}"); - if (!BuildConfig.DEBUG) ACRA.getErrorReporter().putCustomData("androidTimestamp", System.currentTimeMillis() + ""); - if (!BuildConfig.DEBUG) ACRA.getErrorReporter().putCustomData("deviceDetails", this.mDeviceDetails.getCurrentDeviceDetails()); - if (!BuildConfig.DEBUG) ACRA.getErrorReporter().handleException( new Exception("*** User event " + eventType + " ***")); + } } } diff --git a/src/com/github/opensourcefieldlinguistics/fielddb/service/RegisterUserService.java b/src/com/github/opensourcefieldlinguistics/fielddb/service/RegisterUserService.java index 64f5186..2186183 100644 --- a/src/com/github/opensourcefieldlinguistics/fielddb/service/RegisterUserService.java +++ b/src/com/github/opensourcefieldlinguistics/fielddb/service/RegisterUserService.java @@ -278,7 +278,7 @@ public String registerUsers(Uri uri) { } String JSONResponse = this.processResponse(url, urlConnection); if (JSONResponse == null) { - this.userFriendlyErrorMessage = "Unknown error reading sample data from server"; + this.userFriendlyErrorMessage = "Unknown error registering user"; return null; } if (JSONResponse.contains("name already exists")) { diff --git a/src/com/github/opensourcefieldlinguistics/fielddb/service/UploadAudioVideoService.java b/src/com/github/opensourcefieldlinguistics/fielddb/service/UploadAudioVideoService.java index 1e19de7..6c3964d 100644 --- a/src/com/github/opensourcefieldlinguistics/fielddb/service/UploadAudioVideoService.java +++ b/src/com/github/opensourcefieldlinguistics/fielddb/service/UploadAudioVideoService.java @@ -45,8 +45,8 @@ import android.util.Log; public class UploadAudioVideoService extends NotifyingIntentService { - - protected String username = "default"; + protected String mDeviceDetails = "{}"; + protected String mUsername = "default"; public UploadAudioVideoService(String name) { super(name); } @@ -111,8 +111,12 @@ protected void onHandleIntent(Intent intent) { } if (intent.hasExtra(Config.EXTRA_PARTICIPANT_ID)) { - username = intent.getExtras() - .getString(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()); @@ -147,7 +151,8 @@ protected void onHandleIntent(Intent intent) { .cancel(this.notificationId); if (!BuildConfig.DEBUG) ACRA.getErrorReporter().handleException( - new Exception("*** Uploadinged user ssucessfully ***")); + new Exception("*** Uploaded audio sucessfully ***")); + } public String upload(Uri uri) { @@ -172,12 +177,12 @@ public String upload(Uri uri) { try { - entity.addPart("file", new FileBody(new File(filePath))); + 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(username, "text/plain", + entity.addPart("username", new StringBody(mUsername, "text/plain", Charset.forName("UTF-8"))); entity.addPart("dbname", new StringBody(Config.DEFAULT_CORPUS, @@ -259,8 +264,8 @@ protected ClientConnectionManager createClientConnectionManager() { 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); + sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); + // sf.setHostnameVerifier(SSLSocketFactory.STRICT_HOSTNAME_VERIFIER); SchemeRegistry registry = new SchemeRegistry(); registry.register(new Scheme("http", PlainSocketFactory @@ -276,6 +281,9 @@ protected ClientConnectionManager createClientConnectionManager() { } 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")) { @@ -283,9 +291,22 @@ public int processUploadResponse(Uri uri, String jsonResponse) { .getAsString(); return 0; } - if (!json.has("user")) { + 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; From 31605e56b2c817fce33cb0c60ec2d63347bfba8e Mon Sep 17 00:00:00 2001 From: cesine Date: Sat, 14 Jun 2014 12:21:45 +0400 Subject: [PATCH 17/30] deployed v2.4.0 fixes https://github.com/OpenSourceFieldlinguistics/FieldDB/issues/1540 fixes https://github.com/batumi/KartuliPocketSphinx/issues/7 --- .../opensourcefieldlinguistics/fielddb/lessons/Config.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/Config.java b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/Config.java index 106c458..95ded08 100644 --- a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/Config.java +++ b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/Config.java @@ -1,7 +1,7 @@ package com.github.opensourcefieldlinguistics.fielddb.lessons; public class Config extends ca.ilanguage.oprime.Config { - public static final boolean D = true; + public static final boolean D = false; public static final String ACRA_PASS = PrivateConstants.ACRA_PASS; public static final String ACRA_SERVER_URL = PrivateConstants.ACRA_SERVER_URL; public static final String ACRA_USER = PrivateConstants.ACRA_USER; From a187c9d867ac893f4234d312e58cb6ab5aca4124 Mon Sep 17 00:00:00 2001 From: cesine Date: Sat, 14 Jun 2014 13:46:33 +0400 Subject: [PATCH 18/30] downloading samples was on for the speechrec app --- .../fielddb/database/DatumContentProvider.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/com/github/opensourcefieldlinguistics/fielddb/database/DatumContentProvider.java b/src/com/github/opensourcefieldlinguistics/fielddb/database/DatumContentProvider.java index 0a4250f..36a64f5 100644 --- a/src/com/github/opensourcefieldlinguistics/fielddb/database/DatumContentProvider.java +++ b/src/com/github/opensourcefieldlinguistics/fielddb/database/DatumContentProvider.java @@ -189,7 +189,7 @@ public void onCreate(SQLiteDatabase db) { NetworkInfo mWifi = connManager .getNetworkInfo(ConnectivityManager.TYPE_WIFI); - if (mWifi.isConnected()) { + if (!Config.APP_TYPE.equals("speechrec") && mWifi.isConnected()) { // if the user has a wifi connection we can download some // real sample data Intent downloadSamples = new Intent(getContext(), From fdd38df059be4bf11d6a6cb23ed212342753b188 Mon Sep 17 00:00:00 2001 From: cesine Date: Sun, 15 Jun 2014 13:27:33 +0400 Subject: [PATCH 19/30] corrections to acra found while doing https://github.com/OpenSourceFieldlinguistics/FieldDB/issues/1541 --- .../fielddb/FieldDBApplication.java | 6 +- .../lessons/ui/DatumDetailFragment.java | 2 +- .../service/DownloadDatumsService.java | 106 ++++++++++++------ .../service/UploadAudioVideoService.java | 2 +- 4 files changed, 80 insertions(+), 36 deletions(-) diff --git a/src/com/github/opensourcefieldlinguistics/fielddb/FieldDBApplication.java b/src/com/github/opensourcefieldlinguistics/fielddb/FieldDBApplication.java index 2ffd9a3..c563a2b 100644 --- a/src/com/github/opensourcefieldlinguistics/fielddb/FieldDBApplication.java +++ b/src/com/github/opensourcefieldlinguistics/fielddb/FieldDBApplication.java @@ -156,9 +156,11 @@ public final void onCreate() { + Config.APP_TYPE + "/" + Config.DEFAULT_CORPUS; (new File(Config.DEFAULT_OUTPUT_DIRECTORY)).mkdirs(); - if (!BuildConfig.DEBUG) + if (!BuildConfig.DEBUG) { ACRA.getErrorReporter().putCustomData("dbname", - Config.DEFAULT_CORPUS.replace("username", username)); + Config.DEFAULT_CORPUS); + } + Log.d(Config.TAG, cursor.getString(cursor .getColumnIndexOrThrow(UserTable.COLUMN_USERNAME))); cursor.close(); diff --git a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumDetailFragment.java b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumDetailFragment.java index e0ae4dc..2973449 100644 --- a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumDetailFragment.java +++ b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumDetailFragment.java @@ -815,7 +815,7 @@ protected void recordUserEvent(String eventType, String eventValue) { } if (!BuildConfig.DEBUG) { ACRA.getErrorReporter().putCustomData("action", - "{" + eventType + " : " + eventValue + "}"); + "{\"" + eventType + "\" : \"" + eventValue + "\"}"); ACRA.getErrorReporter().putCustomData("androidTimestamp", System.currentTimeMillis() + ""); ACRA.getErrorReporter().putCustomData("deviceDetails", diff --git a/src/com/github/opensourcefieldlinguistics/fielddb/service/DownloadDatumsService.java b/src/com/github/opensourcefieldlinguistics/fielddb/service/DownloadDatumsService.java index 161eee8..a099985 100644 --- a/src/com/github/opensourcefieldlinguistics/fielddb/service/DownloadDatumsService.java +++ b/src/com/github/opensourcefieldlinguistics/fielddb/service/DownloadDatumsService.java @@ -20,7 +20,7 @@ import com.github.opensourcefieldlinguistics.fielddb.database.DatumContentProvider.DatumTable; import com.github.opensourcefieldlinguistics.fielddb.lessons.Config; import com.github.opensourcefieldlinguistics.fielddb.speech.kartuli.BuildConfig; -import com.github.opensourcefieldlinguistics.fielddb.speech.kartuli.R; +import com.github.opensourcefieldlinguistics.fielddb.speech.kartuli.R; import com.google.gson.JsonArray; import com.google.gson.JsonObject; @@ -47,11 +47,11 @@ public DownloadDatumsService() { @Override protected void onHandleIntent(Intent intent) { - - if(Config.D){ + + if (Config.D) { return; } - + this.D = Config.D; this.statusMessage = "Downloading samples " + Config.USER_FRIENDLY_DATA_NAME; @@ -61,7 +61,6 @@ protected void onHandleIntent(Intent intent) { Log.d(Config.TAG, "Inside DownloadDatumsService intent"); } - this.datumTagToDownload = "SampleData"; this.urlStringSampleDataDownload = Config.DEFAULT_SAMPLE_DATA_URL + "?key=%22" + datumTagToDownload + "%22"; @@ -69,17 +68,27 @@ protected void onHandleIntent(Intent intent) { Log.d(Config.TAG, this.urlStringSampleDataDownload); } - if (!BuildConfig.DEBUG) ACRA.getErrorReporter().putCustomData("action", - "downloadDatums:::" + datumTagToDownload); - if (!BuildConfig.DEBUG) 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); - if (!BuildConfig.DEBUG) 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; } @@ -88,8 +97,16 @@ protected void onHandleIntent(Intent intent) { if (!"".equals(this.userFriendlyErrorMessage)) { this.notifyUser(" " + this.userFriendlyErrorMessage, this.noti, this.notificationId, true); - if (!BuildConfig.DEBUG) 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; } @@ -97,8 +114,16 @@ protected void onHandleIntent(Intent intent) { if (!"".equals(this.userFriendlyErrorMessage)) { this.notifyUser(" " + this.userFriendlyErrorMessage, this.noti, this.notificationId, true); - if (!BuildConfig.DEBUG) 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; } @@ -106,20 +131,32 @@ protected void onHandleIntent(Intent intent) { if (!"".equals(this.userFriendlyErrorMessage)) { this.notifyUser(" " + this.userFriendlyErrorMessage, this.noti, this.notificationId, true); - if (!BuildConfig.DEBUG) 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); - if (!BuildConfig.DEBUG) ACRA.getErrorReporter().putCustomData("action", - "downloadDatums:::" + datumTagToDownload); - if (!BuildConfig.DEBUG) ACRA.getErrorReporter().putCustomData("urlString", - this.urlStringSampleDataDownload); - if (!BuildConfig.DEBUG) 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() { @@ -169,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; @@ -330,13 +367,18 @@ public void downloadMediaFile(String mediaFileUrl) { } output.close(); this.statusMessage = "Downloaded " + filename; - if (!BuildConfig.DEBUG) ACRA.getErrorReporter().putCustomData("action", - "downloadMedia:::" + filename); - if (!BuildConfig.DEBUG) ACRA.getErrorReporter() - .putCustomData("urlString", mediaFileUrl); - if (!BuildConfig.DEBUG) 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; } @@ -352,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/UploadAudioVideoService.java b/src/com/github/opensourcefieldlinguistics/fielddb/service/UploadAudioVideoService.java index 6c3964d..52f5175 100644 --- a/src/com/github/opensourcefieldlinguistics/fielddb/service/UploadAudioVideoService.java +++ b/src/com/github/opensourcefieldlinguistics/fielddb/service/UploadAudioVideoService.java @@ -159,7 +159,7 @@ public String upload(Uri uri) { String filePath = uri.getPath(); this.statusMessage = "Uploading audio " + uri.getLastPathSegment(); if (!BuildConfig.DEBUG) - ACRA.getErrorReporter().putCustomData("registerUser", + ACRA.getErrorReporter().putCustomData("uploadAudio", uri.getLastPathSegment()); String urlStringAuthenticationSession = Config.DEFAULT_UPLOAD_AUDIO_VIDEO_URL; From 77c2b83dd67adac198c87594eecda4e2dab0613d Mon Sep 17 00:00:00 2001 From: cesine Date: Sun, 15 Jun 2014 18:22:11 +0400 Subject: [PATCH 20/30] renaming production experiment activity --- .../fielddb/lessons/ui/DatumProductionExperimentFragment.java | 4 ---- ...ragmentActivity.java => ProductionExperimentActivity.java} | 2 +- .../fielddb/lessons/ui/WelcomeActivity.java | 2 +- 3 files changed, 2 insertions(+), 6 deletions(-) rename src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/{ProductionExperimentViewPagerFragmentActivity.java => ProductionExperimentActivity.java} (97%) diff --git a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumProductionExperimentFragment.java b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumProductionExperimentFragment.java index 173cdaf..805ccb6 100644 --- a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumProductionExperimentFragment.java +++ b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumProductionExperimentFragment.java @@ -86,10 +86,6 @@ public void setUserVisibleHint(boolean isVisibleToUser) { } } - public void onToggleAudioRecording(View view) { - this.toggleAudioRecording(null); - } - protected void playPromptContext() { isPlaying = true; diff --git a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/ProductionExperimentViewPagerFragmentActivity.java b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/ProductionExperimentActivity.java similarity index 97% rename from src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/ProductionExperimentViewPagerFragmentActivity.java rename to src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/ProductionExperimentActivity.java index f73771d..9bc1d65 100644 --- a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/ProductionExperimentViewPagerFragmentActivity.java +++ b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/ProductionExperimentActivity.java @@ -15,7 +15,7 @@ import android.support.v4.view.ViewPager; import android.util.Log; -public class ProductionExperimentViewPagerFragmentActivity +public class ProductionExperimentActivity extends FragmentActivity implements LoaderManager.LoaderCallbacks { diff --git a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/WelcomeActivity.java b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/WelcomeActivity.java index af6d9c7..c7e8774 100644 --- a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/WelcomeActivity.java +++ b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/WelcomeActivity.java @@ -18,7 +18,7 @@ protected void onCreate(Bundle savedInstanceState) { public void onTrainClick(View view) { Intent openTrainer = new Intent(this, - ProductionExperimentViewPagerFragmentActivity.class); + ProductionExperimentActivity.class); startActivity(openTrainer); } From 638ea38933a7256227026e8e9b2f286c3f960fb4 Mon Sep 17 00:00:00 2001 From: cesine Date: Mon, 16 Jun 2014 09:15:00 +0400 Subject: [PATCH 21/30] using a datum edit activity for the speech recognition hypothesis display for https://github.com/batumi/KartuliPocketSphinx/issues/8 --- res/layout/activity_speech_recognition.xml | 7 +++ ...umSpeechRecognitionHypothesesFragment.java | 43 +++++++++++++++++++ .../lessons/ui/SpeechRecognitionActivity.java | 36 ++++++++++++++++ .../fielddb/lessons/ui/WelcomeActivity.java | 2 +- 4 files changed, 87 insertions(+), 1 deletion(-) create mode 100644 res/layout/activity_speech_recognition.xml create mode 100644 src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumSpeechRecognitionHypothesesFragment.java create mode 100644 src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/SpeechRecognitionActivity.java 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/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..158b8eb --- /dev/null +++ b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumSpeechRecognitionHypothesesFragment.java @@ -0,0 +1,43 @@ +package com.github.opensourcefieldlinguistics.fielddb.lessons.ui; + +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.View; +import android.view.ViewGroup; +import com.github.opensourcefieldlinguistics.fielddb.speech.kartuli.R; + +public class DatumSpeechRecognitionHypothesesFragment extends DatumDetailFragment { + + private boolean isRecognizing; + @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) { + + } + + return rootView; + } + public void playSpeechRecognitionPrompt(){ + this.isRecognizing = true; + } + + @Override + public void setUserVisibleHint(boolean isVisibleToUser) { + super.setUserVisibleHint(isVisibleToUser); + if (this.isVisible() && !this.isRecognizing) { + playSpeechRecognitionPrompt(); + } + } + +} 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..d0b6e6a --- /dev/null +++ b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/SpeechRecognitionActivity.java @@ -0,0 +1,36 @@ +package com.github.opensourcefieldlinguistics.fielddb.lessons.ui; + +import com.github.opensourcefieldlinguistics.fielddb.speech.kartuli.R; + +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. + Bundle arguments = new Bundle(); + arguments.putString(DatumDetailFragment.ARG_ITEM_ID, getIntent() + .getStringExtra(DatumDetailFragment.ARG_ITEM_ID)); + 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 index c7e8774..8cebf88 100644 --- a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/WelcomeActivity.java +++ b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/WelcomeActivity.java @@ -23,7 +23,7 @@ public void onTrainClick(View view) { } public void onRecognizeClick(View view) { - Intent openRecognizer = new Intent(this, ListenAndRepeat.class); + Intent openRecognizer = new Intent(this, SpeechRecognitionActivity.class); startActivity(openRecognizer); } From b764885749d7a0fa1cac772df058b2c05d56ef3f Mon Sep 17 00:00:00 2001 From: cesine Date: Mon, 16 Jun 2014 15:25:19 +0400 Subject: [PATCH 22/30] matching parrnt to not underflow the action bar --- res/layout/fragment_datum_detail.xml | 12 ++++++------ res/layout/fragment_datum_detail_simple.xml | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/res/layout/fragment_datum_detail.xml b/res/layout/fragment_datum_detail.xml index dbface0..6052cef 100644 --- a/res/layout/fragment_datum_detail.xml +++ b/res/layout/fragment_datum_detail.xml @@ -6,8 +6,8 @@ Date: Mon, 16 Jun 2014 15:26:18 +0400 Subject: [PATCH 23/30] turning off the recording if you scroll to the next item --- .../lessons/ui/DatumDetailFragment.java | 75 ++++++++++--------- .../ui/DatumProductionExperimentFragment.java | 9 ++- 2 files changed, 46 insertions(+), 38 deletions(-) diff --git a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumDetailFragment.java b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumDetailFragment.java index 2973449..9d7b812 100644 --- a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumDetailFragment.java +++ b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumDetailFragment.java @@ -478,45 +478,50 @@ public boolean toggleAudioRecording(MenuItem item) { } } else { - Intent audio = new Intent(getActivity(), AudioRecorder.class); - getActivity().stopService(audio); - - Handler mainHandler = new Handler(getActivity().getMainLooper()); - Runnable launchUploadAudioService = new Runnable() { - - @Override - public void run() { - 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.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() { + 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); } - this.recordUserEvent("stopAudio", ""); + }; + mainHandler.postDelayed(launchUploadAudioService, 1000); - if (mSpeechRecognizerFeedback != null) { - mSpeechRecognizerFeedback - .setImageResource(R.drawable.speech_recognizer_waiting); - } + this.mRecordingAudio = false; + if (item != null) { + item.setIcon(R.drawable.ic_action_mic); + } + this.recordUserEvent("stopAudio", ""); - if (mSpeechRecognizerInstructions != null) { - mSpeechRecognizerInstructions.setText("Tap to speak again"); - } - if (Config.APP_TYPE.equals("speechrec")) { - autoAdvanceAfterRecordingAudio(); - } + if (mSpeechRecognizerFeedback != null) { + mSpeechRecognizerFeedback + .setImageResource(R.drawable.speech_recognizer_waiting); + } + if (mSpeechRecognizerInstructions != null) { + mSpeechRecognizerInstructions.setText("Tap to speak again"); + } + if (Config.APP_TYPE.equals("speechrec")) { + autoAdvanceAfterRecordingAudio(); } return true; } diff --git a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumProductionExperimentFragment.java b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumProductionExperimentFragment.java index 805ccb6..7e4a6b5 100644 --- a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumProductionExperimentFragment.java +++ b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumProductionExperimentFragment.java @@ -58,8 +58,8 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, 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)) { @@ -84,6 +84,9 @@ public void setUserVisibleHint(boolean isVisibleToUser) { if (this.isVisible() && !this.isPlaying) { playPromptContext(); } + if (!this.isVisible()) { + turnOffRecorder(null); + } } protected void playPromptContext() { @@ -178,7 +181,7 @@ public void onClick(DialogInterface dialog, int id) { Intent openRecognizer = new Intent( getActivity(), - ListenAndRepeat.class); + SpeechRecognitionActivity.class); startActivity(openRecognizer); } }); From 51b6149e5352617fd7b42335a83e387ba44f1bfa Mon Sep 17 00:00:00 2001 From: cesine Date: Mon, 16 Jun 2014 15:28:22 +0400 Subject: [PATCH 24/30] Speech recognition creates a new datum with validation status of AutomaticallyRecognized and showing training examples does not show these examples --- ...nt_datum_speech_recognition_hypotheses.xml | 181 +++++++++ ...umSpeechRecognitionHypothesesFragment.java | 352 +++++++++++++++++- .../ui/ProductionExperimentActivity.java | 27 +- .../lessons/ui/SpeechRecognitionActivity.java | 23 +- .../fielddb/model/Datum.java | 37 +- 5 files changed, 604 insertions(+), 16 deletions(-) create mode 100644 res/layout/fragment_datum_speech_recognition_hypotheses.xml 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..00afa50 --- /dev/null +++ b/res/layout/fragment_datum_speech_recognition_hypotheses.xml @@ -0,0 +1,181 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumSpeechRecognitionHypothesesFragment.java b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumSpeechRecognitionHypothesesFragment.java index 158b8eb..e920b57 100644 --- a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumSpeechRecognitionHypothesesFragment.java +++ b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumSpeechRecognitionHypothesesFragment.java @@ -1,37 +1,377 @@ package com.github.opensourcefieldlinguistics.fielddb.lessons.ui; +import android.content.ContentValues; import android.os.Bundle; +import android.text.Editable; +import android.text.TextWatcher; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; import android.view.View; import android.view.ViewGroup; +import android.widget.EditText; +import android.widget.ImageButton; +import android.widget.TableLayout; + +import com.github.opensourcefieldlinguistics.fielddb.database.DatumContentProvider.DatumTable; import com.github.opensourcefieldlinguistics.fielddb.speech.kartuli.R; -public class DatumSpeechRecognitionHypothesesFragment extends DatumDetailFragment { +public class DatumSpeechRecognitionHypothesesFragment + extends + DatumDetailFragment { private boolean isRecognizing; @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, + View rootView = inflater.inflate( + R.layout.fragment_datum_speech_recognition_hypotheses, container, false); if (mItem != null) { - + this.prepareEditTextListeners(rootView); } return rootView; } - public void playSpeechRecognitionPrompt(){ + + protected void showOrthographyOnly(View rootView) { + + TableLayout datumArea = (TableLayout) rootView + .findViewById(R.id.datumArea); + if (datumArea != null) { + datumArea.setVisibility(View.VISIBLE); + } + + TableLayout hypothesesArea = (TableLayout) rootView + .findViewById(R.id.hypothesesArea); + 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 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"); + } + }); + } + + 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) { + 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) { + final EditText 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) { + 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"); + } + }); + } + + 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()); + + } + }); + } + + final EditText 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) { + 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"); + } + }); + } + + 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", + "hypothesis1:::" + + hypothesis2EditText.getText() + .toString()); + + } + }); + } + + final EditText 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) { + 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"); + } + }); + } + + 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()); + + } + }); + } + + final EditText 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) { + 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"); + } + }); + } + + 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()); + + } + }); + } + + final EditText 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) { + 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"); + } + }); + } + + 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.isRecognizing = true; } - + @Override public void setUserVisibleHint(boolean isVisibleToUser) { super.setUserVisibleHint(isVisibleToUser); diff --git a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/ProductionExperimentActivity.java b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/ProductionExperimentActivity.java index 9bc1d65..6abc195 100644 --- a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/ProductionExperimentActivity.java +++ b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/ProductionExperimentActivity.java @@ -1,11 +1,13 @@ 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; @@ -15,10 +17,10 @@ import android.support.v4.view.ViewPager; import android.util.Log; -public class ProductionExperimentActivity - extends - FragmentActivity implements LoaderManager.LoaderCallbacks { - +public class ProductionExperimentActivity extends FragmentActivity + implements + LoaderManager.LoaderCallbacks { + private DatumFragmentPagerAdapter mPagerAdapter; @Override @@ -32,14 +34,19 @@ protected void onCreate(Bundle savedInstanceState) { @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, null, null, null); + 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) { @@ -65,4 +72,12 @@ private void initialisePaging() { 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 index d0b6e6a..b1fcc34 100644 --- a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/SpeechRecognitionActivity.java +++ b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/SpeechRecognitionActivity.java @@ -1,7 +1,14 @@ 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; @@ -24,9 +31,21 @@ protected void onCreate(Bundle savedInstanceState) { 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, getIntent() - .getStringExtra(DatumDetailFragment.ARG_ITEM_ID)); + arguments.putString(DatumDetailFragment.ARG_ITEM_ID, + newDatum.getLastPathSegment()); DatumSpeechRecognitionHypothesesFragment fragment = new DatumSpeechRecognitionHypothesesFragment(); fragment.setArguments(arguments); getSupportFragmentManager().beginTransaction() diff --git a/src/com/github/opensourcefieldlinguistics/fielddb/model/Datum.java b/src/com/github/opensourcefieldlinguistics/fielddb/model/Datum.java index 7bd3ac7..b125dea 100644 --- a/src/com/github/opensourcefieldlinguistics/fielddb/model/Datum.java +++ b/src/com/github/opensourcefieldlinguistics/fielddb/model/Datum.java @@ -24,6 +24,7 @@ public class Datum { protected ArrayList related; protected ArrayList reminders; protected ArrayList tags; + protected ArrayList validationStati; protected ArrayList coments; protected String actualJSON; @@ -34,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; @@ -50,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; } @@ -69,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 = ""; } @@ -89,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 = ""; } @@ -109,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 = ""; } @@ -128,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 = ""; } @@ -268,7 +275,7 @@ public String getTagsString() { } public void setTagsFromSting(String tags) { - if(tags != null && !"".equals(tags)){ + if (tags != null && !"".equals(tags)) { this.tags = new ArrayList(Arrays.asList(tags.split(","))); } } @@ -277,6 +284,32 @@ 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; } From a1cb854def74c4e047914ffb09f6c0a338848f54 Mon Sep 17 00:00:00 2001 From: cesine Date: Mon, 16 Jun 2014 23:03:09 +0400 Subject: [PATCH 25/30] new speech recognition interface is ready fixes https://github.com/batumi/KartuliSpeechRecognition/issues/8 --- ...nt_datum_speech_recognition_hypotheses.xml | 12 +- .../fielddb/lessons/Config.java | 2 +- .../lessons/ui/DatumDetailFragment.java | 3 + .../ui/DatumProductionExperimentFragment.java | 6 +- ...umSpeechRecognitionHypothesesFragment.java | 146 ++++++++++++++++-- .../service/UploadAudioVideoService.java | 3 + 6 files changed, 151 insertions(+), 21 deletions(-) diff --git a/res/layout/fragment_datum_speech_recognition_hypotheses.xml b/res/layout/fragment_datum_speech_recognition_hypotheses.xml index 00afa50..1a51b38 100644 --- a/res/layout/fragment_datum_speech_recognition_hypotheses.xml +++ b/res/layout/fragment_datum_speech_recognition_hypotheses.xml @@ -99,7 +99,7 @@ android:layout_weight="80" android:inputType="textMultiLine" android:scrollHorizontally="false" - android:text="first hypothesis" /> + android:text="" /> + android:text="" /> + android:text="" /> + android:text="" /> + android:text="" /> - \ No newline at end of file + diff --git a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/Config.java b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/Config.java index 95ded08..106c458 100644 --- a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/Config.java +++ b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/Config.java @@ -1,7 +1,7 @@ package com.github.opensourcefieldlinguistics.fielddb.lessons; public class Config extends ca.ilanguage.oprime.Config { - public static final boolean D = false; + public static final boolean D = true; public static final String ACRA_PASS = PrivateConstants.ACRA_PASS; public static final String ACRA_SERVER_URL = PrivateConstants.ACRA_SERVER_URL; public static final String ACRA_USER = PrivateConstants.ACRA_USER; diff --git a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumDetailFragment.java b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumDetailFragment.java index 9d7b812..413722b 100644 --- a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumDetailFragment.java +++ b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumDetailFragment.java @@ -493,6 +493,9 @@ protected boolean turnOffRecorder(MenuItem item) { @Override public void run() { + if(getActivity() == null){ + return; + } Intent uploadAudioFile = new Intent(getActivity(), UploadAudioVideoService.class); uploadAudioFile.setData(Uri.parse(mAudioFileName)); diff --git a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumProductionExperimentFragment.java b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumProductionExperimentFragment.java index 7e4a6b5..031e6a7 100644 --- a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumProductionExperimentFragment.java +++ b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumProductionExperimentFragment.java @@ -22,9 +22,9 @@ public class DatumProductionExperimentFragment extends DatumDetailFragment { - private int mAudioPromptResource; - private boolean mIsInstructions = false; - private long WAIT_TO_RECORD_AFTER_PROMPT_START = 400; + protected int mAudioPromptResource; + protected boolean mIsInstructions = false; + protected long WAIT_TO_RECORD_AFTER_PROMPT_START = 400; @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { diff --git a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumSpeechRecognitionHypothesesFragment.java b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumSpeechRecognitionHypothesesFragment.java index e920b57..43bc426 100644 --- a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumSpeechRecognitionHypothesesFragment.java +++ b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumSpeechRecognitionHypothesesFragment.java @@ -1,7 +1,12 @@ package com.github.opensourcefieldlinguistics.fielddb.lessons.ui; +import java.util.ArrayList; + +import android.app.Activity; import android.content.ContentValues; +import android.content.Intent; import android.os.Bundle; +import android.speech.RecognizerIntent; import android.text.Editable; import android.text.TextWatcher; import android.view.LayoutInflater; @@ -18,9 +23,17 @@ public class DatumSpeechRecognitionHypothesesFragment extends - DatumDetailFragment { + DatumProductionExperimentFragment { + + private boolean mHasRecognized; + private boolean mIsRecognizing; + private static final int RETURN_FROM_VOICE_RECOGNITION_REQUEST_CODE = 341; + EditText hypothesis1EditText; + EditText hypothesis2EditText; + EditText hypothesis3EditText; + EditText hypothesis4EditText; + EditText hypothesis5EditText; - private boolean isRecognizing; @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { // no menu @@ -35,13 +48,16 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, 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) { @@ -110,6 +126,8 @@ public void onTextChanged(CharSequence arg0, int arg1, .findViewById(R.id.orthography)); if (orthographyEditText != null) { orthographyEditText.setText(mItem.getOrthography()); + int textLength = mItem.getOrthography().length(); + orthographyEditText.setSelection(textLength, textLength); orthographyEditText.addTextChangedListener(new TextWatcher() { @Override public void afterTextChanged(Editable arg0) { @@ -137,7 +155,7 @@ public void onTextChanged(CharSequence arg0, int arg1, } protected void prepareEditTextListeners(final View rootView) { - final EditText hypothesis1EditText = ((EditText) rootView + hypothesis1EditText = ((EditText) rootView .findViewById(R.id.hypothesis1)); if (hypothesis1EditText != null) { // hypothesis1EditText.setText(mItem.getOrthography()); @@ -152,6 +170,9 @@ public void beforeTextChanged(CharSequence arg0, int arg1, @Override public void onTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) { + if (mHasRecognized == false) { + return; + } String currentText = hypothesis1EditText.getText() .toString(); mItem.setOrthography(currentText); @@ -183,7 +204,7 @@ public void onClick(View v) { }); } - final EditText hypothesis2EditText = ((EditText) rootView + hypothesis2EditText = ((EditText) rootView .findViewById(R.id.hypothesis2)); if (hypothesis2EditText != null) { // hypothesis2EditText.setText(mItem.getOrthography()); @@ -198,6 +219,9 @@ public void beforeTextChanged(CharSequence arg0, int arg1, @Override public void onTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) { + if (mHasRecognized == false) { + return; + } String currentText = hypothesis2EditText.getText() .toString(); mItem.setOrthography(currentText); @@ -229,7 +253,7 @@ public void onClick(View v) { }); } - final EditText hypothesis3EditText = ((EditText) rootView + hypothesis3EditText = ((EditText) rootView .findViewById(R.id.hypothesis3)); if (hypothesis3EditText != null) { // hypothesis3EditText.setText(mItem.getOrthography()); @@ -244,6 +268,9 @@ public void beforeTextChanged(CharSequence arg0, int arg1, @Override public void onTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) { + if (mHasRecognized == false) { + return; + } String currentText = hypothesis3EditText.getText() .toString(); mItem.setOrthography(currentText); @@ -275,7 +302,7 @@ public void onClick(View v) { }); } - final EditText hypothesis4EditText = ((EditText) rootView + hypothesis4EditText = ((EditText) rootView .findViewById(R.id.hypothesis4)); if (hypothesis4EditText != null) { // hypothesis4EditText.setText(mItem.getOrthography()); @@ -290,6 +317,9 @@ public void beforeTextChanged(CharSequence arg0, int arg1, @Override public void onTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) { + if (mHasRecognized == false) { + return; + } String currentText = hypothesis4EditText.getText() .toString(); mItem.setOrthography(currentText); @@ -321,7 +351,7 @@ public void onClick(View v) { }); } - final EditText hypothesis5EditText = ((EditText) rootView + hypothesis5EditText = ((EditText) rootView .findViewById(R.id.hypothesis5)); if (hypothesis5EditText != null) { // hypothesis5EditText.setText(mItem.getOrthography()); @@ -336,6 +366,9 @@ public void beforeTextChanged(CharSequence arg0, int arg1, @Override public void onTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) { + if (mHasRecognized == false) { + return; + } String currentText = hypothesis5EditText.getText() .toString(); mItem.setOrthography(currentText); @@ -369,15 +402,106 @@ public void onClick(View v) { } public void playSpeechRecognitionPrompt() { - this.isRecognizing = true; + this.mIsRecognizing = true; + mAudioPromptResource = R.raw.im_listening; + playPromptContext(); + // Handler mainHandler = new Handler(getActivity().getMainLooper()); + // Runnable myRunnable = new Runnable() { + // @Override + // public void run() { + // } + // }; + // mainHandler.postDelayed(myRunnable, 200); + startVoiceRecognitionActivity(); } @Override public void setUserVisibleHint(boolean isVisibleToUser) { super.setUserVisibleHint(isVisibleToUser); - if (this.isVisible() && !this.isRecognizing) { - playSpeechRecognitionPrompt(); + if (this.isVisible() && !this.mIsRecognizing) { + // playSpeechRecognitionPrompt(); + } + } + + /** + * 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 + public void onActivityResult(int requestCode, int resultCode, Intent data) { + getActivity(); + if (requestCode == RETURN_FROM_VOICE_RECOGNITION_REQUEST_CODE + && resultCode == Activity.RESULT_OK) { + turnOffRecorder(null); + /* + * 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); + } + } + + if (hypothesis2EditText != null) { + if (matches.size() > 1 && matches.get(1) != null) { + hypothesis2EditText.setText(matches.get(1)); + } else { + hypothesis2EditText.setVisibility(View.GONE); + } + } + if (hypothesis3EditText != null) { + if (matches.size() > 2 && matches.get(2) != null) { + hypothesis3EditText.setText(matches.get(2)); + } else { + hypothesis3EditText.setVisibility(View.GONE); + } + } + if (hypothesis4EditText != null) { + if (matches.size() > 3 && matches.get(3) != null) { + hypothesis4EditText.setText(matches.get(3)); + } else { + hypothesis4EditText.setVisibility(View.GONE); + } + } + if (hypothesis5EditText != null) { + if (matches.size() > 4 && matches.get(4) != null) { + hypothesis5EditText.setText(matches.get(4)); + } else { + hypothesis5EditText.setVisibility(View.GONE); + } + } + + if (matches.size() > 0) { + this.mHasRecognized = true; + } + } + super.onActivityResult(requestCode, resultCode, data); + } + + @Override + public void onPause() { + turnOffRecorder(null); + super.onPause(); } } diff --git a/src/com/github/opensourcefieldlinguistics/fielddb/service/UploadAudioVideoService.java b/src/com/github/opensourcefieldlinguistics/fielddb/service/UploadAudioVideoService.java index 52f5175..c19419e 100644 --- a/src/com/github/opensourcefieldlinguistics/fielddb/service/UploadAudioVideoService.java +++ b/src/com/github/opensourcefieldlinguistics/fielddb/service/UploadAudioVideoService.java @@ -57,6 +57,9 @@ public UploadAudioVideoService() { @Override protected void onHandleIntent(Intent intent) { + if (Config.D) { + return; + } /* only upload files when connected to wifi */ ConnectivityManager connManager = (ConnectivityManager) getApplicationContext() From 806db0363c64cb9e76b4712bafb865280aac80bc Mon Sep 17 00:00:00 2001 From: cesine Date: Tue, 17 Jun 2014 13:43:13 +0400 Subject: [PATCH 26/30] forcing locale to kartuli and adding color to the speech recognitoin hypotheses and handling edge cases when recognizer is not installed etc --- ...nt_datum_speech_recognition_hypotheses.xml | 64 ++++-- res/menu/actions_datum_speech_recognition.xml | 15 ++ .../fielddb/FieldDBApplication.java | 38 ++++ .../lessons/ui/DatumDetailFragment.java | 15 +- ...umSpeechRecognitionHypothesesFragment.java | 199 ++++++++++++++++-- 5 files changed, 288 insertions(+), 43 deletions(-) create mode 100644 res/menu/actions_datum_speech_recognition.xml diff --git a/res/layout/fragment_datum_speech_recognition_hypotheses.xml b/res/layout/fragment_datum_speech_recognition_hypotheses.xml index 1a51b38..b11ee9b 100644 --- a/res/layout/fragment_datum_speech_recognition_hypotheses.xml +++ b/res/layout/fragment_datum_speech_recognition_hypotheses.xml @@ -2,7 +2,7 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" - android:background="#ffffffff" > + android:background="#232323" > + android:text="" + android:textColor="#ffffffff" + android:textSize="25sp" /> @@ -65,12 +67,14 @@ android:inputType="textMultiLine" android:scrollHorizontally="false" android:text="" + android:textColor="#ffcccccc" + android:textSize="15sp" android:visibility="gone" /> - @@ -90,87 +96,117 @@ android:layout_gravity="center" android:orientation="vertical" > - + + android:text="" + android:textColor="#ffffffff" + android:textSize="25sp" /> - + + android:text="" + android:textColor="#ffffffff" + android:textSize="25sp" /> - + + android:text="" + android:textColor="#ffffffff" + android:textSize="25sp" /> - + + android:text="" + android:textColor="#ffffffff" + android:textSize="25sp" /> - + + android:text="" + android:textColor="#ffffffff" + android:textSize="25sp" /> @@ -178,4 +214,4 @@ - + \ 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/src/com/github/opensourcefieldlinguistics/fielddb/FieldDBApplication.java b/src/com/github/opensourcefieldlinguistics/fielddb/FieldDBApplication.java index c563a2b..b7364e4 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; @@ -30,6 +31,7 @@ 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; @@ -43,6 +45,8 @@ 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(); @@ -207,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/lessons/ui/DatumDetailFragment.java b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumDetailFragment.java index 413722b..957bcb8 100644 --- a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumDetailFragment.java +++ b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumDetailFragment.java @@ -493,7 +493,7 @@ protected boolean turnOffRecorder(MenuItem item) { @Override public void run() { - if(getActivity() == null){ + if (getActivity() == null) { return; } Intent uploadAudioFile = new Intent(getActivity(), @@ -547,11 +547,11 @@ protected boolean autoAdvanceAfterRecordingAudio() { 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 @@ -583,7 +583,6 @@ public void onClick(DialogInterface dialog, deleteConfirmationDialog.show(); return true; } - protected void loadVisuals(boolean playImmediately) { loadMainVideo(playImmediately); } @@ -796,6 +795,9 @@ public void onPause() { it.remove(); // avoids a ConcurrentModificationException } edits = "[" + edits + "]"; + if (Config.D) { + Log.d(Config.TAG, "edits: " + edits); + } recordUserEvent("totalDatumEditsOnPause", edits); } @@ -808,7 +810,6 @@ public void onPause() { super.onPause(); } - protected void recordUserEvent(String eventType, String eventValue) { if ("editDatum".equals(eventType)) { if (this.mDatumEditCounts == null) { diff --git a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumSpeechRecognitionHypothesesFragment.java b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumSpeechRecognitionHypothesesFragment.java index 43bc426..18c86aa 100644 --- a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumSpeechRecognitionHypothesesFragment.java +++ b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumSpeechRecognitionHypothesesFragment.java @@ -1,24 +1,37 @@ 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.View.OnFocusChangeListener; 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 @@ -33,10 +46,28 @@ public class DatumSpeechRecognitionHypothesesFragment EditText hypothesis3EditText; EditText hypothesis4EditText; EditText hypothesis5EditText; + TableLayout hypothesesArea; + + private static final String[] TAGS = new String[]{"WebSearch", "SMS", + "EMail"}; @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { - // no menu + 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 @@ -64,8 +95,6 @@ protected void showOrthographyOnly(View rootView) { datumArea.setVisibility(View.VISIBLE); } - TableLayout hypothesesArea = (TableLayout) rootView - .findViewById(R.id.hypothesesArea); if (hypothesesArea != null) { hypothesesArea.setVisibility(View.GONE); } @@ -96,9 +125,13 @@ public void onTextChanged(CharSequence arg0, int arg1, }); } - final EditText tagsEditText = ((EditText) rootView + 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 @@ -155,6 +188,9 @@ public void onTextChanged(CharSequence arg0, int arg1, } protected void prepareEditTextListeners(final View rootView) { + hypothesesArea = (TableLayout) rootView + .findViewById(R.id.hypothesesArea); + hypothesis1EditText = ((EditText) rootView .findViewById(R.id.hypothesis1)); if (hypothesis1EditText != null) { @@ -176,7 +212,6 @@ public void onTextChanged(CharSequence arg0, int arg1, 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, @@ -184,6 +219,19 @@ public void onTextChanged(CharSequence arg0, int arg1, 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 @@ -233,6 +281,19 @@ public void onTextChanged(CharSequence arg0, int arg1, 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 @@ -245,7 +306,7 @@ public void onClick(View v) { removeHypothesis2Button.setVisibility(View.GONE); hypothesis2EditText.setVisibility(View.GONE); recordUserEvent("removeHypothesis", - "hypothesis1:::" + "hypothesis2:::" + hypothesis2EditText.getText() .toString()); @@ -282,6 +343,19 @@ public void onTextChanged(CharSequence arg0, int arg1, 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 @@ -331,6 +405,19 @@ public void onTextChanged(CharSequence arg0, int arg1, 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 @@ -380,6 +467,19 @@ public void onTextChanged(CharSequence arg0, int arg1, 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 @@ -403,16 +503,17 @@ public void onClick(View v) { } 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() { - // } - // }; - // mainHandler.postDelayed(myRunnable, 200); - startVoiceRecognitionActivity(); + Handler mainHandler = new Handler(getActivity().getMainLooper()); + Runnable myRunnable = new Runnable() { + @Override + public void run() { + startVoiceRecognitionActivity(); + } + }; + mainHandler.postDelayed(myRunnable, 200); } @Override @@ -427,13 +528,47 @@ public void setUserVisibleHint(boolean isVisibleToUser) { * 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); + 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); + } + } /** @@ -445,6 +580,7 @@ public void onActivityResult(int requestCode, int resultCode, Intent data) { 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 @@ -459,14 +595,15 @@ public void onActivityResult(int requestCode, int resultCode, Intent data) { } 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) { @@ -474,6 +611,7 @@ public void onActivityResult(int requestCode, int resultCode, Intent data) { } else { hypothesis3EditText.setVisibility(View.GONE); } + hypothesis3EditText.clearFocus(); } if (hypothesis4EditText != null) { if (matches.size() > 3 && matches.get(3) != null) { @@ -481,6 +619,7 @@ public void onActivityResult(int requestCode, int resultCode, Intent data) { } else { hypothesis4EditText.setVisibility(View.GONE); } + hypothesis4EditText.clearFocus(); } if (hypothesis5EditText != null) { if (matches.size() > 4 && matches.get(4) != null) { @@ -488,12 +627,20 @@ public void onActivityResult(int requestCode, int resultCode, Intent data) { } 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)); + } } super.onActivityResult(requestCode, resultCode, data); } @@ -504,4 +651,12 @@ public void onPause() { 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; + } + } From aa2ded4b5728e438feb7396d0f33987247a8fcac Mon Sep 17 00:00:00 2001 From: cesine Date: Tue, 17 Jun 2014 13:43:41 +0400 Subject: [PATCH 27/30] new layout for horizontal tablets with buttons and text next to eachother --- res/layout-sw600dp/activity_welcome.xml | 67 +++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 res/layout-sw600dp/activity_welcome.xml 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 From 4ff0369d3ffa14c38aafd19577f39a9e36878828 Mon Sep 17 00:00:00 2001 From: cesine Date: Tue, 17 Jun 2014 15:52:33 +0400 Subject: [PATCH 28/30] using speechrecognition as the app type and preparing for release --- .../fielddb/FieldDBApplication.java | 2 +- .../fielddb/database/DatumContentProvider.java | 2 +- .../opensourcefieldlinguistics/fielddb/lessons/Config.java | 4 ++-- .../fielddb/lessons/ui/DatumDetailFragment.java | 6 +++--- .../fielddb/lessons/ui/DatumFragmentPagerAdapter.java | 2 +- .../opensourcefieldlinguistics/fielddb/model/Datum.java | 2 +- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/com/github/opensourcefieldlinguistics/fielddb/FieldDBApplication.java b/src/com/github/opensourcefieldlinguistics/fielddb/FieldDBApplication.java index b7364e4..8a1ccb7 100644 --- a/src/com/github/opensourcefieldlinguistics/fielddb/FieldDBApplication.java +++ b/src/com/github/opensourcefieldlinguistics/fielddb/FieldDBApplication.java @@ -178,7 +178,7 @@ public final void onCreate() { .getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo wifi = connManager .getNetworkInfo(ConnectivityManager.TYPE_WIFI); - if (Config.APP_TYPE.equals("speechrec")) { + if (Config.APP_TYPE.equals("speechrecognition")) { Log.d(Config.TAG, "Not downloading samples, they are included in the training app"); diff --git a/src/com/github/opensourcefieldlinguistics/fielddb/database/DatumContentProvider.java b/src/com/github/opensourcefieldlinguistics/fielddb/database/DatumContentProvider.java index 36a64f5..bb26c74 100644 --- a/src/com/github/opensourcefieldlinguistics/fielddb/database/DatumContentProvider.java +++ b/src/com/github/opensourcefieldlinguistics/fielddb/database/DatumContentProvider.java @@ -189,7 +189,7 @@ public void onCreate(SQLiteDatabase db) { NetworkInfo mWifi = connManager .getNetworkInfo(ConnectivityManager.TYPE_WIFI); - if (!Config.APP_TYPE.equals("speechrec") && 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(), diff --git a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/Config.java b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/Config.java index 106c458..42268fd 100644 --- a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/Config.java +++ b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/Config.java @@ -1,13 +1,13 @@ package com.github.opensourcefieldlinguistics.fielddb.lessons; public class Config extends ca.ilanguage.oprime.Config { - public static final boolean D = true; + public static final boolean D = false; public static final String ACRA_PASS = PrivateConstants.ACRA_PASS; public static final String ACRA_SERVER_URL = PrivateConstants.ACRA_SERVER_URL; 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 APP_TYPE = "speechrec"; + public static final String APP_TYPE = "speechrecognition"; // public static final String DATA_IS_ABOUT_LANGUAGE_NAME = "ქართული"; public static String DEFAULT_CORPUS = "username-" diff --git a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumDetailFragment.java b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumDetailFragment.java index 957bcb8..432e027 100644 --- a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumDetailFragment.java +++ b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumDetailFragment.java @@ -165,7 +165,7 @@ 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("speechrec")) { + if (Config.APP_TYPE.equals("speechrecognition")) { rootView = inflater.inflate(R.layout.fragment_datum_detail_simple, container, false); } @@ -513,7 +513,7 @@ public void run() { if (item != null) { item.setIcon(R.drawable.ic_action_mic); } - this.recordUserEvent("stopAudio", ""); + this.recordUserEvent("stopAudio", this.mAudioFileName); if (mSpeechRecognizerFeedback != null) { mSpeechRecognizerFeedback @@ -523,7 +523,7 @@ public void run() { if (mSpeechRecognizerInstructions != null) { mSpeechRecognizerInstructions.setText("Tap to speak again"); } - if (Config.APP_TYPE.equals("speechrec")) { + if (Config.APP_TYPE.equals("speechrecognition")) { autoAdvanceAfterRecordingAudio(); } return true; diff --git a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumFragmentPagerAdapter.java b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumFragmentPagerAdapter.java index aed3e0a..9436fda 100644 --- a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumFragmentPagerAdapter.java +++ b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumFragmentPagerAdapter.java @@ -56,7 +56,7 @@ public Fragment getItem(int position) { } Bundle arguments = new Bundle(); DatumDetailFragment fragment = new DatumProductionExperimentFragment(); - if (Config.APP_TYPE.equals("speechrec")) { + if (Config.APP_TYPE.equals("speechrecognition")) { // fragment = new DatumProductionExperimentFragment(); } else { fragment = new DatumDetailFragment(); diff --git a/src/com/github/opensourcefieldlinguistics/fielddb/model/Datum.java b/src/com/github/opensourcefieldlinguistics/fielddb/model/Datum.java index b125dea..205a97c 100644 --- a/src/com/github/opensourcefieldlinguistics/fielddb/model/Datum.java +++ b/src/com/github/opensourcefieldlinguistics/fielddb/model/Datum.java @@ -581,7 +581,7 @@ public String getBaseFilename() { } if (filenameBasedOnMorphemesOrWhateverIsAvailable == null || "".equals(filenameBasedOnMorphemesOrWhateverIsAvailable)) { - filenameBasedOnMorphemesOrWhateverIsAvailable = "unknown"; + filenameBasedOnMorphemesOrWhateverIsAvailable = "audio"; } filenameBasedOnMorphemesOrWhateverIsAvailable = Config .getSafeUri(filenameBasedOnMorphemesOrWhateverIsAvailable); From 7a5828bbf4860a1b4c004d1acd0d5db212696cff Mon Sep 17 00:00:00 2001 From: cesine Date: Tue, 17 Jun 2014 15:52:58 +0400 Subject: [PATCH 29/30] Getting on focus change listeners to set the orthography isnt working --- ...umSpeechRecognitionHypothesesFragment.java | 169 ++++++++++-------- 1 file changed, 91 insertions(+), 78 deletions(-) diff --git a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumSpeechRecognitionHypothesesFragment.java b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumSpeechRecognitionHypothesesFragment.java index 18c86aa..37e01f5 100644 --- a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumSpeechRecognitionHypothesesFragment.java +++ b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumSpeechRecognitionHypothesesFragment.java @@ -20,7 +20,6 @@ import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; -import android.view.View.OnFocusChangeListener; import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.AutoCompleteTextView; @@ -40,6 +39,7 @@ public class DatumSpeechRecognitionHypothesesFragment private boolean mHasRecognized; private boolean mIsRecognizing; + private boolean mPerfectMatch; private static final int RETURN_FROM_VOICE_RECOGNITION_REQUEST_CODE = 341; EditText hypothesis1EditText; EditText hypothesis2EditText; @@ -47,10 +47,12 @@ public class DatumSpeechRecognitionHypothesesFragment 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); @@ -160,7 +162,11 @@ public void onTextChanged(CharSequence arg0, int arg1, if (orthographyEditText != null) { orthographyEditText.setText(mItem.getOrthography()); int textLength = mItem.getOrthography().length(); - orthographyEditText.setSelection(textLength, textLength); + if (this.mPerfectMatch) { + orthographyEditText.setSelection(0, textLength); + } else { + orthographyEditText.setSelection(textLength, textLength); + } orthographyEditText.addTextChangedListener(new TextWatcher() { @Override public void afterTextChanged(Editable arg0) { @@ -212,6 +218,7 @@ public void onTextChanged(CharSequence arg0, int arg1, 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, @@ -219,19 +226,19 @@ public void onTextChanged(CharSequence arg0, int arg1, 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); - } - }); + // 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 @@ -281,19 +288,19 @@ public void onTextChanged(CharSequence arg0, int arg1, 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); - } - }); + // 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 @@ -343,19 +350,19 @@ public void onTextChanged(CharSequence arg0, int arg1, 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); - } - }); + // 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 @@ -405,19 +412,19 @@ public void onTextChanged(CharSequence arg0, int arg1, 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); - } - }); + // 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 @@ -467,19 +474,19 @@ public void onTextChanged(CharSequence arg0, int arg1, 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); - } - }); + // 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 @@ -513,7 +520,10 @@ public void run() { startVoiceRecognitionActivity(); } }; - mainHandler.postDelayed(myRunnable, 200); + mainHandler.postDelayed(myRunnable, 1000);/* + * make delay long to get some + * idea of what they will say + */ } @Override @@ -593,41 +603,41 @@ public void onActivityResult(int requestCode, int resultCode, Intent data) { if (matches.size() > 0 && matches.get(0) != null) { hypothesis1EditText.setText(matches.get(0)); } else { - hypothesis1EditText.setVisibility(View.GONE); + // hypothesis1EditText.setVisibility(View.GONE); } - hypothesis1EditText.clearFocus(); + // hypothesis1EditText.clearFocus(); } if (hypothesis2EditText != null) { if (matches.size() > 1 && matches.get(1) != null) { hypothesis2EditText.setText(matches.get(1)); } else { - hypothesis2EditText.setVisibility(View.GONE); + // hypothesis2EditText.setVisibility(View.GONE); } - hypothesis2EditText.clearFocus(); + // hypothesis2EditText.clearFocus(); } if (hypothesis3EditText != null) { if (matches.size() > 2 && matches.get(2) != null) { hypothesis3EditText.setText(matches.get(2)); } else { - hypothesis3EditText.setVisibility(View.GONE); + // hypothesis3EditText.setVisibility(View.GONE); } - hypothesis3EditText.clearFocus(); + // hypothesis3EditText.clearFocus(); } if (hypothesis4EditText != null) { if (matches.size() > 3 && matches.get(3) != null) { hypothesis4EditText.setText(matches.get(3)); } else { - hypothesis4EditText.setVisibility(View.GONE); + // hypothesis4EditText.setVisibility(View.GONE); } - hypothesis4EditText.clearFocus(); + // hypothesis4EditText.clearFocus(); } if (hypothesis5EditText != null) { if (matches.size() > 4 && matches.get(4) != null) { hypothesis5EditText.setText(matches.get(4)); } else { - hypothesis5EditText.setVisibility(View.GONE); + // hypothesis5EditText.setVisibility(View.GONE); } - hypothesis5EditText.clearFocus(); + // hypothesis5EditText.clearFocus(); } if (matches.size() > 0) { @@ -640,7 +650,10 @@ public void onActivityResult(int requestCode, int resultCode, Intent data) { 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); } From ebe4eaff07e6647b6e7001a7ef19521d6099224e Mon Sep 17 00:00:00 2001 From: cesine Date: Tue, 17 Jun 2014 15:53:08 +0400 Subject: [PATCH 30/30] dont need on buffered listener --- .../ui/DatumProductionExperimentFragment.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumProductionExperimentFragment.java b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumProductionExperimentFragment.java index 031e6a7..49cb51f 100644 --- a/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumProductionExperimentFragment.java +++ b/src/com/github/opensourcefieldlinguistics/fielddb/lessons/ui/DatumProductionExperimentFragment.java @@ -106,14 +106,14 @@ public void onCompletion(MediaPlayer mp) { } } }); - mAudioPlayer - .setOnBufferingUpdateListener(new MediaPlayer.OnBufferingUpdateListener() { - - @Override - public void onBufferingUpdate(MediaPlayer arg0, int arg1) { - Log.d(Config.TAG, "Buffering " + arg1); - } - }); +// 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