diff --git a/app/build.gradle b/app/build.gradle
index 2ba54e6..cfea828 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -6,7 +6,7 @@ android {
defaultConfig {
applicationId "uk.org.openseizuredetector"
- minSdkVersion 21
+ minSdkVersion 24
targetSdkVersion 29
multiDexEnabled true
}
@@ -24,6 +24,10 @@ android {
includeAndroidResources = true
}
}
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
}
dependencies {
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 4375192..069609f 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -65,6 +65,7 @@
android:exported="false" />
+
diff --git a/app/src/main/java/uk/org/openseizuredetector/EditEventActivity.java b/app/src/main/java/uk/org/openseizuredetector/EditEventActivity.java
new file mode 100644
index 0000000..caada9a
--- /dev/null
+++ b/app/src/main/java/uk/org/openseizuredetector/EditEventActivity.java
@@ -0,0 +1,174 @@
+package uk.org.openseizuredetector;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.os.Bundle;
+import android.os.Handler;
+import android.support.v7.app.AppCompatActivity;
+import android.util.Log;
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.LinearLayout;
+import android.widget.ListAdapter;
+import android.widget.ListView;
+import android.widget.SimpleAdapter;
+import android.widget.TextView;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+
+public class EditEventActivity extends AppCompatActivity
+ implements AuthCallbackInterface, EventCallbackInterface, DatapointCallbackInterface {
+ private String TAG = "EditEventActivity";
+ private Context mContext;
+ private WebApiConnection mWac;
+ private LogManager mLm;
+ final Handler serverStatusHandler = new Handler();
+ private OsdUtil mUtil;
+ private List mEventTypesList = null;
+ private HashMap> mEventSubTypesHashMap = null;
+
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ Log.v(TAG, "onCreate()");
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_edit_event);
+ Bundle extras = getIntent().getExtras();
+ if (extras != null) {
+ Long eventId = extras.getLong("eventId");
+ Log.v(TAG, "onCreate - eventId=" + eventId);
+ }
+ mUtil = new OsdUtil(this, serverStatusHandler);
+
+ Button cancelBtn =
+ (Button) findViewById(R.id.cancelBtn);
+ cancelBtn.setOnClickListener(onCancel);
+ Button OKBtn = (Button) findViewById(R.id.OKBtn);
+ OKBtn.setOnClickListener(onOK);
+
+ ListView lv = (ListView) findViewById(R.id.eventTypeLv);
+ lv.setOnItemClickListener(onEventTypeClick);
+
+ mWac = new WebApiConnection(this, this, this, this);
+ mLm = new LogManager(this);
+
+ // 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");
+
+ if (eventTypesObj == null) {
+ Log.e(TAG, "onCreate.getEventTypes Callback: Error Retrieving event types");
+ mUtil.showToast("Error Retrieving Event Types from Server - Please Try Again Later!");
+ } else {
+ Iterator keys = eventTypesObj.keys();
+ mEventTypesList = new ArrayList();
+ mEventSubTypesHashMap = new HashMap>();
+ while (keys.hasNext()) {
+ String key = keys.next();
+ Log.v(TAG, "onCreate.getEventTypes Callback: key=" + key);
+ mEventTypesList.add(key);
+ try {
+ JSONArray eventSubTypes = eventTypesObj.getJSONArray(key);
+ ArrayList eventSubtypesList = new ArrayList();
+ for (int i = 0; i < eventSubTypes.length(); i++) {
+ eventSubtypesList.add(eventSubTypes.getString(i));
+ }
+ mEventSubTypesHashMap.put(key, eventSubtypesList);
+ } catch (JSONException e) {
+ Log.e(TAG, "onCreate(getEventTypes Callback: Error parsing JSONObject" + e.getMessage() + e.toString());
+ }
+ }
+ updateUi();
+ }
+ });
+ }
+
+ @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");
+ if (mEventTypesList != null) {
+ //TextView tv = (TextView) findViewById(R.id.tokenTv);
+ //tv.setText("Logged in with Token:" + storedAuthToken);
+ Log.v(TAG, "updateUi: " + mEventTypesList.toString());
+ ListView lv = (ListView) findViewById(R.id.eventTypeLv);
+ ArrayAdapter adapter = new ArrayAdapter(this,
+ R.layout.event_type_list_item, R.id.eventTypeTv, mEventTypesList);
+ lv.setAdapter(adapter);
+ }
+ }
+
+ View.OnClickListener onCancel =
+ new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Log.v(TAG, "onCancel");
+ //m_status=false;
+ finish();
+ }
+ };
+
+ View.OnClickListener onOK =
+ new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ //m_status=true;
+ Log.v(TAG, "onOK()");
+ //String uname = mUnameEt.getText().toString();
+ //String passwd = mPasswdEt.getText().toString();
+ //Log.v(TAG,"onOK() - uname="+uname+", passwd="+passwd);
+ //mWac.authenticate(uname,passwd);
+ //finish();
+ }
+ };
+
+ private void setSubTypesLV(String eventType) {
+ ArrayList subtypesArrayList = mEventSubTypesHashMap.get(eventType);
+ Log.v(TAG,"setSubtypesLV - eventType="+eventType+", subtypes="+subtypesArrayList);
+ ListView lv = (ListView)findViewById(R.id.eventSubTypeLv);
+ ArrayAdapter adapter = new ArrayAdapter(this,
+ R.layout.event_sub_type_list_item, R.id.eventSubTypeLv, subtypesArrayList);
+ lv.setAdapter(adapter);
+ }
+
+ AdapterView.OnItemClickListener onEventTypeClick =
+ new AdapterView.OnItemClickListener() {
+ public void onItemClick(AdapterView> adapter, View v, int position, long id) {
+ Log.v(TAG, "onEventTypeClick() - Position=" + position + ", id=" + id);// Confirmation dialog based on: https://stackoverflow.com/a/12213536/2104584
+ String selectedEventType = (String) adapter.getItemAtPosition(position);
+ Log.v(TAG,"onEventTypeClick - selected "+selectedEventType);
+ setSubTypesLV(selectedEventType);
+ }
+ };
+}
\ No newline at end of file
diff --git a/app/src/main/java/uk/org/openseizuredetector/LogManagerControlActivity.java b/app/src/main/java/uk/org/openseizuredetector/LogManagerControlActivity.java
index a58b6bd..e76b768 100644
--- a/app/src/main/java/uk/org/openseizuredetector/LogManagerControlActivity.java
+++ b/app/src/main/java/uk/org/openseizuredetector/LogManagerControlActivity.java
@@ -210,7 +210,13 @@ public class LogManagerControlActivity extends AppCompatActivity {
new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView> adapter, View v, int position, long id) {
Log.v(TAG, "onItemClicKListener() - Position=" + position + ", id=" + id);// Confirmation dialog based on: https://stackoverflow.com/a/12213536/2104584
- AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
+ HashMap eventObj = (HashMap)adapter.getItemAtPosition(position);
+ Long eventId = Long.parseLong(eventObj.get("uploaded"));
+ Log.d(TAG,"onItemClickListener(): eventId="+eventId+", eventObj="+eventObj);
+ Intent i = new Intent(getApplicationContext(), EditEventActivity.class);
+ i.putExtra("eventId",eventId);
+ startActivity(i);
+ /*AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
builder.setTitle("Edit Remote Event Details");
builder.setMessage("Edit this event details on the remote database?");
builder.setPositiveButton("YES", new DialogInterface.OnClickListener() {
@@ -228,7 +234,8 @@ public class LogManagerControlActivity extends AppCompatActivity {
});
AlertDialog alert = builder.create();
alert.show();
-
+ */
+
//MyClass selItem = (MyClass) myList.getSelectedItem(); //
//String value= selItem.getTheValue(); //getter method
}
diff --git a/app/src/main/java/uk/org/openseizuredetector/WebApiConnection.java b/app/src/main/java/uk/org/openseizuredetector/WebApiConnection.java
index 2ce534b..677e682 100644
--- a/app/src/main/java/uk/org/openseizuredetector/WebApiConnection.java
+++ b/app/src/main/java/uk/org/openseizuredetector/WebApiConnection.java
@@ -27,6 +27,7 @@ import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
+import java.util.function.Consumer;
// This class is intended to handle all interactions with the OSD WebAPI
@@ -297,4 +298,60 @@ public class WebApiConnection {
}
+ /**
+ * Retrieve the file containing the standard event types from the server.
+ * Calls the specified callback function, passing a JSONObject as a parameter when the data has been received and parsed.
+ * Note it uses a Consumer callback function to avoid having to create another interface
+ * - see https://medium.com/@pra4mesh/callback-function-in-java-20fa48b27797
+ * @return true if request sent successfully or else false.
+ */
+ public boolean getEventTypes(Consumer callback) {
+ Log.v(TAG, "getEventTypes()");
+ String urlStr = mUrlBase + "/static/eventTypes.json";
+ Log.v(TAG, "urlStr=" + urlStr);
+ final String authtoken = getStoredToken();
+
+ if (!isLoggedIn()) {
+ Log.v(TAG, "not logged in - doing nothing");
+ return (false);
+ }
+
+ StringRequest req = new StringRequest(Request.Method.GET, urlStr,
+ new Response.Listener() {
+ @Override
+ public void onResponse(String response) {
+ Log.v(TAG, "getEventTypes.onResponse(): Response is: " + response);
+ try {
+ JSONObject retObj = new JSONObject(response);
+ callback.accept(retObj);
+ } catch (JSONException e) {
+ Log.e(TAG,"getEventTypes.onRespons(): Error: "+e.getMessage()+","+e.toString());
+ callback.accept(null);
+ }
+ }
+ },
+ new Response.ErrorListener() {
+ @Override
+ public void onErrorResponse(VolleyError error) {
+ String responseBody = new String(error.networkResponse.data);
+ Log.e(TAG, "getEventTypes.onErrorResponse(): " + error.toString() + ", message:" + error.getMessage() + ", Response Code:" + error.networkResponse.statusCode + ", Response: " + responseBody);
+ callback.accept(null);
+ }
+ }) {
+ // Note, this is overriding part of StringRequest, not one of the sub-classes above!
+ @Override
+ public Map getHeaders() throws AuthFailureError {
+ Map params = new HashMap();
+ params.put("Content-Type", "application/json; charset=UTF-8");
+ params.put("Authorization", "Token " + getStoredToken());
+ return params;
+ }
+ };
+
+ mQueue.add(req);
+ return (true);
+
+ }
+
+
}
diff --git a/app/src/main/res/layout/activity_edit_event.xml b/app/src/main/res/layout/activity_edit_event.xml
new file mode 100644
index 0000000..3a6e4db
--- /dev/null
+++ b/app/src/main/res/layout/activity_edit_event.xml
@@ -0,0 +1,79 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
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
new file mode 100644
index 0000000..437e3c0
--- /dev/null
+++ b/app/src/main/res/layout/event_sub_type_list_item.xml
@@ -0,0 +1,10 @@
+
+
+
+
\ 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
new file mode 100644
index 0000000..f6341af
--- /dev/null
+++ b/app/src/main/res/layout/event_type_list_item.xml
@@ -0,0 +1,10 @@
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 25476a8..2a9f7ae 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -319,4 +319,5 @@
The period (in seconds) between attempts to upload data to the remote server. Each attempt only uploads a single event, not all the available data.
Remote Log Period (seconds)
Raise Alarm
+ Save