diff --git a/app/src/main/java/uk/org/openseizuredetector/EditEventActivity.java b/app/src/main/java/uk/org/openseizuredetector/EditEventActivity.java index 14c91b7..df2b73b 100644 --- a/app/src/main/java/uk/org/openseizuredetector/EditEventActivity.java +++ b/app/src/main/java/uk/org/openseizuredetector/EditEventActivity.java @@ -67,12 +67,16 @@ public class EditEventActivity extends AppCompatActivity try { mWac.getEvent(mEventId, (JSONObject eventObj) -> { Log.v(TAG,"onCreate.getEvent"); - mEventObj = eventObj; - Log.v(TAG, "onCreate.getEvent: eventObj=" + eventObj.toString()); - updateUi(); - // FIXME: modify updateUi to use mEventObj - } - ); + 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(); diff --git a/app/src/main/java/uk/org/openseizuredetector/LogManagerControlActivity.java b/app/src/main/java/uk/org/openseizuredetector/LogManagerControlActivity.java index 697e290..727a6c7 100644 --- a/app/src/main/java/uk/org/openseizuredetector/LogManagerControlActivity.java +++ b/app/src/main/java/uk/org/openseizuredetector/LogManagerControlActivity.java @@ -2,12 +2,14 @@ package uk.org.openseizuredetector; //import androidx.appcompat.app.AppCompatActivity; +import android.content.ComponentName; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.os.Bundle; import android.os.CountDownTimer; import android.os.Handler; +import android.os.IBinder; import android.support.v7.app.AlertDialog; import android.support.v7.app.AppCompatActivity; import android.util.Log; @@ -44,8 +46,8 @@ public class LogManagerControlActivity extends AppCompatActivity { Log.v(TAG, "onCreate()"); super.onCreate(savedInstanceState); mContext = this; - mUtil = new OsdUtil(this, serverStatusHandler); - mConnection = new SdServiceConnection(this); + mUtil = new OsdUtil(getApplicationContext(), serverStatusHandler); + mConnection = new SdServiceConnection(getApplicationContext()); setContentView(R.layout.activity_log_manager_control); @@ -64,20 +66,25 @@ public class LogManagerControlActivity extends AppCompatActivity { ListView lv = (ListView) findViewById(R.id.eventLogListView); lv.setOnItemClickListener(onEventListClick); + + lv = (ListView) findViewById(R.id.remoteEventsLv); + lv.setOnItemClickListener(onRemoteEventListClick); } @Override protected void onStart() { Log.v(TAG, "onStart()"); super.onStart(); - mUtil.bindToServer(this, mConnection); - //startUiTimer(); + mUtil.bindToServer(getApplicationContext(), mConnection); + waitForConnection(); + startUiTimer(); } @Override protected void onStop() { Log.v(TAG,"onStop()"); super.onStop(); + stopUiTimer(); mUtil.unbindFromServer(this, mConnection); } @@ -85,56 +92,136 @@ public class LogManagerControlActivity extends AppCompatActivity { protected void onPause() { Log.v(TAG,"onPause()"); super.onPause(); - stopUiTimer(); + //stopUiTimer(); } @Override protected void onResume() { Log.v(TAG,"onResume()"); super.onResume(); - startUiTimer(); + //startUiTimer(); + } + + 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) - new Handler().postDelayed(new Runnable() { - @Override - public void run() { - Log.v(TAG,"onResume(): Updating UI after delay"); - updateUi(); - } - }, 100); + 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); + } + } + // FIXME - for some reason this never gets called, which is why we have the 'waitForConnection()' + // function that polls the connection until it is connected. + public void onServiceConnected(ComponentName name, IBinder service) { + Log.w(TAG, "onServiceConnected()"); + initialiseServiceConnection(); + } + + private void initialiseServiceConnection() { + mLm = mConnection.mSdServer.mLm; + getRemoteEvents(); + // 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); + } + + + + private void getRemoteEvents() { + // Retrieve events from remote database + mLm.mWac.getEvents((JSONObject remoteEventsObj) -> { + Log.v(TAG, "getRemoteEvents()"); + if (remoteEventsObj == null) { + Log.e(TAG, "getRemoteEvents Callback: Error Retrieving events"); + mUtil.showToast("Error Retrieving Remote Events from Server - Please Try Again Later!"); + } else { + Log.v(TAG, "remoteEventsObj = " + remoteEventsObj.toString()); + try { + JSONArray eventsArray = remoteEventsObj.getJSONArray("events"); + mRemoteEventsList = new ArrayList>(); + // A bit of a hack to display in reverse chronological order + for (int i = eventsArray.length()-1; i>=0; i--) { + JSONObject eventObj = eventsArray.getJSONObject(i); + Long id = eventObj.getLong("id"); + int osdAlarmState = eventObj.getInt("osdAlarmState"); + String dataTime = eventObj.getString("dataTime"); + String typeStr = eventObj.getString("type"); + String subType = eventObj.getString("subType"); + String desc = eventObj.getString("desc"); + HashMap eventHashMap = new HashMap(); + eventHashMap.put("id", String.valueOf(id)); + eventHashMap.put("osdAlarmState", String.valueOf(osdAlarmState)); + eventHashMap.put("dataTime", dataTime); + eventHashMap.put("type", typeStr); + eventHashMap.put("subType", subType); + eventHashMap.put("desc", desc); + mRemoteEventsList.add(eventHashMap); + } + } catch (JSONException e) { + Log.e(TAG, "getRemoteEvents(): Error Parsing remoteEventsObj: " + e.getMessage()); + mUtil.showToast("Error Parsing remoteEventsObj - this should not happen!!!"); + mRemoteEventsList = null; + } + Log.v(TAG, "getRemoteEvents(): mRemoteEventsList = " + mRemoteEventsList.toString()); + } + }); } private void updateUi() { //Log.v(TAG,"updateUi()"); + boolean stopUpdating = true; TextView tv; Button btn; - if (mConnection.mBound) { - mLm = mConnection.mSdServer.mLm; - - // Local Database Information + // Local Database Information + if (mLm != null) { tv = (TextView) findViewById(R.id.num_local_events_tv); int eventCount = mLm.getLocalEventsCount(true); tv.setText(String.format("%d", eventCount)); tv = (TextView) findViewById(R.id.num_local_datapoints_tv); int datapointsCount = mLm.getLocalDatapointsCount(); tv.setText(String.format("%d", datapointsCount)); + } else { + stopUpdating = false; + } - // 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); + if (mEventsList != null) { ListView lv = (ListView) findViewById(R.id.eventLogListView); ListAdapter adapter = new SimpleAdapter(LogManagerControlActivity.this, mEventsList, R.layout.log_entry_layout, new String[]{"dataTime", "status", "uploaded"}, new int[]{R.id.event_date, R.id.event_alarmState, R.id.event_uploaded}); lv.setAdapter(adapter); //Log.v(TAG,"eventsList="+mEventsList); + } else { + stopUpdating = false; + } + // Remote Database List View + if (mRemoteEventsList != null) { + ListView lv = (ListView) findViewById(R.id.remoteEventsLv); + ListAdapter adapter = new SimpleAdapter(LogManagerControlActivity.this, mRemoteEventsList, R.layout.log_entry_layout, + new String[]{"dataTime", "type", "subType"}, + new int[]{R.id.event_date, R.id.event_alarmState, R.id.event_uploaded}); + lv.setAdapter(adapter); + } else { + //mUtil.showToast("No Remote Events"); + Log.d(TAG,"UpdateUi: No Remote Events"); + stopUpdating = false; + } - // Remote Database Information + // Remote Database Information + if (mLm != null) { tv = (TextView) findViewById(R.id.authStatusTv); btn = (Button) findViewById(R.id.auth_button); if (mLm.mWac.isLoggedIn()) { @@ -144,50 +231,11 @@ public class LogManagerControlActivity extends AppCompatActivity { tv.setText("NOT AUTHENTICATED"); btn.setText("Log In"); } - - // Retrieve events from remote database - mLm.mWac.getEvents((JSONObject remoteEventsObj) -> { - Log.v(TAG, "onResume.getEvents"); - if (remoteEventsObj == null) { - Log.e(TAG, "onResume.getEvents Callback: Error Retrieving events"); - mUtil.showToast("Error Retrieving Remote Events from Server - Please Try Again Later!"); - } else { - Log.v(TAG,"remoteEventsObj = "+remoteEventsObj.toString()); -/* 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); - mEventTypesListChanged = true; - } catch (JSONException e) { - Log.e(TAG, "onCreate(getEventTypes Callback: Error parsing JSONObject" + e.getMessage() + e.toString()); - } - } - updateUi(); - - */ - } - - - }); - - - - - } else { - Log.e(TAG, "ERROR: Not connected to SDServer - not updating UI"); + } else { + stopUpdating = false; } - } - //updateUi(); + if (stopUpdating) stopUiTimer(); + } //updateUi(); @@ -258,34 +306,30 @@ public class LogManagerControlActivity extends AppCompatActivity { HashMap eventObj = (HashMap)adapter.getItemAtPosition(position); Long eventId = Long.parseLong(eventObj.get("uploaded")); Log.d(TAG,"onItemClickListener(): eventId="+eventId+", eventObj="+eventObj); + if (eventId>0) { + Intent i = new Intent(getApplicationContext(), EditEventActivity.class); + i.putExtra("eventId", eventId); + startActivity(i); + } else { + mUtil.showToast("You Must Wait for Event to Upload before Editing it"); + } + } + }; + + AdapterView.OnItemClickListener onRemoteEventListClick = + new AdapterView.OnItemClickListener() { + public void onItemClick(AdapterView adapter, View v, int position, long id) { + Log.v(TAG, "onRemoteEventList Click() - Position=" + position + ", id=" + id);// Confirmation dialog based on: https://stackoverflow.com/a/12213536/2104584 + HashMap eventObj = (HashMap)adapter.getItemAtPosition(position); + Long eventId = Long.parseLong(eventObj.get("id")); + 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() { - @Override - public void onClick(DialogInterface dialog, int which) { - // Do Something! - dialog.dismiss(); - } - }); - builder.setNegativeButton("NO", new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - dialog.dismiss(); - } - }); - AlertDialog alert = builder.create(); - alert.show(); - */ - - //MyClass selItem = (MyClass) myList.getSelectedItem(); // - //String value= selItem.getTheValue(); //getter method } }; + /* * Start the timer that will update the user interface every 5 seconds.. */ @@ -307,7 +351,7 @@ public class LogManagerControlActivity extends AppCompatActivity { */ public void stopUiTimer() { if (mUiTimer != null) { - Log.v(TAG, "stopRemoteLogTimer(): cancelling Remote Log timer"); + Log.v(TAG, "stopUiTimer(): cancelling UI timer"); mUiTimer.cancel(); mUiTimer = null; } @@ -331,7 +375,8 @@ public class LogManagerControlActivity extends AppCompatActivity { //Log.v(TAG, "UiTimer - onFinish - Updating UI"); updateUi(); // Restart this timer. - start(); + if (mUiTimer != null) + start(); } } diff --git a/app/src/main/java/uk/org/openseizuredetector/MainActivity.java b/app/src/main/java/uk/org/openseizuredetector/MainActivity.java index 854f60d..05e55e4 100644 --- a/app/src/main/java/uk/org/openseizuredetector/MainActivity.java +++ b/app/src/main/java/uk/org/openseizuredetector/MainActivity.java @@ -98,7 +98,7 @@ public class MainActivity extends AppCompatActivity { .build(); //int i = 5/0; // Force exception to test handler. - mUtil = new OsdUtil(this,serverStatusHandler); + mUtil = new OsdUtil(getApplicationContext(),serverStatusHandler); mConnection = new SdServiceConnection(this); mUtil.writeToSysLogFile(""); mUtil.writeToSysLogFile("* MainActivity Started *"); diff --git a/app/src/main/java/uk/org/openseizuredetector/OsdUtil.java b/app/src/main/java/uk/org/openseizuredetector/OsdUtil.java index 1a2dafb..4066a2c 100644 --- a/app/src/main/java/uk/org/openseizuredetector/OsdUtil.java +++ b/app/src/main/java/uk/org/openseizuredetector/OsdUtil.java @@ -214,7 +214,7 @@ public class OsdUtil implements ActivityCompat.OnRequestPermissionsResultCallbac /** * bind an activity to to an already running server. */ - public void bindToServer(Activity activity, SdServiceConnection sdServiceConnection) { + public void bindToServer(Context activity, SdServiceConnection sdServiceConnection) { Log.i(TAG, "OsdUtil.bindToServer() - binding to SdServer"); writeToSysLogFile("bindToServer() - binding to SdServer"); Intent intent = new Intent(sdServiceConnection.mContext, SdServer.class); diff --git a/app/src/main/java/uk/org/openseizuredetector/StartupActivity.java b/app/src/main/java/uk/org/openseizuredetector/StartupActivity.java index 4c86409..10b5a2d 100644 --- a/app/src/main/java/uk/org/openseizuredetector/StartupActivity.java +++ b/app/src/main/java/uk/org/openseizuredetector/StartupActivity.java @@ -88,7 +88,7 @@ public class StartupActivity extends Activity { mHandler = new Handler(); - mUtil = new OsdUtil(this, mHandler); + mUtil = new OsdUtil(getApplicationContext(), mHandler); mUtil.writeToSysLogFile(""); mUtil.writeToSysLogFile("*******************************"); mUtil.writeToSysLogFile("* StartUpActivity Started *"); diff --git a/app/src/main/java/uk/org/openseizuredetector/WebApiConnection.java b/app/src/main/java/uk/org/openseizuredetector/WebApiConnection.java index 9c8d15e..ecc715f 100644 --- a/app/src/main/java/uk/org/openseizuredetector/WebApiConnection.java +++ b/app/src/main/java/uk/org/openseizuredetector/WebApiConnection.java @@ -17,6 +17,7 @@ import com.android.volley.toolbox.JsonObjectRequest; import com.android.volley.toolbox.StringRequest; import com.android.volley.toolbox.Volley; +import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; @@ -288,7 +289,9 @@ public class WebApiConnection { public void onResponse(String response) { Log.v(TAG, "Response is: " + response); try { - JSONObject retObj = new JSONObject(response); + JSONObject retObj = new JSONObject(); + JSONArray eventArray = new JSONArray(response); + retObj.put("events", eventArray); callback.accept(retObj); } catch (JSONException e) { Log.e(TAG,"getEventTypes.onRespons(): Error: "+e.getMessage()+","+e.toString());