Added notification to alert the user if data sharing is not enabled, and provide information on why it is good to enable it.

This commit is contained in:
Graham Jones
2022-02-27 19:43:01 +00:00
parent 26690efa11
commit dc27b5eb67
9 changed files with 297 additions and 96 deletions

View File

@@ -3,7 +3,7 @@
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
package="uk.org.openseizuredetector" package="uk.org.openseizuredetector"
android:versionCode="92" android:versionCode="92"
android:versionName="4.0.0k"> android:versionName="4.0.0l">
<!-- android:allowBackup="false" --> <!-- android:allowBackup="false" -->
<uses-permission android:name="android.permission.BLUETOOTH" /> <uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" /> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />

View File

@@ -26,6 +26,8 @@
package uk.org.openseizuredetector; package uk.org.openseizuredetector;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.graphics.Color; import android.graphics.Color;
@@ -81,6 +83,7 @@ public class MainActivity extends AppCompatActivity {
final Handler serverStatusHandler = new Handler(); final Handler serverStatusHandler = new Handler();
Messenger messenger = new Messenger(new ResponseHandler()); Messenger messenger = new Messenger(new ResponseHandler());
Timer mUiTimer; Timer mUiTimer;
private Context mContext;
/** /**
* Called when the activity is first created. * Called when the activity is first created.
@@ -88,7 +91,7 @@ public class MainActivity extends AppCompatActivity {
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
Log.i(TAG,"onCreate()"); Log.i(TAG, "onCreate()");
// Set our custom uncaught exception handler to report issues. // Set our custom uncaught exception handler to report issues.
//Thread.setDefaultUncaughtExceptionHandler(new OsdUncaughtExceptionHandler(MainActivity.this)); //Thread.setDefaultUncaughtExceptionHandler(new OsdUncaughtExceptionHandler(MainActivity.this));
@@ -97,11 +100,12 @@ public class MainActivity extends AppCompatActivity {
.build(); .build();
//int i = 5/0; // Force exception to test handler. //int i = 5/0; // Force exception to test handler.
mUtil = new OsdUtil(getApplicationContext(),serverStatusHandler); mUtil = new OsdUtil(getApplicationContext(), serverStatusHandler);
mConnection = new SdServiceConnection(getApplicationContext()); mConnection = new SdServiceConnection(getApplicationContext());
mUtil.writeToSysLogFile(""); mUtil.writeToSysLogFile("");
mUtil.writeToSysLogFile("* MainActivity Started *"); mUtil.writeToSysLogFile("* MainActivity Started *");
mUtil.writeToSysLogFile("MainActivity.onCreate()"); mUtil.writeToSysLogFile("MainActivity.onCreate()");
mContext = this;
// Initialise the User Interface // Initialise the User Interface
setContentView(R.layout.main); setContentView(R.layout.main);
@@ -135,12 +139,11 @@ public class MainActivity extends AppCompatActivity {
Log.v(TAG, "acceptAlarmButton.onClick()"); Log.v(TAG, "acceptAlarmButton.onClick()");
if (mConnection.mBound) { if (mConnection.mBound) {
if ((mConnection.mSdServer.mSmsTimer != null) if ((mConnection.mSdServer.mSmsTimer != null)
&& (mConnection.mSdServer.mSmsTimer.mTimeLeft > 0 )){ && (mConnection.mSdServer.mSmsTimer.mTimeLeft > 0)) {
Log.v(TAG, "acceptAlarmButton.onClick() - Stopping SMS Timer"); Log.v(TAG, "acceptAlarmButton.onClick() - Stopping SMS Timer");
mUtil.showToast(getString(R.string.SMSAlarmCancelledMsg)); mUtil.showToast(getString(R.string.SMSAlarmCancelledMsg));
mConnection.mSdServer.stopSmsTimer(); mConnection.mSdServer.stopSmsTimer();
} } else {
else {
Log.v(TAG, "acceptAlarmButton.onClick() - Accepting Alarm"); Log.v(TAG, "acceptAlarmButton.onClick() - Accepting Alarm");
mConnection.mSdServer.acceptAlarm(); mConnection.mSdServer.acceptAlarm();
} }
@@ -191,7 +194,42 @@ public class MainActivity extends AppCompatActivity {
} }
}); });
// The background service might ask us to show the data sharing dialog if data sharing is not working correctly
String actionStr = getIntent().getAction();
if (actionStr != null) {
Log.i(TAG, "onCreate() - action=" + actionStr);
if (actionStr.equals("showDataSharingDialog")) {
showDataSharingDialog();
}
} else {
Log.i(TAG, "onCreate - action is null - starting normally");
}
}
@Override
protected void onNewIntent(Intent intent) {
String actionStr;
Log.i(TAG, "onNewIntent");
Bundle extras = intent.getExtras();
// The background service might ask us to show the data sharing dialog if data sharing is not working correctly
actionStr = getIntent().getAction();
if (actionStr != null) {
Log.i(TAG, "onNewIntent() - action=" + actionStr);
if (actionStr.equals("showDataSharingDialog")) {
showDataSharingDialog();
}
} else {
if (extras != null) {
actionStr = extras.getString("action");
if (actionStr.equals("showDataSharingDialog")) {
showDataSharingDialog();
}
Log.i(TAG, "onNewIntent - extra actionstr is "+actionStr);
} else {
Log.i(TAG, "onNewIntent - extra actionstr is null - starting normally");
}
}
} }
/** /**
@@ -292,7 +330,10 @@ public class MainActivity extends AppCompatActivity {
Log.i(TAG, "exception starting export activity " + ex.toString()); Log.i(TAG, "exception starting export activity " + ex.toString());
} }
return true; return true;
case R.id.action_about_datasharing:
Log.i(TAG, "action_about_datasharing");
showDataSharingDialog();
return true;
/* /*
case R.id.action_export: case R.id.action_export:
Log.i(TAG, "action_export"); Log.i(TAG, "action_export");
@@ -370,7 +411,7 @@ public class MainActivity extends AppCompatActivity {
@Override @Override
protected void onStart() { protected void onStart() {
super.onStart(); super.onStart();
Log.d(TAG,"onStart()"); Log.i(TAG, "onStart()");
mUtil.writeToSysLogFile("MainActivity.onStart()"); mUtil.writeToSysLogFile("MainActivity.onStart()");
SharedPreferences SP = PreferenceManager SharedPreferences SP = PreferenceManager
.getDefaultSharedPreferences(getBaseContext()); .getDefaultSharedPreferences(getBaseContext());
@@ -386,7 +427,7 @@ public class MainActivity extends AppCompatActivity {
mUtil.writeToSysLogFile("MainActivity.onStart - Binding to Server"); mUtil.writeToSysLogFile("MainActivity.onStart - Binding to Server");
mUtil.bindToServer(getApplicationContext(), mConnection); mUtil.bindToServer(getApplicationContext(), mConnection);
} else { } else {
Log.i(TAG,"onStart() - Server Not Running"); Log.i(TAG, "onStart() - Server Not Running");
mUtil.writeToSysLogFile("MainActivity.onStart - Server Not Running"); mUtil.writeToSysLogFile("MainActivity.onStart - Server Not Running");
} }
// start timer to refresh user interface every second. // start timer to refresh user interface every second.
@@ -404,7 +445,7 @@ public class MainActivity extends AppCompatActivity {
@Override @Override
protected void onStop() { protected void onStop() {
super.onStop(); super.onStop();
Log.d(TAG,"onStop() - unbinding from server"); Log.i(TAG, "onStop() - unbinding from server");
mUtil.writeToSysLogFile("MainActivity.onStop()"); mUtil.writeToSysLogFile("MainActivity.onStop()");
mUtil.unbindFromServer(getApplicationContext(), mConnection); mUtil.unbindFromServer(getApplicationContext(), mConnection);
mUiTimer.cancel(); mUiTimer.cancel();
@@ -465,7 +506,7 @@ public class MainActivity extends AppCompatActivity {
tv.setBackgroundColor(okColour); tv.setBackgroundColor(okColour);
tv.setTextColor(okTextColour); tv.setTextColor(okTextColour);
tv = (TextView) findViewById(R.id.serverIpTv); tv = (TextView) findViewById(R.id.serverIpTv);
tv.setText(getString(R.string.AccessServerAt)+" http://" tv.setText(getString(R.string.AccessServerAt) + " http://"
+ mUtil.getLocalIpAddress() + mUtil.getLocalIpAddress()
+ ":8080"); + ":8080");
tv.setBackgroundColor(okColour); tv.setBackgroundColor(okColour);
@@ -523,7 +564,7 @@ public class MainActivity extends AppCompatActivity {
// Pebble Connected Phrase - use for HR if active instead. // Pebble Connected Phrase - use for HR if active instead.
tv = (TextView) findViewById(R.id.pebbleTv); tv = (TextView) findViewById(R.id.pebbleTv);
if (mConnection.mSdServer.mSdData.mHRAlarmActive) { if (mConnection.mSdServer.mSdData.mHRAlarmActive) {
tv.setText(getString(R.string.HR_Equals) + mConnection.mSdServer.mSdData.mHR +" bpm\n" tv.setText(getString(R.string.HR_Equals) + mConnection.mSdServer.mSdData.mHR + " bpm\n"
+ "O2 Sat = " + mConnection.mSdServer.mSdData.mO2Sat + "%"); + "O2 Sat = " + mConnection.mSdServer.mSdData.mO2Sat + "%");
if (mConnection.mSdServer.mSdData.mHRAlarmStanding || mConnection.mSdServer.mSdData.mO2SatAlarmStanding) { if (mConnection.mSdServer.mSdData.mHRAlarmStanding || mConnection.mSdServer.mSdData.mO2SatAlarmStanding) {
tv.setBackgroundColor(alarmColour); tv.setBackgroundColor(alarmColour);
@@ -655,9 +696,9 @@ public class MainActivity extends AppCompatActivity {
specRatio = 0; specRatio = 0;
((TextView) findViewById(R.id.powerTv)).setText(getString(R.string.PowerEquals) + mConnection.mSdServer.mSdData.roiPower + ((TextView) findViewById(R.id.powerTv)).setText(getString(R.string.PowerEquals) + mConnection.mSdServer.mSdData.roiPower +
" ("+ getString(R.string.Threshold) + "=" + mConnection.mSdServer.mSdData.alarmThresh + ")"); " (" + getString(R.string.Threshold) + "=" + mConnection.mSdServer.mSdData.alarmThresh + ")");
((TextView) findViewById(R.id.spectrumTv)).setText(getString(R.string.SpectrumRatioEquals) + specRatio + ((TextView) findViewById(R.id.spectrumTv)).setText(getString(R.string.SpectrumRatioEquals) + specRatio +
" ("+ getString(R.string.Threshold) + "=" + mConnection.mSdServer.mSdData.alarmRatioThresh + ")"); " (" + getString(R.string.Threshold) + "=" + mConnection.mSdServer.mSdData.alarmRatioThresh + ")");
ProgressBar pb; ProgressBar pb;
Drawable pbDrawable; Drawable pbDrawable;
@@ -712,17 +753,17 @@ public class MainActivity extends AppCompatActivity {
tv.setTextColor(warnTextColour); tv.setTextColor(warnTextColour);
tv = (TextView) findViewById(R.id.pebbleTv); tv = (TextView) findViewById(R.id.pebbleTv);
tv.setText(getString(R.string.HR_Equals)+" --- bpm\nO2 Sat = --- %"); tv.setText(getString(R.string.HR_Equals) + " --- bpm\nO2 Sat = --- %");
tv.setBackgroundColor(warnColour); tv.setBackgroundColor(warnColour);
tv.setTextColor(warnTextColour); tv.setTextColor(warnTextColour);
tv = (TextView) findViewById(R.id.appTv); tv = (TextView) findViewById(R.id.appTv);
tv.setText(getString(R.string.WatchApp)+" ----"); tv.setText(getString(R.string.WatchApp) + " ----");
tv.setBackgroundColor(warnColour); tv.setBackgroundColor(warnColour);
tv.setTextColor(warnTextColour); tv.setTextColor(warnTextColour);
tv = (TextView) findViewById(R.id.battTv); tv = (TextView) findViewById(R.id.battTv);
tv.setText(getString(R.string.WatchBatteryEquals)+" ---%"); tv.setText(getString(R.string.WatchBatteryEquals) + " ---%");
tv.setBackgroundColor(warnColour); tv.setBackgroundColor(warnColour);
tv.setTextColor(warnTextColour); tv.setTextColor(warnTextColour);
} }
@@ -742,17 +783,17 @@ public class MainActivity extends AppCompatActivity {
tv.setTextColor(warnTextColour); tv.setTextColor(warnTextColour);
tv = (TextView) findViewById(R.id.pebbleTv); tv = (TextView) findViewById(R.id.pebbleTv);
tv.setText(getString(R.string.HR_Equals)+"---"); tv.setText(getString(R.string.HR_Equals) + "---");
tv.setBackgroundColor(warnColour); tv.setBackgroundColor(warnColour);
tv.setTextColor(warnTextColour); tv.setTextColor(warnTextColour);
tv = (TextView) findViewById(R.id.appTv); tv = (TextView) findViewById(R.id.appTv);
tv.setText(getString(R.string.WatchApp)+" -----"); tv.setText(getString(R.string.WatchApp) + " -----");
tv.setBackgroundColor(warnColour); tv.setBackgroundColor(warnColour);
tv.setTextColor(warnTextColour); tv.setTextColor(warnTextColour);
tv = (TextView) findViewById(R.id.battTv); tv = (TextView) findViewById(R.id.battTv);
tv.setText(getString(R.string.WatchBatteryEquals)+" ---%"); tv.setText(getString(R.string.WatchBatteryEquals) + " ---%");
tv.setBackgroundColor(warnColour); tv.setBackgroundColor(warnColour);
tv.setTextColor(warnTextColour); tv.setTextColor(warnTextColour);
@@ -774,7 +815,7 @@ public class MainActivity extends AppCompatActivity {
&& (mConnection.mSdServer.mSmsTimer.mTimeLeft > 0)) { && (mConnection.mSdServer.mSmsTimer.mTimeLeft > 0)) {
acceptAlarmButton.setText(getString(R.string.SMSWillBeSentIn) + " " + acceptAlarmButton.setText(getString(R.string.SMSWillBeSentIn) + " " +
mConnection.mSdServer.mSmsTimer.mTimeLeft / 1000 + mConnection.mSdServer.mSmsTimer.mTimeLeft / 1000 +
" s - "+getString(R.string.Cancel)); " s - " + getString(R.string.Cancel));
acceptAlarmButton.setBackgroundColor(alarmColour); acceptAlarmButton.setBackgroundColor(alarmColour);
acceptAlarmButton.setEnabled(true); acceptAlarmButton.setEnabled(true);
} else { } else {
@@ -800,7 +841,7 @@ public class MainActivity extends AppCompatActivity {
if (mConnection.mBound) if (mConnection.mBound)
if (mConnection.mSdServer.isAudibleCancelled()) { if (mConnection.mSdServer.isAudibleCancelled()) {
cancelAudibleButton.setText(getString(R.string.AudibleAlarmsCancelledFor) cancelAudibleButton.setText(getString(R.string.AudibleAlarmsCancelledFor)
+ " " +mConnection.mSdServer. + " " + mConnection.mSdServer.
cancelAudibleTimeRemaining() cancelAudibleTimeRemaining()
+ " sec"); + " sec");
cancelAudibleButton.setEnabled(true); cancelAudibleButton.setEnabled(true);
@@ -825,17 +866,16 @@ public class MainActivity extends AppCompatActivity {
ArrayList<String> xVals = new ArrayList<String>(); ArrayList<String> xVals = new ArrayList<String>();
ArrayList<BarEntry> yBarVals = new ArrayList<BarEntry>(); ArrayList<BarEntry> yBarVals = new ArrayList<BarEntry>();
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++) {
xVals.add(i+"-"+(i+1)+" Hz"); xVals.add(i + "-" + (i + 1) + " Hz");
if (mConnection.mSdServer != null) { if (mConnection.mSdServer != null) {
yBarVals.add(new BarEntry(mConnection.mSdServer.mSdData.simpleSpec[i], i)); yBarVals.add(new BarEntry(mConnection.mSdServer.mSdData.simpleSpec[i], i));
} } else {
else { yBarVals.add(new BarEntry(i, i));
yBarVals.add(new BarEntry(i,i));
} }
} }
// create a dataset and give it a type // create a dataset and give it a type
BarDataSet barDataSet = new BarDataSet(yBarVals,"Spectrum"); BarDataSet barDataSet = new BarDataSet(yBarVals, "Spectrum");
try { try {
int[] barColours = new int[10]; int[] barColours = new int[10];
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++) {
@@ -847,12 +887,12 @@ public class MainActivity extends AppCompatActivity {
} }
} }
barDataSet.setColors(barColours); barDataSet.setColors(barColours);
} catch (NullPointerException e){ } catch (NullPointerException e) {
Log.e(TAG,"Null pointer exception setting bar colours"); Log.e(TAG, "Null pointer exception setting bar colours");
} }
barDataSet.setBarSpacePercent(20f); barDataSet.setBarSpacePercent(20f);
barDataSet.setBarShadowColor(Color.WHITE); barDataSet.setBarShadowColor(Color.WHITE);
BarData barData = new BarData(xVals,barDataSet); BarData barData = new BarData(xVals, barDataSet);
barData.setValueFormatter(new ValueFormatter() { barData.setValueFormatter(new ValueFormatter() {
@Override @Override
public String getFormattedValue(float v) { public String getFormattedValue(float v) {
@@ -893,7 +933,7 @@ public class MainActivity extends AppCompatActivity {
try { try {
mChart.getLegend().setEnabled(false); mChart.getLegend().setEnabled(false);
} catch (NullPointerException e) { } catch (NullPointerException e) {
Log.e(TAG,"Null Pointer Exception setting legend"); Log.e(TAG, "Null Pointer Exception setting legend");
} }
mChart.invalidate(); mChart.invalidate();
@@ -904,14 +944,14 @@ public class MainActivity extends AppCompatActivity {
@Override @Override
protected void onPause() { protected void onPause() {
super.onPause(); super.onPause();
Log.d(TAG,"onPause()"); Log.i(TAG, "onPause()");
mUtil.writeToSysLogFile("MainActivity.onPause()"); mUtil.writeToSysLogFile("MainActivity.onPause()");
} }
@Override @Override
protected void onResume() { protected void onResume() {
super.onResume(); super.onResume();
Log.d(TAG,"onResume()"); Log.i(TAG, "onResume()");
mUtil.writeToSysLogFile("MainActivity.onResume()"); mUtil.writeToSysLogFile("MainActivity.onResume()");
} }
@@ -924,11 +964,40 @@ public class MainActivity extends AppCompatActivity {
AlertDialog.Builder builder = new AlertDialog.Builder(this); AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setIcon(R.drawable.icon_24x24); builder.setIcon(R.drawable.icon_24x24);
builder.setTitle("OpenSeizureDetector V" + versionName); builder.setTitle("OpenSeizureDetector V" + versionName);
builder.setPositiveButton("OK", null);
builder.setView(aboutView); builder.setView(aboutView);
builder.create(); builder.create();
builder.show(); builder.show();
} }
private void showDataSharingDialog() {
mUtil.writeToSysLogFile("MainActivity.showDataSharingDialog()");
View aboutView = getLayoutInflater().inflate(R.layout.data_sharing_dialog_layout, null, false);
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setIcon(R.drawable.datasharing_fault_24x24);
builder.setTitle("OpenSeizureDetector Data Sharing");
builder.setNegativeButton(getString(R.string.cancel), null);
builder.setPositiveButton(getString(R.string.login), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Log.i(TAG, "dataSharingDialog.positiveButton.onClick()");
try {
Intent i = new Intent(
MainActivity.this,
AuthenticateActivity.class);
mContext.startActivity(i);
} catch (Exception ex) {
Log.i(TAG, "exception starting activity " + ex.toString());
}
}
});
builder.setView(aboutView);
builder.create();
builder.show();
}
static class ResponseHandler extends Handler { static class ResponseHandler extends Handler {
@Override @Override
public void handleMessage(Message message) { public void handleMessage(Message message) {

View File

@@ -84,11 +84,15 @@ public class SdServer extends Service implements SdDataReceiver {
private String mUuidStr = "0f675b21-5a36-4fe7-9761-fd0c691651f3"; // UUID to Identify OSD. private String mUuidStr = "0f675b21-5a36-4fe7-9761-fd0c691651f3"; // UUID to Identify OSD.
// Notification ID // Notification ID
private int NOTIFICATION_ID = 1; private final int NOTIFICATION_ID = 1;
private int EVENT_NOTIFICATION_ID = 2; private final int EVENT_NOTIFICATION_ID = 2;
private final int DATASHARE_NOTIFICATION_ID = 3;
private String mNotChId = "OSD Notification Channel"; private String mNotChId = "OSD Notification Channel";
private CharSequence mNotChName = "OSD Notification Channel"; private CharSequence mNotChName = "OSD Notification Channel";
private String mNotChDesc = "OSD Notification Channel Description"; private String mNotChDesc = "OSD Notification Channel Description";
private String mEventNotChId = "OSD Event Notification Channel";
private CharSequence mEventNotChName = "OSD Event Notification Channel";
private String mEventNotChDesc = "OSD Event Notification Channel Description";
private NotificationManager mNM; private NotificationManager mNM;
private NotificationCompat.Builder mNotificationBuilder; private NotificationCompat.Builder mNotificationBuilder;
@@ -100,7 +104,7 @@ public class SdServer extends Service implements SdDataReceiver {
private int mCancelAudiblePeriod = 10; // Cancel Audible Period in minutes private int mCancelAudiblePeriod = 10; // Cancel Audible Period in minutes
private long mCancelAudibleTimeRemaining = 0; private long mCancelAudibleTimeRemaining = 0;
private FaultTimer mFaultTimer = null; private FaultTimer mFaultTimer = null;
private CheckUnvalidatedEventsTimer mEventsTimer = null; private CheckEventsTimer mEventsTimer = null;
private int mFaultTimerPeriod = 30; // Fault Timer Period in sec private int mFaultTimerPeriod = 30; // Fault Timer Period in sec
private boolean mFaultTimerCompleted = false; private boolean mFaultTimerCompleted = false;
@@ -132,6 +136,7 @@ public class SdServer extends Service implements SdDataReceiver {
public boolean mLogDataRemote = false; public boolean mLogDataRemote = false;
public boolean mLogDataRemoteMobile = false; public boolean mLogDataRemoteMobile = false;
private String mAuthToken = null; private String mAuthToken = null;
private long mEventsTimerPeriod = 60; // Number of seconds between checks to see if there are unvalidated remote events.
private long mEventDuration = 120; // event duration in seconds - uploads datapoints that cover this time range centred on the event time. 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) 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 mRemoteLogPeriod = 60; // Period in seconds between uploads to the remote server.
@@ -324,7 +329,7 @@ public class SdServer extends Service implements SdDataReceiver {
} }
if (mLogDataRemote) { if (mLogDataRemote) {
startValidatedEventsTimer(); startEventsTimer();
} }
@@ -393,17 +398,17 @@ public class SdServer extends Service implements SdDataReceiver {
// Stop the Event timer // Stop the Event timer
if (mEventsTimer != null) { if (mEventsTimer != null) {
Log.d(TAG, "onDestroy(): Cancelling events timer"); Log.d(TAG, "onDestroy(): Cancelling events timer");
stopValidatedEventsTimer(); stopEventsTimer();
} }
// Stop the Cancel Alarm Latch timer // Stop the Cancel Alarm Latch timer
Log.d(TAG,"onDestroy(): stopping alarm latch timer"); Log.d(TAG, "onDestroy(): stopping alarm latch timer");
stopLatchTimer(); stopLatchTimer();
// Stop the location finder. // Stop the location finder.
if (mLocationFinder != null) { if (mLocationFinder != null) {
Log.d(TAG,"onDestroy(): stopping Location Finder"); Log.d(TAG, "onDestroy(): stopping Location Finder");
mLocationFinder.destroy(); mLocationFinder.destroy();
mLocationFinder = null; mLocationFinder = null;
} }
@@ -425,6 +430,7 @@ public class SdServer extends Service implements SdDataReceiver {
mUtil.writeToSysLogFile("SdServer.onDestroy - cancelling notification"); mUtil.writeToSysLogFile("SdServer.onDestroy - cancelling notification");
mNM.cancel(NOTIFICATION_ID); mNM.cancel(NOTIFICATION_ID);
mNM.cancel(EVENT_NOTIFICATION_ID); mNM.cancel(EVENT_NOTIFICATION_ID);
mNM.cancel(DATASHARE_NOTIFICATION_ID);
// stop this service. // stop this service.
@@ -1513,18 +1519,18 @@ public class SdServer extends Service implements SdDataReceiver {
/** /**
* Start the events timer. * Start the events timer.
*/ */
public void startValidatedEventsTimer() { public void startEventsTimer() {
if (mEventsTimer != null) { if (mEventsTimer != null) {
Log.v(TAG, "startValidatedEventsTimer(): timer already running - not doing anything."); Log.v(TAG, "startEventsTimer(): timer already running - not doing anything.");
mUtil.writeToSysLogFile("startValidatedEventsTimer() - timer already running"); mUtil.writeToSysLogFile("startEventsTimer() - timer already running");
} else { } else {
Log.v(TAG, "startValidatedEventsTimer(): starting timer."); Log.v(TAG, "startEventsTimer(): starting timer.");
mUtil.writeToSysLogFile("startValidatedEventsTimer() - starting timer"); mUtil.writeToSysLogFile("startEventsTimer() - starting timer");
runOnUiThread(new Runnable() { runOnUiThread(new Runnable() {
public void run() { public void run() {
mEventsTimer = mEventsTimer =
// Run every 10 sec (convert to ms.) // Run every 10 sec (convert to ms.)
new CheckUnvalidatedEventsTimer(10 * 1000, 1000); new CheckEventsTimer(mEventsTimerPeriod * 1000, 1000);
mEventsTimer.mIsRunning = true; mEventsTimer.mIsRunning = true;
mEventsTimer.start(); mEventsTimer.start();
} }
@@ -1532,7 +1538,7 @@ public class SdServer extends Service implements SdDataReceiver {
} }
} }
public void stopValidatedEventsTimer() { public void stopEventsTimer() {
if (mEventsTimer != null) { if (mEventsTimer != null) {
Log.v(TAG, "stopEventsTimer(): timer already running - cancelling it."); Log.v(TAG, "stopEventsTimer(): timer already running - cancelling it.");
mUtil.writeToSysLogFile("stopEventsTimer() - stopping timer, setting mIsRunning to false"); mUtil.writeToSysLogFile("stopEventsTimer() - stopping timer, setting mIsRunning to false");
@@ -1548,22 +1554,22 @@ public class SdServer extends Service implements SdDataReceiver {
* Periodically check if we have unvalidated events in the remote database. * Periodically check if we have unvalidated events in the remote database.
* Show a notification if we do. * Show a notification if we do.
*/ */
private class CheckUnvalidatedEventsTimer extends CountDownTimer { private class CheckEventsTimer extends CountDownTimer {
long mFirstUnvalidatedEvent; long mFirstUnvalidatedEvent;
public boolean mIsRunning = true; public boolean mIsRunning = true;
public CheckUnvalidatedEventsTimer(long startTime, long interval) { public CheckEventsTimer(long startTime, long interval) {
super(startTime, interval); super(startTime, interval);
} }
@Override @Override
public void onFinish() { public void onFinish() {
Log.v(TAG, "CheckUnvalidatedEventsTimer.onFinish()"); Log.v(TAG, "CheckEventsTimer.onFinish()");
// Retrieve events from remote database // Retrieve events from remote database
if (mLm.mWac.getEvents((JSONObject remoteEventsObj) -> { if (mLm.mWac.getEvents((JSONObject remoteEventsObj) -> {
Log.v(TAG, "CheckUnvalidatedEventsTimer.onFinish.getEvents.Callback()"); Log.v(TAG, "CheckEventsTimer.onFinish.getEvents.Callback()");
if (remoteEventsObj == null) { if (remoteEventsObj == null) {
Log.e(TAG, "CheckUnvalidatedEventsTimer.onFinish() Callback: Error Retrieving events"); Log.e(TAG, "CheckEventsTimer.onFinish() Callback: Error Retrieving events");
} else { } else {
try { try {
JSONArray eventsArray = remoteEventsObj.getJSONArray("events"); JSONArray eventsArray = remoteEventsObj.getJSONArray("events");
@@ -1573,33 +1579,36 @@ public class SdServer extends Service implements SdDataReceiver {
JSONObject eventObj = eventsArray.getJSONObject(i); JSONObject eventObj = eventsArray.getJSONObject(i);
Long id = eventObj.getLong("id"); Long id = eventObj.getLong("id");
String typeStr = eventObj.getString("type"); String typeStr = eventObj.getString("type");
//Log.v(TAG,"CheckUnvalidatedEventsTimer: id="+id+", typeStr="+typeStr); //Log.v(TAG,"CheckEventsTimer: id="+id+", typeStr="+typeStr);
if (typeStr.equals("null")) { if (typeStr.equals("null")) {
mFirstUnvalidatedEvent = id; mFirstUnvalidatedEvent = id;
//Log.v(TAG,"CheckUnvalidatedEventsTimer:setting mFirstUnvalidatedEvent to "+mFirstUnvalidatedEvent); //Log.v(TAG,"CheckEventsTimer:setting mFirstUnvalidatedEvent to "+mFirstUnvalidatedEvent);
} }
} }
Log.v(TAG, "CheckUnvalidatedEventsTimer.onFinish.callback - mFirstUnvalidatedEvent = " + Log.v(TAG, "CheckEventsTimer.onFinish.callback - mFirstUnvalidatedEvent = " +
mFirstUnvalidatedEvent); mFirstUnvalidatedEvent);
if (mFirstUnvalidatedEvent >= 0) { if (mFirstUnvalidatedEvent >= 0) {
showEventNotification(mFirstUnvalidatedEvent); showEventNotification(mFirstUnvalidatedEvent);
mNM.cancel(DATASHARE_NOTIFICATION_ID);
} else { } else {
mNM.cancel(EVENT_NOTIFICATION_ID); mNM.cancel(EVENT_NOTIFICATION_ID);
mNM.cancel(DATASHARE_NOTIFICATION_ID);
} }
} catch (JSONException e) { } catch (JSONException e) {
Log.e(TAG, "CheckUnvalidatedEventsTimer.onFinish(): Error Parsing remoteEventsObj: " + e.getMessage()); Log.e(TAG, "CheckEventsTimer.onFinish(): Error Parsing remoteEventsObj: " + e.getMessage());
//mUtil.showToast("Error Parsing remoteEventsObj - this should not happen!!!"); //mUtil.showToast("Error Parsing remoteEventsObj - this should not happen!!!");
} }
} }
})) { })) {
Log.v(TAG,"CheckUnvalidatedEventsTimer() - requested events"); Log.v(TAG, "CheckEventsTimer() - requested events");
} else { } else {
Log.v(TAG,"CheckUnvalidatedEventsTimer() - Not Logged In"); Log.v(TAG, "CheckEventsTimer() - Not Logged In");
mNM.cancel(EVENT_NOTIFICATION_ID); mNM.cancel(EVENT_NOTIFICATION_ID);
showDatashareNotification();
} }
if (mIsRunning) { if (mIsRunning) {
// Restart this timer. // Restart this timer.
Log.v(TAG,"CheckUnvalidatedEventsTimer.onFinish() - mIsRunning is true, so re-starting timer"); Log.v(TAG, "CheckEventsTimer.onFinish() - mIsRunning is true, so re-starting timer");
start(); start();
} }
} }
@@ -1616,17 +1625,31 @@ public class SdServer extends Service implements SdDataReceiver {
int iconId; int iconId;
String titleStr; String titleStr;
Uri soundUri = null; Uri soundUri = null;
iconId = R.drawable.star_of_life_query_24x24;
// Initialise Notification channel for API level 26 and over
// from https://stackoverflow.com/questions/44443690/notificationcompat-with-api-26
NotificationManager nM = (NotificationManager) getApplicationContext().getSystemService(Context.NOTIFICATION_SERVICE);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(getApplicationContext(), mEventNotChId);
if (Build.VERSION.SDK_INT >= 26) {
NotificationChannel channel = new NotificationChannel(mEventNotChId,
mEventNotChName,
NotificationManager.IMPORTANCE_DEFAULT);
channel.setDescription(mEventNotChDesc);
nM.createNotificationChannel(channel);
}
iconId = R.drawable.datasharing_query_24x24;
titleStr = getString(R.string.unvalidatedEventsTitle); titleStr = getString(R.string.unvalidatedEventsTitle);
Intent i = new Intent(getApplicationContext(), LogManagerControlActivity.class); Intent i = new Intent(getApplicationContext(), LogManagerControlActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); i.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
i.setAction("None");
PendingIntent contentIntent = PendingIntent contentIntent =
PendingIntent.getActivity(getApplicationContext(), PendingIntent.getActivity(getApplicationContext(),
0, i, PendingIntent.FLAG_UPDATE_CURRENT); 0, i, PendingIntent.FLAG_UPDATE_CURRENT);
String contentStr = getString(R.string.please_confirm_seizure_events); String contentStr = getString(R.string.please_confirm_seizure_events);
if (mNotificationBuilder != null) {
mNotification = mNotificationBuilder.setContentIntent(contentIntent) Notification notification = notificationBuilder.setContentIntent(contentIntent)
.setSmallIcon(iconId) .setSmallIcon(iconId)
.setColor(0x00ffffff) .setColor(0x00ffffff)
.setAutoCancel(false) .setAutoCancel(false)
@@ -1634,13 +1657,65 @@ public class SdServer extends Service implements SdDataReceiver {
.setContentText(contentStr) .setContentText(contentStr)
.setOnlyAlertOnce(true) .setOnlyAlertOnce(true)
.build(); .build();
mNM.notify(EVENT_NOTIFICATION_ID, mNotification); nM.notify(EVENT_NOTIFICATION_ID, notification);
} else {
Log.i(TAG, "showEventNotification() - notification builder is null, so not showing notification.");
} }
} }
/**
* Show a notification asking the user to set-up data sharing.
*/
private void showDatashareNotification() {
Log.v(TAG, "showDatashareNotification()");
int iconId;
String titleStr;
Uri soundUri = null;
// Initialise Notification channel for API level 26 and over
// from https://stackoverflow.com/questions/44443690/notificationcompat-with-api-26
NotificationManager nM = (NotificationManager) getApplicationContext().getSystemService(Context.NOTIFICATION_SERVICE);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(getApplicationContext(), mEventNotChId);
if (Build.VERSION.SDK_INT >= 26) {
NotificationChannel channel = new NotificationChannel(mEventNotChId,
mEventNotChName,
NotificationManager.IMPORTANCE_DEFAULT);
channel.setDescription(mEventNotChDesc);
nM.createNotificationChannel(channel);
} }
iconId = R.drawable.datasharing_fault_24x24;
titleStr = getString(R.string.datasharing_notification_title);
Intent i = new Intent(getApplicationContext(), MainActivity.class);
i.putExtra("action", "showDataSharingDialog");
i.setAction("showDataSharingDialog");
i.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent contentIntent =
PendingIntent.getActivity(getApplicationContext(),
0, i, PendingIntent.FLAG_UPDATE_CURRENT);
Intent loginIntent = new Intent(getApplicationContext(), AuthenticateActivity.class);
loginIntent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
PendingIntent loginPendingIntent =
PendingIntent.getActivity(getApplicationContext(),
0, loginIntent, PendingIntent.FLAG_UPDATE_CURRENT);
String contentStr = getString(R.string.datasharing_notification_text);
Notification notification = notificationBuilder
.setContentIntent(contentIntent)
.setSmallIcon(iconId)
.setColor(0x00ffffff)
.setAutoCancel(false)
.setContentTitle(titleStr)
.setContentText(contentStr)
.setOnlyAlertOnce(true)
.addAction(R.drawable.common_google_signin_btn_icon_dark, getString(R.string.login), loginPendingIntent)
.setPriority(0)
.build();
nM.notify(DATASHARE_NOTIFICATION_ID, notification);
}
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 347 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 311 B

View File

@@ -2,11 +2,11 @@
<!-- Copyright (C) 2009 The Android Open Source Project <!-- Copyright (C) 2009 The Android Open Source Project
http://www.apache.org/licenses/LICENSE-2.0 http://www.apache.org/licenses/LICENSE-2.0
--> -->
<ScrollView> <ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent">
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical" android:orientation="vertical"

View File

@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2009 The Android Open Source Project
http://www.apache.org/licenses/LICENSE-2.0
-->
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="20dip">
<!--
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="16sp"
android:autoLink="web"
android:text="@string/datasharing_about_title"
/>
-->
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="20dip"
android:textSize="16sp"
android:text="@string/datasharing_about_text"
android:autoLink="web"
/>
</LinearLayout>
</ScrollView>

View File

@@ -35,6 +35,13 @@
android:showAsAction="never|withText" android:showAsAction="never|withText"
android:title="@string/data_sharing_log_in" /> android:title="@string/data_sharing_log_in" />
<item
android:id="@+id/action_about_datasharing"
android:enabled="true"
android:icon="@drawable/ic_action_settings"
android:showAsAction="never|withText"
android:title="About Data Sharing..." />
</group> </group>
<group android:id="@+id/grp4"> <group android:id="@+id/grp4">
<item <item

View File

@@ -348,4 +348,20 @@
<string name="error_server_not_running">ERROR: OpenSeizureDetector Server is not running - please re-start it</string> <string name="error_server_not_running">ERROR: OpenSeizureDetector Server is not running - please re-start it</string>
<string name="system_logs">System Logs</string> <string name="system_logs">System Logs</string>
<string name="logged_in_as_user_id">Logged in as User Id:</string> <string name="logged_in_as_user_id">Logged in as User Id:</string>
<string name="datasharing_notification_text">Select for more information</string>
<string name="datasharing_notification_title">OpenSeizureDetector Data Sharing Problem</string>
<string name="datasharing_about_title">OpenSeizureDetector Data Sharing</string>
<string name="datasharing_about_text">
Data Sharing is not working correctly. \n
This might be because you have not registered an account and logged in to the data sharing system,\n
or it may be a networking problem. \n\n
<b>Please register for Data Sharing and Log in using the App menu or button below</b>\n\n
This will help with developing OpenSeizureDetector to increase the
detection reliability and reduce the false alarm rate\n\n
If you would like more information about the data sharing system and privacy policy, please see the
Data Sharing page (https://www.openseizuredetector.org.uk/?page_id=1818)
\n on the
https://openseizuredetector.org.uk web site.
</string>
</resources> </resources>