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:
BIN
app/release/app-release-3.1.9a.apk
Normal file
BIN
app/release/app-release-3.1.9a.apk
Normal file
Binary file not shown.
@@ -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":{}}]
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -89,9 +89,11 @@ public abstract class SdDataSource {
|
||||
String url = "http://www.openseizuredetector.org.uk/?page_id=1207";
|
||||
Intent i = new Intent(Intent.ACTION_VIEW);
|
||||
i.setData(Uri.parse(url));
|
||||
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
mContext.startActivity(i);
|
||||
} catch (Exception ex) {
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -98,7 +98,7 @@ public class SdServiceConnection implements ServiceConnection {
|
||||
* Check if the pebble watch is connected to the server device via bluetooth.
|
||||
* @return true if watch connected.
|
||||
*/
|
||||
public boolean pebbleConnected() {
|
||||
public boolean watchConnected() {
|
||||
if (mSdServer!=null) {
|
||||
if (mSdServer.mSdData!=null) {
|
||||
if (mSdServer.mSdData.watchConnected) {
|
||||
|
||||
@@ -32,15 +32,11 @@ import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.text.SpannableString;
|
||||
import android.text.method.LinkMovementMethod;
|
||||
import android.text.util.Linkify;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
@@ -115,24 +111,6 @@ public class StartupActivity extends Activity {
|
||||
|
||||
|
||||
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.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.setOnClickListener(new View.OnClickListener() {
|
||||
@@ -203,19 +172,6 @@ public class StartupActivity extends Activity {
|
||||
tv = (TextView) findViewById(R.id.dataSourceTextView);
|
||||
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()) {
|
||||
Log.i(TAG, "onStart() - server running - stopping it");
|
||||
@@ -319,11 +275,11 @@ public class StartupActivity extends Activity {
|
||||
allOk = false;
|
||||
}
|
||||
|
||||
// Is Pebble Watch Connected?
|
||||
// Is Watch Connected?
|
||||
tv = (TextView) findViewById(R.id.textItem3);
|
||||
pb = (ProgressBar) findViewById(R.id.progressBar3);
|
||||
if (mConnection.pebbleConnected()) {
|
||||
tv.setText("Pebble Watch Connected OK");
|
||||
if (mConnection.watchConnected()) {
|
||||
tv.setText("Watch Connected OK");
|
||||
tv.setBackgroundColor(okColour);
|
||||
tv.setTextColor(okTextColour);
|
||||
pb.setIndeterminateDrawable(getResources().getDrawable(R.drawable.start_server));
|
||||
@@ -336,24 +292,6 @@ public class StartupActivity extends Activity {
|
||||
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?
|
||||
@@ -391,37 +329,6 @@ public class StartupActivity extends Activity {
|
||||
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
|
||||
|
||||
@@ -90,30 +90,6 @@
|
||||
android:id="@+id/textItem2" />
|
||||
</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
|
||||
android:orientation="horizontal"
|
||||
@@ -131,31 +107,9 @@
|
||||
android:gravity="center_vertical"
|
||||
android:text="New Text"
|
||||
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
|
||||
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
|
||||
android:orientation="horizontal"
|
||||
android:layout_width="match_parent"
|
||||
@@ -194,24 +148,6 @@
|
||||
android:id="@+id/textItem6" />
|
||||
</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>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user