V3.1.9 - fixed problem with crash of start-up activity in Android 9, and got warnings working for Garmin Data Source

This commit is contained in:
Graham Jones
2019-07-11 19:57:14 +01:00
parent 238b3c504f
commit 0c5e7e2d2d
8 changed files with 9 additions and 359 deletions

Binary file not shown.

View File

@@ -1 +1 @@
[{"outputType":{"type":"APK"},"apkData":{"type":"MAIN","splits":[],"versionCode":62,"versionName":"3.1.8","enabled":true,"outputFile":"app-release.apk","fullName":"release","baseName":"release"},"path":"app-release.apk","properties":{}}] [{"outputType":{"type":"APK"},"apkData":{"type":"MAIN","splits":[],"versionCode":63,"versionName":"3.1.9","enabled":true,"outputFile":"app-release.apk","fullName":"release","baseName":"release"},"path":"app-release.apk","properties":{}}]

View File

@@ -1,195 +0,0 @@
/*
Android_Pebble_SD - a simple accelerometer based seizure detector that runs on a
Pebble smart watch (http://getpebble.com).
See http://openseizuredetector.org for more information.
Copyright Graham Jones, 2015, 2016, 2017, 2018, 2019.
This file is part of android_pebble_sd.
Android_pebble_sd is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Android_pebble_sd is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with android_pebble_sd. If not, see <http://www.gnu.org/licenses/>.
*/
package uk.org.openseizuredetector;
import android.util.Log;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.jtransforms.fft.DoubleFFT_1D;
/**
* SdAnalyser implements the seizure detection algorithm on an Android Phone - it is used by SdDatasourceGarmin
*/
public class SdAnalyser {
private String TAG = "SdAnalyser";
private double mSampleFreq;
private double mAlarmFreqMin;
private double mAlarmFreqMax;
private double mSamplePeriod;
private double mWarnTime;
private double mAlarmTime;
private double mAlarmThresh;
private double mAlarmRatioThresh;
private double mFreqRes;
private int mAlarmCount;
private double mFreqCutoff;
private int mNSamp;
double roiPower;
double specPower;
double roiRatio;
SdAnalyser(double sampleFreq,
double alarmFreqMin,
double alarmFreqMax,
double samplePeriod,
double warnTime,
double alarmThresh,
double alarmRatioThresh) {
mSampleFreq = sampleFreq;
mAlarmFreqMin = alarmFreqMin;
mAlarmFreqMax = alarmFreqMax;
mSamplePeriod = samplePeriod;
mWarnTime = warnTime;
mAlarmThresh = alarmThresh;
mAlarmRatioThresh = alarmRatioThresh;
mFreqRes = 1.0 / mSamplePeriod;
mFreqCutoff = mSampleFreq / 2.0;
mNSamp = (int)(mSamplePeriod * mSampleFreq);
}
int freq2fftBin(double freq) {
int n = (int)(freq/mFreqRes);
return(n);
}
/**
* doAnalysis() - analyse the data if the accelerometer data array mAccData
* and populate the output data structure mSdData
*/
void calculateSpectralPowers(double[] rawData) {
// Set the frequency bounds for the analysis in fft output bin numbers.
int nMin = freq2fftBin(mAlarmFreqMin);
int nMax = freq2fftBin(mAlarmFreqMax);
int nFreqCutoff = freq2fftBin(mFreqCutoff);
DoubleFFT_1D fftDo = new DoubleFFT_1D(mNSamp);
double[] fft = new double[mNSamp * 2];
System.arraycopy(rawData, 0, fft, 0, mNSamp);
fftDo.realForward(fft);
// Calculate the whole spectrum power (well a value equivalent to it that avoids square root calculations
// and zero any readings that are above the frequency cutoff.
double specPower = 0;
for (int i = 1; i < mNSamp / 2; i++) {
if (i <= nFreqCutoff) {
specPower = specPower + getMagnitude(fft, i);
} else {
fft[2 * i] = 0.;
fft[2 * i + 1] = 0.;
}
}
specPower = specPower / (mNSamp / 2);
// Calculate the Region of Interest power and power ratio.
double roiPower = 0;
for (int i = nMin; i < nMax; i++) {
roiPower = roiPower + getMagnitude(fft, i);
}
roiPower = roiPower / (nMax - nMin);
double roiRatio = 10 * roiPower / specPower;
}
/**
* Calculate the magnitude of entry i in the fft array fft
*
* @param fft
* @param i
* @return magnitude ( Re*Re + Im*Im )
*/
double getMagnitude(double[] fft, int i) {
double mag;
mag = (fft[2 * i] * fft[2 * i] + fft[2 * i + 1] * fft[2 * i + 1]);
return mag;
}
// Force the data stored in this datasource to update in line with the JSON string encoded data provided.
// Used by webServer to update the GarminDatasource.
// Returns a message string that is passed back to the watch.
public String updateFromJSON(String jsonStr) {
String retVal = "undefined";
Log.v(TAG,"updateFromJSON - "+jsonStr);
try {
JSONObject mainObject = new JSONObject(jsonStr);
//JSONObject dataObject = mainObject.getJSONObject("dataObj");
JSONObject dataObject = mainObject;
String dataTypeStr = dataObject.getString("dataType");
Log.v(TAG,"updateFromJSON - dataType="+dataTypeStr);
if (dataTypeStr.equals("raw")) {
Log.v(TAG,"updateFromJSON - processing raw data");
try {
mSdData.mHR = dataObject.getDouble("HR");
} catch (JSONException e) {
// if we get 'null' HR (For example if the heart rate is not working)
mSdData.mHR = -1;
}
try {
mMute = dataObject.getInt("Mute");
} catch (JSONException e) {
// if we get 'null' HR (For example if the heart rate is not working)
mMute = 0;
}
JSONArray accelVals = dataObject.getJSONArray("data");
Log.v(TAG, "Received " + accelVals.length() + " acceleration values");
int i;
for (i = 0; i < accelVals.length(); i++) {
mSdData.rawData[i] = accelVals.getInt(i);
}
mSdData.mNsamp = accelVals.length();
//mNSamp = accelVals.length();
mWatchAppRunningCheck = true;
doAnalysis();
if (mSdData.haveSettings == false) {
retVal = "sendSettings";
} else {
retVal = "OK";
}
} else if (dataTypeStr.equals("settings")){
Log.v(TAG,"updateFromJSON - processing settings");
mSamplePeriod = (short)dataObject.getInt("analysisPeriod");
mSampleFreq = (short)dataObject.getInt("sampleFreq");
mSdData.batteryPc = (short)dataObject.getInt("battery");
Log.v(TAG,"updateFromJSON - mSamplePeriod="+mSamplePeriod+" mSampleFreq="+mSampleFreq);
mSdData.haveSettings = true;
mSdData.mSampleFreq = mSampleFreq;
mWatchAppRunningCheck = true;
retVal = "OK";
} else {
Log.e(TAG,"updateFromJSON - unrecognised dataType "+dataTypeStr);
retVal = "ERROR";
}
} catch (Exception e) {
Log.e(TAG,"updateFromJSON - Error Parsing JSON String - "+e.toString());
e.printStackTrace();
retVal = "ERROR";
}
return(retVal);
}
}

