diff --git a/CHANGELOG.md b/CHANGELOG.md
index e6e3e37..b986685 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,11 +2,12 @@
============================================
V2.0.4 - 09 May 2016
- Improved handling of watch app settings to make sure
+ - Improved handling of watch app settings to make sure
they are loaded correctly without having to re-start app.
- Added watch app to Andid phone app package so watch app can be
+ - Added watch app to Android phone app package so watch app can be
installed directly from phone rather than using pebble store.
- Changed main screen graph to bar chart.
+ - Changed main screen graph to bar chart and highlights frequency
+ region of interest.
V2.0.3 - 23 April 2016
Further modification to beep code to avoid occasional crashes
diff --git a/app/app-release-2.0.4.apk b/app/app-release-2.0.4.apk
new file mode 100644
index 0000000..059fc7c
Binary files /dev/null and b/app/app-release-2.0.4.apk differ
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 01016aa..40924a3 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -2,7 +2,7 @@
+ android:versionName="2.0.4">
@@ -23,30 +23,28 @@
-
+ android:label="@string/app_name">
+
+
-
-
+ android:icon="@drawable/star_of_life_48x48"
+ android:label="@string/app_name">
-
+ android:label="OpenSeizureDetector Preferences">
+
diff --git a/app/src/main/assets/pebble_sd.pbw b/app/src/main/assets/pebble_sd.pbw
index 4ab17a0..b31526c 100644
Binary files a/app/src/main/assets/pebble_sd.pbw and b/app/src/main/assets/pebble_sd.pbw differ
diff --git a/app/src/main/java/uk/org/openseizuredetector/EventLogManager/EventLogListAdapter.java b/app/src/main/java/uk/org/openseizuredetector/EventLogManager/EventLogListAdapter.java
new file mode 100644
index 0000000..91db4ef
--- /dev/null
+++ b/app/src/main/java/uk/org/openseizuredetector/EventLogManager/EventLogListAdapter.java
@@ -0,0 +1,98 @@
+package uk.org.openseizuredetector.EventLogManager;
+
+import java.util.ArrayList;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import uk.org.openseizuredetector.R;
+
+public class EventLogListAdapter extends BaseAdapter {
+ EventLogManager dm;
+ ArrayList logEntryModelList;
+ LayoutInflater inflater;
+ Context _context;
+
+ public EventLogListAdapter(Context context) {
+
+ logEntryModelList = new ArrayList();
+ _context = context;
+ inflater = (LayoutInflater) context
+ .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ dm = new EventLogManager(_context);
+ logEntryModelList = dm.getAllData();
+
+ }
+
+ @Override
+ public void notifyDataSetChanged() {
+ super.notifyDataSetChanged();
+ //refetching the new data from database
+ logEntryModelList = dm.getAllData();
+
+ }
+
+ public void delRow(int delPosition) {
+
+ dm.deleteRow(logEntryModelList.get(delPosition).getId());
+ logEntryModelList.remove(delPosition);
+
+ }
+
+ @Override
+ public int getCount() {
+ return logEntryModelList.size();
+ }
+
+ @Override
+ public Object getItem(int position) {
+ return logEntryModelList.get(position);
+ }
+
+ @Override
+ public long getItemId(int position) {
+ return 0;
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ ViewHolder vHolder;
+ if (convertView == null) {
+ convertView = inflater.inflate(R.layout.log_entry_layout, null);
+ vHolder = new ViewHolder();
+
+ vHolder.date = (TextView) convertView
+ .findViewById(R.id.event_date);
+ vHolder.alarmState = (TextView) convertView
+ .findViewById(R.id.event_alarmState);
+ vHolder.note = (TextView) convertView
+ .findViewById(R.id.event_note);
+ vHolder.dataJSON = (TextView) convertView
+ .findViewById(R.id.event_dataJSON);
+ convertView.setTag(vHolder);
+ } else {
+ vHolder = (ViewHolder) convertView.getTag();
+ }
+
+ LogEntryModel eventObj = logEntryModelList.get(position);
+
+ //vHolder.date.setText(eventObj.getDate().toString());
+ vHolder.alarmState.setText(eventObj.getAlarmState());
+ vHolder.note.setText(eventObj.getNote());
+ vHolder.dataJSON.setText(eventObj.getDataJSON());
+
+ return convertView;
+ }
+
+ class ViewHolder {
+ TextView date,alarmState,note,dataJSON;
+ }
+
+}
diff --git a/app/src/main/java/uk/org/openseizuredetector/EventLogManager/EventLogManager.java b/app/src/main/java/uk/org/openseizuredetector/EventLogManager/EventLogManager.java
new file mode 100644
index 0000000..daebfca
--- /dev/null
+++ b/app/src/main/java/uk/org/openseizuredetector/EventLogManager/EventLogManager.java
@@ -0,0 +1,210 @@
+/**
+ * Database manager for logging events and associated seizure detector data.
+ */
+package uk.org.openseizuredetector.EventLogManager;
+
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.Locale;
+
+import android.content.ContentValues;
+import android.content.Context;
+import android.database.Cursor;
+import android.database.SQLException;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteOpenHelper;
+import android.util.Log;
+
+public class EventLogManager {
+ final static String TAG = "EventLogManager";
+ private SQLiteDatabase db; // a reference to the database manager class.
+ private static final String DB_NAME = "eventlog"; // the name of our database
+ private static final int DB_VERSION = 1; // the version of the database
+
+ private static final String TABLE_NAME = "events";// table name
+
+ // the names for our database columns
+ private static final String TABLE_ROW_ID = "_id";
+ private static final String TABLE_ROW_DATE = "event_date";
+ private static final String TABLE_ROW_ALARM_STATE = "alarm_state";
+ private static final String TABLE_ROW_DATA_JSON = "data_json";
+ private static final String TABLE_ROW_NOTE = "note";
+ private Context context;
+
+ public EventLogManager(Context context) {
+ this.context = context;
+
+ // create or open the database
+ CustomSQLiteOpenHelper helper = new CustomSQLiteOpenHelper(context);
+ this.db = helper.getWritableDatabase();
+
+ helper.onCreate(this.db);
+ }
+
+ // the beginnings our SQLiteOpenHelper class
+ private class CustomSQLiteOpenHelper extends SQLiteOpenHelper {
+
+ public CustomSQLiteOpenHelper(Context context) {
+ super(context, DB_NAME, null, DB_VERSION);
+ }
+
+ @Override
+ public void onCreate(SQLiteDatabase db) {
+ // the SQLite query string that will create our column database
+ // table.
+ String newTableQueryString = "create table " + TABLE_NAME + " ("
+ + TABLE_ROW_ID
+ + " integer primary key autoincrement not null,"
+ + TABLE_ROW_DATE + " timestamp not null," + TABLE_ROW_ALARM_STATE
+ + " integer not null," + TABLE_ROW_NOTE + " text not null,"
+ + TABLE_ROW_DATA_JSON + " text not null" + ");";
+
+ // execute the query string to the database.
+ db.execSQL(newTableQueryString);
+ }
+
+ @Override
+ public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
+
+ // LATER, WE WOULD SPECIFIY HOW TO UPGRADE THE DATABASE
+ // FROM OLDER VERSIONS.
+ String DROP_TABLE = "DROP TABLE IF EXISTS " + TABLE_NAME;
+ db.execSQL(DROP_TABLE);
+ onCreate(db);
+
+ }
+
+ }
+
+ public void addRow(LogEntryModel eventObj) {
+ ContentValues values = prepareData(eventObj);
+ // ask the database object to insert the new data
+ try {
+ db.insert(TABLE_NAME, null, values);
+ } catch (Exception e) {
+ Log.e("DB ERROR", e.toString()); // prints the error message to
+ // the log
+ e.printStackTrace(); // prints the stack trace to the log
+ }
+ }
+
+ private String getDateTime(Date date) {
+ SimpleDateFormat dateFormat = new SimpleDateFormat(
+ "yyyy-MM-dd HH:mm:ss", Locale.getDefault());
+ if (date==null)
+ return "";
+ else
+ return dateFormat.format(date);
+ }
+
+ private ContentValues prepareData(LogEntryModel eventObj) {
+
+ ContentValues values = new ContentValues();
+ values.put(TABLE_ROW_ALARM_STATE, eventObj.getAlarmState());
+ values.put(TABLE_ROW_DATE, getDateTime(eventObj.getDate()));
+ values.put(TABLE_ROW_NOTE, eventObj.getNote());
+ values.put(TABLE_ROW_DATA_JSON, eventObj.getDataJSON());
+ return values;
+ }
+
+ // Returns row data in form of LogEntryModel object
+ public LogEntryModel getRowAsObject(int rowID) {
+
+ LogEntryModel rowContactObj = new LogEntryModel();
+ Cursor cursor;
+
+ try {
+
+ cursor = db.query(TABLE_NAME, new String[] { TABLE_ROW_ID,
+ TABLE_ROW_ALARM_STATE, TABLE_ROW_DATE, TABLE_ROW_NOTE,
+ TABLE_ROW_DATA_JSON }, TABLE_ROW_ID + "=" + rowID, null,
+ null, null, null, null);
+
+ cursor.moveToFirst();
+ prepareSendObject(rowContactObj, cursor);
+
+ } catch (SQLException e) {
+ Log.e("DB ERROR", e.toString());
+ e.printStackTrace();
+ }
+
+ return rowContactObj;
+ }
+
+ // Returns all the rows data in form of LogEntryModel object list
+
+ public ArrayList getAllData() {
+
+ ArrayList allRowsObj = new ArrayList();
+ Cursor cursor;
+ LogEntryModel rowContactObj;
+
+ String[] columns = new String[] { TABLE_ROW_ID, TABLE_ROW_ALARM_STATE,
+ TABLE_ROW_DATE, TABLE_ROW_NOTE, TABLE_ROW_DATA_JSON };
+
+ try {
+
+ cursor = db
+ .query(TABLE_NAME, columns, null, null, null, null, null);
+ cursor.moveToFirst();
+
+ if (!cursor.isAfterLast()) {
+ do {
+ rowContactObj = new LogEntryModel();
+ rowContactObj.setId(cursor.getInt(0));
+ prepareSendObject(rowContactObj, cursor);
+ allRowsObj.add(rowContactObj);
+
+ } while (cursor.moveToNext()); // try to move the cursor's
+ // pointer forward one position.
+ }
+ } catch (SQLException e) {
+ Log.e("DB ERROR", e.toString());
+ e.printStackTrace();
+ }
+
+ return allRowsObj;
+
+ }
+
+ private void prepareSendObject(LogEntryModel rowObj, Cursor cursor) {
+ rowObj.setId(cursor.getInt(cursor.getColumnIndexOrThrow(TABLE_ROW_ID)));
+ rowObj.setAlarmState(cursor.getInt(cursor
+ .getColumnIndexOrThrow(TABLE_ROW_ALARM_STATE)));
+ String dateTimeStr = cursor.getString(cursor
+ .getColumnIndexOrThrow(TABLE_ROW_DATE));
+ Log.v(TAG,"dateTimeStr = "+dateTimeStr);
+ Date dateVal;
+ try { dateVal = new Date(dateTimeStr); }
+ catch (IllegalArgumentException e) { dateVal = null; }
+ rowObj.setDate(dateVal);
+ rowObj.setNote(cursor.getString(cursor
+ .getColumnIndexOrThrow(TABLE_ROW_NOTE)));
+ rowObj.setDataJSON(cursor.getString(cursor
+ .getColumnIndexOrThrow(TABLE_ROW_DATA_JSON)));
+ }
+
+ public void deleteRow(int rowID) {
+ // ask the database manager to delete the row of given id
+ try {
+ db.delete(TABLE_NAME, TABLE_ROW_ID + "=" + rowID, null);
+ } catch (Exception e) {
+ Log.e("DB ERROR", e.toString());
+ e.printStackTrace();
+ }
+ }
+
+ public void updateRow(int rowId, LogEntryModel contactObj) {
+
+ ContentValues values = prepareData(contactObj);
+
+ String whereClause = TABLE_ROW_ID + "=?";
+ String whereArgs[] = new String[] { String.valueOf(rowId) };
+
+ db.update(TABLE_NAME, values, whereClause, whereArgs);
+
+ }
+
+
+}
diff --git a/app/src/main/java/uk/org/openseizuredetector/EventLogManager/LogEntryModel.java b/app/src/main/java/uk/org/openseizuredetector/EventLogManager/LogEntryModel.java
new file mode 100644
index 0000000..9502239
--- /dev/null
+++ b/app/src/main/java/uk/org/openseizuredetector/EventLogManager/LogEntryModel.java
@@ -0,0 +1,53 @@
+package uk.org.openseizuredetector.EventLogManager;
+
+import java.util.Date;
+
+/**
+ * Our LogEntryModel class which will have fields like id, name, contact number
+ * and email and corresponding getter and setter methods.
+ * **/
+public class LogEntryModel {
+
+ private int id;
+ private Date date;
+ private int alarmState;
+ private String dataJSON;
+ private String note;
+
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public int getAlarmState() {
+ return alarmState;
+ }
+
+ public void setAlarmState(int alarmState) {
+ this.alarmState = alarmState;
+ }
+
+ public String getNote() {
+ return note;
+ }
+
+ public void setNote(String note) {
+ this.note = note;
+ }
+
+ public Date getDate() {
+ return date;
+ }
+
+ public void setDate(Date date) {
+ this.date = date;
+ }
+
+ public String getDataJSON() { return dataJSON; }
+
+ public void setDataJSON(String dataJSON) { this.dataJSON = dataJSON; }
+}
diff --git a/app/src/main/java/uk/org/openseizuredetector/LogManagerActivity.java b/app/src/main/java/uk/org/openseizuredetector/LogManagerActivity.java
new file mode 100644
index 0000000..5da2319
--- /dev/null
+++ b/app/src/main/java/uk/org/openseizuredetector/LogManagerActivity.java
@@ -0,0 +1,42 @@
+package uk.org.openseizuredetector;
+
+import android.app.Activity;
+import android.support.v7.app.AppCompatActivity;
+import android.os.Bundle;
+import android.widget.ListView;
+
+import java.util.Date;
+
+import uk.org.openseizuredetector.EventLogManager.EventLogListAdapter;
+import uk.org.openseizuredetector.EventLogManager.EventLogManager;
+import uk.org.openseizuredetector.EventLogManager.LogEntryModel;
+
+public class LogManagerActivity extends Activity {
+
+ private EventLogListAdapter mEventLogListAdapter;
+ private ListView mEventLogListView;
+ private EventLogManager mElm;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_log_manager);
+
+ LogEntryModel lem = new LogEntryModel();
+ //lem.setDate(new Date());
+ lem.setNote("Test Entry");
+ lem.setDataJSON("[]");
+ lem.setAlarmState(1);
+
+ mElm = new EventLogManager(this);
+ mElm.addRow(lem);
+
+ mEventLogListAdapter = new EventLogListAdapter(this);
+ mEventLogListView = (ListView) findViewById(R.id.eventLogListView);
+ mEventLogListView.setAdapter(mEventLogListAdapter);
+
+
+ }
+
+
+}
diff --git a/app/src/main/java/uk/org/openseizuredetector/MainActivity.java b/app/src/main/java/uk/org/openseizuredetector/MainActivity.java
index 89d9899..f05089d 100644
--- a/app/src/main/java/uk/org/openseizuredetector/MainActivity.java
+++ b/app/src/main/java/uk/org/openseizuredetector/MainActivity.java
@@ -222,6 +222,17 @@ public class MainActivity extends Activity {
mConnection.mSdServer.sendSMSAlarm();
}
return true;
+ case R.id.action_logs:
+ Log.v(TAG, "action_logs");
+ try {
+ Intent prefsIntent = new Intent(
+ MainActivity.this,
+ LogManagerActivity.class);
+ this.startActivity(prefsIntent);
+ } catch (Exception ex) {
+ Log.v(TAG, "exception starting log manager activity " + ex.toString());
+ }
+ return true;
case R.id.action_settings:
Log.v(TAG, "action_settings");
try {
diff --git a/app/src/main/res/layout/activity_log_manager.xml b/app/src/main/res/layout/activity_log_manager.xml
new file mode 100644
index 0000000..5143735
--- /dev/null
+++ b/app/src/main/res/layout/activity_log_manager.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/log_entry_layout.xml b/app/src/main/res/layout/log_entry_layout.xml
new file mode 100644
index 0000000..2c8fa5d
--- /dev/null
+++ b/app/src/main/res/layout/log_entry_layout.xml
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/menu/main_activity_actions.xml b/app/src/main/res/menu/main_activity_actions.xml
index 04321e1..c196140 100644
--- a/app/src/main/res/menu/main_activity_actions.xml
+++ b/app/src/main/res/menu/main_activity_actions.xml
@@ -47,11 +47,20 @@
android:title="Test SMS Alarm Notification" />
+
+
+ android:title="Settings"
+ />