diff --git a/app/build.gradle b/app/build.gradle
index cfea828..1bf48c9 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -28,6 +28,7 @@ android {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
+ buildToolsVersion '29.0.2'
}
dependencies {
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 069609f..66c7269 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -40,7 +40,7 @@
-
+
diff --git a/app/src/main/java/uk/org/openseizuredetector/AccelData.java b/app/src/main/java/uk/org/openseizuredetector/AccelData.java
deleted file mode 100644
index 2eabed3..0000000
--- a/app/src/main/java/uk/org/openseizuredetector/AccelData.java
+++ /dev/null
@@ -1,85 +0,0 @@
-package uk.org.openseizuredetector;
-
-import android.util.Log;
-
-import org.json.JSONException;
-import org.json.JSONObject;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.TimeZone;
-
-/**
- * Created by graham on 27/06/16.
- */
-/* From https://github.com/kramimus/pebble-accel-analyzer */
-public class AccelData {
- private final String TAG = AccelData.class.getSimpleName();
-
- final private int x;
- final private int y;
- final private int z;
-
- private long timestamp = 0;
- final private boolean didVibrate;
-
- public AccelData(byte[] data) {
- x = (data[0] & 0xff) | (data[1] << 8);
- y = (data[2] & 0xff) | (data[3] << 8);
- z = (data[4] & 0xff) | (data[5] << 8);
- didVibrate = data[6] != 0;
-
- for (int i = 0; i < 8; i++) {
- timestamp |= ((long)(data[i+7] & 0xff)) << (i * 8);
- }
- }
-
- public JSONObject toJson() {
- JSONObject json = new JSONObject();
- try {
- json.put("x", x);
- json.put("y", y);
- json.put("z", z);
- json.put("ts", timestamp);
- json.put("v", didVibrate);
- return json;
- } catch (JSONException e) {
- Log.w(TAG, "problem constructing accel data, skipping " + e);
- }
- return null;
- }
-
- public static List fromDataArray(byte[] data) {
- List accels = new ArrayList();
- for (int i = 0; i < data.length; i += 15) {
- accels.add(new AccelData(Arrays.copyOfRange(data, i, i + 15)));
- }
- return accels;
- }
-
- public long getTimestamp() {
- return timestamp;
- }
-
- public int getX() {
- return x;
- }
-
- public int getY() {
- return y;
- }
-
- public int getZ() {
- return z;
- }
-
- public int getMagnitude() {
- return (int)Math.sqrt(x*x + y*y + z*z);
- }
-
- public void applyTimezone(TimeZone tz) {
- timestamp -= tz.getOffset(timestamp);
- }
-}
-
diff --git a/app/src/main/java/uk/org/openseizuredetector/AuthCallbackInterface.java b/app/src/main/java/uk/org/openseizuredetector/AuthCallbackInterface.java
deleted file mode 100644
index 8422ffe..0000000
--- a/app/src/main/java/uk/org/openseizuredetector/AuthCallbackInterface.java
+++ /dev/null
@@ -1,6 +0,0 @@
-package uk.org.openseizuredetector;
-
-// Interface used by the authentication part of WebApi to send back the authentication token
-public interface AuthCallbackInterface {
- void authCallback(boolean success, String tokenStr);
-}
diff --git a/app/src/main/java/uk/org/openseizuredetector/AuthDialogInterface.java b/app/src/main/java/uk/org/openseizuredetector/AuthDialogInterface.java
deleted file mode 100644
index f59b062..0000000
--- a/app/src/main/java/uk/org/openseizuredetector/AuthDialogInterface.java
+++ /dev/null
@@ -1,5 +0,0 @@
-package uk.org.openseizuredetector;
-
-public interface AuthDialogInterface {
- void onDialogDone(boolean state);
-}
\ No newline at end of file
diff --git a/app/src/main/java/uk/org/openseizuredetector/AuthenticateActivity.java b/app/src/main/java/uk/org/openseizuredetector/AuthenticateActivity.java
index f103e6b..8b27303 100644
--- a/app/src/main/java/uk/org/openseizuredetector/AuthenticateActivity.java
+++ b/app/src/main/java/uk/org/openseizuredetector/AuthenticateActivity.java
@@ -2,6 +2,8 @@ package uk.org.openseizuredetector;
import android.content.Context;
import android.content.SharedPreferences;
+import android.os.Handler;
+import android.preference.PreferenceManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
@@ -12,20 +14,28 @@ import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;
-public class AuthenticateActivity extends AppCompatActivity
- implements AuthCallbackInterface, EventCallbackInterface, DatapointCallbackInterface {
+import org.json.JSONObject;
+
+public class AuthenticateActivity extends AppCompatActivity {
private String TAG = "AuthenticateActivity";
- private Context mContext;
private EditText mUnameEt;
private EditText mPasswdEt;
private WebApiConnection mWac;
private LogManager mLm;
+ private SdServiceConnection mConnection;
+ private OsdUtil mUtil;
+ final Handler serverStatusHandler = new Handler();
+ private String TOKEN_ID = "webApiAuthToken";
@Override
protected void onCreate(Bundle savedInstanceState) {
Log.v(TAG, "onCreate()");
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_authenticate);
+
+ mUtil = new OsdUtil(getApplicationContext(), serverStatusHandler);
+ mConnection = new SdServiceConnection(getApplicationContext());
+
Button cancelBtn =
(Button) findViewById(R.id.cancelBtn);
cancelBtn.setOnClickListener(onCancel);
@@ -39,21 +49,47 @@ public class AuthenticateActivity extends AppCompatActivity
mUnameEt = (EditText) findViewById(R.id.username);
mPasswdEt = (EditText) findViewById(R.id.password);
- mWac = new WebApiConnection(this, this, this, this);
- mLm = new LogManager(this);
+ //mWac = new WebApiConnection(this, String tokenStr);
+ //mLm = new LogManager(this);
}
@Override
protected void onStart() {
super.onStart();
+ mUtil.bindToServer(getApplicationContext(), mConnection);
+ waitForConnection();
+
updateUi();
}
- public void authCallback(boolean authSuccess, String tokenStr) {
- Log.v(TAG,"authCallback");
- updateUi();
+ private void waitForConnection() {
+ // We want the UI to update as soon as it is displayed, but it takes a finite time for
+ // the mConnection to bind to the service, so we delay half a second to give it chance
+ // to connect before trying to update the UI for the first time (it happens again periodically using the uiTimer)
+ if (mConnection.mBound) {
+ Log.v(TAG, "waitForConnection - Bound!");
+ initialiseServiceConnection();
+ } else {
+ Log.v(TAG, "waitForConnection - waiting...");
+ new Handler().postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ waitForConnection();
+ }
+ }, 100);
+ }
}
+ private void initialiseServiceConnection() {
+ mLm = mConnection.mSdServer.mLm;
+ mWac = mConnection.mSdServer.mLm.mWac;
+ }
+
+ //public void authCallback(boolean authSuccess, String tokenStr) {
+ //Log.v(TAG,"authCallback");
+ // updateUi();
+ //}
+
public void eventCallback(boolean success, String eventStr) {
Log.v(TAG,"eventCallback");
}
@@ -68,7 +104,7 @@ public class AuthenticateActivity extends AppCompatActivity
LinearLayout loginLl = (LinearLayout)findViewById(R.id.login_ui);
LinearLayout logoutLl = (LinearLayout)findViewById(R.id.logout_ui);
Log.i(TAG, "switchUi()");
- storedAuthToken = mWac.getStoredToken();
+ storedAuthToken = getAuthToken(); //mWac.getStoredToken();
//prefs = PreferenceManager.getDefaultSharedPreferences(this);
//storedAuthToken = (prefs.getString("webApiAuthToken", null));
Log.v(TAG, "storedAuthToken=" + storedAuthToken);
@@ -107,7 +143,13 @@ public class AuthenticateActivity extends AppCompatActivity
String uname = mUnameEt.getText().toString();
String passwd = mPasswdEt.getText().toString();
Log.v(TAG,"onOK() - uname="+uname+", passwd="+passwd);
- mWac.authenticate(uname,passwd);
+ mWac.authenticate(uname,passwd, (String retVal) -> {
+ if (retVal != null) {
+ Log.d(TAG,"Authentication Success - token is "+retVal);
+ saveAuthToken(retVal);
+ updateUi();
+ }
+ });
//finish();
}
};
@@ -119,7 +161,23 @@ public class AuthenticateActivity extends AppCompatActivity
Log.v(TAG, "onLogout");
//m_status=false;
mWac.logout();
+ saveAuthToken(null);
updateUi();
}
};
+
+ private void saveAuthToken(String tokenStr) {
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
+ prefs.edit().putString(TOKEN_ID, tokenStr).commit();
+ mWac.setStoredToken(tokenStr);
+ }
+
+ public String getAuthToken() {
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
+ String authToken = prefs.getString(TOKEN_ID, null);
+ return authToken;
+ }
+
+
+
}
\ No newline at end of file
diff --git a/app/src/main/java/uk/org/openseizuredetector/CircularArrayList.java b/app/src/main/java/uk/org/openseizuredetector/CircularArrayList.java
deleted file mode 100644
index 08d7d10..0000000
--- a/app/src/main/java/uk/org/openseizuredetector/CircularArrayList.java
+++ /dev/null
@@ -1,107 +0,0 @@
-package uk.org.openseizuredetector;
-
-import java.util.AbstractList;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.RandomAccess;
-
-/**
- * Created by graham on 28/06/16.
- */
-public class CircularArrayList
- extends AbstractList implements RandomAccess {
- /**
- * If you use this code, please consider notifying isak at du-preez dot com
- * with a brief description of your application.
- *
- * This is free and unencumbered software released into the public domain.
- * Anyone is free to copy, modify, publish, use, compile, sell, or
- * distribute this software, either in source code form or as a compiled
- * binary, for any purpose, commercial or non-commercial, and by any
- * means.
- */
-
- private final int n; // buffer length
- private final List buf; // a List implementing RandomAccess
- private int head = 0;
- private int tail = 0;
-
- public CircularArrayList(int capacity) {
- n = capacity + 1;
- buf = new ArrayList(Collections.nCopies(n, (E) null));
- }
-
- public int capacity() {
- return n - 1;
- }
-
- private int wrapIndex(int i) {
- int m = i % n;
- if (m < 0) { // java modulus can be negative
- m += n;
- }
- return m;
- }
-
- // This method is O(n) but will never be called if the
- // CircularArrayList is used in its typical/intended role.
- private void shiftBlock(int startIndex, int endIndex) {
- assert (endIndex > startIndex);
- for (int i = endIndex - 1; i >= startIndex; i--) {
- set(i + 1, get(i));
- }
- }
-
- @Override
- public int size() {
- return tail - head + (tail < head ? n : 0);
- }
-
- @Override
- public E get(int i) {
- if (i < 0 || i >= size()) {
- throw new IndexOutOfBoundsException();
- }
- return buf.get(wrapIndex(head + i));
- }
-
- @Override
- public E set(int i, E e) {
- if (i < 0 || i >= size()) {
- throw new IndexOutOfBoundsException();
- }
- return buf.set(wrapIndex(head + i), e);
- }
-
- @Override
- public void add(int i, E e) {
- int s = size();
- if (s == n - 1) {
- throw new IllegalStateException("Cannot add element."
- + " CircularArrayList is filled to capacity.");
- }
- if (i < 0 || i > s) {
- throw new IndexOutOfBoundsException();
- }
- tail = wrapIndex(tail + 1);
- if (i < s) {
- shiftBlock(i, s);
- }
- set(i, e);
- }
-
- @Override
- public E remove(int i) {
- int s = size();
- if (i < 0 || i >= s) {
- throw new IndexOutOfBoundsException();
- }
- E e = get(i);
- if (i > 0) {
- shiftBlock(0, i);
- }
- head = wrapIndex(head + 1);
- return e;
- }
-}
diff --git a/app/src/main/java/uk/org/openseizuredetector/DatapointCallbackInterface.java b/app/src/main/java/uk/org/openseizuredetector/DatapointCallbackInterface.java
deleted file mode 100644
index de4fddc..0000000
--- a/app/src/main/java/uk/org/openseizuredetector/DatapointCallbackInterface.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package uk.org.openseizuredetector;
-
-public interface DatapointCallbackInterface {
- // Interface is called when a new datapoint is created in the database.
- void datapointCallback(boolean success, String eventStr);
- }
-
diff --git a/app/src/main/java/uk/org/openseizuredetector/EditEventActivity.java b/app/src/main/java/uk/org/openseizuredetector/EditEventActivity.java
index 08e4c0c..3c4282b 100644
--- a/app/src/main/java/uk/org/openseizuredetector/EditEventActivity.java
+++ b/app/src/main/java/uk/org/openseizuredetector/EditEventActivity.java
@@ -27,12 +27,12 @@ import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
-public class EditEventActivity extends AppCompatActivity
- implements AuthCallbackInterface, EventCallbackInterface, DatapointCallbackInterface {
+public class EditEventActivity extends AppCompatActivity {
private String TAG = "EditEventActivity";
private Context mContext;
private WebApiConnection mWac;
private LogManager mLm;
+ private SdServiceConnection mConnection;
final Handler serverStatusHandler = new Handler();
private OsdUtil mUtil;
private List mEventTypesList = null;
@@ -54,9 +54,11 @@ public class EditEventActivity extends AppCompatActivity
Log.v(TAG, "onCreate()");
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_edit_event);
+ mUtil = new OsdUtil(getApplicationContext(), serverStatusHandler);
+ mConnection = new SdServiceConnection(getApplicationContext());
- mWac = new WebApiConnection(this, this, this, this);
- mLm = new LogManager(this);
+ //mWac = new WebApiConnection(this, this, this, this);
+ //mLm = new LogManager(this);
Bundle extras = getIntent().getExtras();
@@ -64,25 +66,8 @@ public class EditEventActivity extends AppCompatActivity
Long eventId = extras.getLong("eventId");
mEventId = eventId;
Log.v(TAG, "onCreate - mEventId=" + mEventId);
- try {
- mWac.getEvent(mEventId, (JSONObject eventObj) -> {
- Log.v(TAG,"onCreate.getEvent");
- if (eventObj != null) {
- mEventObj = eventObj;
- Log.v(TAG, "onCreate.getEvent: eventObj=" + eventObj.toString());
- updateUi();
- // FIXME: modify updateUi to use mEventObj
- } else {
- mUtil.showToast("Failed to Retrieve Event from Remote Database");
- finish();
- }
- });
- } catch (Exception e) {
- Log.e(TAG,"ERROR:"+e.getMessage());
- e.printStackTrace();
- }
}
- mUtil = new OsdUtil(this, serverStatusHandler);
+
Button cancelBtn =
(Button) findViewById(R.id.cancelBtn);
@@ -96,13 +81,47 @@ public class EditEventActivity extends AppCompatActivity
mEventSubTypeRg.setOnCheckedChangeListener(onEventSubTypeChange);
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ Log.v(TAG, "onStart()");
+ mUtil.bindToServer(getApplicationContext(), mConnection);
+ waitForConnection();
+
+ updateUi();
+ }
+
+ private void waitForConnection() {
+ // We want the UI to update as soon as it is displayed, but it takes a finite time for
+ // the mConnection to bind to the service, so we delay half a second to give it chance
+ // to connect before trying to update the UI for the first time (it happens again periodically using the uiTimer)
+ if (mConnection.mBound) {
+ Log.v(TAG, "waitForConnection - Bound!");
+ initialiseServiceConnection();
+ } else {
+ Log.v(TAG, "waitForConnection - waiting...");
+ new Handler().postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ waitForConnection();
+ }
+ }, 100);
+ }
+ }
+
+ private void initialiseServiceConnection() {
+ mLm = mConnection.mSdServer.mLm;
+ mWac = mConnection.mSdServer.mLm.mWac;
+
// Retrieve the JSONObject containing the standard event types.
// Note this obscure syntax is to avoid having to create another interface, so it is worth it :)
// See https://medium.com/@pra4mesh/callback-function-in-java-20fa48b27797
mWac.getEventTypes((JSONObject eventTypesObj) -> {
- Log.v(TAG, "onCreate.onEventTypesReceived");
+ Log.v(TAG, "initialiseServiceConnection().onEventTypesReceived");
if (eventTypesObj == null) {
- Log.e(TAG, "onCreate.getEventTypes Callback: Error Retrieving event types");
+ Log.e(TAG, "initialiseServiceConnection().getEventTypes Callback: Error Retrieving event types");
mUtil.showToast("Error Retrieving Event Types from Server - Please Try Again Later!");
} else {
Iterator keys = eventTypesObj.keys();
@@ -110,7 +129,7 @@ public class EditEventActivity extends AppCompatActivity
mEventSubTypesHashMap = new HashMap>();
while (keys.hasNext()) {
String key = keys.next();
- Log.v(TAG, "onCreate.getEventTypes Callback: key=" + key);
+ Log.v(TAG, "initialiseServiceConnection().getEventTypes Callback: key=" + key);
mEventTypesList.add(key);
try {
JSONArray eventSubTypes = eventTypesObj.getJSONArray(key);
@@ -121,33 +140,37 @@ public class EditEventActivity extends AppCompatActivity
mEventSubTypesHashMap.put(key, eventSubtypesList);
mEventTypesListChanged = true;
} catch (JSONException e) {
- Log.e(TAG, "onCreate(getEventTypes Callback: Error parsing JSONObject" + e.getMessage() + e.toString());
+ Log.e(TAG, "initialiseServiceConnection().getEventTypes Callback: Error parsing JSONObject" + e.getMessage() + e.toString());
}
}
updateUi();
}
});
+
+ // Retrieve the event data to edit
+ try {
+ mWac.getEvent(mEventId, (JSONObject eventObj) -> {
+ Log.v(TAG,"onCreate.getEvent");
+ if (eventObj != null) {
+ mEventObj = eventObj;
+ Log.v(TAG, "onCreate.getEvent: eventObj=" + eventObj.toString());
+ updateUi();
+ // FIXME: modify updateUi to use mEventObj
+ } else {
+ mUtil.showToast("Failed to Retrieve Event from Remote Database");
+ finish();
+ }
+ });
+ } catch (Exception e) {
+ Log.e(TAG,"ERROR:"+e.getMessage());
+ e.printStackTrace();
+ }
+
+
}
- @Override
- protected void onStart() {
- super.onStart();
- Log.v(TAG, "onStart()");
- updateUi();
- }
- public void authCallback(boolean authSuccess, String tokenStr) {
- Log.v(TAG, "authCallback");
- updateUi();
- }
- public void eventCallback(boolean success, String eventStr) {
- Log.v(TAG, "eventCallback");
- }
-
- public void datapointCallback(boolean success, String datapointStr) {
- Log.v(TAG, "datapointCallback");
- }
private void updateUi() {
Log.v(TAG, "updateUI");
diff --git a/app/src/main/java/uk/org/openseizuredetector/EventCallbackInterface.java b/app/src/main/java/uk/org/openseizuredetector/EventCallbackInterface.java
deleted file mode 100644
index 01735a9..0000000
--- a/app/src/main/java/uk/org/openseizuredetector/EventCallbackInterface.java
+++ /dev/null
@@ -1,6 +0,0 @@
-package uk.org.openseizuredetector;
-
-public interface EventCallbackInterface {
- // Interface is called when a new event is created in the database.
- void eventCallback(boolean success, String eventStr);
- }
diff --git a/app/src/main/java/uk/org/openseizuredetector/DBQueryActivity.java b/app/src/main/java/uk/org/openseizuredetector/ExportDataActivity.java
similarity index 97%
rename from app/src/main/java/uk/org/openseizuredetector/DBQueryActivity.java
rename to app/src/main/java/uk/org/openseizuredetector/ExportDataActivity.java
index d653e6b..c64e459 100644
--- a/app/src/main/java/uk/org/openseizuredetector/DBQueryActivity.java
+++ b/app/src/main/java/uk/org/openseizuredetector/ExportDataActivity.java
@@ -15,9 +15,9 @@ import android.widget.TimePicker;
import java.util.Calendar;
-public class DBQueryActivity extends AppCompatActivity
+public class ExportDataActivity extends AppCompatActivity
implements View.OnClickListener {
- String TAG = "DBQueryActivity";
+ String TAG = "ExportDataActivity";
Button mDateBtn;
Button mTimeBtn;
Button mExportBtn;
diff --git a/app/src/main/java/uk/org/openseizuredetector/LogManager.java b/app/src/main/java/uk/org/openseizuredetector/LogManager.java
index ce5b309..d0d6e73 100644
--- a/app/src/main/java/uk/org/openseizuredetector/LogManager.java
+++ b/app/src/main/java/uk/org/openseizuredetector/LogManager.java
@@ -70,12 +70,13 @@ import static android.database.sqlite.SQLiteDatabase.openOrCreateDatabase;
* - Upload the datapoints, linking them to the new eventID.
* - Mark all the uploaded datapoints as uploaded.
*/
-public class LogManager implements AuthCallbackInterface, EventCallbackInterface, DatapointCallbackInterface {
+public class LogManager {
private String TAG = "LogManager";
private String mDbName = "osdData";
private String mDbTableName = "datapoints";
private boolean mLogRemote;
private boolean mLogRemoteMobile;
+ private String mAuthToken;
private OsdDbHelper mOSDDb;
private RemoteLogTimer mRemoteLogTimer;
private Context mContext;
@@ -94,38 +95,33 @@ public class LogManager implements AuthCallbackInterface, EventCallbackInterface
private AutoPruneTimer mAutoPruneTimer;
- public LogManager(Context context) {
+ public LogManager(Context context,
+ boolean logRemote, boolean logRemoteMobile, String authToken,
+ long eventDuration, long remoteLogPeriod,
+ boolean autoPruneDb, long dataRetentionPeriod) {
String prefVal;
Log.d(TAG, "LogManger Constructor");
mContext = context;
Handler handler = new Handler();
- SharedPreferences prefs;
- prefs = PreferenceManager.getDefaultSharedPreferences(mContext);
- mLogRemote = (prefs.getBoolean("LogDataRemote", false));
+ mLogRemote = logRemote;
+ mLogRemoteMobile = logRemoteMobile;
+ mAuthToken = authToken;
+ mEventDuration = eventDuration;
+ mAutoPruneDb = autoPruneDb;
+ mDataRetentionPeriod = dataRetentionPeriod;
+ mRemoteLogPeriod = remoteLogPeriod;
Log.v(TAG, "mLogRemote=" + mLogRemote);
- mLogRemoteMobile = (prefs.getBoolean("LogDataRemoteMobile", false));
Log.v(TAG, "mLogRemoteMobile=" + mLogRemoteMobile);
-
- prefVal = prefs.getString("EventDurationSec", "300");
- mEventDuration = Integer.parseInt(prefVal);
Log.v(TAG, "mEventDuration=" + mEventDuration);
-
- mAutoPruneDb = prefs.getBoolean("AutoPruneDb", false);
Log.v(TAG, "mAutoPruneDb=" + mAutoPruneDb);
-
- prefVal = prefs.getString("DataRetentionPeriod", "28");
- mDataRetentionPeriod = Integer.parseInt(prefVal);
Log.v(TAG, "mDataRetentionPeriod=" + mDataRetentionPeriod);
-
- prefVal = prefs.getString("RemoteLogPeriod", "60");
- mRemoteLogPeriod = Integer.parseInt(prefVal);
Log.v(TAG, "mRemoteLogPeriod=" + mRemoteLogPeriod);
-
mUtil = new OsdUtil(mContext, handler);
openDb();
- mWac = new WebApiConnection(mContext, this, this, this);
+ mWac = new WebApiConnection(mContext);
+ mWac.setStoredToken(mAuthToken);
startRemoteLogTimer();
@@ -417,8 +413,8 @@ public class LogManager implements AuthCallbackInterface, EventCallbackInterface
String whereClauseDate = "DataTime";
String whereClause = whereClauseStatus + " AND " + whereClauseUploaded + " AND " + whereClauseDate;
- String[] whereArgs = new String[ whereArgsStatus.length + 1];
- for (int i = 0; i callback) {
Log.v(TAG, "getNextEventToDate - dateStr=" + dateStr);
- String[] columns = {"*","(julianday(dataTime)-julianday(datetime('" + dateStr + "'))) as ddiff"};
+ String[] columns = {"*", "(julianday(dataTime)-julianday(datetime('" + dateStr + "'))) as ddiff"};
//SQLStr = "SELECT *, (julianday(dataTime)-julianday(datetime('" + dateStr + "'))) as ddiff from " + mDbTableName + " order by ABS(ddiff) asc;";
String orderByStr = "ABS(ddiff) asc";
new SelectQueryTask(mDbTableName, columns, null, null,
@@ -601,24 +597,22 @@ public class LogManager implements AuthCallbackInterface, EventCallbackInterface
} else {
whereClause = "Status in (?, ?, ?)";
}
- return(whereClause);
+ return (whereClause);
}
private String[] getEventWhereArgs(boolean includeWarnings) {
String[] whereArgs;
if (includeWarnings) {
- String[] whereArgsWarnings = { "1", "2", "3", "5"};
+ String[] whereArgsWarnings = {"1", "2", "3", "5"};
whereArgs = whereArgsWarnings;
} else {
- String[] whereArgsNoWarnings = { "2", "3", "5"};
+ String[] whereArgsNoWarnings = {"2", "3", "5"};
whereArgs = whereArgsNoWarnings;
}
- return(whereArgs);
+ return (whereArgs);
}
-
-
/***************************************************************************************
* Remote Database Part
*/
@@ -694,17 +688,13 @@ public class LogManager implements AuthCallbackInterface, EventCallbackInterface
Log.e(TAG, "Error parsing date " + eventDateStr);
return;
}
- mWac.createEvent(eventAlarmStatus, eventDate, "Uploaded by OpenSeizureDetector Android App");
+ mWac.createEvent(eventAlarmStatus, eventDate, "", this::createEventCallback);
} else {
Log.v(TAG, "UploadSdData - no data to upload");
}
});
}
- public void authCallback(boolean authSuccess, String tokenStr) {
- Log.v(TAG, "authCallback");
- }
-
// Mark the relevant member variables to show we are not currently doing an upload, so a new one can be
// started if necessary.
@@ -717,7 +707,7 @@ public class LogManager implements AuthCallbackInterface, EventCallbackInterface
// Called by WebApiConnection when a new event record is created.
// Once the event is created it queries the local database to find the datapoints associated with the event
// and uploads those as a batch of data points.
- public void eventCallback(boolean success, String eventStr) {
+ public void createEventCallback(String eventStr) {
Log.v(TAG, "eventCallback(): " + eventStr);
Date eventDate;
String eventDateStr;
@@ -788,7 +778,7 @@ public class LogManager implements AuthCallbackInterface, EventCallbackInterface
}
Log.v(TAG, "uploadDatapoint() - uploading datapoint with local id of " + mCurrentDatapointId);
- mWac.createDatapoint(mDatapointsToUploadList.get(0), mCurrentEventId);
+ mWac.createDatapoint(mDatapointsToUploadList.get(0), mCurrentEventId, this::datapointCallback);
} else {
mCurrentEventId = -1;
@@ -800,7 +790,7 @@ public class LogManager implements AuthCallbackInterface, EventCallbackInterface
// Called by WebApiConnection when a new datapoint is created. It assumes that we have just created
// a datapoint based on mDatapointsToUploadList(0) so removes that from the list and calls UploadDatapoint()
// to upload the next one.
- public void datapointCallback(boolean success, String datapointStr) {
+ public void datapointCallback(String datapointStr) {
Log.v(TAG, "datapointCallback() " + datapointStr + ", mCurrentEventId=" + mCurrentEventId);
mDatapointsToUploadList.remove(0);
setDatapointToUploaded(mCurrentDatapointId, mCurrentEventId);
diff --git a/app/src/main/java/uk/org/openseizuredetector/MainActivity.java b/app/src/main/java/uk/org/openseizuredetector/MainActivity.java
index 05e55e4..7fdcfcd 100644
--- a/app/src/main/java/uk/org/openseizuredetector/MainActivity.java
+++ b/app/src/main/java/uk/org/openseizuredetector/MainActivity.java
@@ -25,9 +25,7 @@
package uk.org.openseizuredetector;
-import android.app.Activity;
import android.app.AlertDialog;
-import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Color;
@@ -294,7 +292,7 @@ public class MainActivity extends AppCompatActivity {
try {
Intent i = new Intent(
MainActivity.this,
- DBQueryActivity.class);
+ ExportDataActivity.class);
this.startActivity(i);
} catch (Exception ex) {
Log.i(TAG, "exception starting export activity " + ex.toString());
diff --git a/app/src/main/java/uk/org/openseizuredetector/RemoteDbActivity.java b/app/src/main/java/uk/org/openseizuredetector/RemoteDbActivity.java
index cc5af03..439a0dc 100644
--- a/app/src/main/java/uk/org/openseizuredetector/RemoteDbActivity.java
+++ b/app/src/main/java/uk/org/openseizuredetector/RemoteDbActivity.java
@@ -4,8 +4,11 @@ package uk.org.openseizuredetector;
import android.content.Context;
import android.content.Intent;
+import android.content.SharedPreferences;
import android.os.Bundle;
import android.os.CountDownTimer;
+import android.os.Handler;
+import android.preference.PreferenceManager;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
@@ -22,6 +25,10 @@ public class RemoteDbActivity extends AppCompatActivity {
private UiTimer mUiTimer;
private LogManager mLm;
private WebView mWebView;
+ private SdServiceConnection mConnection;
+ private OsdUtil mUtil;
+ final Handler serverStatusHandler = new Handler();
+ private String TOKEN_ID = "webApiAuthToken";
@Override
@@ -30,7 +37,12 @@ public class RemoteDbActivity extends AppCompatActivity {
super.onCreate(savedInstanceState);
mContext = this;
setContentView(R.layout.activity_remote_db);
- mLm= new LogManager(mContext);
+ mUtil = new OsdUtil(getApplicationContext(), serverStatusHandler);
+ mConnection = new SdServiceConnection(getApplicationContext());
+ mUtil.bindToServer(getApplicationContext(), mConnection);
+ waitForConnection();
+
+ //mLm= new LogManager(mContext);
Button authBtn =
(Button) findViewById(R.id.auth_button);
@@ -43,12 +55,37 @@ public class RemoteDbActivity extends AppCompatActivity {
WebSettings webSettings = mWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
- updateUi();
}
+ private void waitForConnection() {
+ // We want the UI to update as soon as it is displayed, but it takes a finite time for
+ // the mConnection to bind to the service, so we delay half a second to give it chance
+ // to connect before trying to update the UI for the first time (it happens again periodically using the uiTimer)
+ if (mConnection.mBound) {
+ Log.v(TAG, "waitForConnection - Bound!");
+ initialiseServiceConnection();
+ } else {
+ Log.v(TAG, "waitForConnection - waiting...");
+ new Handler().postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ waitForConnection();
+ }
+ }, 100);
+ }
+ }
+
+ private void initialiseServiceConnection() {
+ mLm = mConnection.mSdServer.mLm;
+ //mWac = mConnection.mSdServer.mLm.mWac;
+ }
+
+
@Override
protected void onStart() {
super.onStart();
+ waitForConnection();
+ updateUi();
//startUiTimer();
}
@@ -67,11 +104,16 @@ public class RemoteDbActivity extends AppCompatActivity {
private HashMap getAuthHeaders() {
HashMap headersMap = new HashMap<>();
- String authToken = mLm.mWac.getStoredToken();
+ String authToken = getAuthToken();
headersMap.put("Authorization", "Token "+authToken);
return (headersMap);
}
+ public String getAuthToken() {
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(mContext);
+ String authToken = prefs.getString(TOKEN_ID, null);
+ return authToken;
+ }
private void updateUi() {
Log.v(TAG,"updateUi()");
diff --git a/app/src/main/java/uk/org/openseizuredetector/SdServer.java b/app/src/main/java/uk/org/openseizuredetector/SdServer.java
index d835586..43eceac 100644
--- a/app/src/main/java/uk/org/openseizuredetector/SdServer.java
+++ b/app/src/main/java/uk/org/openseizuredetector/SdServer.java
@@ -86,8 +86,9 @@ public class SdServer extends Service implements SdDataReceiver {
// Notification ID
private int NOTIFICATION_ID = 1;
+ private int EVENT_NOTIFICATION_ID = 2;
private String mNotChId = "OSD Notification Channel";
- private CharSequence mNotChName = "OSD Notification Chennel";
+ private CharSequence mNotChName = "OSD Notification Channel";
private String mNotChDesc = "OSD Notification Channel Description";
private NotificationManager mNM;
@@ -130,9 +131,13 @@ public class SdServer extends Service implements SdDataReceiver {
private boolean mLogData = false;
private boolean mLogDataRemote = false;
private boolean mLogDataRemoteMobile = false;
- private String mOSDUname = "";
- private String mOSDPasswd = "";
- private int mOSDWearerId = 0;
+ private String mAuthToken = null;
+ private long mEventDuration = 120; // event duration in seconds - uploads datapoints that cover this time range centred on the event time.
+ public long mDataRetentionPeriod = 1; // Prunes the local db so it only retains data younger than this duration (in days)
+ private long mRemoteLogPeriod = 60; // Period in seconds between uploads to the remote server.
+ private long mAutoPrunePeriod = 3600; // Prune the database every hour
+ private boolean mAutoPruneDb;
+
private String mOSDUrl = "";
private OsdUtil mUtil;
@@ -219,7 +224,8 @@ public class SdServer extends Service implements SdDataReceiver {
updatePrefs();
// Create our log manager.
- mLm = new LogManager(this);
+ mLm = new LogManager(this, mLogDataRemote, mLogDataRemoteMobile, mAuthToken, mEventDuration,
+ mRemoteLogPeriod, mAutoPruneDb, mDataRetentionPeriod);
Log.v(TAG, "onStartCommand: Datasource =" + mSdDataSourceName);
switch (mSdDataSourceName) {
@@ -1197,12 +1203,32 @@ public class SdServer extends Service implements SdDataReceiver {
mLogDataRemoteMobile = SP.getBoolean("LogDataRemoteMobile", false);
Log.v(TAG, "updatePrefs() - mLogDataRemoteMobile = " + mLogDataRemoteMobile);
mUtil.writeToSysLogFile("updatePrefs() - mLogDataRemoteMobile = " + mLogDataRemoteMobile);
- mOSDUname = SP.getString("OSDUname", "");
- Log.v(TAG, "updatePrefs() - mOSDUname = " + mOSDUname);
- mOSDPasswd = SP.getString("OSDPasswd", "");
- Log.v(TAG, "updatePrefs() - mOSDPasswd = " + mOSDPasswd);
- mOSDWearerId = Integer.parseInt(SP.getString("OSDWearerId", "0"));
- Log.v(TAG, "updatePrefs() - mOSDWearerId = " + mOSDWearerId);
+ mAuthToken = SP.getString("webApiAuthToken", null);
+ Log.v(TAG, "updatePrefs() - mAuthToken = " + mAuthToken);
+ mUtil.writeToSysLogFile("updatePrefs() - mAuthToken = " + mAuthToken);
+
+ String prefVal;
+ prefVal = SP.getString("EventDurationSec", "300");
+ mEventDuration = Integer.parseInt(prefVal);
+ Log.v(TAG, "mEventDuration=" + mEventDuration);
+
+ mAutoPruneDb = SP.getBoolean("AutoPruneDb", false);
+ Log.v(TAG, "mAutoPruneDb=" + mAutoPruneDb);
+
+ prefVal = SP.getString("DataRetentionPeriod", "28");
+ mDataRetentionPeriod = Integer.parseInt(prefVal);
+ Log.v(TAG, "mDataRetentionPeriod=" + mDataRetentionPeriod);
+
+ prefVal = SP.getString("RemoteLogPeriod", "60");
+ mRemoteLogPeriod = Integer.parseInt(prefVal);
+ Log.v(TAG, "mRemoteLogPeriod=" + mRemoteLogPeriod);
+
+ //mOSDUname = SP.getString("OSDUname", "");
+ //Log.v(TAG, "updatePrefs() - mOSDUname = " + mOSDUname);
+ //mOSDPasswd = SP.getString("OSDPasswd", "");
+ //Log.v(TAG, "updatePrefs() - mOSDPasswd = " + mOSDPasswd);
+ //mOSDWearerId = Integer.parseInt(SP.getString("OSDWearerId", "0"));
+ //Log.v(TAG, "updatePrefs() - mOSDWearerId = " + mOSDWearerId);
mOSDUrl = SP.getString("OSDUrl", "http://openseizuredetector.org.uk/webApi");
Log.v(TAG, "updatePrefs() - mOSDUrl = " + mOSDUrl);
mUtil.writeToSysLogFile( "updatePrefs() - mOSDUrl = " + mOSDUrl);
diff --git a/app/src/main/java/uk/org/openseizuredetector/WebApiConnection.java b/app/src/main/java/uk/org/openseizuredetector/WebApiConnection.java
index de46926..e3e6fcb 100644
--- a/app/src/main/java/uk/org/openseizuredetector/WebApiConnection.java
+++ b/app/src/main/java/uk/org/openseizuredetector/WebApiConnection.java
@@ -38,25 +38,26 @@ public class WebApiConnection {
public int retCode;
private String mUrlBase = "https://osdApi.ddns.net";
private String TAG = "WebApiConnection";
- private AuthCallbackInterface mAuthCallback;
- private EventCallbackInterface mEventCallback;
- private DatapointCallbackInterface mDatapointCallback;
+ private String mAuthToken;
private Context mContext;
- private String TOKEN_ID = "webApiAuthToken";
private OsdUtil mUtil;
RequestQueue mQueue;
- public WebApiConnection(Context context, AuthCallbackInterface authCallback, EventCallbackInterface eventCallback,
- DatapointCallbackInterface datapointCallback) {
+ public WebApiConnection(Context context) {
mContext = context;
- mAuthCallback = authCallback;
- mEventCallback = eventCallback;
- mDatapointCallback = datapointCallback;
mQueue = Volley.newRequestQueue(context);
mUtil = new OsdUtil(mContext, new Handler());
}
- public boolean authenticate(final String uname, final String passwd) {
+ /**
+ * Attempt to authenticate with the web API using user name uname and password passwd. Calls function callback with either
+ * the authentication token on success or null on failure.
+ * @param uname - user name
+ * @param passwd - password
+ * @param callback - call back function callback(String retVal)
+ * @return true if request sent, or false if failed to send request.
+ */
+ public boolean authenticate(final String uname, final String passwd, Consumer callback) {
// NOTE: the 'final' keyword is necessary for uname and passwd to be accessible to getParams below - I don't know why!
// We know that this command works, so we just need the Java equivalent:
// curl -X POST -d 'login=graham4&password=testpwd1' https://osdapi.ddns.net/api/accounts/login/
@@ -69,7 +70,7 @@ public class WebApiConnection {
new Response.Listener() {
@Override
public void onResponse(String response) {
- String tokenStr;
+ String tokenStr = null;
Log.v(TAG, "Response is: " + response);
try {
JSONObject jo = new JSONObject(response);
@@ -77,8 +78,8 @@ public class WebApiConnection {
} catch (JSONException e) {
tokenStr = "Error Parsing Rsponse";
}
- saveStoredToken(tokenStr);
- mAuthCallback.authCallback(true, response);
+ setStoredToken(tokenStr);
+ callback.accept(tokenStr);
}
},
new Response.ErrorListener() {
@@ -90,8 +91,8 @@ public class WebApiConnection {
} else {
Log.e(TAG,"Login Error: Returned null response");
}
- saveStoredToken(null);
- mAuthCallback.authCallback(false, new String(error.networkResponse.data));
+ setStoredToken(null);
+ callback.accept(null);
}
}) {
// Note, this is overriding part of StringRequest, not one of the sub-classes above!
@@ -112,20 +113,16 @@ public class WebApiConnection {
// Remove the stored token so future calls are not authenticated.
public void logout() {
Log.v(TAG, "logout()");
- saveStoredToken(null);
+ setStoredToken(null);
+ //saveStoredToken(null);
}
-
- private void saveStoredToken(String tokenStr) {
- SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(mContext);
- prefs.edit().putString(TOKEN_ID, tokenStr).commit();
-
+ public void setStoredToken(String authToken) {
+ mAuthToken = authToken;
}
- public String getStoredToken() {
- SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(mContext);
- String authToken = prefs.getString(TOKEN_ID, null);
- return authToken;
+ private String getStoredToken() {
+ return(mAuthToken);
}
public boolean isLoggedIn() {
@@ -142,7 +139,7 @@ public class WebApiConnection {
// Create a new event in the remote database, based on the provided parameters.
- public boolean createEvent(final int osdAlarmState, final Date eventDate, final String eventDesc) {
+ public boolean createEvent(final int osdAlarmState, final Date eventDate, final String eventDesc, Consumer callback) {
Log.v(TAG, "createEvent()");
String urlStr = mUrlBase + "/api/events/";
Log.v(TAG, "urlStr=" + urlStr);
@@ -169,7 +166,7 @@ public class WebApiConnection {
@Override
public void onResponse(String response) {
Log.v(TAG, "Response is: " + response);
- mEventCallback.eventCallback(true, response);
+ callback.accept(response);
}
},
new Response.ErrorListener() {
@@ -178,10 +175,10 @@ public class WebApiConnection {
if (error != null) {
String responseBody = new String(error.networkResponse.data);
Log.e(TAG, "Create Event Error: " + error.toString() + ", message:" + error.getMessage() + ", Response Code:" + error.networkResponse.statusCode + ", Response: " + responseBody);
- mEventCallback.eventCallback(false, new String(error.networkResponse.data));
+ callback.accept(null);
} else {
Log.e(TAG,"Create Event Error - null respones");
- mEventCallback.eventCallback(false, null);
+ callback.accept(null);
}
}
}) {
@@ -428,7 +425,7 @@ public class WebApiConnection {
- public boolean createDatapoint(JSONObject dataObj, int eventId) {
+ public boolean createDatapoint(JSONObject dataObj, int eventId, Consumercallback) {
Log.v(TAG, "createDatapoint()");
// Create a new event in the remote database, based on the provided parameters.
String urlStr = mUrlBase + "/api/datapoints/";
@@ -459,7 +456,7 @@ public class WebApiConnection {
@Override
public void onResponse(String response) {
Log.v(TAG, "Response is: " + response);
- mDatapointCallback.datapointCallback(true, response);
+ callback.accept(response);
}
},
new Response.ErrorListener() {
@@ -469,10 +466,10 @@ public class WebApiConnection {
// Fixme = are we sure that networResponse.data is not null???
String responseBody = new String(error.networkResponse.data);
Log.e(TAG, "Create Datapoint Error: " + error.toString() + ", message:" + error.getMessage() + ", Response Code:" + error.networkResponse.statusCode + ", Response: " + responseBody);
- mDatapointCallback.datapointCallback(false, new String(error.networkResponse.data));
+ callback.accept(null);
} else {
Log.e(TAG,"Create Datapoint Error - returned null respones");
- mDatapointCallback.datapointCallback(false, null);
+ callback.accept(null);
}
}
}) {
@@ -484,9 +481,6 @@ public class WebApiConnection {
String authToken = getStoredToken();
params.put("Authorization: Token " + authToken, authToken);
Log.v(TAG, "getParams: params=" + params.toString());
- //params.put("eventType", String.valueOf(eventType));
- //params.put("dataTime", dateFormat.format(eventDate));
- //params.put("desc", eventDesc);
return params;
}
diff --git a/app/src/main/res/drawable/stat_sample.png b/app/src/main/res/drawable/stat_sample.png
deleted file mode 100644
index 1733042..0000000
Binary files a/app/src/main/res/drawable/stat_sample.png and /dev/null differ
diff --git a/app/src/main/res/layout/event_sub_type_list_item.xml b/app/src/main/res/layout/event_sub_type_list_item.xml
deleted file mode 100644
index 437e3c0..0000000
--- a/app/src/main/res/layout/event_sub_type_list_item.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/layout/event_type_list_item.xml b/app/src/main/res/layout/event_type_list_item.xml
deleted file mode 100644
index 68d2454..0000000
--- a/app/src/main/res/layout/event_type_list_item.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/raw/alarm.wav b/app/src/main/res/raw/alarm.wav
deleted file mode 100644
index de8bab5..0000000
Binary files a/app/src/main/res/raw/alarm.wav and /dev/null differ
diff --git a/app/src/main/res/raw/fault.mp3 b/app/src/main/res/raw/fault.mp3
deleted file mode 100644
index 86d7dea..0000000
Binary files a/app/src/main/res/raw/fault.mp3 and /dev/null differ
diff --git a/app/src/main/res/raw/warning.wav b/app/src/main/res/raw/warning.wav
deleted file mode 100644
index 2779a1d..0000000
Binary files a/app/src/main/res/raw/warning.wav and /dev/null differ
diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml
index f33fd20..715463a 100644
--- a/app/src/main/res/values/dimens.xml
+++ b/app/src/main/res/values/dimens.xml
@@ -3,6 +3,4 @@
16dp
16dp
- 16dp
- 16dp
diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml
index 44f664f..5885930 100644
--- a/app/src/main/res/values/styles.xml
+++ b/app/src/main/res/values/styles.xml
@@ -7,11 +7,5 @@
- @color/colorPrimaryDark
- @color/colorAccent
-
-
-
diff --git a/app/src/main/res/xml/prefs.xml b/app/src/main/res/xml/prefs.xml
deleted file mode 100644
index a3d27e8..0000000
--- a/app/src/main/res/xml/prefs.xml
+++ /dev/null
@@ -1,129 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/build.gradle b/build.gradle
index eb2fbaf..f3ef4da 100644
--- a/build.gradle
+++ b/build.gradle
@@ -9,7 +9,7 @@ buildscript {
google()
}
dependencies {
- classpath 'com.android.tools.build:gradle:4.1.1'
+ classpath 'com.android.tools.build:gradle:4.1.3'
}
}
allprojects {