View File

@@ -89,9 +89,11 @@ public abstract class SdDataSource {
String url = "http://www.openseizuredetector.org.uk/?page_id=1207"; String url = "http://www.openseizuredetector.org.uk/?page_id=1207";
Intent i = new Intent(Intent.ACTION_VIEW); Intent i = new Intent(Intent.ACTION_VIEW);
i.setData(Uri.parse(url)); i.setData(Uri.parse(url));
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mContext.startActivity(i); mContext.startActivity(i);
} catch (Exception ex) { } catch (Exception ex) {
Log.i(TAG, "exception starting install watch app activity " + ex.toString()); Log.i(TAG, "exception starting install watch app activity " + ex.toString());
showToast("Error Displaying Installation Instructions - try http://www.openseizuredetector.org.uk/?page_id=1207 instead");
} }
} }

View File

@@ -98,7 +98,7 @@ public class SdServiceConnection implements ServiceConnection {
* Check if the pebble watch is connected to the server device via bluetooth. * Check if the pebble watch is connected to the server device via bluetooth.
* @return true if watch connected. * @return true if watch connected.
*/ */
public boolean pebbleConnected() { public boolean watchConnected() {
if (mSdServer!=null) { if (mSdServer!=null) {
if (mSdServer.mSdData!=null) { if (mSdServer.mSdData!=null) {
if (mSdServer.mSdData.watchConnected) { if (mSdServer.mSdData.watchConnected) {

View File

@@ -32,15 +32,11 @@ import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.content.pm.PackageInfo; import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.graphics.Color; import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.text.SpannableString; import android.text.SpannableString;
import android.text.method.LinkMovementMethod;
import android.text.util.Linkify; import android.text.util.Linkify;
import android.util.Log; import android.util.Log;
import android.view.View; import android.view.View;
@@ -115,24 +111,6 @@ public class StartupActivity extends Activity {
Button b; Button b;
b = (Button) findViewById(R.id.installPebbleAppButton);
b.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Log.v(TAG, "install Pebble app button clicked");
try {
mUtil.writeToSysLogFile("Installing Pebble App");
Intent intent = new Intent(Intent.ACTION_VIEW)
.setData(Uri.parse("market://details?id=" + mUtil.getPreferredPebbleAppPackageName()));
startActivity(intent);
} catch (Exception ex) {
Log.v(TAG, "exception starting play store activity " + ex.toString());
mUtil.writeToSysLogFile("ERROR Starting play store Activity");
mUtil.showToast("Error Starting Google Play Store to Install App - is Play Store instaled?");
}
}
});
b = (Button) findViewById(R.id.settingsButton); b = (Button) findViewById(R.id.settingsButton);
b.setOnClickListener(new View.OnClickListener() { b.setOnClickListener(new View.OnClickListener() {
@@ -153,15 +131,6 @@ public class StartupActivity extends Activity {
} }
}); });
b = (Button) findViewById(R.id.pebbleButton);
b.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Log.v(TAG, "pebble button clicked");
mUtil.writeToSysLogFile("Starting Pebble Phone App");
mConnection.mSdServer.mSdDataSource.startPebbleApp();
}
});
b = (Button) findViewById(R.id.installOsdAppButton); b = (Button) findViewById(R.id.installOsdAppButton);
b.setOnClickListener(new View.OnClickListener() { b.setOnClickListener(new View.OnClickListener() {
@@ -203,19 +172,6 @@ public class StartupActivity extends Activity {
tv = (TextView) findViewById(R.id.dataSourceTextView); tv = (TextView) findViewById(R.id.dataSourceTextView);
tv.setText("DataSource = " + dataSourceName); tv.setText("DataSource = " + dataSourceName);
// disable pebble configuration buttons if we have not selected the pebble datasource
if (!dataSourceName.equals("Pebble")) {
Log.v(TAG, "Not Pebble Datasource - deactivating Pebble Button");
mUsingPebbleDataSource = false;
Button b = (Button) findViewById(R.id.pebbleButton);
b.setEnabled(false);
b = (Button) findViewById(R.id.installOsdAppButton);
b.setEnabled(false);
} else {
mUsingPebbleDataSource = true;
}
if (mUtil.isServerRunning()) { if (mUtil.isServerRunning()) {
Log.i(TAG, "onStart() - server running - stopping it"); Log.i(TAG, "onStart() - server running - stopping it");
@@ -319,11 +275,11 @@ public class StartupActivity extends Activity {
allOk = false; allOk = false;
} }
// Is Pebble Watch Connected? // Is Watch Connected?
tv = (TextView) findViewById(R.id.textItem3); tv = (TextView) findViewById(R.id.textItem3);
pb = (ProgressBar) findViewById(R.id.progressBar3); pb = (ProgressBar) findViewById(R.id.progressBar3);
if (mConnection.pebbleConnected()) { if (mConnection.watchConnected()) {
tv.setText("Pebble Watch Connected OK"); tv.setText("Watch Connected OK");
tv.setBackgroundColor(okColour); tv.setBackgroundColor(okColour);
tv.setTextColor(okTextColour); tv.setTextColor(okTextColour);
pb.setIndeterminateDrawable(getResources().getDrawable(R.drawable.start_server)); pb.setIndeterminateDrawable(getResources().getDrawable(R.drawable.start_server));
@@ -336,24 +292,6 @@ public class StartupActivity extends Activity {
allOk = false; allOk = false;
} }
/*
// Is Pebble Watch App Running?
tv = (TextView) findViewById(R.id.textItem4);
pb = (ProgressBar) findViewById(R.id.progressBar4);
if (mConnection.watchAppRunning()) {
tv.setText("Watch App Running OK");
tv.setBackgroundColor(okColour);
tv.setTextColor(okTextColour);
//pb.setIndeterminateDrawable(getResources().getDrawable(R.drawable.start_server));
pb.setProgressDrawable(getResources().getDrawable(R.drawable.start_server));
} else {
tv.setText("Watch App Not Running");
tv.setBackgroundColor(alarmColour);
tv.setTextColor(alarmTextColour);
pb.setIndeterminate(true);
allOk = false;
}
*/
// Do we have seizure detector data? // Do we have seizure detector data?
@@ -391,37 +329,6 @@ public class StartupActivity extends Activity {
allOk = false; allOk = false;
} }
// Is Pebble Watch App Installed?
tv = (TextView) findViewById(R.id.textItem7);
pb = (ProgressBar) findViewById(R.id.progressBar7);
boolean pebbleAndroidAppInstalled;
mPebbleAppPackageName = mUtil.isPebbleAppInstalled();
if (mPebbleAppPackageName != null)
pebbleAndroidAppInstalled = true;
else
pebbleAndroidAppInstalled = false;
if (mUsingPebbleDataSource) {
if (pebbleAndroidAppInstalled) {
tv.setText("Pebble Android App Installed");
tv.setBackgroundColor(okColour);
tv.setTextColor(okTextColour);
pb.setIndeterminateDrawable(getResources().getDrawable(R.drawable.start_server));
pb.setProgressDrawable(getResources().getDrawable(R.drawable.start_server));
} else {
tv.setText("Pebble App NOT Installed: ");
tv.setBackgroundColor(alarmColour);
tv.setTextColor(alarmTextColour);
pb.setIndeterminate(true);
allOk = false;
}
} else {
tv.setText("Pebble Android App Not Required");
tv.setBackgroundColor(okColour);
tv.setTextColor(okTextColour);
pb.setIndeterminateDrawable(getResources().getDrawable(R.drawable.start_server));
pb.setProgressDrawable(getResources().getDrawable(R.drawable.start_server));
}
// If all the parameters are ok, close this activity and open the main // If all the parameters are ok, close this activity and open the main

View File

@@ -90,30 +90,6 @@
android:id="@+id/textItem2" /> android:id="@+id/textItem2" />
</LinearLayout> </LinearLayout>
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/progressBar7" />
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:autoLink="web"
android:text="New Text"
android:id="@+id/textItem7" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Install Pebble App"
android:id="@+id/installPebbleAppButton"
/>
</LinearLayout>
<LinearLayout <LinearLayout
android:orientation="horizontal" android:orientation="horizontal"
@@ -131,31 +107,9 @@
android:gravity="center_vertical" android:gravity="center_vertical"
android:text="New Text" android:text="New Text"
android:id="@+id/textItem3" /> android:id="@+id/textItem3" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Configure Pebble"
android:id="@+id/pebbleButton"
android:layout_gravity="right" />
</LinearLayout> </LinearLayout>
<!--
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/progressBar4" />
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:text="New Text"
android:id="@+id/textItem4" />
</LinearLayout>
-->
<LinearLayout <LinearLayout
android:orientation="horizontal" android:orientation="horizontal"
android:layout_width="match_parent" android:layout_width="match_parent"
@@ -194,24 +148,6 @@
android:id="@+id/textItem6" /> android:id="@+id/textItem6" />
</LinearLayout> </LinearLayout>
<!--
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/progressBar8" />
<TextView
android:layout_width="fill_parent"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:autoLink="web"
android:text="New Text"
android:id="@+id/textItem8" />
</LinearLayout>
-->
</LinearLayout> </LinearLayout>

View File

@@ -9,7 +9,7 @@ buildscript {
google() google()
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:3.4.1' classpath 'com.android.tools.build:gradle:3.4.2'
} }
} }
allprojects { allprojects {