From 4b67646eea56c3ceb8a31c5741c6789f3e0ec20b Mon Sep 17 00:00:00 2001 From: Graham Jones Date: Tue, 1 Mar 2022 23:34:46 +0000 Subject: [PATCH] Updated to restore compatibility with Android V6 (removed use of Consumer for callbacks) --- app/build.gradle | 2 +- app/src/main/AndroidManifest.xml | 2 +- .../AuthenticateActivity.java | 23 ++-- .../EditEventActivity.java | 113 +++++++++--------- .../org/openseizuredetector/LogManager.java | 24 ++-- .../uk/org/openseizuredetector/SdServer.java | 4 +- .../openseizuredetector/WebApiConnection.java | 37 +++--- 7 files changed, 107 insertions(+), 98 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index d455068..b951980 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -6,7 +6,7 @@ android { defaultConfig { applicationId "uk.org.openseizuredetector" - minSdkVersion 24 + minSdkVersion 23 targetSdkVersion 30 multiDexEnabled true } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index a5460df..4e83a5b 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -3,7 +3,7 @@ xmlns:tools="http://schemas.android.com/tools" package="uk.org.openseizuredetector" android:versionCode="94" - android:versionName="4.0.0n"> + android:versionName="4.0.0p"> diff --git a/app/src/main/java/uk/org/openseizuredetector/AuthenticateActivity.java b/app/src/main/java/uk/org/openseizuredetector/AuthenticateActivity.java index 463967a..57c5793 100644 --- a/app/src/main/java/uk/org/openseizuredetector/AuthenticateActivity.java +++ b/app/src/main/java/uk/org/openseizuredetector/AuthenticateActivity.java @@ -172,16 +172,19 @@ 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, (String retVal) -> { - if (retVal != null) { - Log.d(TAG,"Authentication Success - token is "+retVal); - mUtil.showToast("Login Successful"); - saveAuthToken(retVal); - updateUi(); - } else { - Log.e(TAG,"onOk: Authentication failure for "+uname+", "+passwd); - mUtil.showToast("ERROR: Authentication Failed - Please Try Again"); - mUtil.writeToSysLogFile("AuthActivity - Authorisation failed for "+uname+", "+passwd); + mWac.authenticate(uname, passwd, new WebApiConnection.StringCallback() { + @Override + public void accept(String retVal) { + if (retVal != null) { + Log.d(TAG,"Authentication Success - token is "+retVal); + mUtil.showToast("Login Successful"); + saveAuthToken(retVal); + updateUi(); + } else { + Log.e(TAG,"onOk: Authentication failure for "+uname+", "+passwd); + mUtil.showToast("ERROR: Authentication Failed - Please Try Again"); + mUtil.writeToSysLogFile("AuthActivity - Authorisation failed for "+uname+", "+passwd); + } } }); //finish(); diff --git a/app/src/main/java/uk/org/openseizuredetector/EditEventActivity.java b/app/src/main/java/uk/org/openseizuredetector/EditEventActivity.java index ed10cc4..07e042d 100644 --- a/app/src/main/java/uk/org/openseizuredetector/EditEventActivity.java +++ b/app/src/main/java/uk/org/openseizuredetector/EditEventActivity.java @@ -126,60 +126,61 @@ public class EditEventActivity extends AppCompatActivity { // 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, "initialiseServiceConnection().onEventTypesReceived"); - if (eventTypesObj == null) { - 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(); - mEventTypesList = new ArrayList(); - mEventSubTypesHashMap = new HashMap>(); - while (keys.hasNext()) { - String key = keys.next(); - Log.v(TAG, "initialiseServiceConnection().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)); + mWac.getEventTypes(new WebApiConnection.JSONObjectCallback() { + @Override + public void accept(JSONObject eventTypesObj) { + Log.v(TAG, "initialiseServiceConnection().onEventTypesReceived"); + if (eventTypesObj == null) { + 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(); + mEventTypesList = new ArrayList(); + mEventSubTypesHashMap = new HashMap>(); + while (keys.hasNext()) { + String key = keys.next(); + Log.v(TAG, "initialiseServiceConnection().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); + mEventTypesListChanged = true; + } catch (JSONException e) { + Log.e(TAG, "initialiseServiceConnection().getEventTypes Callback: Error parsing JSONObject" + e.getMessage() + e.toString()); } - mEventSubTypesHashMap.put(key, eventSubtypesList); - mEventTypesListChanged = true; - } catch (JSONException e) { - Log.e(TAG, "initialiseServiceConnection().getEventTypes Callback: Error parsing JSONObject" + e.getMessage() + e.toString()); } + updateUi(); } - 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(); + mWac.getEvent(mEventId, new WebApiConnection.JSONObjectCallback() { + @Override + public void accept(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()); + Log.e(TAG, "ERROR:" + e.getMessage()); e.printStackTrace(); } - - } - - - private void updateUi() { Log.v(TAG, "updateUI"); TextView tv; @@ -293,32 +294,28 @@ public class EditEventActivity extends AppCompatActivity { try { - mWac.updateEvent(mEventObj, (JSONObject eventObj) -> { - Log.v(TAG,"onOk.updateEvent"); - //mEventObj = eventObj; - if (eventObj != null) { - Log.v(TAG, "onOk.getEvent: eventObj=" + eventObj.toString()); - mUtil.showToast("Event Updated OK"); - finish(); - } else { - Log.e(TAG,"onOk.updateEvent - Error - returned NULL"); - mUtil.showToast("Error Updating Event"); - updateUi(); - } + mWac.updateEvent(mEventObj, new WebApiConnection.JSONObjectCallback() { + @Override + public void accept(JSONObject eventObj) { + Log.v(TAG, "onOk.updateEvent"); + //mEventObj = eventObj; + if (eventObj != null) { + Log.v(TAG, "onOk.getEvent: eventObj=" + eventObj.toString()); + mUtil.showToast("Event Updated OK"); + finish(); + } else { + Log.e(TAG, "onOk.updateEvent - Error - returned NULL"); + mUtil.showToast("Error Updating Event"); + updateUi(); } - ); + } + }); } catch (Exception e) { Log.e(TAG,"ERROR:"+e.getMessage()); e.printStackTrace(); mUtil.showToast("Error Updating Event"); updateUi(); } - - //String uname = mUnameEt.getText().toString(); - //String passwd = mPasswdEt.getText().toString(); - //Log.v(TAG,"onOK() - uname="+uname+", passwd="+passwd); - //mWac.authenticate(uname,passwd); - //finish(); } }; diff --git a/app/src/main/java/uk/org/openseizuredetector/LogManager.java b/app/src/main/java/uk/org/openseizuredetector/LogManager.java index 4f182b4..28c1f01 100644 --- a/app/src/main/java/uk/org/openseizuredetector/LogManager.java +++ b/app/src/main/java/uk/org/openseizuredetector/LogManager.java @@ -45,7 +45,6 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import java.util.HashMap; -import java.util.function.Consumer; //import static android.database.sqlite.SQLiteDatabase.openOrCreateDatabase; @@ -89,6 +88,13 @@ public class LogManager { private boolean mAutoPruneDb; private AutoPruneTimer mAutoPruneTimer; + public interface CursorCallback { + void accept(Cursor retVal); + } + + public interface ArrayListCallback { + void accept(ArrayList> retVal); + } public LogManager(Context context, boolean logRemote, boolean logRemoteMobile, String authToken, @@ -312,7 +318,7 @@ public class LogManager { * * @return True on successful start or false if call fails. */ - public boolean getDatapointsByDate(String startDateStr, String endDateStr, Consumer callback) { + public boolean getDatapointsByDate(String startDateStr, String endDateStr, WebApiConnection.StringCallback callback) { Log.d(TAG, "getDatapointsbyDate() - startDateStr=" + startDateStr + ", endDateStr=" + endDateStr); String[] columns = {"*"}; String whereClause = "DataTime>? AND DataTime>> callback) { + public boolean getEventsList(boolean includeWarnings, ArrayListCallback callback) { Log.v(TAG, "getEventsList - includeWarnings=" + includeWarnings); ArrayList> eventsList = new ArrayList<>(); @@ -399,7 +405,7 @@ public class LogManager { * @param includeWarnings - whether to include warnings in the list of events, or just alarm conditions. * @return True on successful start or false if call fails. */ - public boolean getNextEventToUpload(boolean includeWarnings, Consumer callback) { + public boolean getNextEventToUpload(boolean includeWarnings, WebApiConnection.LongCallback callback) { Log.v(TAG, "getNextEventToUpload - includeWarnings=" + includeWarnings); String[] whereArgsStatus = getEventWhereArgs(includeWarnings); @@ -448,7 +454,7 @@ public class LogManager { * * @return True on successful start or false if call fails. */ - public boolean getNearestDatapointToDate(String dateStr, Consumer callback) { + public boolean getNearestDatapointToDate(String dateStr, WebApiConnection.LongCallback callback) { Log.v(TAG, "getNextEventToDate - dateStr=" + dateStr); 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;"; @@ -481,7 +487,7 @@ public class LogManager { * @param includeWarnings - whether to include warnings in the list of events, or just alarm conditions. * @return True on successful start or false if call fails. */ - public boolean getLocalEventsCount(boolean includeWarnings, Consumer callback) { + public boolean getLocalEventsCount(boolean includeWarnings, WebApiConnection.LongCallback callback) { Log.v(TAG, "getLocalEventsCount- includeWarnings=" + includeWarnings); String[] whereArgs = getEventWhereArgs(includeWarnings); String whereClause = getEventWhereClause(includeWarnings); @@ -504,7 +510,7 @@ public class LogManager { * * @return True on successful start or false if call fails. */ - public boolean getLocalDatapointsCount(Consumer callback) { + public boolean getLocalDatapointsCount(WebApiConnection.LongCallback callback) { Log.v(TAG, "getLocalDatapointsCount"); String[] whereArgs = null; String whereClause = null; @@ -537,12 +543,12 @@ public class LogManager { String mGroupBy; String mHaving; String mOrderBy; - Consumer mCallback; + CursorCallback mCallback; //query(String table, String[] columns, String selection, String[] selectionArgs, // String groupBy, String having, String orderBy) SelectQueryTask(String table, String[] columns, String selection, String[] selectionArgs, - String groupBy, String having, String orderBy, Consumer callback) { + String groupBy, String having, String orderBy, CursorCallback callback) { // list all the parameters like in normal class define this.mTable = table; this.mColumns = columns; diff --git a/app/src/main/java/uk/org/openseizuredetector/SdServer.java b/app/src/main/java/uk/org/openseizuredetector/SdServer.java index fb24e21..9f473ca 100644 --- a/app/src/main/java/uk/org/openseizuredetector/SdServer.java +++ b/app/src/main/java/uk/org/openseizuredetector/SdServer.java @@ -279,8 +279,6 @@ public class SdServer extends Service implements SdDataReceiver { mUtil.writeToSysLogFile("SdServer.onStartCommand() - starting SdDataSource"); mSdDataSource.start(); - checkEvents(); - // Initialise Notification channel for API level 26 and over // from https://stackoverflow.com/questions/44443690/notificationcompat-with-api-26 mNM = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE); @@ -349,6 +347,8 @@ public class SdServer extends Service implements SdDataReceiver { mUtil.writeToSysLogFile("SdServer.onStartCommand() - mWakeLock is not null - this shouldn't happen???"); } + checkEvents(); + return START_STICKY; } diff --git a/app/src/main/java/uk/org/openseizuredetector/WebApiConnection.java b/app/src/main/java/uk/org/openseizuredetector/WebApiConnection.java index c390fc4..0abb88a 100644 --- a/app/src/main/java/uk/org/openseizuredetector/WebApiConnection.java +++ b/app/src/main/java/uk/org/openseizuredetector/WebApiConnection.java @@ -1,20 +1,15 @@ package uk.org.openseizuredetector; import android.content.Context; -import android.content.SharedPreferences; -import android.icu.text.RelativeDateTimeFormatter; import android.os.Handler; -import android.preference.PreferenceManager; import android.util.Log; - import com.android.volley.AuthFailureError; import com.android.volley.Request; import com.android.volley.RequestQueue; import com.android.volley.Response; import com.android.volley.VolleyError; import com.android.volley.VolleyLog; -import com.android.volley.toolbox.JsonObjectRequest; import com.android.volley.toolbox.StringRequest; import com.android.volley.toolbox.Volley; @@ -24,12 +19,10 @@ import org.json.JSONObject; import java.io.UnsupportedEncodingException; import java.text.DateFormat; -import java.text.ParseException; 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 @@ -44,6 +37,18 @@ public class WebApiConnection { private OsdUtil mUtil; RequestQueue mQueue; + public interface JSONObjectCallback { + public void accept(JSONObject retValObj); + } + + public interface StringCallback { + public void accept(String retValStr); + } + + public interface LongCallback { + public void accept(Long retVal); + } + public WebApiConnection(Context context) { mContext = context; mQueue = Volley.newRequestQueue(context); @@ -64,7 +69,7 @@ public class WebApiConnection { * @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) { + public boolean authenticate(final String uname, final String passwd, StringCallback 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/ @@ -148,7 +153,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, Consumer callback) { + public boolean createEvent(final int osdAlarmState, final Date eventDate, final String eventDesc, StringCallback callback) { Log.v(TAG, "createEvent()"); String urlStr = mUrlBase + "/api/events/"; Log.v(TAG, "urlStr=" + urlStr); @@ -227,7 +232,7 @@ public class WebApiConnection { return (true); } - public boolean getEvent(Long eventId, Consumer callback) { + public boolean getEvent(Long eventId, JSONObjectCallback callback) { //Long eventId=Long.valueOf(285); Log.v(TAG, "getEvent()"); String urlStr = mUrlBase + "/api/events/" + eventId; @@ -287,7 +292,7 @@ public class WebApiConnection { * @param callback * @return true on success or false on failure to initiate the request. */ - public boolean getEvents(Consumer callback) { + public boolean getEvents(JSONObjectCallback callback) { //Long eventId=Long.valueOf(285); Log.v(TAG, "getEvents()"); String urlStr = mUrlBase + "/api/events/"; @@ -348,7 +353,7 @@ public class WebApiConnection { } - public boolean updateEvent(final JSONObject eventObj, Consumer callback) { + public boolean updateEvent(final JSONObject eventObj, JSONObjectCallback callback) { Long eventId; Log.v(TAG, "updateEvent()"); final String authtoken = getStoredToken(); @@ -447,7 +452,7 @@ public class WebApiConnection { } - public boolean createDatapoint(JSONObject dataObj, int eventId, Consumer callback) { + public boolean createDatapoint(JSONObject dataObj, int eventId, StringCallback callback) { Log.v(TAG, "createDatapoint()"); // Create a new event in the remote database, based on the provided parameters. String urlStr = mUrlBase + "/api/datapoints/"; @@ -537,7 +542,7 @@ public class WebApiConnection { * @param callback - function to be called with a JSONObject as a parameter that contains the user profile data. * @return true if request sent successfully, or else false. */ - public boolean getUserProfile(Consumer callback) { + public boolean getUserProfile(JSONObjectCallback callback) { Log.v(TAG, "getUserProfile()"); String urlStr = mUrlBase + "/api/accounts/profile/"; Log.v(TAG, "getUserProfile(): urlStr=" + urlStr); @@ -595,12 +600,10 @@ 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) { + public boolean getEventTypes(JSONObjectCallback callback) { Log.v(TAG, "getEventTypes()"); String urlStr = mUrlBase + "/static/eventTypes.json"; Log.v(TAG, "urlStr=" + urlStr);