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" + />