Converted some localDB operations to AsyncTask to avoid hogging the UI thread
This commit is contained in:
@@ -30,6 +30,7 @@ import android.database.DatabaseUtils;
|
||||
import android.database.SQLException;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.database.sqlite.SQLiteOpenHelper;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.CountDownTimer;
|
||||
import android.os.Handler;
|
||||
import android.preference.PreferenceManager;
|
||||
@@ -46,6 +47,7 @@ import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import static android.database.sqlite.SQLiteDatabase.openOrCreateDatabase;
|
||||
|
||||
@@ -59,7 +61,7 @@ import static android.database.sqlite.SQLiteDatabase.openOrCreateDatabase;
|
||||
* - It will periodically attempt to upload the oldest logged data to the osdApi remote database - the interface to the
|
||||
* remote database is handled by the WebApiConnection class. It only tries to do one transaction with the external database
|
||||
* at a time - if the periodic timer times out and an upload is in progress it will not do anything and wait for the next timeout.*
|
||||
*
|
||||
* <p>
|
||||
* The data upload process is as follows:
|
||||
* - Select the oldest non-uploaded datapoint that is marked as an alarm or warning state.
|
||||
* - Create an Event in the remote database based on that datapoint date and alarm type, and note the Event ID.
|
||||
@@ -67,8 +69,7 @@ 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 implements AuthCallbackInterface, EventCallbackInterface, DatapointCallbackInterface {
|
||||
private String TAG = "LogManager";
|
||||
private String mDbName = "osdData";
|
||||
private String mDbTableName = "datapoints";
|
||||
@@ -121,7 +122,6 @@ public class LogManager implements AuthCallbackInterface, EventCallbackInterface
|
||||
Log.v(TAG, "mRemoteLogPeriod=" + mRemoteLogPeriod);
|
||||
|
||||
|
||||
|
||||
mUtil = new OsdUtil(mContext, handler);
|
||||
openDb();
|
||||
mWac = new WebApiConnection(mContext, this, this, this);
|
||||
@@ -139,6 +139,7 @@ public class LogManager implements AuthCallbackInterface, EventCallbackInterface
|
||||
|
||||
/**
|
||||
* Returns a JSON String representing an array of datapoints that are selected from sqlite cursor c.
|
||||
*
|
||||
* @param c sqlite cursor pointing to datapoints query result.
|
||||
* @return JSON String.
|
||||
* from https://stackoverflow.com/a/20488153/2104584
|
||||
@@ -175,8 +176,6 @@ public class LogManager implements AuthCallbackInterface, EventCallbackInterface
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
private boolean openDb() {
|
||||
Log.d(TAG, "openDb");
|
||||
try {
|
||||
@@ -184,8 +183,7 @@ public class LogManager implements AuthCallbackInterface, EventCallbackInterface
|
||||
if (!checkTableExists(mOSDDb, mDbTableName)) {
|
||||
Log.e(TAG, "ERROR - Table does not exist");
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
Log.d(TAG, "table " + mDbTableName + " exists ok");
|
||||
}
|
||||
return true;
|
||||
@@ -204,8 +202,7 @@ public class LogManager implements AuthCallbackInterface, EventCallbackInterface
|
||||
c = osdDb.getWritableDatabase().query(osdTableName, null,
|
||||
null, null, null, null, null);
|
||||
tableExists = true;
|
||||
}
|
||||
catch (Exception e) {
|
||||
} catch (Exception e) {
|
||||
Log.d(TAG, osdTableName + " doesn't exist :(((");
|
||||
}
|
||||
return tableExists;
|
||||
@@ -248,10 +245,11 @@ public class LogManager implements AuthCallbackInterface, EventCallbackInterface
|
||||
|
||||
/**
|
||||
* Returns a json representation of datapoint 'id'.
|
||||
*
|
||||
* @param id datapoint id to return
|
||||
* @return JSON representation of requested datapoint (single element JSON array)
|
||||
*/
|
||||
public String getDatapointById(int id) {
|
||||
public String getDatapointById(long id) {
|
||||
Log.d(TAG, "getDatapointById() - id=" + id);
|
||||
Cursor c = null;
|
||||
String retVal;
|
||||
@@ -262,8 +260,7 @@ public class LogManager implements AuthCallbackInterface, EventCallbackInterface
|
||||
// selectStr, selectArgs, null, null, null);
|
||||
c = mOSDDb.getWritableDatabase().rawQuery(selectStr, null);
|
||||
retVal = cursor2Json(c);
|
||||
}
|
||||
catch (Exception e) {
|
||||
} catch (Exception e) {
|
||||
Log.d(TAG, "getDatapointById(): Error Querying Database: " + e.getLocalizedMessage());
|
||||
retVal = null;
|
||||
}
|
||||
@@ -273,6 +270,7 @@ public class LogManager implements AuthCallbackInterface, EventCallbackInterface
|
||||
|
||||
/**
|
||||
* setDatapointToUploaded
|
||||
*
|
||||
* @param id - datapoint ID to change
|
||||
* @param eventId - the eventId associated with the uploaded datapoint - the 'uploaded' field is set to this value.
|
||||
* @return True on success or False on failure.
|
||||
@@ -291,6 +289,7 @@ public class LogManager implements AuthCallbackInterface, EventCallbackInterface
|
||||
|
||||
/**
|
||||
* setDatapointStatus() - Update the status of data point id.
|
||||
*
|
||||
* @param id
|
||||
* @param statusVal
|
||||
* @return true on success or false on failure
|
||||
@@ -311,6 +310,7 @@ public class LogManager implements AuthCallbackInterface, EventCallbackInterface
|
||||
/**
|
||||
* getDatapointsJSON() Returns a JSON Object of all of the datapoints in the local database
|
||||
* between endDateStr-duration and endDateStr
|
||||
*
|
||||
* @param endDateStr String representation of the period end date
|
||||
* @param duration Duration in minutes.
|
||||
* @return JSONObject of all the datapoints in the range.
|
||||
@@ -330,18 +330,42 @@ public class LogManager implements AuthCallbackInterface, EventCallbackInterface
|
||||
+ "' and dataTime<= '" + endDateStr + "'",
|
||||
null);
|
||||
retVal = cursor2Json(c);
|
||||
}
|
||||
catch (Exception e) {
|
||||
} catch (Exception e) {
|
||||
Log.d(TAG, "Error selecting datapoints" + e.toString());
|
||||
retVal = null;
|
||||
}
|
||||
return (retVal);
|
||||
}
|
||||
|
||||
//Consumer<JSONObject> callback
|
||||
|
||||
/**
|
||||
* Return an array list of objects representing the events in the database by calling the specified callback function.
|
||||
*
|
||||
* @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 getEventsList(boolean includeWarnings, Consumer<ArrayList<HashMap<String, String>>> callback) {
|
||||
Log.v(TAG, "getEventsList - includeWarnings=" + includeWarnings);
|
||||
// Based on https://stackoverflow.com/questions/24827312/is-a-good-practice-create-anonymous-asynctask-for-parallel-small-known-freeze-pr
|
||||
new AsyncTask<Boolean, Void, ArrayList<HashMap<String, String>>>() {
|
||||
@Override
|
||||
protected ArrayList<HashMap<String, String>> doInBackground(Boolean... includeWarnings) {
|
||||
Log.v(TAG, "getEventsList.doInBackground - includeWarnings=" + includeWarnings);
|
||||
return _getEventsList(includeWarnings[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(final ArrayList<HashMap<String, String>> result) {
|
||||
callback.accept(result);
|
||||
}
|
||||
}.execute(includeWarnings);
|
||||
return (true);
|
||||
}
|
||||
|
||||
// Return an array list of objects representing the events in the database.
|
||||
// Based on https://www.tutlane.com/tutorial/android/android-sqlite-listview-with-examples
|
||||
public ArrayList<HashMap<String, String>> getEventsList(boolean includeWarnings) {
|
||||
public ArrayList<HashMap<String, String>> _getEventsList(boolean includeWarnings) {
|
||||
//Log.v(TAG,"getEventsList()");
|
||||
SQLiteDatabase db = mOSDDb.getWritableDatabase();
|
||||
ArrayList<HashMap<String, String>> eventsList = new ArrayList<>();
|
||||
@@ -373,7 +397,7 @@ public class LogManager implements AuthCallbackInterface, EventCallbackInterface
|
||||
|
||||
/**
|
||||
* pruneLocalDb() removes data that is older than mLocalDbMaxAgeDays days
|
||||
* */
|
||||
*/
|
||||
public int pruneLocalDb() {
|
||||
Log.d(TAG, "pruneLocalDb()");
|
||||
Cursor c = null;
|
||||
@@ -388,8 +412,7 @@ public class LogManager implements AuthCallbackInterface, EventCallbackInterface
|
||||
String selectStr = "DataTime<=?";
|
||||
String[] selectArgs = {endDateStr};
|
||||
retVal = mOSDDb.getWritableDatabase().delete(mDbTableName, selectStr, selectArgs);
|
||||
}
|
||||
catch (Exception e) {
|
||||
} catch (Exception e) {
|
||||
Log.d(TAG, "Error deleting datapoints" + e.toString());
|
||||
retVal = 0;
|
||||
}
|
||||
@@ -398,10 +421,34 @@ public class LogManager implements AuthCallbackInterface, EventCallbackInterface
|
||||
}
|
||||
|
||||
|
||||
public boolean getNextEventToUpload(Consumer<Long> callback) {
|
||||
Log.v(TAG, "getNextEventToUpload");
|
||||
// Based on https://stackoverflow.com/questions/24827312/is-a-good-practice-create-anonymous-asynctask-for-parallel-small-known-freeze-pr
|
||||
new AsyncTask<Void, Void, Long>() {
|
||||
@Override
|
||||
protected Long doInBackground(Void... params) {
|
||||
Log.v(TAG, "getEventsNextEventToUpload.doInBackground");
|
||||
Long eventId;
|
||||
eventId = _getNextEventToUpload(false);
|
||||
if (eventId == -1) {
|
||||
eventId = _getNextEventToUpload(true);
|
||||
}
|
||||
return (eventId);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(final Long result) {
|
||||
callback.accept(result);
|
||||
}
|
||||
}.execute();
|
||||
return (true);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the ID of the next event (alarm, warning, fall etc that needs to be uploaded (alarm or warning condition and has not yet been uploaded.
|
||||
*/
|
||||
public int getNextEventToUpload(boolean includeWarnings) {
|
||||
public Long _getNextEventToUpload(boolean includeWarnings) {
|
||||
Log.v(TAG, "getNextEventToUpload(" + includeWarnings + ")");
|
||||
Time tnow = new Time(Time.getCurrentTimezone());
|
||||
tnow.setToNow();
|
||||
@@ -409,7 +456,7 @@ public class LogManager implements AuthCallbackInterface, EventCallbackInterface
|
||||
String SQLStr = "SQLStr";
|
||||
String statusListStr;
|
||||
String recordStr;
|
||||
int recordId;
|
||||
Long recordId;
|
||||
|
||||
if (includeWarnings) {
|
||||
statusListStr = "1,2,3,5"; // Warning, Alarm, Fall, Manual Alarm
|
||||
@@ -428,17 +475,17 @@ public class LogManager implements AuthCallbackInterface, EventCallbackInterface
|
||||
resultSet.moveToFirst();
|
||||
if (resultSet.getCount() == 0) {
|
||||
Log.v(TAG, "getNextEventToUpload() - no events to Upload - exiting");
|
||||
recordId = -1;
|
||||
recordId = new Long(-1);
|
||||
} else {
|
||||
recordStr = resultSet.getString(3);
|
||||
recordId = resultSet.getInt(0);
|
||||
recordId = resultSet.getLong(0);
|
||||
Log.d(TAG, "getNextEventToUpload(): id=" + recordId + ", recordStr=" + recordStr);
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
Log.e(TAG, "getNextEventToUpload(): Error selecting Data: " + e.toString());
|
||||
Log.e(TAG, "SQLStr was " + SQLStr);
|
||||
recordStr = "ERROR";
|
||||
recordId = -1;
|
||||
recordId = new Long(-1);
|
||||
}
|
||||
return (recordId);
|
||||
}
|
||||
@@ -478,7 +525,6 @@ public class LogManager implements AuthCallbackInterface, EventCallbackInterface
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Return the number of events stored in the local database
|
||||
*/
|
||||
@@ -555,7 +601,6 @@ public class LogManager implements AuthCallbackInterface, EventCallbackInterface
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Upload a batch of seizure detector data records to the server..
|
||||
* Uses the webApiConnection class to upload the data in the background.
|
||||
@@ -563,13 +608,10 @@ public class LogManager implements AuthCallbackInterface, EventCallbackInterface
|
||||
* eventCallback is called when the event is created.
|
||||
*/
|
||||
public void uploadSdData() {
|
||||
int eventId = -1;
|
||||
//int eventId = -1;
|
||||
Log.v(TAG, "uploadSdData()");
|
||||
// First try uploading full alarms, and only if we do not have any of those, upload warnings.
|
||||
eventId = getNextEventToUpload(false);
|
||||
if (eventId==-1) {
|
||||
eventId = getNextEventToUpload(true);
|
||||
}
|
||||
getNextEventToUpload((Long eventId) -> {
|
||||
if (eventId != -1) {
|
||||
Log.v(TAG, "uploadSdData() - eventId=" + eventId);
|
||||
String eventJsonStr = getDatapointById(eventId);
|
||||
@@ -605,6 +647,7 @@ public class LogManager implements AuthCallbackInterface, EventCallbackInterface
|
||||
} else {
|
||||
Log.v(TAG, "UploadSdData - no data to upload");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void authCallback(boolean authSuccess, String tokenStr) {
|
||||
@@ -850,7 +893,8 @@ public class LogManager implements AuthCallbackInterface, EventCallbackInterface
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTick(long l) { }
|
||||
public void onTick(long l) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFinish() {
|
||||
|
||||
@@ -134,7 +134,10 @@ public class LogManagerControlActivity extends AppCompatActivity {
|
||||
// Populate events list - we only do it once when the activity is created because the query might slow down the UI.
|
||||
// We could try this code in updateUI() and see though.
|
||||
// Based on https://www.tutlane.com/tutorial/android/android-sqlite-listview-with-examples
|
||||
mEventsList = mLm.getEventsList(true);
|
||||
mLm.getEventsList(true, (ArrayList<HashMap<String,String>> eventsList)-> {
|
||||
mEventsList = eventsList;
|
||||
});
|
||||
//mEventsList = mLm.getEventsList(true);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user