Merge branch 'Logging' into main - V4.0.6
This commit is contained in:
5
.gitignore
vendored
5
.gitignore
vendored
@@ -3,7 +3,10 @@ build
|
|||||||
.idea
|
.idea
|
||||||
local.properties
|
local.properties
|
||||||
*.iml
|
*.iml
|
||||||
app/app-release.apk
|
app/release/app-release.apk
|
||||||
app/build
|
app/build
|
||||||
app/app.iml
|
app/app.iml
|
||||||
|
app/release/output-metadata.json
|
||||||
|
app/google-services.json
|
||||||
|
*#
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
OpenSeizureDetector Android App - Change Log
|
OpenSeizureDetector Android App - Change Log
|
||||||
============================================
|
============================================
|
||||||
|
V4.0.6 - fixed issue with O2sat data not being recorded to database
|
||||||
|
V4.0.5 - Added support for 3D data logging
|
||||||
|
- Fixed issue with seizure reporting crashing if quotation marks included in text.
|
||||||
|
V4.0.4 - Added support for Data Sharing system
|
||||||
V3.6.2 - Nov 2020
|
V3.6.2 - Nov 2020
|
||||||
- Extended Polish translation further
|
- Extended Polish translation further
|
||||||
- Improved system log output to help with answering queries from users.
|
- Improved system log output to help with answering queries from users.
|
||||||
|
|||||||
@@ -7,3 +7,4 @@ Thank you to the following people who have contributed to this app:
|
|||||||
* Andreas & Marie Ekstrom - Swedish Translation
|
* Andreas & Marie Ekstrom - Swedish Translation
|
||||||
* Cesareo Mario Guajardo Murillo - Spanish Translation
|
* Cesareo Mario Guajardo Murillo - Spanish Translation
|
||||||
* Jolanta Kowalska and Artur Chlebek - Polish Translation
|
* Jolanta Kowalska and Artur Chlebek - Polish Translation
|
||||||
|
* Jozefus Gaarthuis - high resolution star of life icon.
|
||||||
|
|||||||
BIN
QA/QA_checksheet_pre-release_blank.xlsx
Normal file
BIN
QA/QA_checksheet_pre-release_blank.xlsx
Normal file
Binary file not shown.
13
RELEASE_NOTES.md
Normal file
13
RELEASE_NOTES.md
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
OpenSeizureDetector Android App - RELEASE NOTES
|
||||||
|
==============================================
|
||||||
|
|
||||||
|
Version 4.0.0
|
||||||
|
- Logs all seizure detector data to local database
|
||||||
|
- Adds 'Data Sharing' functionality to upload data to remote database and edit events to say if they are false alarms or genuine seizures
|
||||||
|
- Settings screens tidied up (removed some unnecessary options to simplify settings)
|
||||||
|
- Added check of whether the App is being 'Optimised' for battery usage by the Android System
|
||||||
|
- Fixed problem where the web server receiving data will send it to the analysis routines, even if the data source is not set to Garmin.
|
||||||
|
- for example if you set the data source to phone, but ran OSD on a garmin watch, the data would oscillate between phone and watch
|
||||||
|
data
|
||||||
|
-
|
||||||
|
|
||||||
@@ -1,13 +1,13 @@
|
|||||||
apply plugin: 'com.android.application'
|
apply plugin: 'com.android.application'
|
||||||
|
apply plugin: 'com.google.gms.google-services'
|
||||||
android {
|
android {
|
||||||
compileSdkVersion 28
|
compileSdkVersion 31
|
||||||
useLibrary 'org.apache.http.legacy'
|
useLibrary 'org.apache.http.legacy'
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId "uk.org.openseizuredetector"
|
applicationId "uk.org.openseizuredetector"
|
||||||
minSdkVersion 21
|
minSdkVersion 23
|
||||||
targetSdkVersion 29
|
targetSdkVersion 30
|
||||||
multiDexEnabled true
|
multiDexEnabled true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -24,30 +24,41 @@ android {
|
|||||||
includeAndroidResources = true
|
includeAndroidResources = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
compileOptions {
|
||||||
|
sourceCompatibility JavaVersion.VERSION_1_8
|
||||||
|
targetCompatibility JavaVersion.VERSION_1_8
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation 'com.android.support:multidex:1.0.3'
|
implementation 'androidx.multidex:multidex:2.0.1'
|
||||||
implementation files('libs/mpandroidchartlibrary-2-0-7.jar')
|
implementation files('libs/mpandroidchartlibrary-2-0-7.jar')
|
||||||
implementation 'com.getpebble:pebblekit:3.1.0@aar'
|
implementation 'com.getpebble:pebblekit:3.1.0@aar'
|
||||||
// Unit testing dependencies
|
// Unit testing dependencies
|
||||||
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
|
implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
|
||||||
testImplementation 'junit:junit:4.12'
|
implementation 'com.google.android.material:material:1.4.0'
|
||||||
|
implementation 'com.google.firebase:firebase-auth:19.2.0'
|
||||||
|
implementation 'androidx.test:core:1.4.0'
|
||||||
|
testImplementation 'junit:junit:4.13.2'
|
||||||
// Set this dependency if you want to use Mockito
|
// Set this dependency if you want to use Mockito
|
||||||
testImplementation 'org.mockito:mockito-core:1.10.19'
|
testImplementation 'org.mockito:mockito-core:4.3.1'
|
||||||
// Set this dependency if you want to use Hamcrest matching
|
// Set this dependency if you want to use Hamcrest matching
|
||||||
testImplementation 'org.hamcrest:hamcrest-library:1.1'
|
testImplementation 'org.hamcrest:hamcrest-library:2.2'
|
||||||
implementation 'com.android.support:appcompat-v7:28.0.0'
|
implementation 'androidx.appcompat:appcompat:1.4.1'
|
||||||
implementation 'com.android.support:support-v4:28.0.0'
|
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
|
||||||
//compile files('libs/JTransforms-3.1-with-dependencies.jar')
|
|
||||||
implementation 'org.apache.commons:commons-math3:3.6.1'
|
implementation 'org.apache.commons:commons-math3:3.6.1'
|
||||||
// google play services used for location finding for SMS alerts.
|
// google play services used for location finding for SMS alerts.
|
||||||
implementation 'com.google.android.gms:play-services:10.0.1'
|
//implementation 'com.google.android.gms:play-services:+'
|
||||||
implementation 'com.github.wendykierp:JTransforms:3.0'
|
implementation 'com.google.android.gms:play-services-wearable:+'
|
||||||
implementation 'com.google.android.gms:play-services-location:10.0.0'
|
implementation 'com.github.wendykierp:JTransforms:3.1'
|
||||||
|
implementation 'com.google.android.gms:play-services-location:+'
|
||||||
//implementation 'com.github.RohitSurwase.UCE-Handler:uce_handler:1.3'
|
//implementation 'com.github.RohitSurwase.UCE-Handler:uce_handler:1.3'
|
||||||
testImplementation 'org.robolectric:robolectric:4.3'
|
testImplementation 'org.robolectric:robolectric:4.7.3'
|
||||||
|
implementation 'com.android.volley:volley:1.2.1'
|
||||||
|
implementation platform('com.google.firebase:firebase-bom:29.2.0')
|
||||||
|
implementation 'com.google.firebase:firebase-analytics'
|
||||||
|
implementation 'com.firebaseui:firebase-ui-auth:7.2.0'
|
||||||
|
implementation 'com.google.firebase:firebase-firestore'
|
||||||
}
|
}
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
|
|||||||
BIN
app/release/app-release-4.0.6.apk
Normal file
BIN
app/release/app-release-4.0.6.apk
Normal file
Binary file not shown.
@@ -1,18 +0,0 @@
|
|||||||
{
|
|
||||||
"version": 2,
|
|
||||||
"artifactType": {
|
|
||||||
"type": "APK",
|
|
||||||
"kind": "Directory"
|
|
||||||
},
|
|
||||||
"applicationId": "uk.org.openseizuredetector",
|
|
||||||
"variantName": "processReleaseResources",
|
|
||||||
"elements": [
|
|
||||||
{
|
|
||||||
"type": "SINGLE",
|
|
||||||
"filters": [],
|
|
||||||
"versionCode": 87,
|
|
||||||
"versionName": "3.6.2",
|
|
||||||
"outputFile": "app-release.apk"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
[{"outputType":{"type":"APK"},"apkData":{"type":"MAIN","splits":[],"versionCode":72,"versionName":"3.5.0","enabled":true,"outputFile":"app-release.apk","fullName":"release","baseName":"release","dirName":""},"path":"app-release.apk","properties":{}}]
|
|
||||||
@@ -2,21 +2,23 @@
|
|||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
package="uk.org.openseizuredetector"
|
package="uk.org.openseizuredetector"
|
||||||
android:versionCode="87"
|
android:versionCode="102"
|
||||||
android:versionName="3.6.2">
|
android:versionName="4.0.6">
|
||||||
<!-- 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" />
|
||||||
|
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
|
||||||
|
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
|
||||||
<uses-permission android:name="android.permission.INTERNET" />
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
||||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
|
||||||
<uses-permission android:name="android.permission.SEND_SMS" />
|
<uses-permission android:name="android.permission.SEND_SMS" />
|
||||||
<uses-permission android:name="android.permission.GET_TASKS" />
|
<uses-permission android:name="android.permission.GET_TASKS" />
|
||||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||||
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
|
||||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
||||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||||
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
|
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
|
||||||
@@ -24,16 +26,19 @@
|
|||||||
<uses-feature
|
<uses-feature
|
||||||
android:name="android.hardware.telephony"
|
android:name="android.hardware.telephony"
|
||||||
android:required="false" />
|
android:required="false" />
|
||||||
|
<uses-feature
|
||||||
|
android:name="android.hardware.bluetooth_le"
|
||||||
|
android:required="false" />
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:icon="@drawable/star_of_life_48x48"
|
android:icon="@drawable/star_of_life_48x48"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:networkSecurityConfig="@xml/network_security_config"
|
android:networkSecurityConfig="@xml/network_security_config"
|
||||||
android:theme="@style/AppTheme"
|
android:theme="@style/AppTheme">
|
||||||
> <!--@android:style/Theme.Holo.Light"-->
|
<activity android:name=".AuthenticateActivity"/>
|
||||||
<activity android:name=".BLEScanActivity"></activity>
|
<!-- @android:style/Theme.Holo.Light" -->
|
||||||
<activity android:name=".DBQueryActivity"></activity>
|
<activity android:name=".BLEScanActivity" />
|
||||||
<!-- android:usesCleartextTraffic="true" -->
|
<activity android:name=".ExportDataActivity" /> <!-- android:usesCleartextTraffic="true" -->
|
||||||
<activity android:name=".StartupActivity">
|
<activity android:name=".StartupActivity">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN" />
|
<action android:name="android.intent.action.MAIN" />
|
||||||
@@ -57,7 +62,10 @@
|
|||||||
android:name=".SdServer"
|
android:name=".SdServer"
|
||||||
android:exported="false" />
|
android:exported="false" />
|
||||||
|
|
||||||
<activity android:name=".LogManagerActivity" />
|
<activity android:name=".LogManagerControlActivity" />
|
||||||
|
<activity android:name=".EditEventActivity" />
|
||||||
|
<activity android:name=".RemoteDbActivity" />
|
||||||
|
<activity android:name=".ReportSeizureActivity" />
|
||||||
|
|
||||||
<receiver
|
<receiver
|
||||||
android:name=".BootBroadcastReceiver"
|
android:name=".BootBroadcastReceiver"
|
||||||
|
|||||||
@@ -18,8 +18,6 @@
|
|||||||
package com.rohitss.uceh;
|
package com.rohitss.uceh;
|
||||||
|
|
||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
import android.app.Activity;
|
|
||||||
import android.app.AlertDialog;
|
|
||||||
import android.content.ClipData;
|
import android.content.ClipData;
|
||||||
import android.content.ClipboardManager;
|
import android.content.ClipboardManager;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
@@ -28,7 +26,6 @@ import android.content.Intent;
|
|||||||
import android.content.pm.ApplicationInfo;
|
import android.content.pm.ApplicationInfo;
|
||||||
import android.content.pm.PackageInfo;
|
import android.content.pm.PackageInfo;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.net.Uri;
|
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Environment;
|
import android.os.Environment;
|
||||||
@@ -39,6 +36,9 @@ import android.view.View;
|
|||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import androidx.appcompat.app.AlertDialog;
|
||||||
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -54,7 +54,7 @@ import uk.org.openseizuredetector.R;
|
|||||||
* <p>This class is used to </p>
|
* <p>This class is used to </p>
|
||||||
* Created by Rohit.
|
* Created by Rohit.
|
||||||
*/
|
*/
|
||||||
public final class UCEDefaultActivity extends Activity {
|
public final class UCEDefaultActivity extends AppCompatActivity {
|
||||||
private File txtFile;
|
private File txtFile;
|
||||||
private String strCurrentErrorLog;
|
private String strCurrentErrorLog;
|
||||||
private String TAG = "UCEDefaultActivity";
|
private String TAG = "UCEDefaultActivity";
|
||||||
|
|||||||
@@ -25,6 +25,8 @@ import android.content.Intent;
|
|||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.io.StringWriter;
|
import java.io.StringWriter;
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
@@ -228,7 +230,7 @@ public final class UCEHandler {
|
|||||||
return context.getSharedPreferences(SHARED_PREFERENCES_FILE, Context.MODE_PRIVATE).getLong(SHARED_PREFERENCES_FIELD_TIMESTAMP, -1);
|
return context.getSharedPreferences(SHARED_PREFERENCES_FILE, Context.MODE_PRIVATE).getLong(SHARED_PREFERENCES_FIELD_TIMESTAMP, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void closeApplication(Activity activity) {
|
static void closeApplication(AppCompatActivity activity) {
|
||||||
activity.finish();
|
activity.finish();
|
||||||
killCurrentProcess();
|
killCurrentProcess();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,85 +0,0 @@
|
|||||||
package uk.org.openseizuredetector;
|
|
||||||
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import org.json.JSONException;
|
|
||||||
import org.json.JSONObject;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.TimeZone;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by graham on 27/06/16.
|
|
||||||
*/
|
|
||||||
/* From https://github.com/kramimus/pebble-accel-analyzer */
|
|
||||||
public class AccelData {
|
|
||||||
private final String TAG = AccelData.class.getSimpleName();
|
|
||||||
|
|
||||||
final private int x;
|
|
||||||
final private int y;
|
|
||||||
final private int z;
|
|
||||||
|
|
||||||
private long timestamp = 0;
|
|
||||||
final private boolean didVibrate;
|
|
||||||
|
|
||||||
public AccelData(byte[] data) {
|
|
||||||
x = (data[0] & 0xff) | (data[1] << 8);
|
|
||||||
y = (data[2] & 0xff) | (data[3] << 8);
|
|
||||||
z = (data[4] & 0xff) | (data[5] << 8);
|
|
||||||
didVibrate = data[6] != 0;
|
|
||||||
|
|
||||||
for (int i = 0; i < 8; i++) {
|
|
||||||
timestamp |= ((long)(data[i+7] & 0xff)) << (i * 8);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public JSONObject toJson() {
|
|
||||||
JSONObject json = new JSONObject();
|
|
||||||
try {
|
|
||||||
json.put("x", x);
|
|
||||||
json.put("y", y);
|
|
||||||
json.put("z", z);
|
|
||||||
json.put("ts", timestamp);
|
|
||||||
json.put("v", didVibrate);
|
|
||||||
return json;
|
|
||||||
} catch (JSONException e) {
|
|
||||||
Log.w(TAG, "problem constructing accel data, skipping " + e);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<AccelData> fromDataArray(byte[] data) {
|
|
||||||
List<AccelData> accels = new ArrayList<AccelData>();
|
|
||||||
for (int i = 0; i < data.length; i += 15) {
|
|
||||||
accels.add(new AccelData(Arrays.copyOfRange(data, i, i + 15)));
|
|
||||||
}
|
|
||||||
return accels;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getTimestamp() {
|
|
||||||
return timestamp;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getX() {
|
|
||||||
return x;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getY() {
|
|
||||||
return y;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getZ() {
|
|
||||||
return z;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getMagnitude() {
|
|
||||||
return (int)Math.sqrt(x*x + y*y + z*z);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void applyTimezone(TimeZone tz) {
|
|
||||||
timestamp -= tz.getOffset(timestamp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,78 +0,0 @@
|
|||||||
package uk.org.openseizuredetector;
|
|
||||||
|
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.support.v4.app.DialogFragment;
|
|
||||||
import android.util.Log;
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.widget.Button;
|
|
||||||
import android.widget.EditText;
|
|
||||||
|
|
||||||
public class AuthDialog extends DialogFragment {
|
|
||||||
private String TAG = "AuthDialog";
|
|
||||||
private AuthDialogInterface mListener;
|
|
||||||
private Context mContext;
|
|
||||||
private EditText mUnameEt;
|
|
||||||
private EditText mPasswdEt;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public View onCreateView(
|
|
||||||
LayoutInflater inflater,
|
|
||||||
ViewGroup container,
|
|
||||||
Bundle savedInstanceState) {
|
|
||||||
Log.v(TAG, "onCreateView()");
|
|
||||||
View v = inflater.inflate(R.layout.dialog_authenticate,
|
|
||||||
container, false);
|
|
||||||
Button cancelBtn =
|
|
||||||
(Button) v.findViewById(R.id.cancelBtn);
|
|
||||||
cancelBtn.setOnClickListener(onCancel);
|
|
||||||
Button OKBtn = (Button) v.findViewById(R.id.OKBtn);
|
|
||||||
OKBtn.setOnClickListener(onOK);
|
|
||||||
|
|
||||||
mUnameEt = (EditText) v.findViewById(R.id.username);
|
|
||||||
mPasswdEt = (EditText) v.findViewById(R.id.password);
|
|
||||||
|
|
||||||
return v;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
View.OnClickListener onCancel =
|
|
||||||
new View.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View view) {
|
|
||||||
Log.v(TAG, "onCancel");
|
|
||||||
//m_status=false;
|
|
||||||
mListener.onDialogDone(false);
|
|
||||||
dismiss();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
View.OnClickListener onOK =
|
|
||||||
new View.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View view) {
|
|
||||||
//m_status=true;
|
|
||||||
Log.v(TAG, "onOK()");
|
|
||||||
String uname = mUnameEt.getText().toString();
|
|
||||||
String passwd = mPasswdEt.getText().toString();
|
|
||||||
Log.v(TAG,"onOK() - uname="+uname+", passwd="+passwd);
|
|
||||||
mListener.onDialogDone(true);
|
|
||||||
dismiss();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onAttach(Context context) {
|
|
||||||
super.onAttach(context);
|
|
||||||
try {
|
|
||||||
mListener = (AuthDialogInterface) context;
|
|
||||||
} catch (ClassCastException e) {
|
|
||||||
throw new ClassCastException(context.toString()
|
|
||||||
+ " must implement dialogDoneistener");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
package uk.org.openseizuredetector;
|
|
||||||
|
|
||||||
public interface AuthDialogInterface {
|
|
||||||
void onDialogDone(boolean state);
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,343 @@
|
|||||||
|
package uk.org.openseizuredetector;
|
||||||
|
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.preference.PreferenceManager;
|
||||||
|
|
||||||
|
import androidx.activity.result.ActivityResultLauncher;
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.Button;
|
||||||
|
import android.widget.EditText;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import com.firebase.ui.auth.AuthUI;
|
||||||
|
import com.firebase.ui.auth.FirebaseAuthUIActivityResultContract;
|
||||||
|
import com.google.android.gms.tasks.OnCompleteListener;
|
||||||
|
import com.google.android.gms.tasks.Task;
|
||||||
|
import com.google.firebase.auth.FirebaseAuth;
|
||||||
|
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
public class AuthenticateActivity extends AppCompatActivity {
|
||||||
|
private String TAG = "AuthenticateActivity";
|
||||||
|
private OsdUtil mUtil;
|
||||||
|
private EditText mUnameEt;
|
||||||
|
private EditText mPasswdEt;
|
||||||
|
private SdServiceConnection mConnection;
|
||||||
|
final Handler serverStatusHandler = new Handler();
|
||||||
|
private WebApiConnection mWac;
|
||||||
|
private LogManager mLm;
|
||||||
|
private static final String TOKEN_ID = "webApiAuthToken";
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
Log.d(TAG, "onCreate()");
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
setContentView(R.layout.activity_authenticate);
|
||||||
|
|
||||||
|
mUtil = new OsdUtil(getApplicationContext(), serverStatusHandler);
|
||||||
|
if (!mUtil.isServerRunning()) {
|
||||||
|
mUtil.showToast(getString(R.string.error_server_not_running));
|
||||||
|
finish();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Button cancelBtn =
|
||||||
|
(Button) findViewById(R.id.cancelBtn);
|
||||||
|
cancelBtn.setOnClickListener(onCancel);
|
||||||
|
Button loginBtn = (Button) findViewById(R.id.loginBtn);
|
||||||
|
loginBtn.setOnClickListener(onLogin);
|
||||||
|
Button logoutCancelBtn =
|
||||||
|
(Button) findViewById(R.id.logoutCancelBtn);
|
||||||
|
logoutCancelBtn.setOnClickListener(onCancel);
|
||||||
|
Button logoutBtn = (Button) findViewById(R.id.logoutBtn);
|
||||||
|
logoutBtn.setOnClickListener(onLogout);
|
||||||
|
|
||||||
|
// Components required only for osdapi backend
|
||||||
|
if (LogManager.USE_FIREBASE_BACKEND) { }
|
||||||
|
else {
|
||||||
|
mConnection = new SdServiceConnection(getApplicationContext());
|
||||||
|
|
||||||
|
Button registerBtn = (Button) findViewById(R.id.RegisterBtn);
|
||||||
|
registerBtn.setOnClickListener(onRegister);
|
||||||
|
Button resetPasswordBtn = (Button) findViewById(R.id.ResetPasswordBtn);
|
||||||
|
resetPasswordBtn.setOnClickListener(onResetPassword);
|
||||||
|
|
||||||
|
mUnameEt = (EditText) findViewById(R.id.username);
|
||||||
|
mPasswdEt = (EditText) findViewById(R.id.password);
|
||||||
|
}
|
||||||
|
|
||||||
|
Button aboutDataSharingBtn = (Button) findViewById(R.id.aboutDataSharingBtn);
|
||||||
|
aboutDataSharingBtn.setOnClickListener(
|
||||||
|
new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View view) {
|
||||||
|
Log.v(TAG,"aboutDataSharingBtn.onClick()");
|
||||||
|
String url = OsdUtil.DATA_SHARING_URL;
|
||||||
|
Intent i = new Intent(Intent.ACTION_VIEW);
|
||||||
|
i.setData(Uri.parse(url));
|
||||||
|
startActivity(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
Button privacyPolicyBtn = (Button) findViewById(R.id.privacyPolicyBtn);
|
||||||
|
privacyPolicyBtn.setOnClickListener(
|
||||||
|
new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View view) {
|
||||||
|
Log.v(TAG,"privacyPolicyBtn.onClick()");
|
||||||
|
String url = OsdUtil.PRIVACY_POLICY_URL;
|
||||||
|
Intent i = new Intent(Intent.ACTION_VIEW);
|
||||||
|
i.setData(Uri.parse(url));
|
||||||
|
startActivity(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onStart() {
|
||||||
|
Log.d(TAG, "onStart()");
|
||||||
|
super.onStart();
|
||||||
|
if (LogManager.USE_FIREBASE_BACKEND) {
|
||||||
|
updateUi();
|
||||||
|
} else {
|
||||||
|
mUtil.bindToServer(getApplicationContext(), mConnection);
|
||||||
|
waitForConnection();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onStop() {
|
||||||
|
Log.d(TAG, "onStop()");
|
||||||
|
super.onStop();
|
||||||
|
if (LogManager.USE_FIREBASE_BACKEND) {
|
||||||
|
|
||||||
|
} else {
|
||||||
|
mUtil.unbindFromServer(getApplicationContext(), mConnection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initialiseServiceConnection() {
|
||||||
|
Log.v(TAG,"initialiseServiceConnection()");
|
||||||
|
mLm = mConnection.mSdServer.mLm;
|
||||||
|
mWac = mConnection.mSdServer.mLm.mWac;
|
||||||
|
updateUi();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Called after the Firebase Auth UI has completed
|
||||||
|
private ActivityResultLauncher<Intent> signInLauncher = registerForActivityResult(
|
||||||
|
new FirebaseAuthUIActivityResultContract(),
|
||||||
|
(result) -> {
|
||||||
|
Log.i(TAG, "FirebaseAuthUIActivityResult - " + result.toString());
|
||||||
|
updateUi();
|
||||||
|
});
|
||||||
|
|
||||||
|
// ...
|
||||||
|
|
||||||
|
|
||||||
|
private void updateUi() {
|
||||||
|
Log.v(TAG,"updateUi()");
|
||||||
|
LinearLayout loginLl = (LinearLayout) findViewById(R.id.login_ui);
|
||||||
|
LinearLayout osdApiLoginLl = (LinearLayout) findViewById(R.id.login_osdapi_ui);
|
||||||
|
LinearLayout logoutLl = (LinearLayout) findViewById(R.id.logout_ui);
|
||||||
|
|
||||||
|
if (mWac == null) {
|
||||||
|
Log.i(TAG,"mWac is null - not updating UI");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mWac.isLoggedIn()) {
|
||||||
|
Log.v(TAG, "Already Logged in - showing Log Out prompt");
|
||||||
|
loginLl.setVisibility(View.GONE);
|
||||||
|
logoutLl.setVisibility(View.VISIBLE);
|
||||||
|
if (!LogManager.USE_FIREBASE_BACKEND) {
|
||||||
|
osdApiLoginLl.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
mWac.getUserProfile((JSONObject profileObj) -> {
|
||||||
|
try {
|
||||||
|
String userId = profileObj.getString("id");
|
||||||
|
String userName = profileObj.getString("username");
|
||||||
|
TextView tv2 = (TextView) findViewById(R.id.userIdTv);
|
||||||
|
tv2.setText(userId);
|
||||||
|
tv2 = (TextView) findViewById(R.id.usernameTv);
|
||||||
|
tv2.setText(userName);
|
||||||
|
} catch (JSONException e) {
|
||||||
|
Log.e(TAG, "Error Parsing profileObj: " + e.getMessage());
|
||||||
|
mUtil.showToast("Error Parsing profileObj - this should not happen!!!");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
Log.v(TAG,"updateUi() - not logged in..");
|
||||||
|
loginLl.setVisibility(View.VISIBLE);
|
||||||
|
logoutLl.setVisibility(View.GONE);
|
||||||
|
if (!LogManager.USE_FIREBASE_BACKEND) {
|
||||||
|
osdApiLoginLl.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
View.OnClickListener onCancel =
|
||||||
|
new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View view) {
|
||||||
|
Log.v(TAG, "onCancel");
|
||||||
|
//m_status=false;
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
View.OnClickListener onLogin =
|
||||||
|
new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View view) {
|
||||||
|
//m_status=true;
|
||||||
|
if (LogManager.USE_FIREBASE_BACKEND) {
|
||||||
|
Log.v(TAG, "onLogin() - using Firebase Login");
|
||||||
|
Intent signInIntent = AuthUI.getInstance()
|
||||||
|
.createSignInIntentBuilder()
|
||||||
|
.setAvailableProviders(Arrays.asList(
|
||||||
|
new AuthUI.IdpConfig.GoogleBuilder().build(),
|
||||||
|
//new AuthUI.IdpConfig.FacebookBuilder().build(),
|
||||||
|
//new AuthUI.IdpConfig.TwitterBuilder().build(),
|
||||||
|
//new AuthUI.IdpConfig.MicrosoftBuilder().build(),
|
||||||
|
//new AuthUI.IdpConfig.YahooBuilder().build(),
|
||||||
|
//new AuthUI.IdpConfig.AppleBuilder().build(),
|
||||||
|
new AuthUI.IdpConfig.EmailBuilder().build()
|
||||||
|
//new AuthUI.IdpConfig.PhoneBuilder().build()
|
||||||
|
//new AuthUI.IdpConfig.AnonymousBuilder().build()))
|
||||||
|
))
|
||||||
|
// ... options ...
|
||||||
|
.build();
|
||||||
|
signInLauncher.launch(signInIntent);
|
||||||
|
} else {
|
||||||
|
// Use Username and password authentication for OSDAPI.
|
||||||
|
// FIXME - make this work with Google Authentication like we do for Firebase.
|
||||||
|
String uname = mUnameEt.getText().toString();
|
||||||
|
String passwd = mPasswdEt.getText().toString();
|
||||||
|
Log.v(TAG,"onOK() - uname="+uname+", passwd="+passwd);
|
||||||
|
mWac.authenticate(uname, passwd, new WebApiConnection.StringCallback() {
|
||||||
|
@Override
|
||||||
|
public void accept(String retVal) {
|
||||||
|
if (retVal != null) {
|
||||||
|
Log.d(TAG,"Authentication Success - token is "+retVal);
|
||||||
|
mUtil.showToast("Login Successful");
|
||||||
|
saveAuthToken(retVal);
|
||||||
|
updateUi();
|
||||||
|
} else {
|
||||||
|
Log.e(TAG,"onOk: Authentication failure for "+uname+", "+passwd);
|
||||||
|
mUtil.showToast("ERROR: Authentication Failed - Please Try Again");
|
||||||
|
mUtil.writeToSysLogFile("AuthActivity - Authorisation failed for "+uname+", "+passwd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
View.OnClickListener onLogout = new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View view) {
|
||||||
|
Log.v(TAG, "onLogout");
|
||||||
|
if (LogManager.USE_FIREBASE_BACKEND) {
|
||||||
|
AuthUI.getInstance()
|
||||||
|
.signOut(getApplicationContext())
|
||||||
|
.addOnCompleteListener(new OnCompleteListener<Void>() {
|
||||||
|
public void onComplete(@NonNull Task<Void> task) {
|
||||||
|
// user is now signed out
|
||||||
|
updateUi();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
if (mWac != null) {
|
||||||
|
mWac.logout();
|
||||||
|
saveAuthToken(null);
|
||||||
|
} else {
|
||||||
|
Log.e(TAG,"logout() - mWac is null - not doing anything");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
updateUi();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
View.OnClickListener onRegister =
|
||||||
|
new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View view) {
|
||||||
|
Log.d(TAG, "onRegisterBtn");
|
||||||
|
//Intent i;
|
||||||
|
//i = new Intent(getApplicationContext(), RemoteDbActivity.class);
|
||||||
|
//i.putExtra("url", "https://osdapi.ddns.net/static/register.html");
|
||||||
|
//startActivity(i);
|
||||||
|
String url = "https://osdapi.ddns.net/static/register.html";
|
||||||
|
Intent i = new Intent(Intent.ACTION_VIEW);
|
||||||
|
i.setData(Uri.parse(url));
|
||||||
|
startActivity(i);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
View.OnClickListener onResetPassword =
|
||||||
|
new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View view) {
|
||||||
|
Log.d(TAG, "onResetPasswordBtn");
|
||||||
|
//Intent i;
|
||||||
|
//i = new Intent(getApplicationContext(), RemoteDbActivity.class);
|
||||||
|
//i.putExtra("url", "https://osdapi.ddns.net/static/register.html");
|
||||||
|
//startActivity(i);
|
||||||
|
String url = "https://osdapi.ddns.net/static/request_password_reset.html";
|
||||||
|
Intent i = new Intent(Intent.ACTION_VIEW);
|
||||||
|
i.setData(Uri.parse(url));
|
||||||
|
startActivity(i);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
private void saveAuthToken(String tokenStr) {
|
||||||
|
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
|
||||||
|
prefs.edit().putString(TOKEN_ID, tokenStr).commit();
|
||||||
|
mWac.setStoredToken(tokenStr);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAuthToken() {
|
||||||
|
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
|
||||||
|
String authToken = prefs.getString(TOKEN_ID, null);
|
||||||
|
return authToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -17,12 +17,17 @@ package uk.org.openseizuredetector;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
import static androidx.core.content.PermissionChecker.PERMISSION_GRANTED;
|
||||||
|
|
||||||
import android.Manifest;
|
import android.Manifest;
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.app.ListActivity;
|
import android.app.ListActivity;
|
||||||
import android.bluetooth.BluetoothAdapter;
|
import android.bluetooth.BluetoothAdapter;
|
||||||
import android.bluetooth.BluetoothDevice;
|
import android.bluetooth.BluetoothDevice;
|
||||||
import android.bluetooth.BluetoothManager;
|
import android.bluetooth.BluetoothManager;
|
||||||
|
import android.bluetooth.le.BluetoothLeScanner;
|
||||||
|
import android.bluetooth.le.ScanCallback;
|
||||||
|
import android.bluetooth.le.ScanResult;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
@@ -30,19 +35,23 @@ import android.content.pm.PackageManager;
|
|||||||
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.support.v4.app.ActivityCompat;
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.AdapterView;
|
|
||||||
import android.widget.BaseAdapter;
|
import android.widget.BaseAdapter;
|
||||||
|
import android.widget.Button;
|
||||||
import android.widget.ListView;
|
import android.widget.ListView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
import androidx.core.app.ActivityCompat;
|
||||||
|
import androidx.core.content.ContextCompat;
|
||||||
|
import androidx.core.view.MenuItemCompat;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -51,16 +60,20 @@ import java.util.ArrayList;
|
|||||||
public class BLEScanActivity extends ListActivity {
|
public class BLEScanActivity extends ListActivity {
|
||||||
private LeDeviceListAdapter mLeDeviceListAdapter;
|
private LeDeviceListAdapter mLeDeviceListAdapter;
|
||||||
private BluetoothAdapter mBluetoothAdapter;
|
private BluetoothAdapter mBluetoothAdapter;
|
||||||
|
private BluetoothLeScanner mBluetoothLeScanner;
|
||||||
private boolean mScanning;
|
private boolean mScanning;
|
||||||
private Handler mHandler;
|
private Handler mHandler;
|
||||||
|
private boolean bleAvailable = false;
|
||||||
|
|
||||||
private boolean mPermissionsRequested = false;
|
private boolean mPermissionsRequested = false;
|
||||||
private final String TAG = "BLEScanActivity";
|
private final String TAG = "BLEScanActivity";
|
||||||
|
|
||||||
private final String[] REQUIRED_PERMISSIONS = {
|
private final String[] REQUIRED_PERMISSIONS = {
|
||||||
|
Manifest.permission.ACCESS_FINE_LOCATION,
|
||||||
Manifest.permission.ACCESS_COARSE_LOCATION,
|
Manifest.permission.ACCESS_COARSE_LOCATION,
|
||||||
Manifest.permission.BLUETOOTH,
|
Manifest.permission.BLUETOOTH,
|
||||||
Manifest.permission.BLUETOOTH_ADMIN,
|
Manifest.permission.BLUETOOTH_ADMIN,
|
||||||
|
//Manifest.permission.BLUETOOTH_PRIVILEGED,
|
||||||
};
|
};
|
||||||
|
|
||||||
private static final int REQUEST_ENABLE_BT = 1;
|
private static final int REQUEST_ENABLE_BT = 1;
|
||||||
@@ -70,6 +83,7 @@ public class BLEScanActivity extends ListActivity {
|
|||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
setContentView(R.layout.ble_scan_activity);
|
||||||
//this.getActionBar().setTitle(R.string.title_devices);
|
//this.getActionBar().setTitle(R.string.title_devices);
|
||||||
this.setTitle(R.string.title_devices);
|
this.setTitle(R.string.title_devices);
|
||||||
mHandler = new Handler();
|
mHandler = new Handler();
|
||||||
@@ -79,6 +93,8 @@ public class BLEScanActivity extends ListActivity {
|
|||||||
if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
|
if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
|
||||||
Toast.makeText(this, R.string.ble_not_supported, Toast.LENGTH_SHORT).show();
|
Toast.makeText(this, R.string.ble_not_supported, Toast.LENGTH_SHORT).show();
|
||||||
finish();
|
finish();
|
||||||
|
} else {
|
||||||
|
bleAvailable = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initializes a Bluetooth adapter. For API level 18 and above, get a reference to
|
// Initializes a Bluetooth adapter. For API level 18 and above, get a reference to
|
||||||
@@ -93,6 +109,8 @@ public class BLEScanActivity extends ListActivity {
|
|||||||
finish();
|
finish();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mBluetoothLeScanner = mBluetoothAdapter.getBluetoothLeScanner();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -101,7 +119,7 @@ public class BLEScanActivity extends ListActivity {
|
|||||||
if (!mScanning) {
|
if (!mScanning) {
|
||||||
menu.findItem(R.id.menu_stop).setVisible(false);
|
menu.findItem(R.id.menu_stop).setVisible(false);
|
||||||
menu.findItem(R.id.menu_scan).setVisible(true);
|
menu.findItem(R.id.menu_scan).setVisible(true);
|
||||||
menu.findItem(R.id.menu_refresh).setActionView(null);
|
MenuItemCompat.setActionView(menu.findItem(R.id.menu_refresh), null);
|
||||||
} else {
|
} else {
|
||||||
menu.findItem(R.id.menu_stop).setVisible(true);
|
menu.findItem(R.id.menu_stop).setVisible(true);
|
||||||
menu.findItem(R.id.menu_scan).setVisible(false);
|
menu.findItem(R.id.menu_scan).setVisible(false);
|
||||||
@@ -125,17 +143,79 @@ public class BLEScanActivity extends ListActivity {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void onScanButtonClick(View v) {
|
||||||
|
scanLeDevice(true);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onResume() {
|
protected void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
|
SharedPreferences SP = PreferenceManager
|
||||||
|
.getDefaultSharedPreferences(this);
|
||||||
|
TextView tv = (TextView) findViewById(R.id.current_ble_device_tv);
|
||||||
|
try {
|
||||||
|
String bleAddr = SP.getString("BLE_Device_Addr", "none");
|
||||||
|
String bleName = SP.getString("BLE_Device_Name", "none");
|
||||||
|
tv.setText("Current Device=" + bleName + " (" + bleAddr + ")");
|
||||||
|
} catch (Exception e) {
|
||||||
|
tv.setText("Current Device=" + "none" + " (" + "none" + ")");
|
||||||
|
}
|
||||||
|
|
||||||
|
tv = (TextView) findViewById(R.id.ble_present_tv);
|
||||||
|
if (mBluetoothAdapter == null) {
|
||||||
|
tv.setText("ERROR - Bluetooth Adapter Not Present");
|
||||||
|
} else {
|
||||||
|
tv.setText("Bluetooth Adapter Present - OK");
|
||||||
|
}
|
||||||
// Ensures Bluetooth is enabled on the device. If Bluetooth is not currently enabled,
|
// Ensures Bluetooth is enabled on the device. If Bluetooth is not currently enabled,
|
||||||
// fire an intent to display a dialog asking the user to grant permission to enable it.
|
// fire an intent to display a dialog asking the user to grant permission to enable it.
|
||||||
|
tv = (TextView) findViewById(R.id.ble_adapter_tv);
|
||||||
if (!mBluetoothAdapter.isEnabled()) {
|
if (!mBluetoothAdapter.isEnabled()) {
|
||||||
|
tv.setText("ERROR - Bluetoot NOT Enabled");
|
||||||
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
|
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
|
||||||
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
|
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
|
||||||
|
} else {
|
||||||
|
tv.setText("Bluetooth Adapter Enabled OK");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
requestBTPermissions(this);
|
||||||
|
|
||||||
|
for (int i = 0; i < REQUIRED_PERMISSIONS.length; i++) {
|
||||||
|
if (ContextCompat.checkSelfPermission(this, REQUIRED_PERMISSIONS[i]) == PERMISSION_GRANTED) {
|
||||||
|
Log.i(TAG, "Permission " + REQUIRED_PERMISSIONS[i] + " OK");
|
||||||
|
} else {
|
||||||
|
Log.e(TAG, "Permission " + REQUIRED_PERMISSIONS[i] + " NOT GRANTED");
|
||||||
|
Toast.makeText(this, "ERROR - Permission " + REQUIRED_PERMISSIONS[i] + " not Granted - this will not work!!!!!", Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tv = (TextView) findViewById(R.id.ble_perm1_tv);
|
||||||
|
if (ContextCompat.checkSelfPermission(this, REQUIRED_PERMISSIONS[0]) == PERMISSION_GRANTED) {
|
||||||
|
tv.setText("Permission " + REQUIRED_PERMISSIONS[0] + " OK");
|
||||||
|
} else {
|
||||||
|
tv.setText("ERROR: Permission " + REQUIRED_PERMISSIONS[0] + " NOT GRANTED");
|
||||||
|
}
|
||||||
|
tv = (TextView) findViewById(R.id.ble_perm2_tv);
|
||||||
|
if (ContextCompat.checkSelfPermission(this, REQUIRED_PERMISSIONS[1]) == PERMISSION_GRANTED) {
|
||||||
|
tv.setText("Permission " + REQUIRED_PERMISSIONS[1] + " OK");
|
||||||
|
} else {
|
||||||
|
tv.setText("ERROR: Permission " + REQUIRED_PERMISSIONS[1] + " NOT GRANTED");
|
||||||
|
}
|
||||||
|
tv = (TextView) findViewById(R.id.ble_perm3_tv);
|
||||||
|
if (ContextCompat.checkSelfPermission(this, REQUIRED_PERMISSIONS[2]) == PERMISSION_GRANTED) {
|
||||||
|
tv.setText("Permission " + REQUIRED_PERMISSIONS[2] + " OK");
|
||||||
|
} else {
|
||||||
|
tv.setText("ERROR: Permission " + REQUIRED_PERMISSIONS[2] + " NOT GRANTED");
|
||||||
|
}
|
||||||
|
tv = (TextView) findViewById(R.id.ble_perm4_tv);
|
||||||
|
if (ContextCompat.checkSelfPermission(this, REQUIRED_PERMISSIONS[3]) == PERMISSION_GRANTED) {
|
||||||
|
tv.setText("Permission " + REQUIRED_PERMISSIONS[3] + " OK");
|
||||||
|
} else {
|
||||||
|
tv.setText("ERROR: Permission " + REQUIRED_PERMISSIONS[3] + " NOT GRANTED");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Initializes list view adapter.
|
// Initializes list view adapter.
|
||||||
mLeDeviceListAdapter = new LeDeviceListAdapter();
|
mLeDeviceListAdapter = new LeDeviceListAdapter();
|
||||||
setListAdapter(mLeDeviceListAdapter);
|
setListAdapter(mLeDeviceListAdapter);
|
||||||
@@ -166,10 +246,10 @@ public class BLEScanActivity extends ListActivity {
|
|||||||
if (device == null) return;
|
if (device == null) return;
|
||||||
Log.v(TAG, "onListItemClick: Device=" + device.getName() + ", Addr=" + device.getAddress());
|
Log.v(TAG, "onListItemClick: Device=" + device.getName() + ", Addr=" + device.getAddress());
|
||||||
if (mScanning) {
|
if (mScanning) {
|
||||||
mBluetoothAdapter.stopLeScan(mLeScanCallback);
|
mBluetoothLeScanner.stopScan(mLeScanCallback);
|
||||||
mScanning = false;
|
mScanning = false;
|
||||||
}
|
}
|
||||||
Log.v(TAG,"Saving Device Details");
|
Log.v(TAG, "Saving Device Details");
|
||||||
SharedPreferences.Editor SPE = PreferenceManager
|
SharedPreferences.Editor SPE = PreferenceManager
|
||||||
.getDefaultSharedPreferences(this).edit();
|
.getDefaultSharedPreferences(this).edit();
|
||||||
try {
|
try {
|
||||||
@@ -178,36 +258,70 @@ public class BLEScanActivity extends ListActivity {
|
|||||||
SPE.apply();
|
SPE.apply();
|
||||||
SPE.commit();
|
SPE.commit();
|
||||||
|
|
||||||
Log.v(TAG, "Saved Device Name="+device.getName()+" and Address="+device.getAddress());
|
Log.v(TAG, "Saved Device Name=" + device.getName() + " and Address=" + device.getAddress());
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
Log.e(TAG, "Error Saving Devie Name and Address!");
|
Log.e(TAG, "Error Saving Device Name and Address!");
|
||||||
Toast toast = Toast.makeText(this, "Problem Saving Device Name and Address", Toast.LENGTH_SHORT);
|
Toast toast = Toast.makeText(this, "Problem Saving Device Name and Address", Toast.LENGTH_SHORT);
|
||||||
toast.show();
|
toast.show();
|
||||||
}
|
}
|
||||||
SharedPreferences SP = PreferenceManager.getDefaultSharedPreferences((this));
|
SharedPreferences SP = PreferenceManager.getDefaultSharedPreferences((this));
|
||||||
Log.v(TAG,"Check of saved values - Name="+SP.getString("BLE_Device_Name","NOT SET")+", Addr="+SP.getString("BLE_Device_Addr","NOT SET"));
|
Log.v(TAG, "Check of saved values - Name=" + SP.getString("BLE_Device_Name", "NOT SET") + ", Addr=" + SP.getString("BLE_Device_Addr", "NOT SET"));
|
||||||
|
|
||||||
finish();
|
finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void requestBTPermissions(Activity activity) {
|
||||||
|
if (mPermissionsRequested) {
|
||||||
|
Log.i(TAG, "requestPermissions() - request already sent - not doing anything");
|
||||||
|
} else {
|
||||||
|
Log.i(TAG, "requestPermissions() - requesting permissions");
|
||||||
|
for (int i = 0; i < REQUIRED_PERMISSIONS.length; i++) {
|
||||||
|
if (ActivityCompat.shouldShowRequestPermissionRationale(activity,
|
||||||
|
REQUIRED_PERMISSIONS[i])) {
|
||||||
|
Log.i(TAG, "shouldShowRationale for permission" + REQUIRED_PERMISSIONS[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ActivityCompat.requestPermissions(activity,
|
||||||
|
REQUIRED_PERMISSIONS,
|
||||||
|
42);
|
||||||
|
mPermissionsRequested = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private void scanLeDevice(final boolean enable) {
|
private void scanLeDevice(final boolean enable) {
|
||||||
requestPermissions(this);
|
TextView tv;
|
||||||
|
|
||||||
if (enable) {
|
if (enable) {
|
||||||
// Stops scanning after a pre-defined scan period.
|
// Stops scanning after a pre-defined scan period.
|
||||||
mHandler.postDelayed(new Runnable() {
|
mHandler.postDelayed(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
mScanning = false;
|
mScanning = false;
|
||||||
mBluetoothAdapter.stopLeScan(mLeScanCallback);
|
mBluetoothLeScanner.stopScan(mLeScanCallback);
|
||||||
invalidateOptionsMenu();
|
invalidateOptionsMenu();
|
||||||
|
TextView tv = (TextView) (findViewById(R.id.ble_scan_status_tv));
|
||||||
|
tv.setText("Stopped");
|
||||||
|
Button b = (Button) findViewById(R.id.startScanButton);
|
||||||
|
b.setEnabled(true);
|
||||||
|
|
||||||
}
|
}
|
||||||
}, SCAN_PERIOD);
|
}, SCAN_PERIOD);
|
||||||
|
|
||||||
mScanning = true;
|
mScanning = true;
|
||||||
mBluetoothAdapter.startLeScan(mLeScanCallback);
|
mBluetoothLeScanner.startScan(mLeScanCallback);
|
||||||
|
tv = (TextView) (findViewById(R.id.ble_scan_status_tv));
|
||||||
|
tv.setText("Scanning");
|
||||||
|
Button b = (Button) findViewById(R.id.startScanButton);
|
||||||
|
b.setEnabled(false);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
mScanning = false;
|
mScanning = false;
|
||||||
mBluetoothAdapter.stopLeScan(mLeScanCallback);
|
mBluetoothLeScanner.stopScan(mLeScanCallback);
|
||||||
|
tv = (TextView) (findViewById(R.id.ble_scan_status_tv));
|
||||||
|
tv.setText("Stopped");
|
||||||
|
Button b = (Button) findViewById(R.id.startScanButton);
|
||||||
|
b.setEnabled(true);
|
||||||
}
|
}
|
||||||
invalidateOptionsMenu();
|
invalidateOptionsMenu();
|
||||||
}
|
}
|
||||||
@@ -225,7 +339,7 @@ public class BLEScanActivity extends ListActivity {
|
|||||||
|
|
||||||
public void addDevice(BluetoothDevice device) {
|
public void addDevice(BluetoothDevice device) {
|
||||||
if (!mLeDevices.contains(device)) {
|
if (!mLeDevices.contains(device)) {
|
||||||
Log.v(TAG,"addDevice - "+device.getName());
|
Log.v(TAG, "addDevice - " + device.getName());
|
||||||
mLeDevices.add(device);
|
mLeDevices.add(device);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -256,7 +370,7 @@ public class BLEScanActivity extends ListActivity {
|
|||||||
@Override
|
@Override
|
||||||
public View getView(int i, View view, ViewGroup viewGroup) {
|
public View getView(int i, View view, ViewGroup viewGroup) {
|
||||||
ViewHolder viewHolder;
|
ViewHolder viewHolder;
|
||||||
Log.v(TAG,"scanner getView i="+i);
|
Log.v(TAG, "scanner getView i=" + i);
|
||||||
// General ListView optimization code.
|
// General ListView optimization code.
|
||||||
if (view == null) {
|
if (view == null) {
|
||||||
view = mInflator.inflate(R.layout.ble_list_item_device, null);
|
view = mInflator.inflate(R.layout.ble_list_item_device, null);
|
||||||
@@ -281,19 +395,14 @@ public class BLEScanActivity extends ListActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Device scan callback.
|
// Device scan callback.
|
||||||
private BluetoothAdapter.LeScanCallback mLeScanCallback =
|
private ScanCallback mLeScanCallback =
|
||||||
new BluetoothAdapter.LeScanCallback() {
|
new ScanCallback() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) {
|
public void onScanResult(int callbackType, ScanResult result) {
|
||||||
Log.v(TAG,"LEScanCallback - device="+device.getName());
|
//super.onScanResult(callbackType, result);
|
||||||
runOnUiThread(new Runnable() {
|
Log.v(TAG, "ScanCallback - " + result.getDevice().getName());
|
||||||
@Override
|
mLeDeviceListAdapter.addDevice(result.getDevice());
|
||||||
public void run() {
|
mLeDeviceListAdapter.notifyDataSetChanged();
|
||||||
mLeDeviceListAdapter.addDevice(device);
|
|
||||||
mLeDeviceListAdapter.notifyDataSetChanged();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -303,21 +412,4 @@ public class BLEScanActivity extends ListActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void requestPermissions(Activity activity) {
|
|
||||||
if (mPermissionsRequested) {
|
|
||||||
Log.i(TAG, "requestPermissions() - request already sent - not doing anything");
|
|
||||||
} else {
|
|
||||||
Log.i(TAG, "requestPermissions() - requesting permissions");
|
|
||||||
for (int i = 0; i < REQUIRED_PERMISSIONS.length; i++) {
|
|
||||||
if (ActivityCompat.shouldShowRequestPermissionRationale(activity,
|
|
||||||
REQUIRED_PERMISSIONS[i])) {
|
|
||||||
Log.i(TAG, "shouldShowRationale for permission" + REQUIRED_PERMISSIONS[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ActivityCompat.requestPermissions(activity,
|
|
||||||
REQUIRED_PERMISSIONS,
|
|
||||||
42);
|
|
||||||
mPermissionsRequested = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,107 +0,0 @@
|
|||||||
package uk.org.openseizuredetector;
|
|
||||||
|
|
||||||
import java.util.AbstractList;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.RandomAccess;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by graham on 28/06/16.
|
|
||||||
*/
|
|
||||||
public class CircularArrayList<E>
|
|
||||||
extends AbstractList<E> implements RandomAccess {
|
|
||||||
/**
|
|
||||||
* If you use this code, please consider notifying isak at du-preez dot com
|
|
||||||
* with a brief description of your application.
|
|
||||||
*
|
|
||||||
* This is free and unencumbered software released into the public domain.
|
|
||||||
* Anyone is free to copy, modify, publish, use, compile, sell, or
|
|
||||||
* distribute this software, either in source code form or as a compiled
|
|
||||||
* binary, for any purpose, commercial or non-commercial, and by any
|
|
||||||
* means.
|
|
||||||
*/
|
|
||||||
|
|
||||||
private final int n; // buffer length
|
|
||||||
private final List<E> buf; // a List implementing RandomAccess
|
|
||||||
private int head = 0;
|
|
||||||
private int tail = 0;
|
|
||||||
|
|
||||||
public CircularArrayList(int capacity) {
|
|
||||||
n = capacity + 1;
|
|
||||||
buf = new ArrayList<E>(Collections.nCopies(n, (E) null));
|
|
||||||
}
|
|
||||||
|
|
||||||
public int capacity() {
|
|
||||||
return n - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
private int wrapIndex(int i) {
|
|
||||||
int m = i % n;
|
|
||||||
if (m < 0) { // java modulus can be negative
|
|
||||||
m += n;
|
|
||||||
}
|
|
||||||
return m;
|
|
||||||
}
|
|
||||||
|
|
||||||
// This method is O(n) but will never be called if the
|
|
||||||
// CircularArrayList is used in its typical/intended role.
|
|
||||||
private void shiftBlock(int startIndex, int endIndex) {
|
|
||||||
assert (endIndex > startIndex);
|
|
||||||
for (int i = endIndex - 1; i >= startIndex; i--) {
|
|
||||||
set(i + 1, get(i));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int size() {
|
|
||||||
return tail - head + (tail < head ? n : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public E get(int i) {
|
|
||||||
if (i < 0 || i >= size()) {
|
|
||||||
throw new IndexOutOfBoundsException();
|
|
||||||
}
|
|
||||||
return buf.get(wrapIndex(head + i));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public E set(int i, E e) {
|
|
||||||
if (i < 0 || i >= size()) {
|
|
||||||
throw new IndexOutOfBoundsException();
|
|
||||||
}
|
|
||||||
return buf.set(wrapIndex(head + i), e);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void add(int i, E e) {
|
|
||||||
int s = size();
|
|
||||||
if (s == n - 1) {
|
|
||||||
throw new IllegalStateException("Cannot add element."
|
|
||||||
+ " CircularArrayList is filled to capacity.");
|
|
||||||
}
|
|
||||||
if (i < 0 || i > s) {
|
|
||||||
throw new IndexOutOfBoundsException();
|
|
||||||
}
|
|
||||||
tail = wrapIndex(tail + 1);
|
|
||||||
if (i < s) {
|
|
||||||
shiftBlock(i, s);
|
|
||||||
}
|
|
||||||
set(i, e);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public E remove(int i) {
|
|
||||||
int s = size();
|
|
||||||
if (i < 0 || i >= s) {
|
|
||||||
throw new IndexOutOfBoundsException();
|
|
||||||
}
|
|
||||||
E e = get(i);
|
|
||||||
if (i > 0) {
|
|
||||||
shiftBlock(0, i);
|
|
||||||
}
|
|
||||||
head = wrapIndex(head + 1);
|
|
||||||
return e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,360 @@
|
|||||||
|
package uk.org.openseizuredetector;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.os.Handler;
|
||||||
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.Button;
|
||||||
|
import android.widget.RadioButton;
|
||||||
|
import android.widget.RadioGroup;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import org.json.JSONArray;
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import java.text.ParseException;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class EditEventActivity extends AppCompatActivity {
|
||||||
|
private String TAG = "EditEventActivity";
|
||||||
|
private Context mContext;
|
||||||
|
private WebApiConnection mWac;
|
||||||
|
private LogManager mLm;
|
||||||
|
private SdServiceConnection mConnection;
|
||||||
|
final Handler serverStatusHandler = new Handler();
|
||||||
|
private OsdUtil mUtil;
|
||||||
|
private List<String> mEventTypesList = null;
|
||||||
|
private HashMap<String, ArrayList<String>> mEventSubTypesHashMap = null;
|
||||||
|
private String mEventTypeStr = null;
|
||||||
|
private String mEventSubTypeStr = null;
|
||||||
|
private String mEventId;
|
||||||
|
private String mEventNotes = "";
|
||||||
|
//private Date mEventDateTime;
|
||||||
|
private RadioGroup mEventTypeRg;
|
||||||
|
private boolean mEventTypesListChanged = false;
|
||||||
|
private RadioGroup mEventSubTypeRg;
|
||||||
|
private boolean mEventSubTypesListChanged = false;
|
||||||
|
private JSONObject mEventObj;
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
Log.v(TAG, "onCreate()");
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
setContentView(R.layout.activity_edit_event);
|
||||||
|
mUtil = new OsdUtil(getApplicationContext(), serverStatusHandler);
|
||||||
|
mConnection = new SdServiceConnection(getApplicationContext());
|
||||||
|
|
||||||
|
//mWac = new WebApiConnection(this, this, this, this);
|
||||||
|
//mLm = new LogManager(this);
|
||||||
|
|
||||||
|
|
||||||
|
Bundle extras = getIntent().getExtras();
|
||||||
|
if (extras != null) {
|
||||||
|
String eventId = extras.getString("eventId");
|
||||||
|
mEventId = eventId;
|
||||||
|
Log.v(TAG, "onCreate - mEventId=" + mEventId);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Button cancelBtn =
|
||||||
|
(Button) findViewById(R.id.cancelBtn);
|
||||||
|
cancelBtn.setOnClickListener(onCancel);
|
||||||
|
Button OKBtn = (Button) findViewById(R.id.loginBtn);
|
||||||
|
OKBtn.setOnClickListener(onOK);
|
||||||
|
|
||||||
|
mEventTypeRg = findViewById(R.id.eventTypeRg);
|
||||||
|
mEventTypeRg.setOnCheckedChangeListener(onEventTypeChange);
|
||||||
|
mEventSubTypeRg = findViewById(R.id.eventSubTypeRg);
|
||||||
|
mEventSubTypeRg.setOnCheckedChangeListener(onEventSubTypeChange);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onStart() {
|
||||||
|
super.onStart();
|
||||||
|
Log.i(TAG, "onStart()");
|
||||||
|
mUtil.bindToServer(getApplicationContext(), mConnection);
|
||||||
|
waitForConnection();
|
||||||
|
|
||||||
|
updateUi();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onStop() {
|
||||||
|
super.onStop();
|
||||||
|
Log.i(TAG, "onStop()");
|
||||||
|
mUtil.unbindFromServer(getApplicationContext(), mConnection);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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)
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initialiseServiceConnection() {
|
||||||
|
mLm = mConnection.mSdServer.mLm;
|
||||||
|
mWac = mConnection.mSdServer.mLm.mWac;
|
||||||
|
|
||||||
|
// Retrieve the JSONObject containing the standard event types.
|
||||||
|
// Note this obscure syntax is to avoid having to create another interface, so it is worth it :)
|
||||||
|
// See https://medium.com/@pra4mesh/callback-function-in-java-20fa48b27797
|
||||||
|
mWac.getEventTypes(new WebApiConnection.JSONObjectCallback() {
|
||||||
|
@Override
|
||||||
|
public void accept(JSONObject eventTypesObj) {
|
||||||
|
Log.v(TAG, "initialiseServiceConnection().onEventTypesReceived");
|
||||||
|
if (eventTypesObj == null) {
|
||||||
|
Log.e(TAG, "initialiseServiceConnection().getEventTypes Callback: Error Retrieving event types");
|
||||||
|
mUtil.showToast("Error Retrieving Event Types from Server - Please Try Again Later!");
|
||||||
|
} else {
|
||||||
|
Iterator<String> keys = eventTypesObj.keys();
|
||||||
|
mEventTypesList = new ArrayList<String>();
|
||||||
|
mEventSubTypesHashMap = new HashMap<String, ArrayList<String>>();
|
||||||
|
while (keys.hasNext()) {
|
||||||
|
String key = keys.next();
|
||||||
|
Log.v(TAG, "initialiseServiceConnection().getEventTypes Callback: key=" + key);
|
||||||
|
mEventTypesList.add(key);
|
||||||
|
try {
|
||||||
|
JSONArray eventSubTypes = eventTypesObj.getJSONArray(key);
|
||||||
|
ArrayList<String> eventSubtypesList = new ArrayList<String>();
|
||||||
|
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, "initialiseServiceConnection().getEventTypes Callback: Error parsing JSONObject" + e.getMessage() + e.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
updateUi();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Retrieve the event data to edit
|
||||||
|
try {
|
||||||
|
mWac.getEvent(mEventId, new WebApiConnection.JSONObjectCallback() {
|
||||||
|
@Override
|
||||||
|
public void accept(JSONObject eventObj) {
|
||||||
|
Log.v(TAG, "initialiseServiceConnection.getEvent");
|
||||||
|
if (eventObj != null) {
|
||||||
|
mEventObj = eventObj;
|
||||||
|
Log.v(TAG, "initialiseServiceConnection.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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateUi() {
|
||||||
|
Log.v(TAG, "updateUI");
|
||||||
|
TextView tv;
|
||||||
|
RadioButton b;
|
||||||
|
|
||||||
|
// Populate event type button group if necessary
|
||||||
|
if (mEventTypesList != null && mEventTypesListChanged) {
|
||||||
|
Log.v(TAG, "updateUi: " + mEventTypesList.toString());
|
||||||
|
mEventTypeRg.removeAllViews();
|
||||||
|
for (String eventTypeStr : mEventTypesList) {
|
||||||
|
b = new RadioButton(this);
|
||||||
|
b.setText(eventTypeStr);
|
||||||
|
mEventTypeRg.addView(b);
|
||||||
|
}
|
||||||
|
mEventTypesListChanged = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (mEventObj != null) {
|
||||||
|
tv = (TextView) findViewById(R.id.eventIdTv);
|
||||||
|
tv.setText(mEventId);
|
||||||
|
tv = (TextView) findViewById(R.id.eventAlarmStateTv);
|
||||||
|
String alarmStateStr = mEventObj.getString("osdAlarmState");
|
||||||
|
try {
|
||||||
|
int alarmStateVal = Integer.parseInt(alarmStateStr);
|
||||||
|
alarmStateStr = mUtil.alarmStatusToString(alarmStateVal);
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.v(TAG,"updateUi: alarmState does not parse to int so displaying it as string: " +alarmStateStr);
|
||||||
|
}
|
||||||
|
tv.setText(alarmStateStr);
|
||||||
|
tv = (TextView) findViewById(R.id.eventNotsTv);
|
||||||
|
tv.setText(mEventObj.getString("desc"));
|
||||||
|
|
||||||
|
|
||||||
|
tv = (TextView) findViewById(R.id.eventDateTv);
|
||||||
|
try {
|
||||||
|
String dateStr = mEventObj.getString("dataTime");
|
||||||
|
Date dataTime = mUtil.string2date(dateStr);
|
||||||
|
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||||
|
tv.setText(dateFormat.format(dataTime));
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG,"updateUI: Error Parsing dataDate "+e.getLocalizedMessage());
|
||||||
|
tv.setText("---");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check the correct seizure type button in the event type group
|
||||||
|
for (int index = 0; index < mEventTypeRg.getChildCount(); index++) {
|
||||||
|
b = (RadioButton) mEventTypeRg.getChildAt(index);
|
||||||
|
String buttonText = b.getText().toString();
|
||||||
|
if (buttonText.equals(mEventObj.getString("type"))) {
|
||||||
|
Log.v(TAG, "updateUi - selecting button " + mEventObj.getString("type"));
|
||||||
|
b.setChecked(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Populate the event sub-types radio button list.
|
||||||
|
Log.v(TAG,"updateUi() - meventsubtypeshashmap="+mEventSubTypesHashMap+", mEventSubtypesListChanged="+mEventSubTypesListChanged);
|
||||||
|
if (mEventSubTypesHashMap != null && mEventSubTypesListChanged) {
|
||||||
|
Log.v(TAG,"UpdateUi() - populating event sub types list");
|
||||||
|
if (mEventObj.getString("type") != null) {
|
||||||
|
// based on https://androidexample.com/create-a-simple-listview
|
||||||
|
ArrayList<String> subtypesArrayList = mEventSubTypesHashMap.get(mEventObj.getString("type"));
|
||||||
|
Log.v(TAG, "updateUi() - eventType=" + mEventObj.getString("type") + ", subtypes=" + subtypesArrayList);
|
||||||
|
mEventSubTypeRg.removeAllViews();
|
||||||
|
for (String eventSubTypeStr : subtypesArrayList) {
|
||||||
|
b = new RadioButton(this);
|
||||||
|
b.setText(eventSubTypeStr);
|
||||||
|
mEventSubTypeRg.addView(b);
|
||||||
|
}
|
||||||
|
mEventSubTypesListChanged = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// And show the correct sub-type selected.
|
||||||
|
for (int index = 0; index < mEventSubTypeRg.getChildCount(); index++) {
|
||||||
|
b = (RadioButton) mEventSubTypeRg.getChildAt(index);
|
||||||
|
String buttonText = b.getText().toString();
|
||||||
|
if (buttonText.equals(mEventObj.getString("subType"))) {
|
||||||
|
Log.v(TAG, "updateUi - selecting button " + mEventObj.getString("subType"));
|
||||||
|
b.setChecked(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
} catch (JSONException e) {
|
||||||
|
Log.e(TAG,"Error Parsing mEventObj: "+e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
} // updateUi()
|
||||||
|
|
||||||
|
View.OnClickListener onCancel =
|
||||||
|
new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View view) {
|
||||||
|
Log.v(TAG, "onCancel");
|
||||||
|
//m_status=false;
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
View.OnClickListener onOK =
|
||||||
|
new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View view) {
|
||||||
|
//m_status=true;
|
||||||
|
TextView tv = (TextView)findViewById(R.id.eventNotsTv);
|
||||||
|
try {
|
||||||
|
mEventObj.put("desc",tv.getText());
|
||||||
|
mEventObj.put("id",mEventId); // Add event Id to event object manually because firestore does not include it by default.
|
||||||
|
} catch (JSONException e) {
|
||||||
|
Log.e(TAG,"Error writing mEventObj: "+e.getMessage());
|
||||||
|
}
|
||||||
|
Log.v(TAG, "onOK() - eventObj="+mEventObj.toString());
|
||||||
|
|
||||||
|
try {
|
||||||
|
mWac.updateEvent(mEventObj, new WebApiConnection.JSONObjectCallback() {
|
||||||
|
@Override
|
||||||
|
public void accept(JSONObject eventObj) {
|
||||||
|
Log.v(TAG, "onOk.updateEvent");
|
||||||
|
//mEventObj = eventObj;
|
||||||
|
if (eventObj != null) {
|
||||||
|
Log.v(TAG, "onOk.getEvent: eventObj=" + eventObj.toString());
|
||||||
|
mUtil.showToast("Event Updated OK");
|
||||||
|
finish();
|
||||||
|
} else {
|
||||||
|
Log.e(TAG, "onOk.updateEvent - Error - returned NULL");
|
||||||
|
mUtil.showToast("Error Updating Event");
|
||||||
|
updateUi();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG,"onOK() - ERROR: "+e.getMessage()+" : " +e.toString());
|
||||||
|
e.printStackTrace();
|
||||||
|
mUtil.showToast("Error Updating Event");
|
||||||
|
updateUi();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
RadioGroup.OnCheckedChangeListener onEventTypeChange =
|
||||||
|
new RadioGroup.OnCheckedChangeListener() {
|
||||||
|
@Override
|
||||||
|
public void onCheckedChanged(RadioGroup group, int checkedId) {
|
||||||
|
Log.v(TAG,"onEventTypeChange() - id="+checkedId);
|
||||||
|
RadioButton b = (RadioButton)findViewById(group.getCheckedRadioButtonId());
|
||||||
|
String selectedEventType = b.getText().toString();
|
||||||
|
try {
|
||||||
|
mEventObj.put("type", selectedEventType);
|
||||||
|
} catch (JSONException e) {
|
||||||
|
Log.e(TAG,"Error setting mEventObj.type: "+e.getMessage());
|
||||||
|
}
|
||||||
|
mEventSubTypesListChanged = true;
|
||||||
|
Log.v(TAG,"onEventTypeChange() - mEventSubTypesListChanged="+mEventSubTypesListChanged);
|
||||||
|
updateUi();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
RadioGroup.OnCheckedChangeListener onEventSubTypeChange =
|
||||||
|
new RadioGroup.OnCheckedChangeListener() {
|
||||||
|
@Override
|
||||||
|
public void onCheckedChanged(RadioGroup group, int checkedId) {
|
||||||
|
Log.v(TAG,"onEventSubTypeChange() - id="+checkedId);
|
||||||
|
RadioButton b = (RadioButton)findViewById(group.getCheckedRadioButtonId());
|
||||||
|
String selectedEventSubType = b.getText().toString();
|
||||||
|
try {
|
||||||
|
mEventObj.put("subType", selectedEventSubType);
|
||||||
|
} catch (JSONException e) {
|
||||||
|
Log.e(TAG,"Error setting mEventObj.type: "+e.getMessage());
|
||||||
|
}
|
||||||
|
updateUi();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,98 +0,0 @@
|
|||||||
package uk.org.openseizuredetector.EventLogManager;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.graphics.Bitmap;
|
|
||||||
import android.graphics.BitmapFactory;
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.widget.BaseAdapter;
|
|
||||||
import android.widget.ImageView;
|
|
||||||
import android.widget.TextView;
|
|
||||||
|
|
||||||
import uk.org.openseizuredetector.R;
|
|
||||||
|
|
||||||
public class EventLogListAdapter extends BaseAdapter {
|
|
||||||
EventLogManager dm;
|
|
||||||
ArrayList<LogEntryModel> logEntryModelList;
|
|
||||||
LayoutInflater inflater;
|
|
||||||
Context _context;
|
|
||||||
|
|
||||||
public EventLogListAdapter(Context context) {
|
|
||||||
|
|
||||||
logEntryModelList = new ArrayList<LogEntryModel>();
|
|
||||||
_context = context;
|
|
||||||
inflater = (LayoutInflater) context
|
|
||||||
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
|
||||||
dm = new EventLogManager(_context);
|
|
||||||
logEntryModelList = dm.getAllData();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void notifyDataSetChanged() {
|
|
||||||
super.notifyDataSetChanged();
|
|
||||||
//refetching the new data from database
|
|
||||||
logEntryModelList = dm.getAllData();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public void delRow(int delPosition) {
|
|
||||||
|
|
||||||
dm.deleteRow(logEntryModelList.get(delPosition).getId());
|
|
||||||
logEntryModelList.remove(delPosition);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getCount() {
|
|
||||||
return logEntryModelList.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object getItem(int position) {
|
|
||||||
return logEntryModelList.get(position);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getItemId(int position) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public View getView(int position, View convertView, ViewGroup parent) {
|
|
||||||
ViewHolder vHolder;
|
|
||||||
if (convertView == null) {
|
|
||||||
convertView = inflater.inflate(R.layout.log_entry_layout, null);
|
|
||||||
vHolder = new ViewHolder();
|
|
||||||
|
|
||||||
vHolder.date = (TextView) convertView
|
|
||||||
.findViewById(R.id.event_date);
|
|
||||||
vHolder.alarmState = (TextView) convertView
|
|
||||||
.findViewById(R.id.event_alarmState);
|
|
||||||
vHolder.note = (TextView) convertView
|
|
||||||
.findViewById(R.id.event_note);
|
|
||||||
vHolder.dataJSON = (TextView) convertView
|
|
||||||
.findViewById(R.id.event_dataJSON);
|
|
||||||
convertView.setTag(vHolder);
|
|
||||||
} else {
|
|
||||||
vHolder = (ViewHolder) convertView.getTag();
|
|
||||||
}
|
|
||||||
|
|
||||||
LogEntryModel eventObj = logEntryModelList.get(position);
|
|
||||||
|
|
||||||
//vHolder.date.setText(eventObj.getDate().toString());
|
|
||||||
vHolder.alarmState.setText(eventObj.getAlarmState());
|
|
||||||
vHolder.note.setText(eventObj.getNote());
|
|
||||||
vHolder.dataJSON.setText(eventObj.getDataJSON());
|
|
||||||
|
|
||||||
return convertView;
|
|
||||||
}
|
|
||||||
|
|
||||||
class ViewHolder {
|
|
||||||
TextView date,alarmState,note,dataJSON;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,210 +0,0 @@
|
|||||||
/**
|
|
||||||
* Database manager for logging events and associated seizure detector data.
|
|
||||||
*/
|
|
||||||
package uk.org.openseizuredetector.EventLogManager;
|
|
||||||
|
|
||||||
import java.text.SimpleDateFormat;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.Locale;
|
|
||||||
|
|
||||||
import android.content.ContentValues;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.database.Cursor;
|
|
||||||
import android.database.SQLException;
|
|
||||||
import android.database.sqlite.SQLiteDatabase;
|
|
||||||
import android.database.sqlite.SQLiteOpenHelper;
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
public class EventLogManager {
|
|
||||||
final static String TAG = "EventLogManager";
|
|
||||||
private SQLiteDatabase db; // a reference to the database manager class.
|
|
||||||
private static final String DB_NAME = "eventlog"; // the name of our database
|
|
||||||
private static final int DB_VERSION = 1; // the version of the database
|
|
||||||
|
|
||||||
private static final String TABLE_NAME = "events";// table name
|
|
||||||
|
|
||||||
// the names for our database columns
|
|
||||||
private static final String TABLE_ROW_ID = "_id";
|
|
||||||
private static final String TABLE_ROW_DATE = "event_date";
|
|
||||||
private static final String TABLE_ROW_ALARM_STATE = "alarm_state";
|
|
||||||
private static final String TABLE_ROW_DATA_JSON = "data_json";
|
|
||||||
private static final String TABLE_ROW_NOTE = "note";
|
|
||||||
private Context context;
|
|
||||||
|
|
||||||
public EventLogManager(Context context) {
|
|
||||||
this.context = context;
|
|
||||||
|
|
||||||
// create or open the database
|
|
||||||
CustomSQLiteOpenHelper helper = new CustomSQLiteOpenHelper(context);
|
|
||||||
this.db = helper.getWritableDatabase();
|
|
||||||
|
|
||||||
helper.onCreate(this.db);
|
|
||||||
}
|
|
||||||
|
|
||||||
// the beginnings our SQLiteOpenHelper class
|
|
||||||
private class CustomSQLiteOpenHelper extends SQLiteOpenHelper {
|
|
||||||
|
|
||||||
public CustomSQLiteOpenHelper(Context context) {
|
|
||||||
super(context, DB_NAME, null, DB_VERSION);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCreate(SQLiteDatabase db) {
|
|
||||||
// the SQLite query string that will create our column database
|
|
||||||
// table.
|
|
||||||
String newTableQueryString = "create table " + TABLE_NAME + " ("
|
|
||||||
+ TABLE_ROW_ID
|
|
||||||
+ " integer primary key autoincrement not null,"
|
|
||||||
+ TABLE_ROW_DATE + " timestamp not null," + TABLE_ROW_ALARM_STATE
|
|
||||||
+ " integer not null," + TABLE_ROW_NOTE + " text not null,"
|
|
||||||
+ TABLE_ROW_DATA_JSON + " text not null" + ");";
|
|
||||||
|
|
||||||
// execute the query string to the database.
|
|
||||||
db.execSQL(newTableQueryString);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
|
|
||||||
|
|
||||||
// LATER, WE WOULD SPECIFIY HOW TO UPGRADE THE DATABASE
|
|
||||||
// FROM OLDER VERSIONS.
|
|
||||||
String DROP_TABLE = "DROP TABLE IF EXISTS " + TABLE_NAME;
|
|
||||||
db.execSQL(DROP_TABLE);
|
|
||||||
onCreate(db);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addRow(LogEntryModel eventObj) {
|
|
||||||
ContentValues values = prepareData(eventObj);
|
|
||||||
// ask the database object to insert the new data
|
|
||||||
try {
|
|
||||||
db.insert(TABLE_NAME, null, values);
|
|
||||||
} catch (Exception e) {
|
|
||||||
Log.e("DB ERROR", e.toString()); // prints the error message to
|
|
||||||
// the log
|
|
||||||
e.printStackTrace(); // prints the stack trace to the log
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getDateTime(Date date) {
|
|
||||||
SimpleDateFormat dateFormat = new SimpleDateFormat(
|
|
||||||
"yyyy-MM-dd HH:mm:ss", Locale.getDefault());
|
|
||||||
if (date==null)
|
|
||||||
return "";
|
|
||||||
else
|
|
||||||
return dateFormat.format(date);
|
|
||||||
}
|
|
||||||
|
|
||||||
private ContentValues prepareData(LogEntryModel eventObj) {
|
|
||||||
|
|
||||||
ContentValues values = new ContentValues();
|
|
||||||
values.put(TABLE_ROW_ALARM_STATE, eventObj.getAlarmState());
|
|
||||||
values.put(TABLE_ROW_DATE, getDateTime(eventObj.getDate()));
|
|
||||||
values.put(TABLE_ROW_NOTE, eventObj.getNote());
|
|
||||||
values.put(TABLE_ROW_DATA_JSON, eventObj.getDataJSON());
|
|
||||||
return values;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns row data in form of LogEntryModel object
|
|
||||||
public LogEntryModel getRowAsObject(int rowID) {
|
|
||||||
|
|
||||||
LogEntryModel rowContactObj = new LogEntryModel();
|
|
||||||
Cursor cursor;
|
|
||||||
|
|
||||||
try {
|
|
||||||
|
|
||||||
cursor = db.query(TABLE_NAME, new String[] { TABLE_ROW_ID,
|
|
||||||
TABLE_ROW_ALARM_STATE, TABLE_ROW_DATE, TABLE_ROW_NOTE,
|
|
||||||
TABLE_ROW_DATA_JSON }, TABLE_ROW_ID + "=" + rowID, null,
|
|
||||||
null, null, null, null);
|
|
||||||
|
|
||||||
cursor.moveToFirst();
|
|
||||||
prepareSendObject(rowContactObj, cursor);
|
|
||||||
|
|
||||||
} catch (SQLException e) {
|
|
||||||
Log.e("DB ERROR", e.toString());
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
|
|
||||||
return rowContactObj;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns all the rows data in form of LogEntryModel object list
|
|
||||||
|
|
||||||
public ArrayList<LogEntryModel> getAllData() {
|
|
||||||
|
|
||||||
ArrayList<LogEntryModel> allRowsObj = new ArrayList<LogEntryModel>();
|
|
||||||
Cursor cursor;
|
|
||||||
LogEntryModel rowContactObj;
|
|
||||||
|
|
||||||
String[] columns = new String[] { TABLE_ROW_ID, TABLE_ROW_ALARM_STATE,
|
|
||||||
TABLE_ROW_DATE, TABLE_ROW_NOTE, TABLE_ROW_DATA_JSON };
|
|
||||||
|
|
||||||
try {
|
|
||||||
|
|
||||||
cursor = db
|
|
||||||
.query(TABLE_NAME, columns, null, null, null, null, null);
|
|
||||||
cursor.moveToFirst();
|
|
||||||
|
|
||||||
if (!cursor.isAfterLast()) {
|
|
||||||
do {
|
|
||||||
rowContactObj = new LogEntryModel();
|
|
||||||
rowContactObj.setId(cursor.getInt(0));
|
|
||||||
prepareSendObject(rowContactObj, cursor);
|
|
||||||
allRowsObj.add(rowContactObj);
|
|
||||||
|
|
||||||
} while (cursor.moveToNext()); // try to move the cursor's
|
|
||||||
// pointer forward one position.
|
|
||||||
}
|
|
||||||
} catch (SQLException e) {
|
|
||||||
Log.e("DB ERROR", e.toString());
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
|
|
||||||
return allRowsObj;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private void prepareSendObject(LogEntryModel rowObj, Cursor cursor) {
|
|
||||||
rowObj.setId(cursor.getInt(cursor.getColumnIndexOrThrow(TABLE_ROW_ID)));
|
|
||||||
rowObj.setAlarmState(cursor.getInt(cursor
|
|
||||||
.getColumnIndexOrThrow(TABLE_ROW_ALARM_STATE)));
|
|
||||||
String dateTimeStr = cursor.getString(cursor
|
|
||||||
.getColumnIndexOrThrow(TABLE_ROW_DATE));
|
|
||||||
Log.v(TAG,"dateTimeStr = "+dateTimeStr);
|
|
||||||
Date dateVal;
|
|
||||||
try { dateVal = new Date(dateTimeStr); }
|
|
||||||
catch (IllegalArgumentException e) { dateVal = null; }
|
|
||||||
rowObj.setDate(dateVal);
|
|
||||||
rowObj.setNote(cursor.getString(cursor
|
|
||||||
.getColumnIndexOrThrow(TABLE_ROW_NOTE)));
|
|
||||||
rowObj.setDataJSON(cursor.getString(cursor
|
|
||||||
.getColumnIndexOrThrow(TABLE_ROW_DATA_JSON)));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void deleteRow(int rowID) {
|
|
||||||
// ask the database manager to delete the row of given id
|
|
||||||
try {
|
|
||||||
db.delete(TABLE_NAME, TABLE_ROW_ID + "=" + rowID, null);
|
|
||||||
} catch (Exception e) {
|
|
||||||
Log.e("DB ERROR", e.toString());
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void updateRow(int rowId, LogEntryModel contactObj) {
|
|
||||||
|
|
||||||
ContentValues values = prepareData(contactObj);
|
|
||||||
|
|
||||||
String whereClause = TABLE_ROW_ID + "=?";
|
|
||||||
String whereArgs[] = new String[] { String.valueOf(rowId) };
|
|
||||||
|
|
||||||
db.update(TABLE_NAME, values, whereClause, whereArgs);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,53 +0,0 @@
|
|||||||
package uk.org.openseizuredetector.EventLogManager;
|
|
||||||
|
|
||||||
import java.util.Date;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Our LogEntryModel class which will have fields like id, name, contact number
|
|
||||||
* and email and corresponding getter and setter methods.
|
|
||||||
* **/
|
|
||||||
public class LogEntryModel {
|
|
||||||
|
|
||||||
private int id;
|
|
||||||
private Date date;
|
|
||||||
private int alarmState;
|
|
||||||
private String dataJSON;
|
|
||||||
private String note;
|
|
||||||
|
|
||||||
|
|
||||||
public int getId() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setId(int id) {
|
|
||||||
this.id = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getAlarmState() {
|
|
||||||
return alarmState;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setAlarmState(int alarmState) {
|
|
||||||
this.alarmState = alarmState;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getNote() {
|
|
||||||
return note;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setNote(String note) {
|
|
||||||
this.note = note;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Date getDate() {
|
|
||||||
return date;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDate(Date date) {
|
|
||||||
this.date = date;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getDataJSON() { return dataJSON; }
|
|
||||||
|
|
||||||
public void setDataJSON(String dataJSON) { this.dataJSON = dataJSON; }
|
|
||||||
}
|
|
||||||
@@ -2,9 +2,8 @@ package uk.org.openseizuredetector;
|
|||||||
|
|
||||||
import android.app.DatePickerDialog;
|
import android.app.DatePickerDialog;
|
||||||
import android.app.TimePickerDialog;
|
import android.app.TimePickerDialog;
|
||||||
import android.content.Context;
|
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.support.v7.app.AppCompatActivity;
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
@@ -15,9 +14,9 @@ import android.widget.TimePicker;
|
|||||||
|
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
|
|
||||||
public class DBQueryActivity extends AppCompatActivity
|
public class ExportDataActivity extends AppCompatActivity
|
||||||
implements View.OnClickListener {
|
implements View.OnClickListener {
|
||||||
String TAG = "DBQueryActivity";
|
String TAG = "ExportDataActivity";
|
||||||
Button mDateBtn;
|
Button mDateBtn;
|
||||||
Button mTimeBtn;
|
Button mTimeBtn;
|
||||||
Button mExportBtn;
|
Button mExportBtn;
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,66 +0,0 @@
|
|||||||
package uk.org.openseizuredetector;
|
|
||||||
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.support.v4.app.FragmentActivity;
|
|
||||||
import android.util.Log;
|
|
||||||
import android.view.View;
|
|
||||||
import android.widget.Button;
|
|
||||||
import android.widget.ListView;
|
|
||||||
|
|
||||||
import uk.org.openseizuredetector.EventLogManager.EventLogListAdapter;
|
|
||||||
import uk.org.openseizuredetector.EventLogManager.EventLogManager;
|
|
||||||
import uk.org.openseizuredetector.EventLogManager.LogEntryModel;
|
|
||||||
|
|
||||||
|
|
||||||
public class LogManagerActivity extends FragmentActivity
|
|
||||||
implements AuthDialogInterface {
|
|
||||||
private String TAG = "LogManagerActivity";
|
|
||||||
private EventLogListAdapter mEventLogListAdapter;
|
|
||||||
private ListView mEventLogListView;
|
|
||||||
private EventLogManager mElm;
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
setContentView(R.layout.activity_log_manager);
|
|
||||||
|
|
||||||
LogEntryModel lem = new LogEntryModel();
|
|
||||||
//lem.setDate(new Date());
|
|
||||||
lem.setNote("Test Entry");
|
|
||||||
lem.setDataJSON("[]");
|
|
||||||
lem.setAlarmState(1);
|
|
||||||
|
|
||||||
//mElm = new EventLogManager(this);
|
|
||||||
//mElm.addRow(lem);
|
|
||||||
|
|
||||||
//mEventLogListAdapter = new EventLogListAdapter(this);
|
|
||||||
//mEventLogListView = (ListView) findViewById(R.id.eventLogListView);
|
|
||||||
//mEventLogListView.setAdapter(mEventLogListAdapter);
|
|
||||||
|
|
||||||
Button b;
|
|
||||||
|
|
||||||
b = (Button) findViewById(R.id.authenticate_button);
|
|
||||||
b.setOnClickListener(new View.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View view) {
|
|
||||||
Log.v(TAG, "authenticate button clicked");
|
|
||||||
AuthDialog authDialog = new AuthDialog();
|
|
||||||
authDialog.show(getSupportFragmentManager(),"authDialog");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public void updateUi() {
|
|
||||||
Log.v(TAG, "updateUi");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onDialogDone(boolean State) {
|
|
||||||
|
|
||||||
Log.v(TAG,"onDialogDone()");
|
|
||||||
LogManager lm = new LogManager(this);
|
|
||||||
lm.authenticate("test", "testpw");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,653 @@
|
|||||||
|
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.graphics.Color;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.os.CountDownTimer;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.os.IBinder;
|
||||||
|
|
||||||
|
import androidx.core.view.MenuCompat;
|
||||||
|
import androidx.appcompat.app.AlertDialog;
|
||||||
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.Menu;
|
||||||
|
import android.view.MenuItem;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewConfiguration;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.AdapterView;
|
||||||
|
import android.widget.Button;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.ListAdapter;
|
||||||
|
import android.widget.ListView;
|
||||||
|
import android.widget.RadioButton;
|
||||||
|
import android.widget.SimpleAdapter;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import org.json.JSONArray;
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.text.ParseException;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class LogManagerControlActivity extends AppCompatActivity {
|
||||||
|
private String TAG = "LogManagerControlActivity";
|
||||||
|
private LogManager mLm;
|
||||||
|
private Context mContext;
|
||||||
|
private UiTimer mUiTimer;
|
||||||
|
private ArrayList<HashMap<String, String>> mEventsList;
|
||||||
|
private ArrayList<HashMap<String, String>> mRemoteEventsList;
|
||||||
|
private ArrayList<HashMap<String, String>> mSysLogList;
|
||||||
|
private SdServiceConnection mConnection;
|
||||||
|
private OsdUtil mUtil;
|
||||||
|
final Handler serverStatusHandler = new Handler();
|
||||||
|
private Integer mUiTimerPeriodFast = 2000; // 2 seconds - we use fast updating while UI is blank and we are waiting for first data
|
||||||
|
private Integer mUiTimerPeriodSlow = 60000; // 60 seconds - once data has been received and UI populated we only update once per minute.
|
||||||
|
private boolean mUpdateSysLog = true;
|
||||||
|
//private Integer UI_MODE_LOCAL = 0;
|
||||||
|
//private Integer UI_MODE_SHARED = 1;
|
||||||
|
//private Integer mUiMode = UI_MODE_SHARED;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
Log.v(TAG, "onCreate()");
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
mContext = this;
|
||||||
|
mUtil = new OsdUtil(getApplicationContext(), serverStatusHandler);
|
||||||
|
|
||||||
|
if (!mUtil.isServerRunning()) {
|
||||||
|
mUtil.showToast(getString(R.string.error_server_not_running));
|
||||||
|
finish();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mConnection = new SdServiceConnection(getApplicationContext());
|
||||||
|
|
||||||
|
setContentView(R.layout.activity_log_manager_control);
|
||||||
|
|
||||||
|
/* Force display of overflow menu - from stackoverflow
|
||||||
|
* "how to force use of..."
|
||||||
|
*/
|
||||||
|
try {
|
||||||
|
Log.v(TAG, "trying menubar fiddle...");
|
||||||
|
ViewConfiguration config = ViewConfiguration.get(this);
|
||||||
|
Field menuKeyField =
|
||||||
|
ViewConfiguration.class.getDeclaredField("sHasPermanentMenuKey");
|
||||||
|
if (menuKeyField != null) {
|
||||||
|
Log.v(TAG, "menuKeyField is not null - configuring....");
|
||||||
|
menuKeyField.setAccessible(true);
|
||||||
|
menuKeyField.setBoolean(config, false);
|
||||||
|
} else {
|
||||||
|
Log.v(TAG, "menuKeyField is null - doing nothing...");
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.v(TAG, "menubar fiddle exception: " + e.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
Button authBtn =
|
||||||
|
(Button) findViewById(R.id.auth_button);
|
||||||
|
authBtn.setOnClickListener(onAuth);
|
||||||
|
//Button pruneBtn =
|
||||||
|
// (Button) findViewById(R.id.pruneDatabaseBtn);
|
||||||
|
//pruneBtn.setOnClickListener(onPruneBtn);
|
||||||
|
//Button reportSeizureBtn =
|
||||||
|
// (Button) findViewById(R.id.reportSeizureBtn);
|
||||||
|
//reportSeizureBtn.setOnClickListener(onReportSeizureBtn);
|
||||||
|
Button remoteDbBtn =
|
||||||
|
(Button) findViewById(R.id.refresh_button);
|
||||||
|
remoteDbBtn.setOnClickListener(onRefreshBtn);
|
||||||
|
|
||||||
|
ListView lv = (ListView) findViewById(R.id.eventLogListView);
|
||||||
|
lv.setOnItemClickListener(onEventListClick);
|
||||||
|
|
||||||
|
lv = (ListView) findViewById(R.id.remoteEventsLv);
|
||||||
|
lv.setOnItemClickListener(onRemoteEventListClick);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create Action Bar
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean onCreateOptionsMenu(Menu menu) {
|
||||||
|
Log.i(TAG, "onCreateOptionsMenu()");
|
||||||
|
getMenuInflater().inflate(R.menu.log_manager_activity_menu, menu);
|
||||||
|
MenuCompat.setGroupDividerEnabled(menu, true);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onStart() {
|
||||||
|
Log.v(TAG, "onStart()");
|
||||||
|
super.onStart();
|
||||||
|
mUtil.bindToServer(getApplicationContext(), mConnection);
|
||||||
|
waitForConnection();
|
||||||
|
startUiTimer(mUiTimerPeriodFast);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onStop() {
|
||||||
|
Log.v(TAG, "onStop()");
|
||||||
|
super.onStop();
|
||||||
|
stopUiTimer();
|
||||||
|
mUtil.unbindFromServer(getApplicationContext(), mConnection);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPause() {
|
||||||
|
Log.v(TAG, "onPause()");
|
||||||
|
super.onPause();
|
||||||
|
//stopUiTimer();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onResume() {
|
||||||
|
Log.v(TAG, "onResume()");
|
||||||
|
super.onResume();
|
||||||
|
//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)
|
||||||
|
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;
|
||||||
|
startUiTimer(mUiTimerPeriodFast);
|
||||||
|
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
|
||||||
|
mLm.getEventsList(true, (ArrayList<HashMap<String, String>> eventsList) -> {
|
||||||
|
mEventsList = eventsList;
|
||||||
|
Log.v(TAG, "initialiseServiceConnection() - set mEventsList - Updating UI");
|
||||||
|
updateUi();
|
||||||
|
});
|
||||||
|
mUtil.getSysLogList((ArrayList<HashMap<String, String>> syslogList) -> {
|
||||||
|
mSysLogList = syslogList;
|
||||||
|
Log.v(TAG, "initialiseServiceConnection() - set mSysLogList - Updating UI");
|
||||||
|
updateUi();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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<HashMap<String, String>>();
|
||||||
|
// 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);
|
||||||
|
Log.v(TAG, "getRemoteEvents() - " + eventObj.toString());
|
||||||
|
String id = null;
|
||||||
|
if (!eventObj.isNull("id")) {
|
||||||
|
id = eventObj.getString("id");
|
||||||
|
}
|
||||||
|
int osdAlarmState = -1;
|
||||||
|
if (!eventObj.isNull("osdAlarmState")) {
|
||||||
|
osdAlarmState = eventObj.getInt("osdAlarmState");
|
||||||
|
}
|
||||||
|
String dataTime = "null";
|
||||||
|
if (!eventObj.isNull("dataTime")) {
|
||||||
|
dataTime = eventObj.getString("dataTime");
|
||||||
|
Log.v(TAG, "getRemoteEvents() - dataTime=" + dataTime);
|
||||||
|
}
|
||||||
|
String typeStr = "null";
|
||||||
|
if (!eventObj.isNull("type")) {
|
||||||
|
typeStr = eventObj.getString("type");
|
||||||
|
}
|
||||||
|
String subType = "null";
|
||||||
|
if (!eventObj.isNull("subType")) {
|
||||||
|
subType = eventObj.getString("subType");
|
||||||
|
}
|
||||||
|
String desc = "null";
|
||||||
|
if (!eventObj.isNull("desc")) {
|
||||||
|
desc = eventObj.getString("desc");
|
||||||
|
}
|
||||||
|
HashMap<String, String> eventHashMap = new HashMap<String, String>();
|
||||||
|
eventHashMap.put("id", id);
|
||||||
|
eventHashMap.put("osdAlarmState", String.valueOf(osdAlarmState));
|
||||||
|
eventHashMap.put("osdAlarmStateStr", mUtil.alarmStatusToString(osdAlarmState));
|
||||||
|
eventHashMap.put("dataTime", dataTime);
|
||||||
|
eventHashMap.put("type", typeStr);
|
||||||
|
eventHashMap.put("subType", subType);
|
||||||
|
eventHashMap.put("desc", desc);
|
||||||
|
mRemoteEventsList.add(eventHashMap);
|
||||||
|
}
|
||||||
|
Log.v(TAG, "getRemoteEvents() - set mRemoteEventsList(). Updating UI");
|
||||||
|
updateUi();
|
||||||
|
} 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.i(TAG, "updateUi()");
|
||||||
|
boolean stopUpdating = true;
|
||||||
|
TextView tv;
|
||||||
|
Button btn;
|
||||||
|
// Local Database Information
|
||||||
|
if (mLm != null) {
|
||||||
|
mLm.getLocalEventsCount(true, (Long eventCount) -> {
|
||||||
|
TextView tv1 = (TextView) findViewById(R.id.num_local_events_tv);
|
||||||
|
tv1.setText(String.format("%d", eventCount));
|
||||||
|
});
|
||||||
|
mLm.getLocalDatapointsCount((Long datapointsCount) -> {
|
||||||
|
TextView tv2 = (TextView) findViewById(R.id.num_local_datapoints_tv);
|
||||||
|
tv2.setText(String.format("%d", datapointsCount));
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
stopUpdating = false;
|
||||||
|
}
|
||||||
|
// Local Database ListView
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
// SysLog ListView
|
||||||
|
if (mSysLogList != null && mUpdateSysLog) {
|
||||||
|
ListView lv = (ListView) findViewById(R.id.sysLogListView);
|
||||||
|
ListAdapter adapter = new SimpleAdapter(LogManagerControlActivity.this, mSysLogList, R.layout.syslog_entry_layout,
|
||||||
|
new String[]{"dataTime", "logLevel", "dataJSON"},
|
||||||
|
new int[]{R.id.syslog_entry_date_tv, R.id.syslog_level_tv, R.id.syslog_entry_text_tv});
|
||||||
|
lv.setAdapter(adapter);
|
||||||
|
//Log.v(TAG,"eventsList="+mEventsList);
|
||||||
|
mUpdateSysLog = false;
|
||||||
|
}
|
||||||
|
// Remote Database List View
|
||||||
|
if (mRemoteEventsList != null) {
|
||||||
|
ListView lv = (ListView) findViewById(R.id.remoteEventsLv);
|
||||||
|
ListAdapter adapter = new RemoteEventsAdapter(LogManagerControlActivity.this, mRemoteEventsList, R.layout.log_entry_layout_remote,
|
||||||
|
new String[]{"id", "dataTime", "type", "subType", "osdAlarmStateStr", "desc"},
|
||||||
|
new int[]{R.id.event_id_remote_tv, R.id.event_date_remote_tv, R.id.event_type_remote_tv, R.id.event_subtype_remote_tv,
|
||||||
|
R.id.event_alarmState_remote_tv, R.id.event_notes_remote_tv});
|
||||||
|
lv.setAdapter(adapter);
|
||||||
|
//Log.i(TAG,"adapter[0]="+adapter.getItem(0));
|
||||||
|
//Log.i(TAG,"adapter[3]="+adapter.getItem(3));
|
||||||
|
} else {
|
||||||
|
//mUtil.showToast("No Remote Events");
|
||||||
|
Log.i(TAG, "UpdateUi: No Remote Events");
|
||||||
|
stopUpdating = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Remote Database Information
|
||||||
|
if (mLm != null) {
|
||||||
|
tv = (TextView) findViewById(R.id.authStatusTv);
|
||||||
|
btn = (Button) findViewById(R.id.auth_button);
|
||||||
|
if (mLm.mWac.isLoggedIn()) {
|
||||||
|
tv.setText(getString(R.string.logged_in_with_token));
|
||||||
|
btn.setText(getString(R.string.logout));
|
||||||
|
} else {
|
||||||
|
tv.setText(getString(R.string.not_authenticated));
|
||||||
|
btn.setText(getString(R.string.login));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
stopUpdating = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note we do not really stop updating the UI, just change from the fast update period to the slow update period
|
||||||
|
// to save hammering the databases once the UI has been populated once.
|
||||||
|
if (stopUpdating) {
|
||||||
|
stopUiTimer();
|
||||||
|
startUiTimer(mUiTimerPeriodSlow);
|
||||||
|
}
|
||||||
|
} //updateUi();
|
||||||
|
|
||||||
|
public void onRadioButtonClicked(View view) {
|
||||||
|
LinearLayout localDataLl = (LinearLayout) findViewById(R.id.local_data_ll);
|
||||||
|
LinearLayout sharedDataLl = (LinearLayout) findViewById(R.id.shared_data_ll);
|
||||||
|
LinearLayout syslogLl = (LinearLayout) findViewById(R.id.syslog_ll);
|
||||||
|
// Is the button now checked?
|
||||||
|
boolean checked = ((RadioButton) view).isChecked();
|
||||||
|
|
||||||
|
// Check which radio button was clicked
|
||||||
|
switch (view.getId()) {
|
||||||
|
case R.id.local_data_rb:
|
||||||
|
if (checked) {
|
||||||
|
// Switch to the local data view
|
||||||
|
localDataLl.setVisibility(View.VISIBLE);
|
||||||
|
sharedDataLl.setVisibility(View.GONE);
|
||||||
|
syslogLl.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case R.id.shared_data_rb:
|
||||||
|
if (checked) {
|
||||||
|
// Switch to the local data view
|
||||||
|
localDataLl.setVisibility(View.GONE);
|
||||||
|
sharedDataLl.setVisibility(View.VISIBLE);
|
||||||
|
syslogLl.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case R.id.syslog_rb:
|
||||||
|
if (checked) {
|
||||||
|
// Switch to the local data view
|
||||||
|
localDataLl.setVisibility(View.GONE);
|
||||||
|
sharedDataLl.setVisibility(View.GONE);
|
||||||
|
syslogLl.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
|
Log.i(TAG, "onOptionsItemSelected() : " + item.getItemId() + " selected");
|
||||||
|
switch (item.getItemId()) {
|
||||||
|
case R.id.action_authenticate_api:
|
||||||
|
Log.i(TAG, "action_autheticate_api");
|
||||||
|
try {
|
||||||
|
Intent i = new Intent(
|
||||||
|
getApplicationContext(),
|
||||||
|
AuthenticateActivity.class);
|
||||||
|
this.startActivity(i);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
Log.i(TAG, "exception starting export activity " + ex.toString());
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
case R.id.pruneDatabaseMenuItem:
|
||||||
|
Log.i(TAG, "action_pruneDatabase");
|
||||||
|
onPruneBtn.onClick(null);
|
||||||
|
return true;
|
||||||
|
case R.id.action_report_seizure:
|
||||||
|
Log.i(TAG, "action_report_seizure");
|
||||||
|
try {
|
||||||
|
Intent intent = new Intent(
|
||||||
|
getApplicationContext(),
|
||||||
|
ReportSeizureActivity.class);
|
||||||
|
this.startActivity(intent);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
Log.i(TAG, "exception starting Report Seizure activity " + ex.toString());
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
case R.id.action_settings:
|
||||||
|
Log.i(TAG, "action_settings");
|
||||||
|
try {
|
||||||
|
Intent prefsIntent = new Intent(
|
||||||
|
getApplicationContext(),
|
||||||
|
PrefActivity.class);
|
||||||
|
this.startActivity(prefsIntent);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
Log.i(TAG, "exception starting settings activity " + ex.toString());
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
case R.id.action_mark_unknown:
|
||||||
|
Log.i(TAG, "action_mark_unknown");
|
||||||
|
new AlertDialog.Builder(this)
|
||||||
|
.setTitle(R.string.mark_unverified_events_unknown_dialog_title)
|
||||||
|
.setMessage(R.string.mark_unverified_events_unknown_dialog_message)
|
||||||
|
.setIcon(android.R.drawable.ic_dialog_alert)
|
||||||
|
.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
|
||||||
|
public void onClick(DialogInterface dialog, int whichButton) {
|
||||||
|
mLm.mWac.markUnverifiedEventsAsUnknown();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.setNegativeButton(android.R.string.no, null)
|
||||||
|
.show();
|
||||||
|
default:
|
||||||
|
return super.onOptionsItemSelected(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
View.OnClickListener onAuth =
|
||||||
|
new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View view) {
|
||||||
|
Log.v(TAG, "onAuth");
|
||||||
|
Intent i;
|
||||||
|
i = new Intent(mContext, AuthenticateActivity.class);
|
||||||
|
startActivity(i);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
View.OnClickListener onPruneBtn =
|
||||||
|
new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View view) {
|
||||||
|
Log.v(TAG, "onPruneBtn");
|
||||||
|
// Confirmation dialog based on: https://stackoverflow.com/a/12213536/2104584
|
||||||
|
AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
|
||||||
|
builder.setTitle("Prune Database");
|
||||||
|
builder.setMessage(String.format("This will remove all data from the database that is more than %d days old."
|
||||||
|
+ "\nThis can NOT be undone.\nAre you sure?", mLm.mDataRetentionPeriod));
|
||||||
|
builder.setPositiveButton("YES", new DialogInterface.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(DialogInterface dialog, int which) {
|
||||||
|
mLm.pruneLocalDb();
|
||||||
|
dialog.dismiss();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
builder.setNegativeButton("NO", new DialogInterface.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(DialogInterface dialog, int which) {
|
||||||
|
dialog.dismiss();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
AlertDialog alert = builder.create();
|
||||||
|
alert.show();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
View.OnClickListener onReportSeizureBtn =
|
||||||
|
new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View view) {
|
||||||
|
Log.v(TAG, "onReportSeizureBtn");
|
||||||
|
Intent i;
|
||||||
|
i = new Intent(mContext, ReportSeizureActivity.class);
|
||||||
|
startActivity(i);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
View.OnClickListener onRemoteDbBtn =
|
||||||
|
new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View view) {
|
||||||
|
Log.v(TAG, "onRemoteDbBtn");
|
||||||
|
Intent i;
|
||||||
|
i = new Intent(mContext, RemoteDbActivity.class);
|
||||||
|
startActivity(i);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
View.OnClickListener onRefreshBtn =
|
||||||
|
new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View view) {
|
||||||
|
Log.v(TAG, "onRefreshBtn");
|
||||||
|
initialiseServiceConnection();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
AdapterView.OnItemClickListener onEventListClick =
|
||||||
|
new AdapterView.OnItemClickListener() {
|
||||||
|
public void onItemClick(AdapterView<?> adapter, View v, int position, long id) {
|
||||||
|
Log.v(TAG, "onItemClicKListener() - Position=" + position + ", id=" + id);// Confirmation dialog based on: https://stackoverflow.com/a/12213536/2104584
|
||||||
|
HashMap<String, String> eventObj = (HashMap<String, String>) adapter.getItemAtPosition(position);
|
||||||
|
String eventId = eventObj.get("uploaded");
|
||||||
|
Log.d(TAG, "onItemClickListener(): eventId=" + eventId + ", eventObj=" + eventObj);
|
||||||
|
if (eventId != null) {
|
||||||
|
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<String, String> eventObj = (HashMap<String, String>) adapter.getItemAtPosition(position);
|
||||||
|
String eventId = eventObj.get("id");
|
||||||
|
Log.d(TAG, "onItemClickListener(): eventId=" + eventId + ", eventObj=" + eventObj);
|
||||||
|
Intent i = new Intent(getApplicationContext(), EditEventActivity.class);
|
||||||
|
i.putExtra("eventId", eventId);
|
||||||
|
startActivity(i);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Start the timer that will update the user interface every 5 seconds..
|
||||||
|
*/
|
||||||
|
private void startUiTimer(Integer uiTimerPeriod) {
|
||||||
|
if (mUiTimer != null) {
|
||||||
|
Log.v(TAG, "startUiTimer -timer already running - cancelling it");
|
||||||
|
mUiTimer.cancel();
|
||||||
|
mUiTimer = null;
|
||||||
|
}
|
||||||
|
Log.v(TAG, "startUiTimer() - starting UiTimer");
|
||||||
|
mUiTimer =
|
||||||
|
new UiTimer(uiTimerPeriod, 1000);
|
||||||
|
mUiTimer.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Cancel the remote logging timer to prevent attempts to upload to remote database.
|
||||||
|
*/
|
||||||
|
public void stopUiTimer() {
|
||||||
|
if (mUiTimer != null) {
|
||||||
|
Log.v(TAG, "stopUiTimer(): cancelling UI timer");
|
||||||
|
mUiTimer.cancel();
|
||||||
|
mUiTimer = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Upload recorded data to the remote database periodically.
|
||||||
|
*/
|
||||||
|
private class UiTimer extends CountDownTimer {
|
||||||
|
public UiTimer(long startTime, long interval) {
|
||||||
|
super(startTime, interval);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTick(long l) {
|
||||||
|
// Do Nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFinish() {
|
||||||
|
//Log.v(TAG, "UiTimer - onFinish - Updating UI");
|
||||||
|
updateUi();
|
||||||
|
// Restart this timer.
|
||||||
|
if (mUiTimer != null)
|
||||||
|
start();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private class RemoteEventsAdapter extends SimpleAdapter {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*
|
||||||
|
* @param context The context where the View associated with this SimpleAdapter is running
|
||||||
|
* @param data A List of Maps. Each entry in the List corresponds to one row in the list. The
|
||||||
|
* Maps contain the data for each row, and should include all the entries specified in
|
||||||
|
* "from"
|
||||||
|
* @param resource Resource identifier of a view layout that defines the views for this list
|
||||||
|
* item. The layout file should include at least those named views defined in "to"
|
||||||
|
* @param from A list of column names that will be added to the Map associated with each
|
||||||
|
* item.
|
||||||
|
* @param to The views that should display column in the "from" parameter. These should all be
|
||||||
|
* TextViews. The first N views in this list are given the values of the first N columns
|
||||||
|
*/
|
||||||
|
public RemoteEventsAdapter(Context context, List<? extends Map<String, ?>> data, int resource, String[] from, int[] to) {
|
||||||
|
super(context, data, resource, from, to);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View getView(int position, View convertView, ViewGroup parent) {
|
||||||
|
View v = super.getView(position, convertView, parent);
|
||||||
|
Map<String, ?> dataItem = (Map<String, ?>) getItem(position);
|
||||||
|
Log.v(TAG, "getView() " + dataItem.toString());
|
||||||
|
switch (dataItem.get("type").toString()) {
|
||||||
|
case "null":
|
||||||
|
case "":
|
||||||
|
v.setBackgroundColor(Color.parseColor("#ffaaaa"));
|
||||||
|
break;
|
||||||
|
case "Seizure":
|
||||||
|
v.setBackgroundColor(Color.parseColor("#ff6060"));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
v.setBackgroundColor(Color.TRANSPARENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert date format to something more readable.
|
||||||
|
TextView tv = (TextView) v.findViewById(R.id.event_date_remote_tv);
|
||||||
|
Date dataTime = null;
|
||||||
|
String dateStr = (String) dataItem.get("dataTime");
|
||||||
|
dataTime = mUtil.string2date(dateStr);
|
||||||
|
if (dataTime != null) {
|
||||||
|
SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
|
||||||
|
tv.setText(dateFormat.format(dataTime));
|
||||||
|
} else {
|
||||||
|
tv.setText("---");
|
||||||
|
}
|
||||||
|
return (v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -25,7 +25,8 @@
|
|||||||
|
|
||||||
package uk.org.openseizuredetector;
|
package uk.org.openseizuredetector;
|
||||||
|
|
||||||
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;
|
||||||
@@ -36,24 +37,20 @@ import android.os.Handler;
|
|||||||
import android.os.Message;
|
import android.os.Message;
|
||||||
import android.os.Messenger;
|
import android.os.Messenger;
|
||||||
import android.preference.PreferenceManager;
|
import android.preference.PreferenceManager;
|
||||||
import android.support.v7.app.AppCompatActivity;
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewConfiguration;
|
import android.view.ViewConfiguration;
|
||||||
import android.view.WindowManager;
|
import android.view.WindowManager;
|
||||||
|
import android.widget.Button;
|
||||||
import android.widget.ProgressBar;
|
import android.widget.ProgressBar;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import android.widget.Button;
|
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
import androidx.appcompat.app.AlertDialog;
|
||||||
import java.text.DecimalFormat;
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
import java.util.ArrayList;
|
import androidx.core.view.MenuCompat;
|
||||||
import java.util.Timer;
|
|
||||||
import java.util.TimerTask;
|
|
||||||
|
|
||||||
//MPAndroidChart
|
|
||||||
import com.github.mikephil.charting.charts.BarChart;
|
import com.github.mikephil.charting.charts.BarChart;
|
||||||
import com.github.mikephil.charting.components.XAxis;
|
import com.github.mikephil.charting.components.XAxis;
|
||||||
import com.github.mikephil.charting.components.YAxis;
|
import com.github.mikephil.charting.components.YAxis;
|
||||||
@@ -63,6 +60,14 @@ import com.github.mikephil.charting.data.BarEntry;
|
|||||||
import com.github.mikephil.charting.utils.ValueFormatter;
|
import com.github.mikephil.charting.utils.ValueFormatter;
|
||||||
import com.rohitss.uceh.UCEHandler;
|
import com.rohitss.uceh.UCEHandler;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.text.DecimalFormat;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Timer;
|
||||||
|
import java.util.TimerTask;
|
||||||
|
|
||||||
|
//MPAndroidChart
|
||||||
|
|
||||||
public class MainActivity extends AppCompatActivity {
|
public class MainActivity extends AppCompatActivity {
|
||||||
static final String TAG = "MainActivity";
|
static final String TAG = "MainActivity";
|
||||||
private int okColour = Color.BLUE;
|
private int okColour = Color.BLUE;
|
||||||
@@ -80,6 +85,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.
|
||||||
@@ -87,7 +93,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));
|
||||||
@@ -96,18 +102,19 @@ 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(this,serverStatusHandler);
|
mUtil = new OsdUtil(getApplicationContext(), serverStatusHandler);
|
||||||
mConnection = new SdServiceConnection(this);
|
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);
|
||||||
|
|
||||||
/* Force display of overflow menu - from stackoverflow
|
/* Force display of overflow menu - from stackoverflow
|
||||||
* "how to force use of..."
|
* "how to force use of..."
|
||||||
*/
|
*/
|
||||||
try {
|
try {
|
||||||
Log.v(TAG, "trying menubar fiddle...");
|
Log.v(TAG, "trying menubar fiddle...");
|
||||||
ViewConfiguration config = ViewConfiguration.get(this);
|
ViewConfiguration config = ViewConfiguration.get(this);
|
||||||
@@ -134,15 +141,14 @@ 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.i(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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -158,7 +164,74 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Deal with the 'Raise Alarm'
|
||||||
|
button = (Button) findViewById(R.id.manualAlarmButton);
|
||||||
|
button.setOnClickListener(new View.OnClickListener() {
|
||||||
|
public void onClick(View v) {
|
||||||
|
Log.v(TAG, "manualAlarmButton.onClick()");
|
||||||
|
// Confirmation dialog based on: https://stackoverflow.com/a/12213536/2104584
|
||||||
|
//AlertDialog.Builder builder = new AlertDialog.Builder(getBaseContext());
|
||||||
|
//builder.setTitle("Raise Alarm");
|
||||||
|
//builder.setMessage(String.format("Raise a Seizure Detected Alarm NOW?"));
|
||||||
|
//builder.setPositiveButton("YES", new DialogInterface.OnClickListener() {
|
||||||
|
// @Override
|
||||||
|
// public void onClick(DialogInterface dialog, int which) {
|
||||||
|
if (mConnection.mBound) {
|
||||||
|
mConnection.mSdServer.raiseManualAlarm();
|
||||||
|
}
|
||||||
|
// dialog.dismiss();
|
||||||
|
// }
|
||||||
|
//});
|
||||||
|
//builder.setNegativeButton("NO", new DialogInterface.OnClickListener() {
|
||||||
|
// @Override
|
||||||
|
// public void onClick(DialogInterface dialog, int which) {
|
||||||
|
// dialog.dismiss();
|
||||||
|
// }
|
||||||
|
//});
|
||||||
|
//AlertDialog alert = builder.create();
|
||||||
|
//if (!(this).isFinishing()) {
|
||||||
|
// alert.show();
|
||||||
|
//}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// 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");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -168,6 +241,7 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
public boolean onCreateOptionsMenu(Menu menu) {
|
public boolean onCreateOptionsMenu(Menu menu) {
|
||||||
Log.i(TAG, "onCreateOptionsMenu()");
|
Log.i(TAG, "onCreateOptionsMenu()");
|
||||||
getMenuInflater().inflate(R.menu.main_activity_actions, menu);
|
getMenuInflater().inflate(R.menu.main_activity_actions, menu);
|
||||||
|
MenuCompat.setGroupDividerEnabled(menu, true);
|
||||||
//mOptionsMenu = menu;
|
//mOptionsMenu = menu;
|
||||||
//if (mConnection.mSdServer.mSdDataSourceName != "Pebble") {
|
//if (mConnection.mSdServer.mSdDataSourceName != "Pebble") {
|
||||||
// Log.v(TAG,"Disabling Pebble Specific Menu Items");
|
// Log.v(TAG,"Disabling Pebble Specific Menu Items");
|
||||||
@@ -191,7 +265,7 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
mConnection.mSdServer.mSdDataSource.installWatchApp();
|
mConnection.mSdServer.mSdDataSource.installWatchApp();
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case R.id.action_accept_alarm:
|
case R.id.action_accept_alarm:
|
||||||
Log.i(TAG, "action_accept_alarm");
|
Log.i(TAG, "action_accept_alarm");
|
||||||
if (mConnection.mBound) {
|
if (mConnection.mBound) {
|
||||||
mConnection.mSdServer.acceptAlarm();
|
mConnection.mSdServer.acceptAlarm();
|
||||||
@@ -202,14 +276,14 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
Log.i(TAG, "action_sart_stop");
|
Log.i(TAG, "action_sart_stop");
|
||||||
if (mConnection.mBound) {
|
if (mConnection.mBound) {
|
||||||
Log.i(TAG, "Stopping Server");
|
Log.i(TAG, "Stopping Server");
|
||||||
mUtil.unbindFromServer(this, mConnection);
|
mUtil.unbindFromServer(getApplicationContext(), mConnection);
|
||||||
stopServer();
|
stopServer();
|
||||||
} else {
|
} else {
|
||||||
Log.i(TAG, "Starting Server");
|
Log.i(TAG, "Starting Server");
|
||||||
startServer();
|
startServer();
|
||||||
// and bind to it so we can see its data
|
// and bind to it so we can see its data
|
||||||
Log.i(TAG, "Binding to Server");
|
Log.i(TAG, "Binding to Server");
|
||||||
mUtil.bindToServer(this, mConnection);
|
mUtil.bindToServer(getApplicationContext(), mConnection);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
/* fault beep test does not work with fault timer, so disable test option.
|
/* fault beep test does not work with fault timer, so disable test option.
|
||||||
@@ -238,24 +312,44 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
mConnection.mSdServer.sendSMSAlarm();
|
mConnection.mSdServer.sendSMSAlarm();
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
case R.id.action_test_phone_alarm:
|
|
||||||
|
/*case R.id.action_test_phone_alarm:
|
||||||
Log.i(TAG, "action_test_phone_alarm");
|
Log.i(TAG, "action_test_phone_alarm");
|
||||||
if (mConnection.mBound) {
|
if (mConnection.mBound) {
|
||||||
mConnection.mSdServer.sendPhoneAlarm();
|
mConnection.mSdServer.sendPhoneAlarm();
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
case R.id.action_export:
|
*/
|
||||||
Log.i(TAG, "action_export");
|
|
||||||
|
case R.id.action_authenticate_api:
|
||||||
|
Log.i(TAG, "action_autheticate_api");
|
||||||
try {
|
try {
|
||||||
Intent i = new Intent(
|
Intent i = new Intent(
|
||||||
MainActivity.this,
|
MainActivity.this,
|
||||||
DBQueryActivity.class);
|
AuthenticateActivity.class);
|
||||||
this.startActivity(i);
|
this.startActivity(i);
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
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_logs:
|
case R.id.action_about_datasharing:
|
||||||
|
Log.i(TAG, "action_about_datasharing");
|
||||||
|
showDataSharingDialog();
|
||||||
|
return true;
|
||||||
|
/*
|
||||||
|
case R.id.action_export:
|
||||||
|
Log.i(TAG, "action_export");
|
||||||
|
try {
|
||||||
|
Intent i = new Intent(
|
||||||
|
MainActivity.this,
|
||||||
|
ExportDataActivity.class);
|
||||||
|
this.startActivity(i);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
Log.i(TAG, "exception starting export activity " + ex.toString());
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
*/
|
||||||
|
/* case R.id.action_logs:
|
||||||
Log.i(TAG, "action_logs");
|
Log.i(TAG, "action_logs");
|
||||||
try {
|
try {
|
||||||
String url = "http://"
|
String url = "http://"
|
||||||
@@ -272,17 +366,29 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
Log.i(TAG, "exception starting log manager activity " + ex.toString());
|
Log.i(TAG, "exception starting log manager activity " + ex.toString());
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
*/
|
||||||
case R.id.action_logmanager:
|
case R.id.action_logmanager:
|
||||||
Log.i(TAG, "action_logmanager");
|
Log.i(TAG, "action_logmanager");
|
||||||
try {
|
try {
|
||||||
Intent intent = new Intent(
|
Intent intent = new Intent(
|
||||||
MainActivity.this,
|
MainActivity.this,
|
||||||
LogManagerActivity.class);
|
LogManagerControlActivity.class);
|
||||||
this.startActivity(intent);
|
this.startActivity(intent);
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
Log.i(TAG, "exception starting log manager activity " + ex.toString());
|
Log.i(TAG, "exception starting log manager activity " + ex.toString());
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
case R.id.action_report_seizure:
|
||||||
|
Log.i(TAG, "action_report_seizure");
|
||||||
|
try {
|
||||||
|
Intent intent = new Intent(
|
||||||
|
MainActivity.this,
|
||||||
|
ReportSeizureActivity.class);
|
||||||
|
this.startActivity(intent);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
Log.i(TAG, "exception starting Report Seizure activity " + ex.toString());
|
||||||
|
}
|
||||||
|
return true;
|
||||||
case R.id.action_settings:
|
case R.id.action_settings:
|
||||||
Log.i(TAG, "action_settings");
|
Log.i(TAG, "action_settings");
|
||||||
try {
|
try {
|
||||||
@@ -307,7 +413,7 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
@Override
|
@Override
|
||||||
protected void onStart() {
|
protected void onStart() {
|
||||||
super.onStart();
|
super.onStart();
|
||||||
Log.i(TAG,"onStart()");
|
Log.i(TAG, "onStart()");
|
||||||
mUtil.writeToSysLogFile("MainActivity.onStart()");
|
mUtil.writeToSysLogFile("MainActivity.onStart()");
|
||||||
SharedPreferences SP = PreferenceManager
|
SharedPreferences SP = PreferenceManager
|
||||||
.getDefaultSharedPreferences(getBaseContext());
|
.getDefaultSharedPreferences(getBaseContext());
|
||||||
@@ -321,9 +427,9 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
|
|
||||||
if (mUtil.isServerRunning()) {
|
if (mUtil.isServerRunning()) {
|
||||||
mUtil.writeToSysLogFile("MainActivity.onStart - Binding to Server");
|
mUtil.writeToSysLogFile("MainActivity.onStart - Binding to Server");
|
||||||
mUtil.bindToServer(this, 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.
|
||||||
@@ -341,9 +447,9 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
@Override
|
@Override
|
||||||
protected void onStop() {
|
protected void onStop() {
|
||||||
super.onStop();
|
super.onStop();
|
||||||
Log.i(TAG,"onStop() - unbinding from server");
|
Log.i(TAG, "onStop() - unbinding from server");
|
||||||
mUtil.writeToSysLogFile("MainActivity.onStop()");
|
mUtil.writeToSysLogFile("MainActivity.onStop()");
|
||||||
mUtil.unbindFromServer(this, mConnection);
|
mUtil.unbindFromServer(getApplicationContext(), mConnection);
|
||||||
mUiTimer.cancel();
|
mUiTimer.cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -402,7 +508,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);
|
||||||
@@ -460,11 +566,17 @@ 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);
|
if (mConnection.mSdServer.mSdData.mO2Sat>0) {
|
||||||
if (mConnection.mSdServer.mSdData.mHRAlarmStanding) {
|
tv.setText(getString(R.string.HR_Equals) + mConnection.mSdServer.mSdData.mHR + " bpm\n"
|
||||||
|
+ "O2 Sat = " + mConnection.mSdServer.mSdData.mO2Sat + "%");
|
||||||
|
} else {
|
||||||
|
tv.setText(getString(R.string.HR_Equals) + mConnection.mSdServer.mSdData.mHR + " bpm\n"
|
||||||
|
+ "O2 Sat = ---%");
|
||||||
|
}
|
||||||
|
if (mConnection.mSdServer.mSdData.mHRAlarmStanding || mConnection.mSdServer.mSdData.mO2SatAlarmStanding) {
|
||||||
tv.setBackgroundColor(alarmColour);
|
tv.setBackgroundColor(alarmColour);
|
||||||
tv.setTextColor(alarmTextColour);
|
tv.setTextColor(alarmTextColour);
|
||||||
} else if (mConnection.mSdServer.mSdData.mHRFaultStanding) {
|
} else if (mConnection.mSdServer.mSdData.mHRFaultStanding || mConnection.mSdServer.mSdData.mO2SatFaultStanding) {
|
||||||
tv.setBackgroundColor(warnColour);
|
tv.setBackgroundColor(warnColour);
|
||||||
tv.setTextColor(warnTextColour);
|
tv.setTextColor(warnTextColour);
|
||||||
} else {
|
} else {
|
||||||
@@ -507,6 +619,65 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
tv.setBackgroundColor(okColour);
|
tv.setBackgroundColor(okColour);
|
||||||
tv.setTextColor(okTextColour);
|
tv.setTextColor(okTextColour);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
// Populate the Data Sharing Status Box
|
||||||
|
// We start off with it set to OK, then check for several different abnormal conditions
|
||||||
|
// in turn - the last one that is active is the one that is displayed.
|
||||||
|
tv = (TextView) findViewById(R.id.remoteDbTv);
|
||||||
|
tv.setText(getString(R.string.data_sharing_status)
|
||||||
|
+ ": "
|
||||||
|
+ getString(R.string.data_sharing_setup_ok));
|
||||||
|
tv.setBackgroundColor(okColour);
|
||||||
|
tv.setTextColor(okTextColour);
|
||||||
|
|
||||||
|
if (!mConnection.mSdServer.mLm.mWac.checkServerConnection()) {
|
||||||
|
// Problem connecting to server
|
||||||
|
tv = (TextView) findViewById(R.id.remoteDbTv);
|
||||||
|
tv.setText(getString(R.string.data_sharing_status)
|
||||||
|
+ ": "
|
||||||
|
+ getString(R.string.error_connecting_to_server));
|
||||||
|
tv.setBackgroundColor(warnColour);
|
||||||
|
tv.setTextColor(warnTextColour);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mConnection.mSdServer.mLogDataRemoteMobile && mUtil.isMobileDataActive()) {
|
||||||
|
// We are on mobile internet but we are set to not upload over mobile data.
|
||||||
|
tv.setText(getString(R.string.data_sharing_status)
|
||||||
|
+ ": "
|
||||||
|
+ getString(R.string.not_updating_mobile));
|
||||||
|
tv.setBackgroundColor(warnColour);
|
||||||
|
tv.setTextColor(warnTextColour);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mUtil.isNetworkConnected()) {
|
||||||
|
// No network connection
|
||||||
|
tv.setText(getString(R.string.data_sharing_status)
|
||||||
|
+ ": "
|
||||||
|
+ getString(R.string.not_updating_no_network));
|
||||||
|
tv.setBackgroundColor(warnColour);
|
||||||
|
tv.setTextColor(warnTextColour);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mConnection.mSdServer.mLm.mWac.isLoggedIn()) {
|
||||||
|
// Not Logged In
|
||||||
|
tv.setText(getString(R.string.data_sharing_status)
|
||||||
|
+ ": "
|
||||||
|
+ getString(R.string.not_logged_in));
|
||||||
|
tv.setBackgroundColor(warnColour);
|
||||||
|
tv.setTextColor(warnTextColour);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mConnection.mSdServer.mLogData) {
|
||||||
|
// Not set to share data
|
||||||
|
tv.setText(getString(R.string.data_sharing_status)
|
||||||
|
+ ": "
|
||||||
|
+ getString(R.string.not_sharing_logged_data));
|
||||||
|
tv.setBackgroundColor(warnColour);
|
||||||
|
tv.setTextColor(warnTextColour);
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////
|
||||||
// Set ProgressBars to show margin to alarm.
|
// Set ProgressBars to show margin to alarm.
|
||||||
long powerPc;
|
long powerPc;
|
||||||
if (mConnection.mSdServer.mSdData.alarmThresh != 0)
|
if (mConnection.mSdServer.mSdData.alarmThresh != 0)
|
||||||
@@ -532,9 +703,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;
|
||||||
@@ -589,21 +760,20 @@ 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) + " --- 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else { // Not bound to server
|
} else { // Not bound to server
|
||||||
tv = (TextView) findViewById(R.id.alarmTv);
|
tv = (TextView) findViewById(R.id.alarmTv);
|
||||||
tv.setText(R.string.Dashes);
|
tv.setText(R.string.Dashes);
|
||||||
@@ -620,17 +790,22 @@ 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.setTextColor(warnTextColour);
|
||||||
|
|
||||||
|
tv = (TextView) findViewById(R.id.remoteDbTv);
|
||||||
|
tv.setText("---");
|
||||||
tv.setBackgroundColor(warnColour);
|
tv.setBackgroundColor(warnColour);
|
||||||
tv.setTextColor(warnTextColour);
|
tv.setTextColor(warnTextColour);
|
||||||
}
|
}
|
||||||
@@ -647,12 +822,12 @@ 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 {
|
||||||
acceptAlarmButton.setText(R.string.AcceptAlarm);
|
acceptAlarmButton.setText(R.string.AcceptAlarm);
|
||||||
acceptAlarmButton.setBackgroundColor(Color.DKGRAY);
|
acceptAlarmButton.setBackgroundColor(Color.GRAY);
|
||||||
if (mConnection.mBound)
|
if (mConnection.mBound)
|
||||||
if ((mConnection.mSdServer.isLatchAlarms())
|
if ((mConnection.mSdServer.isLatchAlarms())
|
||||||
|| mConnection.mSdServer.mSdData.mFallActive) {
|
|| mConnection.mSdServer.mSdData.mFallActive) {
|
||||||
@@ -673,15 +848,17 @@ 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");
|
||||||
+ getString(R.string.PressToReEnable));
|
cancelAudibleButton.setEnabled(true);
|
||||||
} else {
|
} else {
|
||||||
if (mConnection.mSdServer.mAudibleAlarm) {
|
if (mConnection.mSdServer.mAudibleAlarm) {
|
||||||
cancelAudibleButton.setText(R.string.CancelAudibleAlarms);
|
cancelAudibleButton.setText(R.string.CancelAudibleAlarms);
|
||||||
|
cancelAudibleButton.setEnabled(true);
|
||||||
} else {
|
} else {
|
||||||
cancelAudibleButton.setText(R.string.AudibleAlarmsOff);
|
cancelAudibleButton.setText(R.string.AudibleAlarmsOff);
|
||||||
|
cancelAudibleButton.setEnabled(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -696,17 +873,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++) {
|
||||||
@@ -718,20 +894,20 @@ 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) {
|
||||||
DecimalFormat format = new DecimalFormat("####");
|
DecimalFormat format = new DecimalFormat("####");
|
||||||
return format.format(v);
|
return format.format(v);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
mChart.setData(barData);
|
mChart.setData(barData);
|
||||||
|
|
||||||
// format the axes
|
// format the axes
|
||||||
XAxis xAxis = mChart.getXAxis();
|
XAxis xAxis = mChart.getXAxis();
|
||||||
@@ -764,7 +940,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();
|
||||||
@@ -775,14 +951,14 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
@Override
|
@Override
|
||||||
protected void onPause() {
|
protected void onPause() {
|
||||||
super.onPause();
|
super.onPause();
|
||||||
Log.i(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.i(TAG,"onResume()");
|
Log.i(TAG, "onResume()");
|
||||||
mUtil.writeToSysLogFile("MainActivity.onResume()");
|
mUtil.writeToSysLogFile("MainActivity.onResume()");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -795,16 +971,69 @@ 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.setNeutralButton(getString(R.string.closeBtnTxt), new DialogInterface.OnClickListener() {
|
||||||
|
public void onClick(DialogInterface dialog, int id) {
|
||||||
|
dialog.cancel();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
builder.setPositiveButton("Privacy Policy", new DialogInterface.OnClickListener() {
|
||||||
|
public void onClick(DialogInterface dialog, int id) {
|
||||||
|
dialog.cancel();
|
||||||
|
String url = OsdUtil.PRIVACY_POLICY_URL;
|
||||||
|
Intent i = new Intent(Intent.ACTION_VIEW);
|
||||||
|
i.setData(Uri.parse(url));
|
||||||
|
startActivity(i);
|
||||||
|
dialog.cancel();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
builder.setNegativeButton("Data Sharing", new DialogInterface.OnClickListener() {
|
||||||
|
public void onClick(DialogInterface dialog, int id) {
|
||||||
|
dialog.cancel();
|
||||||
|
String url = OsdUtil.DATA_SHARING_URL;
|
||||||
|
Intent i = new Intent(Intent.ACTION_VIEW);
|
||||||
|
i.setData(Uri.parse(url));
|
||||||
|
startActivity(i);
|
||||||
|
dialog.cancel();
|
||||||
|
}
|
||||||
|
});
|
||||||
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) {
|
||||||
Log.i(TAG, "Message=" + message.toString());
|
Log.i(TAG, "Message=" + message.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package uk.org.openseizuredetector;
|
package uk.org.openseizuredetector;
|
||||||
|
|
||||||
import android.app.AlertDialog;
|
|
||||||
import android.app.Dialog;
|
import android.app.Dialog;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
@@ -11,7 +10,8 @@ import android.os.Environment;
|
|||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
import android.os.StatFs;
|
import android.os.StatFs;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.WindowManager;
|
|
||||||
|
import androidx.appcompat.app.AlertDialog;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
|
|||||||
@@ -27,93 +27,75 @@ package uk.org.openseizuredetector;
|
|||||||
import android.Manifest;
|
import android.Manifest;
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.app.ActivityManager;
|
import android.app.ActivityManager;
|
||||||
import android.content.ComponentName;
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.IntentFilter;
|
|
||||||
import android.content.ServiceConnection;
|
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.content.pm.ActivityInfo;
|
|
||||||
import android.content.pm.ApplicationInfo;
|
|
||||||
import android.content.pm.FeatureInfo;
|
|
||||||
import android.content.pm.InstrumentationInfo;
|
|
||||||
import android.content.pm.PackageInfo;
|
import android.content.pm.PackageInfo;
|
||||||
import android.content.pm.PackageInstaller;
|
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.content.pm.PermissionGroupInfo;
|
import android.database.Cursor;
|
||||||
import android.content.pm.PermissionInfo;
|
import android.database.DatabaseUtils;
|
||||||
import android.content.pm.ProviderInfo;
|
import android.database.SQLException;
|
||||||
import android.content.pm.ResolveInfo;
|
import android.database.sqlite.SQLiteDatabase;
|
||||||
import android.content.pm.ServiceInfo;
|
import android.database.sqlite.SQLiteOpenHelper;
|
||||||
import android.content.res.Resources;
|
|
||||||
import android.content.res.XmlResourceParser;
|
|
||||||
import android.graphics.Rect;
|
|
||||||
import android.graphics.drawable.Drawable;
|
|
||||||
import android.net.ConnectivityManager;
|
import android.net.ConnectivityManager;
|
||||||
import android.net.NetworkInfo;
|
import android.net.NetworkInfo;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
import android.os.AsyncTask;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Environment;
|
import android.os.Environment;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.IBinder;
|
|
||||||
import android.os.UserHandle;
|
|
||||||
import android.preference.PreferenceManager;
|
import android.preference.PreferenceManager;
|
||||||
import android.support.annotation.NonNull;
|
|
||||||
import android.support.annotation.Nullable;
|
|
||||||
import android.support.v4.app.ActivityCompat;
|
|
||||||
import android.support.v4.content.ContextCompat;
|
|
||||||
import android.text.format.Time;
|
import android.text.format.Time;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.MenuItem;
|
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
import androidx.core.app.ActivityCompat;
|
||||||
|
import androidx.core.content.ContextCompat;
|
||||||
|
|
||||||
import org.apache.http.conn.util.InetAddressUtils;
|
import org.apache.http.conn.util.InetAddressUtils;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileWriter;
|
import java.io.FileWriter;
|
||||||
import java.io.IOException;
|
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.net.NetworkInterface;
|
import java.net.NetworkInterface;
|
||||||
import java.util.AbstractList;
|
import java.text.ParseException;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Arrays;
|
||||||
|
import java.util.Date;
|
||||||
import java.util.Enumeration;
|
import java.util.Enumeration;
|
||||||
import java.util.List;
|
import java.util.HashMap;
|
||||||
import java.util.RandomAccess;
|
import java.util.function.Consumer;
|
||||||
import java.util.concurrent.RunnableFuture;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* OsdUtil - OpenSeizureDetector Utilities
|
* OsdUtil - OpenSeizureDetector Utilities
|
||||||
* Deals with starting and stopping the background service and binding to it to receive data.
|
* Deals with starting and stopping the background service and binding to it to receive data.
|
||||||
*/
|
*/
|
||||||
public class OsdUtil implements ActivityCompat.OnRequestPermissionsResultCallback {
|
public class OsdUtil {
|
||||||
|
public final static String PRIVACY_POLICY_URL = "https://www.openseizuredetector.org.uk/?page_id=1415";
|
||||||
|
public final static String DATA_SHARING_URL = "https://www.openseizuredetector.org.uk/?page_id=1818";
|
||||||
|
|
||||||
private final String SYSLOG = "SysLog";
|
private final String SYSLOG = "SysLog";
|
||||||
private final String ALARMLOG = "AlarmLog";
|
private final String ALARMLOG = "AlarmLog";
|
||||||
private final String DATALOG = "DataLog";
|
private final String DATALOG = "DataLog";
|
||||||
|
|
||||||
private final String[] REQUIRED_PERMISSIONS = {
|
|
||||||
Manifest.permission.WRITE_EXTERNAL_STORAGE,
|
|
||||||
Manifest.permission.WAKE_LOCK,
|
|
||||||
};
|
|
||||||
|
|
||||||
private final String[] SMS_PERMISSIONS = {
|
|
||||||
Manifest.permission.SEND_SMS,
|
|
||||||
Manifest.permission.ACCESS_FINE_LOCATION,
|
|
||||||
Manifest.permission.READ_PHONE_STATE,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Based on http://stackoverflow.com/questions/7440473/android-how-to-check-if-the-intent-service-is-still-running-or-has-stopped-running
|
* Based on http://stackoverflow.com/questions/7440473/android-how-to-check-if-the-intent-service-is-still-running-or-has-stopped-running
|
||||||
*/
|
*/
|
||||||
private Context mContext;
|
private static Context mContext;
|
||||||
private Handler mHandler;
|
private Handler mHandler;
|
||||||
private String TAG = "OsdUtil";
|
private static String TAG = "OsdUtil";
|
||||||
private boolean mLogAlarms = true;
|
private boolean mLogAlarms = true;
|
||||||
private boolean mLogSystem = true;
|
private boolean mLogSystem = true;
|
||||||
private boolean mLogData = true;
|
private boolean mLogData = true;
|
||||||
private boolean mPermissionsRequested = false;
|
private boolean mPermissionsRequested = false;
|
||||||
private boolean mSMSPermissionsRequested = false;
|
private boolean mSMSPermissionsRequested = false;
|
||||||
|
private static final String mSysLogTableName = "SysLog";
|
||||||
|
//private LogManager mLm;
|
||||||
|
static private SQLiteDatabase mSysLogDb = null; // SQLite Database for data and log entries.
|
||||||
|
private final static Long mMinPruneInterval = new Long(5 * 60 * 1000); // minimum time between syslog pruning is 5 minutes
|
||||||
|
private static Long mLastPruneMillis = new Long(0); // Record of the last time we pruned the syslog db.
|
||||||
|
|
||||||
private static int mNbound = 0;
|
private static int mNbound = 0;
|
||||||
|
|
||||||
@@ -121,6 +103,9 @@ public class OsdUtil implements ActivityCompat.OnRequestPermissionsResultCallbac
|
|||||||
mContext = context;
|
mContext = context;
|
||||||
mHandler = handler;
|
mHandler = handler;
|
||||||
updatePrefs();
|
updatePrefs();
|
||||||
|
//Log.i(TAG,"Creating Log Manager instance");
|
||||||
|
//mLm = new LogManager(mContext,false,false,null,0,0,false,0);
|
||||||
|
openDb();
|
||||||
writeToSysLogFile("OsdUtil() - initialised");
|
writeToSysLogFile("OsdUtil() - initialised");
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -136,8 +121,8 @@ public class OsdUtil implements ActivityCompat.OnRequestPermissionsResultCallbac
|
|||||||
try {
|
try {
|
||||||
mLogAlarms = SP.getBoolean("LogAlarms", true);
|
mLogAlarms = SP.getBoolean("LogAlarms", true);
|
||||||
Log.v(TAG, "updatePrefs() - mLogAlarms = " + mLogAlarms);
|
Log.v(TAG, "updatePrefs() - mLogAlarms = " + mLogAlarms);
|
||||||
mLogData = SP.getBoolean("LogData", false);
|
mLogData = SP.getBoolean("LogData", true);
|
||||||
Log.v(TAG, "updatePrefs() - mLogData = " + mLogData);
|
Log.v(TAG, "OsdUtil.updatePrefs() - mLogData = " + mLogData);
|
||||||
mLogSystem = SP.getBoolean("LogSystem", true);
|
mLogSystem = SP.getBoolean("LogSystem", true);
|
||||||
Log.v(TAG, "updatePrefs() - mLogSystem = " + mLogSystem);
|
Log.v(TAG, "updatePrefs() - mLogSystem = " + mLogSystem);
|
||||||
|
|
||||||
@@ -170,7 +155,7 @@ public class OsdUtil implements ActivityCompat.OnRequestPermissionsResultCallbac
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (nServers != 0) {
|
if (nServers != 0) {
|
||||||
Log.v(TAG, "isServerRunning() - " + nServers + " instances are running");
|
//Log.v(TAG, "isServerRunning() - " + nServers + " instances are running");
|
||||||
return true;
|
return true;
|
||||||
} else
|
} else
|
||||||
return false;
|
return false;
|
||||||
@@ -199,7 +184,7 @@ public class OsdUtil implements ActivityCompat.OnRequestPermissionsResultCallbac
|
|||||||
* Stop the SdServer service
|
* Stop the SdServer service
|
||||||
*/
|
*/
|
||||||
public void stopServer() {
|
public void stopServer() {
|
||||||
Log.d(TAG, "OsdUtil.stopServer() - stopping Server... - mNbound=" + mNbound);
|
Log.i(TAG, "OsdUtil.stopServer() - stopping Server... - mNbound=" + mNbound);
|
||||||
writeToSysLogFile("stopserver() - stopping server");
|
writeToSysLogFile("stopserver() - stopping server");
|
||||||
|
|
||||||
// then send an Intent to stop the service.
|
// then send an Intent to stop the service.
|
||||||
@@ -213,7 +198,7 @@ public class OsdUtil implements ActivityCompat.OnRequestPermissionsResultCallbac
|
|||||||
/**
|
/**
|
||||||
* bind an activity to to an already running server.
|
* 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");
|
Log.i(TAG, "OsdUtil.bindToServer() - binding to SdServer");
|
||||||
writeToSysLogFile("bindToServer() - binding to SdServer");
|
writeToSysLogFile("bindToServer() - binding to SdServer");
|
||||||
Intent intent = new Intent(sdServiceConnection.mContext, SdServer.class);
|
Intent intent = new Intent(sdServiceConnection.mContext, SdServer.class);
|
||||||
@@ -225,7 +210,7 @@ public class OsdUtil implements ActivityCompat.OnRequestPermissionsResultCallbac
|
|||||||
/**
|
/**
|
||||||
* unbind an activity from server
|
* unbind an activity from server
|
||||||
*/
|
*/
|
||||||
public void unbindFromServer(Activity activity, SdServiceConnection sdServiceConnection) {
|
public void unbindFromServer(Context activity, SdServiceConnection sdServiceConnection) {
|
||||||
// unbind this activity from the service if it is bound.
|
// unbind this activity from the service if it is bound.
|
||||||
if (sdServiceConnection.mBound) {
|
if (sdServiceConnection.mBound) {
|
||||||
Log.i(TAG, "unbindFromServer() - unbinding");
|
Log.i(TAG, "unbindFromServer() - unbinding");
|
||||||
@@ -301,6 +286,7 @@ public class OsdUtil implements ActivityCompat.OnRequestPermissionsResultCallbac
|
|||||||
// return true if we are using mobile data, otherwise return false
|
// return true if we are using mobile data, otherwise return false
|
||||||
ConnectivityManager cm = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
|
ConnectivityManager cm = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||||
NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
|
NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
|
||||||
|
if (activeNetwork == null) return false;
|
||||||
if (activeNetwork.getType() == ConnectivityManager.TYPE_MOBILE) {
|
if (activeNetwork.getType() == ConnectivityManager.TYPE_MOBILE) {
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
@@ -312,7 +298,11 @@ public class OsdUtil implements ActivityCompat.OnRequestPermissionsResultCallbac
|
|||||||
// return true if we have a network connection, otherwise false.
|
// return true if we have a network connection, otherwise false.
|
||||||
ConnectivityManager cm = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
|
ConnectivityManager cm = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||||
NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
|
NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
|
||||||
return (activeNetwork.isConnected());
|
if (activeNetwork != null) {
|
||||||
|
return (activeNetwork.isConnected());
|
||||||
|
} else {
|
||||||
|
return (false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -331,16 +321,18 @@ public class OsdUtil implements ActivityCompat.OnRequestPermissionsResultCallbac
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Write a message to the system log file, provided mLogSystem is true.
|
* Write a message to the system log database.
|
||||||
*
|
*
|
||||||
* @param msgStr
|
* @param msgStr
|
||||||
*/
|
*/
|
||||||
public void writeToSysLogFile(String msgStr) {
|
public void writeToSysLogFile(String msgStr,String logType) {
|
||||||
if (mLogSystem)
|
writeLogEntryToLocalDb(msgStr,logType);
|
||||||
writeToLogFile(SYSLOG, msgStr);
|
|
||||||
else
|
|
||||||
Log.v(TAG, "writeToSysLogFile - mLogSystem False so not writing");
|
|
||||||
}
|
}
|
||||||
|
public void writeToSysLogFile(String msgStr) {
|
||||||
|
writeLogEntryToLocalDb(msgStr,"v");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Write a message to the alarm log file, provided mLogAlarms is true.
|
* Write a message to the alarm log file, provided mLogAlarms is true.
|
||||||
@@ -462,82 +454,289 @@ public class OsdUtil implements ActivityCompat.OnRequestPermissionsResultCallbac
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean arePermissionsOK() {
|
/**
|
||||||
boolean allOk = true;
|
* string2date - returns a Date object represented by string dateStr
|
||||||
Log.v(TAG, "arePermissionsOK");
|
* It first attempts to parse it as a long integer, in which case it is assumed to
|
||||||
for (int i = 0; i < REQUIRED_PERMISSIONS.length; i++) {
|
* be a unix timestamp.
|
||||||
if (ContextCompat.checkSelfPermission(mContext, REQUIRED_PERMISSIONS[i])
|
* If that fails it attempts to parse it as yyyy-MM-dd'T'HH:mm:ss'Z' format.
|
||||||
!= PackageManager.PERMISSION_GRANTED) {
|
* @param dateStr String reprenting a date
|
||||||
Log.i(TAG, REQUIRED_PERMISSIONS[i] + " Permission Not Granted");
|
* @return Date object or null if parsing fails.
|
||||||
allOk = false;
|
*/
|
||||||
|
public Date string2date(String dateStr) {
|
||||||
|
Date dataTime = null;
|
||||||
|
try {
|
||||||
|
Long tstamp = Long.parseLong(dateStr);
|
||||||
|
dataTime = new Date(tstamp);
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
Log.v(TAG, "remoteEventsAdapter.getView: Error Parsing dataDate as Long: " + e.getLocalizedMessage()+" trying as string");
|
||||||
|
try {
|
||||||
|
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
|
||||||
|
dataTime = dateFormat.parse(dateStr);
|
||||||
|
} catch (ParseException e2) {
|
||||||
|
Log.e(TAG, "remoteEventsAdapter.getView: Error Parsing dataDate " + e2.getLocalizedMessage());
|
||||||
|
dataTime = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return allOk;
|
return(dataTime);
|
||||||
}
|
|
||||||
|
|
||||||
public boolean areSMSPermissionsOK() {
|
|
||||||
boolean allOk = true;
|
|
||||||
Log.v(TAG, "areSMSPermissionsOK()");
|
|
||||||
for (int i = 0; i < SMS_PERMISSIONS.length; i++) {
|
|
||||||
if (ContextCompat.checkSelfPermission(mContext, SMS_PERMISSIONS[i])
|
|
||||||
!= PackageManager.PERMISSION_GRANTED) {
|
|
||||||
Log.i(TAG, SMS_PERMISSIONS[i] + " Permission Not Granted");
|
|
||||||
allOk = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return allOk;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void requestPermissions(Activity activity) {
|
public final int ALARM_STATUS_WARNING = 1;
|
||||||
if (mPermissionsRequested) {
|
public final int ALARM_STATUS_ALARM = 2;
|
||||||
Log.i(TAG, "requestPermissions() - request already sent - not doing anything");
|
public final int ALARM_STATUS_FALL = 3;
|
||||||
} else {
|
public final int ALARM_STATUS_MANUAL = 5;
|
||||||
Log.i(TAG, "requestPermissions() - requesting permissions");
|
|
||||||
for (int i = 0; i < REQUIRED_PERMISSIONS.length; i++) {
|
public String alarmStatusToString(int eventAlarmStatus) {
|
||||||
if (ActivityCompat.shouldShowRequestPermissionRationale(activity,
|
String retVal = "Unknown";
|
||||||
REQUIRED_PERMISSIONS[i])) {
|
switch (eventAlarmStatus) {
|
||||||
Log.i(TAG, "shouldShowRationale for permission" + REQUIRED_PERMISSIONS[i]);
|
case ALARM_STATUS_WARNING: // Warning
|
||||||
|
retVal = "WARNING";
|
||||||
|
break;
|
||||||
|
case ALARM_STATUS_ALARM: // alarm
|
||||||
|
retVal = "ALARM";
|
||||||
|
break;
|
||||||
|
case ALARM_STATUS_FALL: // fall
|
||||||
|
retVal = "FALL";
|
||||||
|
break;
|
||||||
|
case ALARM_STATUS_MANUAL: // Manual alarm
|
||||||
|
retVal = "MANUAL ALARM";
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
return(retVal);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean openDb() {
|
||||||
|
Log.d(TAG, "openDb");
|
||||||
|
try {
|
||||||
|
if (mSysLogDb == null) {
|
||||||
|
Log.i(TAG,"openDb: mSysLogDb is null - initialising");
|
||||||
|
mSysLogDb = new OsdSysLogHelper(mContext).getWritableDatabase();
|
||||||
|
} else {
|
||||||
|
Log.i(TAG,"openDb: mSysLogDb has been initialised already so not doing anything");
|
||||||
|
}
|
||||||
|
if (!checkTableExists(mSysLogDb, mSysLogTableName)) {
|
||||||
|
Log.e(TAG, "ERROR - Table "+mSysLogTableName+" does not exist");
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
Log.d(TAG, "table " + mSysLogTableName + " exists ok");
|
||||||
|
}
|
||||||
|
} catch (SQLException e) {
|
||||||
|
Log.e(TAG, "Failed to open Database: " + e.toString());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean checkTableExists(SQLiteDatabase osdDb, String osdTableName) {
|
||||||
|
Cursor c = null;
|
||||||
|
boolean tableExists = false;
|
||||||
|
Log.d(TAG, "checkTableExists()");
|
||||||
|
try {
|
||||||
|
c = osdDb.query(osdTableName, null,
|
||||||
|
null, null, null, null, null);
|
||||||
|
tableExists = true;
|
||||||
|
c.close();
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.d(TAG, osdTableName + " doesn't exist :(((");
|
||||||
|
}
|
||||||
|
return tableExists;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write syslog string to local database
|
||||||
|
* FIXME - I am sure we should not be using raw SQL Srings to do this!
|
||||||
|
*/
|
||||||
|
public void writeLogEntryToLocalDb(String logText, String statusVal) {
|
||||||
|
Log.v(TAG, "writeLogEntryToLocalDb()");
|
||||||
|
Date curDate = new Date();
|
||||||
|
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||||
|
|
||||||
|
String dateStr = dateFormat.format(curDate);
|
||||||
|
String SQLStr = "SQLStr";
|
||||||
|
|
||||||
|
try {
|
||||||
|
SQLStr = "INSERT INTO " + mSysLogTableName
|
||||||
|
+ "(dataTime, logLevel, dataJSON, uploaded)"
|
||||||
|
+ " VALUES("
|
||||||
|
+ "'" + dateStr + "',"
|
||||||
|
+ DatabaseUtils.sqlEscapeString(statusVal) + ","
|
||||||
|
+ DatabaseUtils.sqlEscapeString(logText) + ","
|
||||||
|
+ 0
|
||||||
|
+ ")";
|
||||||
|
mSysLogDb.execSQL(SQLStr);
|
||||||
|
Log.v(TAG, "syslog entry written to database: "+logText);
|
||||||
|
pruneSysLogDb();
|
||||||
|
|
||||||
|
} catch (SQLException e) {
|
||||||
|
Log.e(TAG, "writeLogEngryToLocalDb(): Error Writing Data: " + e.toString());
|
||||||
|
Log.e(TAG, "SQLStr was " + SQLStr);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return an array list of objects representing the syslog entries in the database by calling the specified callback function.
|
||||||
|
*
|
||||||
|
* @return True on successful start or false if call fails.
|
||||||
|
*/
|
||||||
|
public boolean getSysLogList(Consumer<ArrayList<HashMap<String, String>>> callback) {
|
||||||
|
Log.v(TAG, "getSysLogList");
|
||||||
|
ArrayList<HashMap<String, String>> eventsList = new ArrayList<>();
|
||||||
|
|
||||||
|
String whereClause = "";
|
||||||
|
String[] whereArgs = {};
|
||||||
|
String[] columns = {"*"};
|
||||||
|
new SelectQueryTask(mSysLogTableName, columns, null, null,
|
||||||
|
null, null, "dataTime DESC", (Cursor cursor) -> {
|
||||||
|
Log.v(TAG, "getSysLogList - returned " + cursor);
|
||||||
|
if (cursor != null) {
|
||||||
|
Log.v(TAG, "getSysLogList - returned " + cursor.getCount() + " records");
|
||||||
|
while (!cursor.isAfterLast()) {
|
||||||
|
HashMap<String, String> event = new HashMap<>();
|
||||||
|
//event.put("id", cursor.getString(cursor.getColumnIndex("id")));
|
||||||
|
event.put("dataTime", cursor.getString(cursor.getColumnIndex("dataTime")));
|
||||||
|
String loglevel = cursor.getString(cursor.getColumnIndex("logLevel"));
|
||||||
|
event.put("loglevel", loglevel);
|
||||||
|
event.put("dataJSON", cursor.getString(cursor.getColumnIndex("dataJSON")));
|
||||||
|
//event.put("dataJSON", cursor.getString(cursor.getColumnIndex("dataJSON")));
|
||||||
|
eventsList.add(event);
|
||||||
|
cursor.moveToNext();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ActivityCompat.requestPermissions(activity,
|
callback.accept(eventsList);
|
||||||
REQUIRED_PERMISSIONS,
|
}).execute();
|
||||||
42);
|
return (true);
|
||||||
mPermissionsRequested = true;
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Executes the sqlite query (=SELECT statement)
|
||||||
|
* Use as new SelectQueryTask(xxx,xxx,xx,xxxx).execute()
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static private class SelectQueryTask extends AsyncTask<Void, Void, Cursor> {
|
||||||
|
// Based on https://stackoverflow.com/a/21120199/2104584
|
||||||
|
String mTable;
|
||||||
|
String[] mColumns;
|
||||||
|
String mSelection;
|
||||||
|
String[] mSelectionArgs;
|
||||||
|
String mGroupBy;
|
||||||
|
String mHaving;
|
||||||
|
String mOrderBy;
|
||||||
|
Consumer<Cursor> mCallback;
|
||||||
|
|
||||||
|
//query(String table, String[] columns, String selection, String[] selectionArgs,
|
||||||
|
// String groupBy, String having, String orderBy)
|
||||||
|
SelectQueryTask(String table, String[] columns, String selection, String[] selectionArgs,
|
||||||
|
String groupBy, String having, String orderBy, Consumer<Cursor> callback) {
|
||||||
|
// list all the parameters like in normal class define
|
||||||
|
this.mTable = table;
|
||||||
|
this.mColumns = columns;
|
||||||
|
this.mSelection = selection;
|
||||||
|
this.mSelectionArgs = selectionArgs;
|
||||||
|
this.mGroupBy = groupBy;
|
||||||
|
this.mHaving = having;
|
||||||
|
this.mOrderBy = orderBy;
|
||||||
|
this.mCallback = callback;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Cursor doInBackground(Void... params) {
|
||||||
|
Log.v(TAG, "runSelect.doInBackground()");
|
||||||
|
Log.v(TAG, "SelectQueryTask.doInBackground: mTable=" + mTable + ", mColumns=" + Arrays.toString(mColumns)
|
||||||
|
+ ", mSelection=" + mSelection + ", mSelectionArgs=" + Arrays.toString(mSelectionArgs) + ", mGroupBy=" + mGroupBy
|
||||||
|
+ ", mHaving =" + mHaving + ", mOrderBy=" + mOrderBy);
|
||||||
|
|
||||||
|
try {
|
||||||
|
Cursor resultSet = mSysLogDb.query(mTable, mColumns, mSelection,
|
||||||
|
mSelectionArgs, mGroupBy, mHaving, mOrderBy);
|
||||||
|
resultSet.moveToFirst();
|
||||||
|
return (resultSet);
|
||||||
|
} catch (SQLException e) {
|
||||||
|
Log.e(TAG, "SelectQueryTask.doInBackground(): Error selecting Data: " + e.toString());
|
||||||
|
return (null);
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
Log.e(TAG, "SelectQueryTask.doInBackground(): Illegal Argument Exception: " + e.toString());
|
||||||
|
return (null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPostExecute(final Cursor result) {
|
||||||
|
mCallback.accept(result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void requestSMSPermissions(Activity activity) {
|
|
||||||
if (mSMSPermissionsRequested) {
|
|
||||||
Log.i(TAG, "requestSMSPermissions() - request already sent - not doing anything");
|
/**
|
||||||
|
* pruneSysLogDb() removes data that is older than 7 days
|
||||||
|
*/
|
||||||
|
public int pruneSysLogDb() {
|
||||||
|
//Log.v(TAG, "pruneSysLogDb()");
|
||||||
|
int retVal;
|
||||||
|
long currentDateMillis = new Date().getTime();
|
||||||
|
if (currentDateMillis > mLastPruneMillis + mMinPruneInterval) {
|
||||||
|
mLastPruneMillis = currentDateMillis;
|
||||||
|
// FIXME - change this to something sensible like 7 days after testing
|
||||||
|
long endDateMillis = currentDateMillis - 5 * 60 * 1000;
|
||||||
|
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||||
|
String endDateStr = dateFormat.format(new Date(endDateMillis));
|
||||||
|
Log.v(TAG, "pruneSysLogDb - endDateStr=" + endDateStr);
|
||||||
|
try {
|
||||||
|
String selectStr = "DataTime<=?";
|
||||||
|
String[] selectArgs = {endDateStr};
|
||||||
|
retVal = mSysLogDb.delete(mSysLogTableName, selectStr, selectArgs);
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, "Error deleting log entries" + e.toString());
|
||||||
|
retVal = 0;
|
||||||
|
}
|
||||||
|
if (retVal > 0) {
|
||||||
|
Log.v(TAG, String.format("pruneSysLogDb() - deleted %d records", retVal));
|
||||||
|
}
|
||||||
|
return (retVal);
|
||||||
} else {
|
} else {
|
||||||
Log.i(TAG, "requestSMSPermissions() - requesting permissions");
|
return (0);
|
||||||
for (int i = 0; i < SMS_PERMISSIONS.length; i++) {
|
|
||||||
if (ActivityCompat.shouldShowRequestPermissionRationale(activity,
|
|
||||||
SMS_PERMISSIONS[i])) {
|
|
||||||
Log.i(TAG, "shouldShowRationale for permission" + SMS_PERMISSIONS[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ActivityCompat.requestPermissions(activity,
|
|
||||||
SMS_PERMISSIONS,
|
|
||||||
43);
|
|
||||||
mSMSPermissionsRequested = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
public static class OsdSysLogHelper extends SQLiteOpenHelper {
|
||||||
public void onRequestPermissionsResult(int requestCode,
|
// If you change the database schema, you must increment the database version.
|
||||||
String permissions[], int[] grantResults) {
|
public static final int DATABASE_VERSION = 1;
|
||||||
Log.i(TAG, "onRequestPermissionsResult - Permission" + permissions + " = " + grantResults);
|
public static final String DATABASE_NAME = "OsdSysLog.db";
|
||||||
showToast(mContext.getString(R.string.RestartingServerMsg));
|
private static final String TAG = "LogManager.OsdSysLogHelper";
|
||||||
stopServer();
|
|
||||||
// Wait 0.1 second to give the server chance to shutdown, then re-start it
|
|
||||||
mHandler.postDelayed(new Runnable() {
|
|
||||||
public void run() {
|
|
||||||
startServer();
|
|
||||||
}
|
|
||||||
}, 100);
|
|
||||||
|
|
||||||
|
public OsdSysLogHelper(Context context) {
|
||||||
|
super(context, DATABASE_NAME, null, DATABASE_VERSION);
|
||||||
|
Log.d(TAG, "OsdSysLogHelper constructor");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onCreate(SQLiteDatabase db) {
|
||||||
|
Log.i(TAG, "onCreate - TableName=" + mSysLogTableName);
|
||||||
|
String SQLStr = "CREATE TABLE IF NOT EXISTS " + mSysLogTableName + "("
|
||||||
|
+ "id INTEGER PRIMARY KEY,"
|
||||||
|
+ "dataTime DATETIME,"
|
||||||
|
+ "logLevel TEXT,"
|
||||||
|
+ "dataJSON TEXT,"
|
||||||
|
+ "uploaded INT"
|
||||||
|
+ ");";
|
||||||
|
db.execSQL(SQLStr);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
|
||||||
|
// This database is only a cache for online data, so its upgrade policy is
|
||||||
|
// to simply to discard the data and start over
|
||||||
|
Log.i(TAG,"onUpgrade()");
|
||||||
|
db.execSQL("Drop table if exists " + mSysLogTableName + ";");
|
||||||
|
onCreate(db);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
|
||||||
|
Log.i(TAG,"onDowngrade()");
|
||||||
|
onUpgrade(db, oldVersion, newVersion);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -75,7 +75,8 @@ public class PrefActivity extends PreferenceActivity implements SharedPreference
|
|||||||
.getDefaultSharedPreferences(this.getApplicationContext());
|
.getDefaultSharedPreferences(this.getApplicationContext());
|
||||||
String dataSourceStr = SP.getString("DataSource", "Pebble");
|
String dataSourceStr = SP.getString("DataSource", "Pebble");
|
||||||
Log.i(TAG, "onBuildHeaders DataSource = " + dataSourceStr);
|
Log.i(TAG, "onBuildHeaders DataSource = " + dataSourceStr);
|
||||||
Boolean advancedMode = SP.getBoolean("advancedMode", false);
|
//Boolean advancedMode = SP.getBoolean("advancedMode", false);
|
||||||
|
Boolean advancedMode = true;
|
||||||
Log.i(TAG, "onBuildHeaders advancedMode = " + advancedMode);
|
Log.i(TAG, "onBuildHeaders advancedMode = " + advancedMode);
|
||||||
|
|
||||||
if (advancedMode) {
|
if (advancedMode) {
|
||||||
@@ -120,7 +121,7 @@ public class PrefActivity extends PreferenceActivity implements SharedPreference
|
|||||||
} else {
|
} else {
|
||||||
titleStr = getResources().getString(h.titleRes);
|
titleStr = getResources().getString(h.titleRes);
|
||||||
}
|
}
|
||||||
Log.v(TAG, "i=" + i + ": found - " + titleStr + " looking for "+ getString(R.string.basic_settings_title));
|
Log.v(TAG, "i=" + i + ": found - " + titleStr + " looking for " + getString(R.string.basic_settings_title));
|
||||||
if (!titleStr.equals(getString(R.string.basic_settings_title))) {
|
if (!titleStr.equals(getString(R.string.basic_settings_title))) {
|
||||||
Log.v(TAG, "an Advanced Mode Header, so removing it....");
|
Log.v(TAG, "an Advanced Mode Header, so removing it....");
|
||||||
target.remove(i);
|
target.remove(i);
|
||||||
@@ -143,18 +144,22 @@ public class PrefActivity extends PreferenceActivity implements SharedPreference
|
|||||||
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String s) {
|
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String s) {
|
||||||
Log.i(TAG, "SharedPreference " + s + " Changed.");
|
Log.i(TAG, "SharedPreference " + s + " Changed.");
|
||||||
|
|
||||||
|
// if we have enabled the SMS alarm, we may need extra permissions approving. This is handled in
|
||||||
|
// StartUpActivity, so we exit this activity and start start-up activity.
|
||||||
if (s.equals("SMSAlarm")) {
|
if (s.equals("SMSAlarm")) {
|
||||||
if (sharedPreferences.getBoolean("SMSAlarm", false) == true) {
|
if (sharedPreferences.getBoolean("SMSAlarm", false) == true) {
|
||||||
if (mUtil.areSMSPermissionsOK() == false) {
|
Log.i(TAG, "onSharedPreferenceChanged(): SMS Alarm Enabled - Restarting start-up activity to check permissions");
|
||||||
Log.i(TAG, "onSharedPreferenceChanged(): SMS Alarm Enabled - Requesting Permissions");
|
Intent i;
|
||||||
mUtil.requestSMSPermissions(this);
|
i = new Intent(this, StartupActivity.class);
|
||||||
} else {
|
startActivity(i);
|
||||||
Log.i(TAG, "OnSharedPreferenceCHanged(): SMS Permissions already granted, doing nothing");
|
Log.i(TAG,"onSharedPreferenceChanged() - finishing PrefActivity");
|
||||||
}
|
finish();
|
||||||
|
return;
|
||||||
} else {
|
} else {
|
||||||
Log.i(TAG, "OnSharedPreferenceChanged(): SMS Alarm disabled so do not need permissions");
|
Log.i(TAG, "OnSharedPreferenceChanged(): SMS Alarm disabled so do not need permissions");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// For all other preference changes we just restart SdServer so it is not as alarming for the user!
|
||||||
//mUtil.showToast("Setting " + s + " Changed - restarting server");
|
//mUtil.showToast("Setting " + s + " Changed - restarting server");
|
||||||
mPrefChanged = true;
|
mPrefChanged = true;
|
||||||
mUtil.stopServer();
|
mUtil.stopServer();
|
||||||
@@ -213,6 +218,7 @@ public class PrefActivity extends PreferenceActivity implements SharedPreference
|
|||||||
protected void onStop() {
|
protected void onStop() {
|
||||||
super.onStop();
|
super.onStop();
|
||||||
mUtil.writeToSysLogFile("PrefActvity.onStop()");
|
mUtil.writeToSysLogFile("PrefActvity.onStop()");
|
||||||
|
Log.i(TAG,"onStop()");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -276,6 +282,17 @@ public class PrefActivity extends PreferenceActivity implements SharedPreference
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class LoggingPrefsFragment extends PreferenceFragment {
|
||||||
|
@Override
|
||||||
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
|
// Load the preferences from an XML resource
|
||||||
|
addPreferencesFromResource(R.xml.logging_prefs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public static class SeizureDetectorPrefsFragment extends PreferenceFragment {
|
public static class SeizureDetectorPrefsFragment extends PreferenceFragment {
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
|
|||||||
@@ -0,0 +1,226 @@
|
|||||||
|
package uk.org.openseizuredetector;
|
||||||
|
|
||||||
|
//import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.os.CountDownTimer;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.preference.PreferenceManager;
|
||||||
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.View;
|
||||||
|
import android.webkit.WebSettings;
|
||||||
|
import android.webkit.WebView;
|
||||||
|
import android.widget.Button;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
public class RemoteDbActivity extends AppCompatActivity {
|
||||||
|
private String TAG = "RemoteDbActivity";
|
||||||
|
private Context mContext;
|
||||||
|
private UiTimer mUiTimer;
|
||||||
|
private LogManager mLm;
|
||||||
|
private WebView mWebView;
|
||||||
|
private SdServiceConnection mConnection;
|
||||||
|
private OsdUtil mUtil;
|
||||||
|
final Handler serverStatusHandler = new Handler();
|
||||||
|
private String TOKEN_ID = "webApiAuthToken";
|
||||||
|
private String mRemtoteUrl = "https://osdapi.ddns.net/";
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
Log.v(TAG, "onCreate()");
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
mContext = this;
|
||||||
|
setContentView(R.layout.activity_remote_db);
|
||||||
|
mUtil = new OsdUtil(getApplicationContext(), serverStatusHandler);
|
||||||
|
mConnection = new SdServiceConnection(getApplicationContext());
|
||||||
|
mUtil.bindToServer(getApplicationContext(), mConnection);
|
||||||
|
|
||||||
|
Bundle extras = getIntent().getExtras();
|
||||||
|
if (extras != null) {
|
||||||
|
String remoteUrl = extras.getString("url");
|
||||||
|
mRemtoteUrl = remoteUrl;
|
||||||
|
Log.d(TAG, "onCreate - mRemoteUrl=" + mRemtoteUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
waitForConnection();
|
||||||
|
|
||||||
|
//mLm= new LogManager(mContext);
|
||||||
|
|
||||||
|
Button authBtn =
|
||||||
|
(Button) findViewById(R.id.auth_button);
|
||||||
|
authBtn.setOnClickListener(onAuth);
|
||||||
|
//Button pruneBtn =
|
||||||
|
// (Button) findViewById(R.id.pruneDatabaseBtn);
|
||||||
|
//pruneBtn.setOnClickListener(onPruneBtn);
|
||||||
|
|
||||||
|
mWebView = (WebView) findViewById(R.id.remote_db_webview);
|
||||||
|
WebSettings webSettings = mWebView.getSettings();
|
||||||
|
webSettings.setJavaScriptEnabled(true);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
if (mConnection.mBound) {
|
||||||
|
Log.d(TAG, "waitForConnection - Bound!");
|
||||||
|
initialiseServiceConnection();
|
||||||
|
} else {
|
||||||
|
Log.v(TAG, "waitForConnection - waiting...");
|
||||||
|
new Handler().postDelayed(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
waitForConnection();
|
||||||
|
}
|
||||||
|
}, 100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initialiseServiceConnection() {
|
||||||
|
mLm = mConnection.mSdServer.mLm;
|
||||||
|
mWebView.loadUrl(mRemtoteUrl, getAuthHeaders());
|
||||||
|
//mWac = mConnection.mSdServer.mLm.mWac;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onStart() {
|
||||||
|
super.onStart();
|
||||||
|
waitForConnection();
|
||||||
|
updateUi();
|
||||||
|
//startUiTimer();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPause() {
|
||||||
|
super.onPause();
|
||||||
|
stopUiTimer();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onResume() {
|
||||||
|
super.onResume();
|
||||||
|
startUiTimer();
|
||||||
|
}
|
||||||
|
|
||||||
|
private HashMap<String, String> getAuthHeaders() {
|
||||||
|
HashMap<String, String> headersMap = new HashMap<>();
|
||||||
|
String authToken = getAuthToken();
|
||||||
|
headersMap.put("Authorization", "Token "+authToken);
|
||||||
|
return (headersMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAuthToken() {
|
||||||
|
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(mContext);
|
||||||
|
String authToken = prefs.getString(TOKEN_ID, null);
|
||||||
|
return authToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateUi() {
|
||||||
|
Log.v(TAG,"updateUi()");
|
||||||
|
TextView tv;
|
||||||
|
Button btn;
|
||||||
|
// Local Database Information
|
||||||
|
//tv = (TextView)findViewById(R.id.num_local_events_tv);
|
||||||
|
//int eventCount = 0;
|
||||||
|
//tv.setText(String.format("%d",eventCount));
|
||||||
|
//tv = (TextView)findViewById(R.id.num_local_datapoints_tv);
|
||||||
|
//int datapointsCount = 0;
|
||||||
|
//tv.setText(String.format("%d",datapointsCount));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Remote Database Information
|
||||||
|
tv = (TextView)findViewById(R.id.authStatusTv);
|
||||||
|
btn = (Button)findViewById(R.id.auth_button);
|
||||||
|
if (mLm != null) {
|
||||||
|
if (mLm.mWac.isLoggedIn()) {
|
||||||
|
tv.setText("Authenticated");
|
||||||
|
btn.setText("Log Out");
|
||||||
|
} else {
|
||||||
|
tv.setText("NOT AUTHENTICATED");
|
||||||
|
btn.setText("Log In");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
View.OnClickListener onAuth =
|
||||||
|
new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View view) {
|
||||||
|
Log.v(TAG, "onAuth");
|
||||||
|
Intent i;
|
||||||
|
i =new Intent(mContext, AuthenticateActivity.class);
|
||||||
|
startActivity(i);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
View.OnClickListener onPruneBtn =
|
||||||
|
new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View view) {
|
||||||
|
Log.v(TAG, "onPruneBtn");
|
||||||
|
mLm.pruneLocalDb();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Start the timer that will upload data to the remote server after a given period.
|
||||||
|
*/
|
||||||
|
private void startUiTimer() {
|
||||||
|
if (mUiTimer != null) {
|
||||||
|
Log.v(TAG, "startRemoteLogTimer -timer already running - cancelling it");
|
||||||
|
mUiTimer.cancel();
|
||||||
|
mUiTimer = null;
|
||||||
|
}
|
||||||
|
Log.v(TAG, "startRemoteLogTimer() - starting RemoteLogTimer");
|
||||||
|
mUiTimer =
|
||||||
|
new UiTimer(1000, 1000);
|
||||||
|
mUiTimer.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Cancel the remote logging timer to prevent attempts to upload to remote database.
|
||||||
|
*/
|
||||||
|
public void stopUiTimer() {
|
||||||
|
if (mUiTimer != null) {
|
||||||
|
Log.v(TAG, "stopRemoteLogTimer(): cancelling Remote Log timer");
|
||||||
|
mUiTimer.cancel();
|
||||||
|
mUiTimer = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Upload recorded data to the remote database periodically.
|
||||||
|
*/
|
||||||
|
private class UiTimer extends CountDownTimer {
|
||||||
|
public UiTimer(long startTime, long interval) {
|
||||||
|
super(startTime, interval);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTick(long l) {
|
||||||
|
// Do Nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFinish() {
|
||||||
|
Log.v(TAG, "UiTimer - onFinish - Updating UI");
|
||||||
|
updateUi();
|
||||||
|
// Restart this timer.
|
||||||
|
start();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,427 @@
|
|||||||
|
package uk.org.openseizuredetector;
|
||||||
|
|
||||||
|
//import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
|
||||||
|
import android.app.DatePickerDialog;
|
||||||
|
import android.app.TimePickerDialog;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.DialogInterface;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.os.CountDownTimer;
|
||||||
|
import android.os.Handler;
|
||||||
|
|
||||||
|
import androidx.appcompat.app.AlertDialog;
|
||||||
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.Button;
|
||||||
|
import android.widget.DatePicker;
|
||||||
|
import android.widget.RadioButton;
|
||||||
|
import android.widget.RadioGroup;
|
||||||
|
import android.widget.TextView;
|
||||||
|
import android.widget.TimePicker;
|
||||||
|
|
||||||
|
import org.json.JSONArray;
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ReportSeizureActivity - Allows the user to report a seizure manually, which is saved in the database for
|
||||||
|
* future analysis - particularlly useful if OpenSeizureDetector did not detect the seizure automatically as this
|
||||||
|
* will ensure the data for the missed seizure is saved.
|
||||||
|
* Based on: https://www.journaldev.com/9976/android-date-time-picker-dialog
|
||||||
|
*/
|
||||||
|
public class ReportSeizureActivity extends AppCompatActivity {
|
||||||
|
private String TAG = "ReportSeizureActivity";
|
||||||
|
private Context mContext;
|
||||||
|
private UiTimer mUiTimer;
|
||||||
|
private LogManager mLm;
|
||||||
|
private WebApiConnection mWac;
|
||||||
|
|
||||||
|
private int mYear, mMonth, mDay, mHour, mMinute;
|
||||||
|
private String mMsg = "Messages";
|
||||||
|
private SdServiceConnection mConnection;
|
||||||
|
private OsdUtil mUtil;
|
||||||
|
final Handler serverStatusHandler = new Handler();
|
||||||
|
private List<String> mEventTypesList = null;
|
||||||
|
private HashMap<String, ArrayList<String>> mEventSubTypesHashMap = null;
|
||||||
|
private String mEventTypeStr = null;
|
||||||
|
private String mEventSubTypeStr = null;
|
||||||
|
private String mEventNotes = "";
|
||||||
|
private RadioGroup mEventTypeRg;
|
||||||
|
private boolean mRedrawEventSubTypesList = false;
|
||||||
|
private boolean mRedrawEventTypesList = false;
|
||||||
|
private RadioGroup mEventSubTypeRg;
|
||||||
|
private boolean mEventSubTypesListChanged = false;
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
Log.v(TAG, "onCreate()");
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
mContext = this;
|
||||||
|
mUtil = new OsdUtil(this, serverStatusHandler);
|
||||||
|
if (!mUtil.isServerRunning()) {
|
||||||
|
mUtil.showToast(getString(R.string.error_server_not_running));
|
||||||
|
finish();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mContext = this;
|
||||||
|
mConnection = new SdServiceConnection(getApplicationContext());
|
||||||
|
|
||||||
|
setContentView(R.layout.activity_report_seizure);
|
||||||
|
|
||||||
|
mEventTypeRg = findViewById(R.id.eventTypeRg);
|
||||||
|
mEventTypeRg.setOnCheckedChangeListener(onEventTypeChange);
|
||||||
|
mEventSubTypeRg = findViewById(R.id.eventSubTypeRg);
|
||||||
|
mEventSubTypeRg.setOnCheckedChangeListener(onEventSubTypeChange);
|
||||||
|
|
||||||
|
Button okBtn =
|
||||||
|
(Button) findViewById(R.id.loginBtn);
|
||||||
|
okBtn.setOnClickListener(onOk);
|
||||||
|
|
||||||
|
Button cancelBtn =
|
||||||
|
(Button) findViewById(R.id.cancelBtn);
|
||||||
|
cancelBtn.setOnClickListener(onCancel);
|
||||||
|
|
||||||
|
Button setDateBtn =
|
||||||
|
(Button) findViewById(R.id.select_date_button);
|
||||||
|
setDateBtn.setOnClickListener(onSelectDate);
|
||||||
|
|
||||||
|
Button setTimeBtn =
|
||||||
|
(Button) findViewById(R.id.select_time_button);
|
||||||
|
setTimeBtn.setOnClickListener(onSelectTime);
|
||||||
|
|
||||||
|
// Get Current Date
|
||||||
|
final Calendar c = Calendar.getInstance();
|
||||||
|
mYear = c.get(Calendar.YEAR);
|
||||||
|
mMonth = c.get(Calendar.MONTH);
|
||||||
|
mDay = c.get(Calendar.DAY_OF_MONTH);
|
||||||
|
mHour = c.get(Calendar.HOUR_OF_DAY);
|
||||||
|
mMinute = c.get(Calendar.MINUTE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onStart() {
|
||||||
|
super.onStart();
|
||||||
|
mUtil.bindToServer(getApplicationContext(), mConnection);
|
||||||
|
waitForConnection();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPause() {
|
||||||
|
super.onPause();
|
||||||
|
stopUiTimer();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onResume() {
|
||||||
|
super.onResume();
|
||||||
|
//startUiTimer();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onStop() {
|
||||||
|
super.onStop();
|
||||||
|
mUtil.unbindFromServer(getApplicationContext(), mConnection);
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initialiseServiceConnection() {
|
||||||
|
mLm = mConnection.mSdServer.mLm;
|
||||||
|
mWac = mConnection.mSdServer.mLm.mWac;
|
||||||
|
|
||||||
|
if (mWac.isLoggedIn()) {
|
||||||
|
|
||||||
|
// Retrieve the JSONObject containing the standard event types.
|
||||||
|
// Note this obscure syntax is to avoid having to create another interface, so it is worth it :)
|
||||||
|
// See https://medium.com/@pra4mesh/callback-function-in-java-20fa48b27797
|
||||||
|
mWac.getEventTypes(new WebApiConnection.JSONObjectCallback() {
|
||||||
|
@Override
|
||||||
|
public void accept(JSONObject eventTypesObj) {
|
||||||
|
Log.v(TAG, "initialiseServiceConnection().onEventTypesReceived");
|
||||||
|
if (eventTypesObj == null) {
|
||||||
|
Log.e(TAG, "initialiseServiceConnection().getEventTypes Callback: Error Retrieving event types");
|
||||||
|
mUtil.showToast("Error Retrieving Event Types from Server - Please Try Again Later!");
|
||||||
|
} else {
|
||||||
|
Iterator<String> keys = eventTypesObj.keys();
|
||||||
|
mEventTypesList = new ArrayList<String>();
|
||||||
|
mEventSubTypesHashMap = new HashMap<String, ArrayList<String>>();
|
||||||
|
while (keys.hasNext()) {
|
||||||
|
String key = keys.next();
|
||||||
|
Log.v(TAG, "initialiseServiceConnection().getEventTypes Callback: key=" + key);
|
||||||
|
mEventTypesList.add(key);
|
||||||
|
try {
|
||||||
|
JSONArray eventSubTypes = eventTypesObj.getJSONArray(key);
|
||||||
|
ArrayList<String> eventSubtypesList = new ArrayList<String>();
|
||||||
|
for (int i = 0; i < eventSubTypes.length(); i++) {
|
||||||
|
eventSubtypesList.add(eventSubTypes.getString(i));
|
||||||
|
}
|
||||||
|
mEventSubTypesHashMap.put(key, eventSubtypesList);
|
||||||
|
mRedrawEventSubTypesList = true;
|
||||||
|
} catch (JSONException e) {
|
||||||
|
Log.e(TAG, "initialiseServiceConnection().getEventTypes Callback: Error parsing JSONObject" + e.getMessage() + e.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mRedrawEventTypesList = true;
|
||||||
|
updateUi();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
new AlertDialog.Builder(mContext)
|
||||||
|
.setTitle(R.string.not_logged_in_dialog_title)
|
||||||
|
.setMessage(R.string.not_logged_in_dialog_message)
|
||||||
|
.setIcon(android.R.drawable.ic_dialog_alert)
|
||||||
|
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
|
||||||
|
public void onClick(DialogInterface dialog, int whichButton) {
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.show();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private void updateUi() {
|
||||||
|
//Log.v(TAG,"updateUi()");
|
||||||
|
TextView tv;
|
||||||
|
Button btn;
|
||||||
|
RadioButton b;
|
||||||
|
|
||||||
|
tv = (TextView)findViewById(R.id.date_day_tv);
|
||||||
|
tv.setText(String.format("%02d",mDay));
|
||||||
|
tv = (TextView)findViewById(R.id.date_mon_tv);
|
||||||
|
tv.setText(String.format("%02d",mMonth+1)); // Month counted from zero
|
||||||
|
tv = (TextView)findViewById(R.id.date_year_tv);
|
||||||
|
tv.setText(String.format("%04d",mYear));
|
||||||
|
tv = (TextView)findViewById(R.id.time_hh_tv);
|
||||||
|
tv.setText(String.format("%02d",mHour));
|
||||||
|
tv = (TextView)findViewById(R.id.time_mm_tv);
|
||||||
|
tv.setText(String.format("%02d",mMinute));
|
||||||
|
tv = (TextView)findViewById(R.id.msg_tv);
|
||||||
|
tv.setText(mMsg);
|
||||||
|
|
||||||
|
// Populate event type button group if necessary
|
||||||
|
if (mEventTypesList != null && mRedrawEventTypesList) {
|
||||||
|
Log.v(TAG, "updateUi: " + mEventTypesList.toString());
|
||||||
|
mEventTypeRg.removeAllViews();
|
||||||
|
for (String eventTypeStr : mEventTypesList) {
|
||||||
|
b = new RadioButton(this);
|
||||||
|
b.setText(eventTypeStr);
|
||||||
|
mEventTypeRg.addView(b);
|
||||||
|
}
|
||||||
|
mRedrawEventTypesList = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
String seizureTypeStr = null;
|
||||||
|
// Find which seizure type is selected
|
||||||
|
int checkedRadioButtonId = mEventTypeRg.getCheckedRadioButtonId();
|
||||||
|
//Log.i(TAG,"updateUi(): checkedRadioButtonId="+checkedRadioButtonId);
|
||||||
|
b = (RadioButton) findViewById(checkedRadioButtonId);
|
||||||
|
if (b != null) {
|
||||||
|
seizureTypeStr = b.getText().toString();
|
||||||
|
}
|
||||||
|
Log.i(TAG,"updateUi - SeizureType="+seizureTypeStr);
|
||||||
|
|
||||||
|
// Populate the event sub-types radio button list.
|
||||||
|
Log.v(TAG,"updateUi() - meventsubtypeshashmap="+mEventSubTypesHashMap+", mEventSubtypesListChanged="+mEventSubTypesListChanged);
|
||||||
|
if (mEventSubTypesHashMap != null && mRedrawEventSubTypesList) {
|
||||||
|
Log.v(TAG,"UpdateUi() - populating event sub types list");
|
||||||
|
if (seizureTypeStr != null) {
|
||||||
|
// based on https://androidexample.com/create-a-simple-listview
|
||||||
|
ArrayList<String> subtypesArrayList = mEventSubTypesHashMap.get(seizureTypeStr);
|
||||||
|
Log.v(TAG, "updateUi() - eventType=" + seizureTypeStr + ", subtypes=" + subtypesArrayList);
|
||||||
|
mEventSubTypeRg.removeAllViews();
|
||||||
|
for (String eventSubTypeStr : subtypesArrayList) {
|
||||||
|
b = new RadioButton(this);
|
||||||
|
b.setText(eventSubTypeStr);
|
||||||
|
mEventSubTypeRg.addView(b);
|
||||||
|
}
|
||||||
|
mRedrawEventSubTypesList = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
View.OnClickListener onOk =
|
||||||
|
new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View view) {
|
||||||
|
RadioButton b;
|
||||||
|
String seizureTypeStr = null;
|
||||||
|
String seizureSubTypeStr = null;
|
||||||
|
String notesStr = null;
|
||||||
|
Log.v(TAG, "onOk");
|
||||||
|
//SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||||
|
String dateStr=String.format("%4d-%02d-%02d %02d:%02d:30",mYear,mMonth+1,mDay, mHour, mMinute);
|
||||||
|
Log.v(TAG, "onOk() - dateSTr="+dateStr);
|
||||||
|
|
||||||
|
// Read seizure type from radio buttons
|
||||||
|
int checkedRadioButtonId = mEventTypeRg.getCheckedRadioButtonId();
|
||||||
|
b = (RadioButton) findViewById(checkedRadioButtonId);
|
||||||
|
if (b != null) {
|
||||||
|
seizureTypeStr = b.getText().toString();
|
||||||
|
}
|
||||||
|
Log.i(TAG,"onOk() - SeizureType="+seizureTypeStr);
|
||||||
|
|
||||||
|
checkedRadioButtonId = mEventSubTypeRg.getCheckedRadioButtonId();
|
||||||
|
b = (RadioButton) findViewById(checkedRadioButtonId);
|
||||||
|
if (b != null) {
|
||||||
|
seizureSubTypeStr = b.getText().toString();
|
||||||
|
}
|
||||||
|
Log.i(TAG,"onOk() - SeizureSubType="+seizureSubTypeStr);
|
||||||
|
|
||||||
|
TextView tv = (TextView)findViewById(R.id.eventNotesTv);
|
||||||
|
notesStr = tv.getText().toString();
|
||||||
|
|
||||||
|
mLm.createLocalEvent(dateStr,5,seizureTypeStr, seizureSubTypeStr, notesStr,
|
||||||
|
mConnection.mSdServer.mSdData.toSettingsJSON());
|
||||||
|
mUtil.showToast("Seizure Event Created");
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
View.OnClickListener onCancel =
|
||||||
|
new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View view) {
|
||||||
|
Log.v(TAG, "onCancel");
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
View.OnClickListener onSelectDate =
|
||||||
|
new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View view) {
|
||||||
|
Log.v(TAG, "onSelectDate()");
|
||||||
|
DatePickerDialog datePickerDialog = new DatePickerDialog(mContext,
|
||||||
|
new DatePickerDialog.OnDateSetListener() {
|
||||||
|
@Override
|
||||||
|
public void onDateSet(DatePicker view, int year,
|
||||||
|
int monthOfYear, int dayOfMonth) {
|
||||||
|
|
||||||
|
mYear = year;
|
||||||
|
mMonth = monthOfYear;
|
||||||
|
mDay = dayOfMonth;
|
||||||
|
}
|
||||||
|
}, mYear, mMonth, mDay);
|
||||||
|
datePickerDialog.show();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
View.OnClickListener onSelectTime =
|
||||||
|
new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View view) {
|
||||||
|
Log.v(TAG, "onSelectTime()");
|
||||||
|
TimePickerDialog timePickerDialog = new TimePickerDialog(mContext,
|
||||||
|
new TimePickerDialog.OnTimeSetListener() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTimeSet(TimePicker view, int hourOfDay,
|
||||||
|
int minute) {
|
||||||
|
|
||||||
|
mHour = hourOfDay;
|
||||||
|
mMinute = minute;
|
||||||
|
}
|
||||||
|
}, mHour, mMinute, true);
|
||||||
|
timePickerDialog.show();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
RadioGroup.OnCheckedChangeListener onEventTypeChange =
|
||||||
|
new RadioGroup.OnCheckedChangeListener() {
|
||||||
|
@Override
|
||||||
|
public void onCheckedChanged(RadioGroup group, int checkedId) {
|
||||||
|
mRedrawEventSubTypesList = true;
|
||||||
|
updateUi();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
RadioGroup.OnCheckedChangeListener onEventSubTypeChange =
|
||||||
|
new RadioGroup.OnCheckedChangeListener() {
|
||||||
|
@Override
|
||||||
|
public void onCheckedChanged(RadioGroup group, int checkedId) {
|
||||||
|
updateUi();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Start the timer that will upload data to the remote server after a given period.
|
||||||
|
*/
|
||||||
|
private void startUiTimer() {
|
||||||
|
if (mUiTimer != null) {
|
||||||
|
Log.v(TAG, "startUiTimer -timer already running - cancelling it");
|
||||||
|
mUiTimer.cancel();
|
||||||
|
mUiTimer = null;
|
||||||
|
}
|
||||||
|
Log.v(TAG, "startUiTimer() - starting UiTimer");
|
||||||
|
mUiTimer =
|
||||||
|
new UiTimer(1000, 1000);
|
||||||
|
mUiTimer.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Cancel the remote logging timer to prevent attempts to upload to remote database.
|
||||||
|
*/
|
||||||
|
public void stopUiTimer() {
|
||||||
|
if (mUiTimer != null) {
|
||||||
|
Log.v(TAG, "stopUiTimer(): cancelling Ui timer");
|
||||||
|
mUiTimer.cancel();
|
||||||
|
mUiTimer = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update User Interface Periodically
|
||||||
|
*/
|
||||||
|
private class UiTimer extends CountDownTimer {
|
||||||
|
public UiTimer(long startTime, long interval) {
|
||||||
|
super(startTime, interval);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTick(long l) {
|
||||||
|
// Do Nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFinish() {
|
||||||
|
//Log.v(TAG, "UiTimer - onFinish - Updating UI");
|
||||||
|
updateUi();
|
||||||
|
// Restart this timer.
|
||||||
|
start();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -38,6 +38,7 @@ public class SdData implements Parcelable {
|
|||||||
private final static String TAG = "SdData";
|
private final static String TAG = "SdData";
|
||||||
private final static int N_RAW_DATA = 500; // 5 seconds at 100 Hz.
|
private final static int N_RAW_DATA = 500; // 5 seconds at 100 Hz.
|
||||||
/* Analysis settings */
|
/* Analysis settings */
|
||||||
|
public String phoneAppVersion = "";
|
||||||
public boolean haveSettings = false; // flag to say if we have received settings or not.
|
public boolean haveSettings = false; // flag to say if we have received settings or not.
|
||||||
public boolean haveData = false; // flag to say we have received data.
|
public boolean haveData = false; // flag to say we have received data.
|
||||||
public short mDataUpdatePeriod;
|
public short mDataUpdatePeriod;
|
||||||
@@ -65,7 +66,22 @@ public class SdData implements Parcelable {
|
|||||||
public boolean mHRNullAsAlarm = false;
|
public boolean mHRNullAsAlarm = false;
|
||||||
public double mHRThreshMin = 40.0;
|
public double mHRThreshMin = 40.0;
|
||||||
public double mHRThreshMax = 150.0;
|
public double mHRThreshMax = 150.0;
|
||||||
|
|
||||||
|
/* Oxygen Saturation Alarm Settings */
|
||||||
|
public boolean mO2SatAlarmActive = false;
|
||||||
|
public boolean mO2SatNullAsAlarm = false;
|
||||||
|
public double mO2SatThreshMin = 80.0;
|
||||||
|
|
||||||
|
/* Watch App Settings */
|
||||||
|
public String dataSourceName = "";
|
||||||
|
public String watchPartNo = "";
|
||||||
|
public String watchFwVersion = "";
|
||||||
|
public String watchSdVersion = "";
|
||||||
|
public String watchSdName = "";
|
||||||
|
|
||||||
|
|
||||||
public double rawData[];
|
public double rawData[];
|
||||||
|
public double rawData3D[];
|
||||||
int mNsamp = 0;
|
int mNsamp = 0;
|
||||||
|
|
||||||
/* Analysis results */
|
/* Analysis results */
|
||||||
@@ -87,14 +103,21 @@ public class SdData implements Parcelable {
|
|||||||
public boolean mHRFaultStanding = false;
|
public boolean mHRFaultStanding = false;
|
||||||
public double mHR = 0;
|
public double mHR = 0;
|
||||||
|
|
||||||
|
public boolean mO2SatAlarmStanding = false;
|
||||||
|
public boolean mO2SatFaultStanding = false;
|
||||||
|
public double mO2Sat = 0;
|
||||||
|
|
||||||
|
|
||||||
public SdData() {
|
public SdData() {
|
||||||
simpleSpec = new int[10];
|
simpleSpec = new int[10];
|
||||||
rawData = new double[N_RAW_DATA];
|
rawData = new double[N_RAW_DATA];
|
||||||
|
rawData3D = new double[N_RAW_DATA * 3];
|
||||||
dataTime = new Time(Time.getCurrentTimezone());
|
dataTime = new Time(Time.getCurrentTimezone());
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Intialise this SdData object from a JSON String
|
* Intialise this SdData object from a JSON String
|
||||||
|
* FIXME - add O2saturation with checking in case it is not included in the data
|
||||||
*/
|
*/
|
||||||
public boolean fromJSON(String jsonStr) {
|
public boolean fromJSON(String jsonStr) {
|
||||||
Log.v(TAG, "fromJSON() - parsing jsonString - " + jsonStr);
|
Log.v(TAG, "fromJSON() - parsing jsonString - " + jsonStr);
|
||||||
@@ -120,12 +143,12 @@ public class SdData implements Parcelable {
|
|||||||
alarmPhrase = jo.optString("alarmPhrase");
|
alarmPhrase = jo.optString("alarmPhrase");
|
||||||
alarmThresh = jo.optInt("alarmThresh");
|
alarmThresh = jo.optInt("alarmThresh");
|
||||||
alarmRatioThresh = jo.optInt("alarmRatioThresh");
|
alarmRatioThresh = jo.optInt("alarmRatioThresh");
|
||||||
mHRAlarmActive=jo.optBoolean("hrAlarmActive");
|
mHRAlarmActive = jo.optBoolean("hrAlarmActive");
|
||||||
mHRAlarmStanding = jo.optBoolean("hrAlarmStanding");
|
mHRAlarmStanding = jo.optBoolean("hrAlarmStanding");
|
||||||
mHRThreshMin = jo.optDouble("hrThreshMin");
|
mHRThreshMin = jo.optDouble("hrThreshMin");
|
||||||
mHRThreshMax = jo.optDouble("hrThreshMax");
|
mHRThreshMax = jo.optDouble("hrThreshMax");
|
||||||
mHR = jo.optDouble("hr");
|
mHR = jo.optDouble("hr");
|
||||||
if (mHR>=0.0) {
|
if (mHR >= 0.0) {
|
||||||
mHRAlarmActive = true;
|
mHRAlarmActive = true;
|
||||||
}
|
}
|
||||||
JSONArray specArr = jo.optJSONArray("simpleSpec");
|
JSONArray specArr = jo.optJSONArray("simpleSpec");
|
||||||
@@ -136,7 +159,7 @@ public class SdData implements Parcelable {
|
|||||||
Log.v(TAG, "fromJSON(): sdData = " + this.toString());
|
Log.v(TAG, "fromJSON(): sdData = " + this.toString());
|
||||||
return true;
|
return true;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Log.v(TAG, "fromJSON() - error parsing result"+e.toString());
|
Log.v(TAG, "fromJSON() - error parsing result" + e.toString());
|
||||||
haveData = false;
|
haveData = false;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -147,6 +170,106 @@ public class SdData implements Parcelable {
|
|||||||
return toDataString(false);
|
return toDataString(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String toJSON(boolean includeRawData) {
|
||||||
|
return toDataString(includeRawData);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toDatapointJSON() {
|
||||||
|
String retval;
|
||||||
|
retval = "SdData.toDatapointJSON() Output";
|
||||||
|
try {
|
||||||
|
JSONObject jsonObj = new JSONObject();
|
||||||
|
if (dataTime != null) {
|
||||||
|
jsonObj.put("dataTime", dataTime.format("%d-%m-%Y %H:%M:%S"));
|
||||||
|
jsonObj.put("dataTimeStr", dataTime.format("%Y%m%dT%H%M%S"));
|
||||||
|
} else {
|
||||||
|
jsonObj.put("dataTimeStr", "00000000T000000");
|
||||||
|
jsonObj.put("dataTime", "00-00-00 00:00:00");
|
||||||
|
}
|
||||||
|
Log.v(TAG, "mSdData.dataTime = " + dataTime);
|
||||||
|
jsonObj.put("maxVal", maxVal);
|
||||||
|
jsonObj.put("maxFreq", maxFreq);
|
||||||
|
jsonObj.put("specPower", specPower);
|
||||||
|
jsonObj.put("roiPower", roiPower);
|
||||||
|
jsonObj.put("roiRatio", 10 * roiPower / specPower);
|
||||||
|
jsonObj.put("alarmState", alarmState);
|
||||||
|
jsonObj.put("alarmPhrase", alarmPhrase);
|
||||||
|
jsonObj.put("hr", mHR);
|
||||||
|
jsonObj.put("o2Sat", mO2Sat);
|
||||||
|
JSONArray arr = new JSONArray();
|
||||||
|
for (int i = 0; i < simpleSpec.length; i++) {
|
||||||
|
arr.put(simpleSpec[i]);
|
||||||
|
}
|
||||||
|
jsonObj.put("simpleSpec", arr);
|
||||||
|
JSONArray rawArr = new JSONArray();
|
||||||
|
for (int i = 0; i < rawData.length; i++) {
|
||||||
|
rawArr.put(rawData[i]);
|
||||||
|
}
|
||||||
|
//Log.v(TAG,"rawData[0]="+rawData[0]+", rawArr[0]="+rawArr.getDouble(0));
|
||||||
|
jsonObj.put("rawData", rawArr);
|
||||||
|
|
||||||
|
JSONArray raw3DArr = new JSONArray();
|
||||||
|
for (int i = 0; i < rawData3D.length; i++) {
|
||||||
|
raw3DArr.put(rawData3D[i]);
|
||||||
|
}
|
||||||
|
jsonObj.put("rawData3D", raw3DArr);
|
||||||
|
|
||||||
|
retval = jsonObj.toString();
|
||||||
|
Log.v(TAG,"retval rawData="+retval);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
Log.v(TAG, "Error Creating Data Object - " + ex.toString());
|
||||||
|
retval = "Error Creating Data Object - " + ex.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
return (retval);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public String toSettingsJSON() {
|
||||||
|
String retval;
|
||||||
|
retval = "SdData.toSettingsJSON() Output";
|
||||||
|
try {
|
||||||
|
JSONObject jsonObj = new JSONObject();
|
||||||
|
if (dataTime != null) {
|
||||||
|
jsonObj.put("dataTime", dataTime.format("%d-%m-%Y %H:%M:%S"));
|
||||||
|
jsonObj.put("dataTimeStr", dataTime.format("%Y%m%dT%H%M%S"));
|
||||||
|
} else {
|
||||||
|
jsonObj.put("dataTimeStr", "00000000T000000");
|
||||||
|
jsonObj.put("dataTime", "00-00-00 00:00:00");
|
||||||
|
}
|
||||||
|
jsonObj.put("batteryPc", batteryPc);
|
||||||
|
jsonObj.put("alarmState", alarmState);
|
||||||
|
jsonObj.put("alarmPhrase", alarmPhrase);
|
||||||
|
jsonObj.put("sdMode", mSdMode);
|
||||||
|
jsonObj.put("sampleFreq", mSampleFreq);
|
||||||
|
jsonObj.put("analysisPeriod", analysisPeriod);
|
||||||
|
jsonObj.put("alarmFreqMin", alarmFreqMin);
|
||||||
|
jsonObj.put("alarmFreqMax", alarmFreqMax);
|
||||||
|
jsonObj.put("alarmThresh", alarmThresh);
|
||||||
|
jsonObj.put("alarmRatioThresh", alarmRatioThresh);
|
||||||
|
jsonObj.put("hrAlarmActive", mHRAlarmActive);
|
||||||
|
jsonObj.put("hrAlarmStanding", mHRAlarmStanding);
|
||||||
|
jsonObj.put("hrThreshMin", mHRThreshMin);
|
||||||
|
jsonObj.put("hrThreshMax", mHRThreshMax);
|
||||||
|
jsonObj.put("o2SatAlarmActive", mO2SatAlarmActive);
|
||||||
|
jsonObj.put("o2SatAlarmStanding", mO2SatAlarmStanding);
|
||||||
|
jsonObj.put("o2SatThreshMin", mO2SatThreshMin);
|
||||||
|
jsonObj.put("dataSourceName", dataSourceName);
|
||||||
|
Log.v(TAG,"phoneAppVersion="+phoneAppVersion);
|
||||||
|
jsonObj.put("phoneAppVersion", phoneAppVersion);
|
||||||
|
jsonObj.put("watchPartNo", watchPartNo);
|
||||||
|
jsonObj.put("watchSdName", watchSdName);
|
||||||
|
jsonObj.put("watchFwVersion", watchFwVersion);
|
||||||
|
jsonObj.put("watchSdVersion", watchSdVersion);
|
||||||
|
|
||||||
|
retval = jsonObj.toString();
|
||||||
|
} catch (Exception ex) {
|
||||||
|
Log.e(TAG, "toSettingsJSON(): Error Creating Data Object - " + ex.toString());
|
||||||
|
retval = "Error Creating Data Object - " + ex.toString();
|
||||||
|
}
|
||||||
|
return (retval);
|
||||||
|
}
|
||||||
|
|
||||||
public String toDataString(boolean includeRawData) {
|
public String toDataString(boolean includeRawData) {
|
||||||
String retval;
|
String retval;
|
||||||
retval = "SdData.toDataString() Output";
|
retval = "SdData.toDataString() Output";
|
||||||
@@ -155,7 +278,7 @@ public class SdData implements Parcelable {
|
|||||||
if (dataTime != null) {
|
if (dataTime != null) {
|
||||||
jsonObj.put("dataTime", dataTime.format("%d-%m-%Y %H:%M:%S"));
|
jsonObj.put("dataTime", dataTime.format("%d-%m-%Y %H:%M:%S"));
|
||||||
jsonObj.put("dataTimeStr", dataTime.format("%Y%m%dT%H%M%S"));
|
jsonObj.put("dataTimeStr", dataTime.format("%Y%m%dT%H%M%S"));
|
||||||
}else{
|
} else {
|
||||||
jsonObj.put("dataTimeStr", "00000000T000000");
|
jsonObj.put("dataTimeStr", "00000000T000000");
|
||||||
jsonObj.put("dataTime", "00-00-00 00:00:00");
|
jsonObj.put("dataTime", "00-00-00 00:00:00");
|
||||||
}
|
}
|
||||||
@@ -170,18 +293,22 @@ public class SdData implements Parcelable {
|
|||||||
jsonObj.put("haveSettings", haveSettings);
|
jsonObj.put("haveSettings", haveSettings);
|
||||||
jsonObj.put("alarmState", alarmState);
|
jsonObj.put("alarmState", alarmState);
|
||||||
jsonObj.put("alarmPhrase", alarmPhrase);
|
jsonObj.put("alarmPhrase", alarmPhrase);
|
||||||
jsonObj.put("sdMode",mSdMode);
|
jsonObj.put("sdMode", mSdMode);
|
||||||
jsonObj.put("sampleFreq",mSampleFreq);
|
jsonObj.put("sampleFreq", mSampleFreq);
|
||||||
jsonObj.put("analysisPeriod",analysisPeriod);
|
jsonObj.put("analysisPeriod", analysisPeriod);
|
||||||
jsonObj.put("alarmFreqMin",alarmFreqMin);
|
jsonObj.put("alarmFreqMin", alarmFreqMin);
|
||||||
jsonObj.put("alarmFreqMax",alarmFreqMax);
|
jsonObj.put("alarmFreqMax", alarmFreqMax);
|
||||||
jsonObj.put("alarmThresh", alarmThresh);
|
jsonObj.put("alarmThresh", alarmThresh);
|
||||||
jsonObj.put("alarmRatioThresh", alarmRatioThresh);
|
jsonObj.put("alarmRatioThresh", alarmRatioThresh);
|
||||||
jsonObj.put("hrAlarmActive", mHRAlarmActive);
|
jsonObj.put("hrAlarmActive", mHRAlarmActive);
|
||||||
jsonObj.put("hrAlarmStanding", mHRAlarmStanding);
|
jsonObj.put("hrAlarmStanding", mHRAlarmStanding);
|
||||||
jsonObj.put("hrThreshMin",mHRThreshMin);
|
jsonObj.put("hrThreshMin", mHRThreshMin);
|
||||||
jsonObj.put("hrThreshMax", mHRThreshMax);
|
jsonObj.put("hrThreshMax", mHRThreshMax);
|
||||||
jsonObj.put("hr",mHR);
|
jsonObj.put("hr", mHR);
|
||||||
|
jsonObj.put("o2SatAlarmActive", mO2SatAlarmActive);
|
||||||
|
jsonObj.put("o2SatAlarmStanding", mO2SatAlarmStanding);
|
||||||
|
jsonObj.put("o2SatThreshMin", mO2SatThreshMin);
|
||||||
|
jsonObj.put("o2Sat", mO2Sat);
|
||||||
JSONArray arr = new JSONArray();
|
JSONArray arr = new JSONArray();
|
||||||
for (int i = 0; i < simpleSpec.length; i++) {
|
for (int i = 0; i < simpleSpec.length; i++) {
|
||||||
arr.put(simpleSpec[i]);
|
arr.put(simpleSpec[i]);
|
||||||
@@ -189,9 +316,17 @@ public class SdData implements Parcelable {
|
|||||||
jsonObj.put("simpleSpec", arr);
|
jsonObj.put("simpleSpec", arr);
|
||||||
if (includeRawData) {
|
if (includeRawData) {
|
||||||
JSONArray rawArr = new JSONArray();
|
JSONArray rawArr = new JSONArray();
|
||||||
for (int i = 0; i< rawData.length;i++) {
|
for (int i = 0; i < rawData.length; i++) {
|
||||||
rawArr.put(rawData[i]);
|
rawArr.put(rawData[i]);
|
||||||
}
|
}
|
||||||
|
jsonObj.put("rawData", rawArr);
|
||||||
|
|
||||||
|
JSONArray raw3DArr = new JSONArray();
|
||||||
|
for (int i = 0; i < rawData3D.length; i++) {
|
||||||
|
raw3DArr.put(rawData3D[i]);
|
||||||
|
}
|
||||||
|
jsonObj.put("rawData3D", raw3DArr);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
retval = jsonObj.toString();
|
retval = jsonObj.toString();
|
||||||
@@ -209,7 +344,7 @@ public class SdData implements Parcelable {
|
|||||||
retval = "";
|
retval = "";
|
||||||
if (dataTime != null) {
|
if (dataTime != null) {
|
||||||
retval = dataTime.format("%d-%m-%Y %H:%M:%S");
|
retval = dataTime.format("%d-%m-%Y %H:%M:%S");
|
||||||
}else{
|
} else {
|
||||||
retval = "00-00-00 00:00:00";
|
retval = "00-00-00 00:00:00";
|
||||||
}
|
}
|
||||||
for (int i = 0; i < simpleSpec.length; i++) {
|
for (int i = 0; i < simpleSpec.length; i++) {
|
||||||
@@ -220,32 +355,37 @@ public class SdData implements Parcelable {
|
|||||||
retval = retval + ", " + mSampleFreq;
|
retval = retval + ", " + mSampleFreq;
|
||||||
retval = retval + ", " + alarmPhrase;
|
retval = retval + ", " + alarmPhrase;
|
||||||
retval = retval + ", " + mHR;
|
retval = retval + ", " + mHR;
|
||||||
|
retval = retval + ", " + mO2Sat;
|
||||||
if (includeRawData) {
|
if (includeRawData) {
|
||||||
for (int i = 0; i< mNsamp;i++) {
|
for (int i = 0; i < mNsamp; i++) {
|
||||||
retval = retval + ", " + rawData[i];
|
retval = retval + ", " + rawData[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return(retval);
|
return (retval);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Return the average acceleration value in the dataset */
|
/**
|
||||||
|
* Return the average acceleration value in the dataset
|
||||||
|
*/
|
||||||
public double getAvAcc() {
|
public double getAvAcc() {
|
||||||
double sumAcc = 0.0;
|
double sumAcc = 0.0;
|
||||||
for (int i = 0; i< mNsamp;i++) {
|
for (int i = 0; i < mNsamp; i++) {
|
||||||
sumAcc += rawData[i];
|
sumAcc += rawData[i];
|
||||||
}
|
}
|
||||||
return(sumAcc/mNsamp);
|
return (sumAcc / mNsamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Return the standard deviation of the acceleration values */
|
/**
|
||||||
|
* Return the standard deviation of the acceleration values
|
||||||
|
*/
|
||||||
public double getSdAcc() {
|
public double getSdAcc() {
|
||||||
double avAcc = 0.0;
|
double avAcc = 0.0;
|
||||||
double varAcc = 0.0;
|
double varAcc = 0.0;
|
||||||
avAcc = getAvAcc();
|
avAcc = getAvAcc();
|
||||||
for (int i = 0; i< mNsamp;i++) {
|
for (int i = 0; i < mNsamp; i++) {
|
||||||
varAcc += Math.pow(rawData[i]-avAcc,2);
|
varAcc += Math.pow(rawData[i] - avAcc, 2);
|
||||||
}
|
}
|
||||||
return(Math.sqrt(varAcc/(mNsamp-1)));
|
return (Math.sqrt(varAcc / (mNsamp - 1)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -254,6 +254,7 @@ public abstract class SdDataSource {
|
|||||||
String sdVersion;
|
String sdVersion;
|
||||||
String sdName;
|
String sdName;
|
||||||
JSONArray accelVals = null;
|
JSONArray accelVals = null;
|
||||||
|
JSONArray accelVals3D = null;
|
||||||
Log.v(TAG, "updateFromJSON - " + jsonStr);
|
Log.v(TAG, "updateFromJSON - " + jsonStr);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -270,6 +271,12 @@ public abstract class SdDataSource {
|
|||||||
// if we get 'null' HR (For example if the heart rate is not working)
|
// if we get 'null' HR (For example if the heart rate is not working)
|
||||||
mSdData.mHR = -1;
|
mSdData.mHR = -1;
|
||||||
}
|
}
|
||||||
|
try {
|
||||||
|
mSdData.mO2Sat = dataObject.getDouble("O2sat");
|
||||||
|
} catch (JSONException e) {
|
||||||
|
// if we get 'null' O2 Saturation (For example if the oxygen sensor is not working)
|
||||||
|
mSdData.mO2Sat = -1;
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
mMute = dataObject.getInt("Mute");
|
mMute = dataObject.getInt("Mute");
|
||||||
} catch (JSONException e) {
|
} catch (JSONException e) {
|
||||||
@@ -284,12 +291,31 @@ public abstract class SdDataSource {
|
|||||||
}
|
}
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < accelVals.length(); i++) {
|
for (i = 0; i < accelVals.length(); i++) {
|
||||||
mSdData.rawData[i] = accelVals.getInt(i);
|
mSdData.rawData[i] = accelVals.getDouble(i);
|
||||||
}
|
}
|
||||||
mSdData.mNsamp = accelVals.length();
|
mSdData.mNsamp = accelVals.length();
|
||||||
//mNSamp = accelVals.length();
|
//Log.d(TAG,"accelVals[0]="+accelVals.getDouble(0)+", mSdData.rawData[0]="+mSdData.rawData[0]);
|
||||||
|
try {
|
||||||
|
accelVals3D = dataObject.getJSONArray("data3D");
|
||||||
|
Log.v(TAG, "Received " + accelVals3D.length() + " acceleration 3D values, rawData Length is " + mSdData.rawData3D.length);
|
||||||
|
if (accelVals3D.length() > mSdData.rawData3D.length) {
|
||||||
|
mUtil.writeToSysLogFile("ERROR: Received " + accelVals3D.length() + " 3D acceleration values, but rawData3D storage length is "
|
||||||
|
+ mSdData.rawData3D.length);
|
||||||
|
}
|
||||||
|
for (i = 0; i < accelVals3D.length(); i++) {
|
||||||
|
mSdData.rawData3D[i] = accelVals3D.getDouble(i);
|
||||||
|
}
|
||||||
|
} catch (JSONException e) {
|
||||||
|
// If we get an error, just set rawData3D to zero
|
||||||
|
Log.i(TAG,"updateFromJSON - error parsing 3D data - setting it to zero");
|
||||||
|
for (i = 0; i < mSdData.rawData3D.length; i++) {
|
||||||
|
mSdData.rawData3D[i] = 0.;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mWatchAppRunningCheck = true;
|
mWatchAppRunningCheck = true;
|
||||||
doAnalysis();
|
doAnalysis();
|
||||||
|
|
||||||
if (mSdData.haveSettings == false) {
|
if (mSdData.haveSettings == false) {
|
||||||
retVal = "sendSettings";
|
retVal = "sendSettings";
|
||||||
} else {
|
} else {
|
||||||
@@ -312,6 +338,10 @@ public abstract class SdDataSource {
|
|||||||
sdName = dataObject.getString("sdName");
|
sdName = dataObject.getString("sdName");
|
||||||
mUtil.writeToSysLogFile(" * sdName = " + sdName + " version " + sdVersion);
|
mUtil.writeToSysLogFile(" * sdName = " + sdName + " version " + sdVersion);
|
||||||
mUtil.writeToSysLogFile(" * watchPartNo = " + watchPartNo + " fwVersion " + watchFwVersion);
|
mUtil.writeToSysLogFile(" * watchPartNo = " + watchPartNo + " fwVersion " + watchFwVersion);
|
||||||
|
mSdData.watchPartNo = watchPartNo;
|
||||||
|
mSdData.watchFwVersion = watchFwVersion;
|
||||||
|
mSdData.watchSdVersion = sdVersion;
|
||||||
|
mSdData.watchSdName = sdName;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Log.e(TAG, "updateFromJSON - Error Parsing V3.2 JSON String - " + e.toString());
|
Log.e(TAG, "updateFromJSON - Error Parsing V3.2 JSON String - " + e.toString());
|
||||||
mUtil.writeToSysLogFile("updateFromJSON - Error Parsing V3.2 JSON String - " + jsonStr + " - " + e.toString());
|
mUtil.writeToSysLogFile("updateFromJSON - Error Parsing V3.2 JSON String - " + jsonStr + " - " + e.toString());
|
||||||
@@ -455,8 +485,10 @@ public abstract class SdDataSource {
|
|||||||
// Check this data to see if it represents an alarm state.
|
// Check this data to see if it represents an alarm state.
|
||||||
alarmCheck();
|
alarmCheck();
|
||||||
hrCheck();
|
hrCheck();
|
||||||
|
o2SatCheck();
|
||||||
fallCheck();
|
fallCheck();
|
||||||
muteCheck();
|
muteCheck();
|
||||||
|
Log.v(TAG,"after fallCheck, mSdData.fallAlarmStanding="+mSdData.fallAlarmStanding);
|
||||||
|
|
||||||
mSdDataReceiver.onSdDataReceived(mSdData); // and tell SdServer we have received data.
|
mSdDataReceiver.onSdDataReceived(mSdData); // and tell SdServer we have received data.
|
||||||
}
|
}
|
||||||
@@ -470,9 +502,12 @@ public abstract class SdDataSource {
|
|||||||
*/
|
*/
|
||||||
private void alarmCheck() {
|
private void alarmCheck() {
|
||||||
boolean inAlarm;
|
boolean inAlarm;
|
||||||
Log.v(TAG, "alarmCheck()");
|
// Avoid potential divide by zero issue
|
||||||
|
if (mSdData.specPower == 0)
|
||||||
|
mSdData.specPower = 1;
|
||||||
|
Log.v(TAG, "alarmCheck() - roiPower="+mSdData.roiPower+" specPower="+ mSdData.specPower+" ratio="+10*mSdData.roiPower/ mSdData.specPower);
|
||||||
// Is the current set of data representing an alarm state?
|
// Is the current set of data representing an alarm state?
|
||||||
if ((mSdData.roiPower > mAlarmThresh) && (10 * (mSdData.roiPower / mSdData.specPower) > mAlarmRatioThresh)) {
|
if ((mSdData.roiPower > mAlarmThresh) && ((10 * mSdData.roiPower / mSdData.specPower) > mAlarmRatioThresh)) {
|
||||||
inAlarm = true;
|
inAlarm = true;
|
||||||
} else {
|
} else {
|
||||||
inAlarm = false;
|
inAlarm = false;
|
||||||
@@ -502,7 +537,7 @@ public abstract class SdDataSource {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.v(TAG, "alarmCheck(): inAlarm=" + inAlarm + ", alarmState = " + mSdData.alarmState + " alarmCount=" + mAlarmCount + " mAlarmTime=" + mAlarmTime);
|
Log.v(TAG, "alarmCheck(): inAlarm=" + inAlarm + ", alarmState = " + mSdData.alarmState + " alarmCount=" + mAlarmCount + " mWarnTime=" + mWarnTime+ " mAlarmTime=" + mAlarmTime);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -543,9 +578,39 @@ public abstract class SdDataSource {
|
|||||||
mSdData.mHRAlarmStanding = false;
|
mSdData.mHRAlarmStanding = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hrCheck - check the Heart rate data in mSdData to see if it represents an alarm condition.
|
||||||
|
* Sets mSdData.mHRAlarmStanding
|
||||||
|
*/
|
||||||
|
public void o2SatCheck() {
|
||||||
|
Log.v(TAG, "o2SatCheck()");
|
||||||
|
/* Check Oxygen Saturation against alarm settings */
|
||||||
|
if (mSdData.mO2SatAlarmActive) {
|
||||||
|
if (mSdData.mO2Sat < 0) {
|
||||||
|
if (mSdData.mO2SatNullAsAlarm) {
|
||||||
|
Log.i(TAG, "Oxygen Saturation Null - Alarming");
|
||||||
|
mSdData.mO2SatFaultStanding = false;
|
||||||
|
mSdData.mO2SatAlarmStanding = true;
|
||||||
|
} else {
|
||||||
|
Log.i(TAG, "Oxygen Saturation Fault (O2Sat<0)");
|
||||||
|
mSdData.mO2SatFaultStanding = true;
|
||||||
|
mSdData.mO2SatAlarmStanding = false;
|
||||||
|
}
|
||||||
|
} else if (mSdData.mO2Sat < mSdData.mO2SatThreshMin) {
|
||||||
|
Log.i(TAG, "Oxygen Saturation Abnormal - " + mSdData.mO2Sat + " %");
|
||||||
|
mSdData.mO2SatFaultStanding = false;
|
||||||
|
mSdData.mO2SatAlarmStanding = true;
|
||||||
|
} else {
|
||||||
|
mSdData.mO2SatFaultStanding = false;
|
||||||
|
mSdData.mO2SatAlarmStanding = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/****************************************************************
|
/****************************************************************
|
||||||
* Simple threshold analysis to chech for fall.
|
* Simple threshold analysis to chech for fall.
|
||||||
* Called from clock_tick_handler()
|
* Called from clock_tick_handler()
|
||||||
@@ -570,8 +635,9 @@ public abstract class SdDataSource {
|
|||||||
if (mSdData.rawData[i + j] < minAcc) minAcc = mSdData.rawData[i + j];
|
if (mSdData.rawData[i + j] < minAcc) minAcc = mSdData.rawData[i + j];
|
||||||
if (mSdData.rawData[i + j] > maxAcc) maxAcc = mSdData.rawData[i + j];
|
if (mSdData.rawData[i + j] > maxAcc) maxAcc = mSdData.rawData[i + j];
|
||||||
}
|
}
|
||||||
|
Log.d(TAG, "check_fall() - minAcc=" + minAcc +" (mFallThreshMin="+mFallThreshMin+ "), maxAcc=" + maxAcc+" (mFallThreshMax="+mFallThreshMax+")") ;
|
||||||
if ((minAcc < mFallThreshMin) && (maxAcc > mFallThreshMax)) {
|
if ((minAcc < mFallThreshMin) && (maxAcc > mFallThreshMax)) {
|
||||||
Log.d(TAG, "check_fall() - minAcc=" + minAcc + ", maxAcc=" + maxAcc);
|
Log.d(TAG, "check_fall() ****FALL DETECTED***** minAcc=" + minAcc + ", maxAcc=" + maxAcc);
|
||||||
Log.d(TAG, "check_fall() - ****FALL DETECTED****");
|
Log.d(TAG, "check_fall() - ****FALL DETECTED****");
|
||||||
mSdData.fallAlarmStanding = true;
|
mSdData.fallAlarmStanding = true;
|
||||||
return;
|
return;
|
||||||
@@ -649,11 +715,11 @@ public abstract class SdDataSource {
|
|||||||
|
|
||||||
// get time since the last data was received from the watch.
|
// get time since the last data was received from the watch.
|
||||||
tdiff = (tnow.toMillis(false) - mDataStatusTime.toMillis(false));
|
tdiff = (tnow.toMillis(false) - mDataStatusTime.toMillis(false));
|
||||||
Log.v(TAG, "faultCheck() - tdiff=" + tdiff + ", mDataUpatePeriod=" + mDataUpdatePeriod + ", mAppRestartTimeout=" + mAppRestartTimeout
|
//Log.v(TAG, "faultCheck() - tdiff=" + tdiff + ", mDataUpatePeriod=" + mDataUpdatePeriod + ", mAppRestartTimeout=" + mAppRestartTimeout
|
||||||
+ ", combined = " + (mDataUpdatePeriod + mAppRestartTimeout) * 1000);
|
// + ", combined = " + (mDataUpdatePeriod + mAppRestartTimeout) * 1000);
|
||||||
if (!mWatchAppRunningCheck &&
|
if (!mWatchAppRunningCheck &&
|
||||||
(tdiff > (mDataUpdatePeriod + mAppRestartTimeout) * 1000)) {
|
(tdiff > (mDataUpdatePeriod + mAppRestartTimeout) * 1000)) {
|
||||||
Log.v(TAG, "faultCheck() - watch app not running so not doing anything");
|
//Log.v(TAG, "faultCheck() - watch app not running so not doing anything");
|
||||||
mAlarmCount = 0;
|
mAlarmCount = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -814,6 +880,19 @@ public abstract class SdDataSource {
|
|||||||
Log.v(TAG, "updatePrefs() HRThreshMax = " + mSdData.mHRThreshMax);
|
Log.v(TAG, "updatePrefs() HRThreshMax = " + mSdData.mHRThreshMax);
|
||||||
mUtil.writeToSysLogFile( "updatePrefs() HRThreshMax = " + mSdData.mHRThreshMax);
|
mUtil.writeToSysLogFile( "updatePrefs() HRThreshMax = " + mSdData.mHRThreshMax);
|
||||||
|
|
||||||
|
mSdData.mO2SatAlarmActive = SP.getBoolean("O2SatAlarmActive", false);
|
||||||
|
Log.v(TAG, "updatePrefs() O2SatAlarmActive = " + mSdData.mO2SatAlarmActive);
|
||||||
|
mUtil.writeToSysLogFile( "updatePrefs() O2SatAlarmActive = " + mSdData.mO2SatAlarmActive);
|
||||||
|
|
||||||
|
mSdData.mO2SatNullAsAlarm = SP.getBoolean("O2SatNullAsAlarm", false);
|
||||||
|
Log.v(TAG, "updatePrefs() O2SatNullAsAlarm = " + mSdData.mO2SatNullAsAlarm);
|
||||||
|
mUtil.writeToSysLogFile( "updatePrefs() O2SatNullAsAlarm = " + mSdData.mO2SatNullAsAlarm);
|
||||||
|
|
||||||
|
prefStr = SP.getString("O2SatThreshMin", "SET_FROM_XML");
|
||||||
|
mSdData.mO2SatThreshMin = (short) Integer.parseInt(prefStr);
|
||||||
|
Log.v(TAG, "updatePrefs() O2SatThreshMin = " + mSdData.mO2SatThreshMin);
|
||||||
|
mUtil.writeToSysLogFile( "updatePrefs() O2SatThreshMin = " + mSdData.mO2SatThreshMin);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
Log.v(TAG, "updatePrefs() - prefStr is null - WHY????");
|
Log.v(TAG, "updatePrefs() - prefStr is null - WHY????");
|
||||||
mUtil.writeToSysLogFile("SDDataSource.updatePrefs() - prefStr is null - WHY??");
|
mUtil.writeToSysLogFile("SDDataSource.updatePrefs() - prefStr is null - WHY??");
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -63,6 +63,7 @@ public class SdDataSourceBLE extends SdDataSource {
|
|||||||
|
|
||||||
private int nRawData = 0;
|
private int nRawData = 0;
|
||||||
private double[] rawData = new double[MAX_RAW_DATA];
|
private double[] rawData = new double[MAX_RAW_DATA];
|
||||||
|
private boolean waitForDescriptorWrite = false;
|
||||||
|
|
||||||
private static final int STATE_DISCONNECTED = 0;
|
private static final int STATE_DISCONNECTED = 0;
|
||||||
private static final int STATE_CONNECTING = 1;
|
private static final int STATE_CONNECTING = 1;
|
||||||
@@ -82,13 +83,12 @@ public class SdDataSourceBLE extends SdDataSource {
|
|||||||
|
|
||||||
public static String SERV_DEV_INFO = "0000180a-0000-1000-8000-00805f9b34fb";
|
public static String SERV_DEV_INFO = "0000180a-0000-1000-8000-00805f9b34fb";
|
||||||
public static String SERV_HEART_RATE = "0000180d-0000-1000-8000-00805f9b34fb";
|
public static String SERV_HEART_RATE = "0000180d-0000-1000-8000-00805f9b34fb";
|
||||||
public static String SERV_OSD = "a19585e9-0001-39d0-015f-b3e2b9a0c854";
|
public static String SERV_OSD = "000085e9-0000-1000-8000-00805f9b34fb";
|
||||||
public static String CHAR_HEART_RATE_MEASUREMENT = "00002a37-0000-1000-8000-00805f9b34fb";
|
public static String CHAR_HEART_RATE_MEASUREMENT = "00002a37-0000-1000-8000-00805f9b34fb";
|
||||||
public static String CHAR_MANUF_NAME = "00002a29-0000-1000-8000-00805f9b34fb";
|
public static String CHAR_MANUF_NAME = "00002a29-0000-1000-8000-00805f9b34fb";
|
||||||
public static String CLIENT_CHARACTERISTIC_CONFIG = "00002902-0000-1000-8000-00805f9b34fb";
|
public static String CLIENT_CHARACTERISTIC_CONFIG = "00002902-0000-1000-8000-00805f9b34fb";
|
||||||
public static String CHAR_OSD_ACC_DATA = "a19585e9-0002-39d0-015f-b3e2b9a0c854";
|
public static String CHAR_OSD_ACC_DATA = "000085ea-0000-1000-8000-00805f9b34fb";
|
||||||
public static String CHAR_OSD_BATT_DATA = "a19585e9-0004-39d0-015f-b3e2b9a0c854";
|
public static String CHAR_OSD_BATT_DATA = "000085eb-0000-1000-8000-00805f9b34fb";
|
||||||
|
|
||||||
|
|
||||||
public final static UUID UUID_HEART_RATE_MEASUREMENT = UUID.fromString(CHAR_HEART_RATE_MEASUREMENT);
|
public final static UUID UUID_HEART_RATE_MEASUREMENT = UUID.fromString(CHAR_HEART_RATE_MEASUREMENT);
|
||||||
private BluetoothGatt mGatt;
|
private BluetoothGatt mGatt;
|
||||||
@@ -264,7 +264,8 @@ public class SdDataSourceBLE extends SdDataSource {
|
|||||||
}
|
}
|
||||||
else if (charUuidStr.equals(CHAR_OSD_BATT_DATA)) {
|
else if (charUuidStr.equals(CHAR_OSD_BATT_DATA)) {
|
||||||
Log.v(TAG,"Saving battery characteristic for later");
|
Log.v(TAG,"Saving battery characteristic for later");
|
||||||
mBattChar = gattCharacteristic;
|
Log.v(TAG, "Subscribing to battery change Notifications");
|
||||||
|
setCharacteristicNotification(gattCharacteristic,true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -287,6 +288,8 @@ public class SdDataSourceBLE extends SdDataSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void onDataReceived(BluetoothGattCharacteristic characteristic) {
|
public void onDataReceived(BluetoothGattCharacteristic characteristic) {
|
||||||
|
Log.v(TAG, "onDataReceived uuid" + characteristic.getUuid().toString());
|
||||||
|
|
||||||
// FIXME - collect data until we have enough to do analysis, then use onDataReceived to process it.
|
// FIXME - collect data until we have enough to do analysis, then use onDataReceived to process it.
|
||||||
//Log.v(TAG,"onDataReceived: Characteristic="+characteristic.getUuid().toString());
|
//Log.v(TAG,"onDataReceived: Characteristic="+characteristic.getUuid().toString());
|
||||||
if (characteristic.getUuid().toString().equals(CHAR_HEART_RATE_MEASUREMENT)) {
|
if (characteristic.getUuid().toString().equals(CHAR_HEART_RATE_MEASUREMENT)) {
|
||||||
@@ -294,12 +297,13 @@ public class SdDataSourceBLE extends SdDataSource {
|
|||||||
int format = -1;
|
int format = -1;
|
||||||
if ((flag & 0x01) != 0) {
|
if ((flag & 0x01) != 0) {
|
||||||
format = BluetoothGattCharacteristic.FORMAT_UINT16;
|
format = BluetoothGattCharacteristic.FORMAT_UINT16;
|
||||||
//Log.d(TAG, "Heart rate format UINT16.");
|
Log.d(TAG, "Heart rate format UINT16.");
|
||||||
} else {
|
} else {
|
||||||
format = BluetoothGattCharacteristic.FORMAT_UINT8;
|
format = BluetoothGattCharacteristic.FORMAT_UINT8;
|
||||||
//Log.d(TAG, "Heart rate format UINT8.");
|
Log.d(TAG, "Heart rate format UINT8.");
|
||||||
}
|
}
|
||||||
final int heartRate = characteristic.getIntValue(format, 1);
|
final int heartRate = characteristic.getIntValue(format, 1);
|
||||||
|
mSdData.mHR = (double) heartRate;
|
||||||
Log.d(TAG, String.format("Received heart rate: %d", heartRate));
|
Log.d(TAG, String.format("Received heart rate: %d", heartRate));
|
||||||
}
|
}
|
||||||
else if (characteristic.getUuid().toString().equals(CHAR_OSD_ACC_DATA)) {
|
else if (characteristic.getUuid().toString().equals(CHAR_OSD_ACC_DATA)) {
|
||||||
@@ -322,21 +326,15 @@ public class SdDataSourceBLE extends SdDataSource {
|
|||||||
//mNSamp = accelVals.length();
|
//mNSamp = accelVals.length();
|
||||||
mWatchAppRunningCheck = true;
|
mWatchAppRunningCheck = true;
|
||||||
mDataStatusTime = new Time(Time.getCurrentTimezone());
|
mDataStatusTime = new Time(Time.getCurrentTimezone());
|
||||||
|
|
||||||
if (mSdData.haveSettings == false) {
|
|
||||||
Log.v(TAG,"Requesting Battery Data");
|
|
||||||
mGatt.readCharacteristic(mBattChar);
|
|
||||||
}
|
|
||||||
|
|
||||||
doAnalysis();
|
doAnalysis();
|
||||||
|
|
||||||
nRawData = 0;
|
nRawData = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (characteristic.getUuid().toString().equals(CHAR_OSD_BATT_DATA)) {
|
else if (characteristic.getUuid().toString().equals(CHAR_OSD_BATT_DATA)) {
|
||||||
mSdData.batteryPc = characteristic.getValue()[0];
|
byte batteryPc = characteristic.getValue()[0];
|
||||||
Log.v(TAG,"Received Battery Data");
|
mSdData.batteryPc = batteryPc;
|
||||||
|
Log.v(TAG,"Received Battery Data" + String.format("%d", batteryPc));
|
||||||
mSdData.haveSettings = true;
|
mSdData.haveSettings = true;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -361,8 +359,13 @@ public class SdDataSourceBLE extends SdDataSource {
|
|||||||
Log.v(TAG,"onCharacteristicChanged(): Characteristic "+characteristic.getUuid()+" changed");
|
Log.v(TAG,"onCharacteristicChanged(): Characteristic "+characteristic.getUuid()+" changed");
|
||||||
onDataReceived(characteristic);
|
onDataReceived(characteristic);
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
|
||||||
|
Log.v(TAG,"onDescriptorWrite(): Characteristic " + descriptor.getUuid() + " changed");
|
||||||
|
waitForDescriptorWrite = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enables or disables notification on a give characteristic.
|
* Enables or disables notification on a give characteristic.
|
||||||
@@ -370,12 +373,27 @@ public class SdDataSourceBLE extends SdDataSource {
|
|||||||
* @param characteristic Characteristic to act on.
|
* @param characteristic Characteristic to act on.
|
||||||
* @param enabled If true, enable notification. False otherwise.
|
* @param enabled If true, enable notification. False otherwise.
|
||||||
*/
|
*/
|
||||||
public void setCharacteristicNotification(BluetoothGattCharacteristic characteristic,
|
public void setCharacteristicNotification(final BluetoothGattCharacteristic characteristic, final boolean enabled) {
|
||||||
boolean enabled) {
|
Log.w(TAG, "setCharacteristicNotification " + characteristic.getUuid());
|
||||||
|
|
||||||
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
|
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
|
||||||
Log.w(TAG, "BluetoothAdapter not initialized");
|
Log.w(TAG, "BluetoothAdapter not initialized");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (waitForDescriptorWrite) {
|
||||||
|
// Apparently if you try to write multiple descriptors too quickly then only
|
||||||
|
// one is processed, hence why this waiting logic is necessary
|
||||||
|
Log.w(TAG, "waitForDescriptor " + characteristic.getUuid());
|
||||||
|
mHandler.postDelayed(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
Log.w(TAG, "delayed");
|
||||||
|
setCharacteristicNotification(characteristic, enabled);
|
||||||
|
}
|
||||||
|
}, 500);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (enabled) {
|
if (enabled) {
|
||||||
Log.v(TAG, "setCharacteristicNotification - Requesting notifications");
|
Log.v(TAG, "setCharacteristicNotification - Requesting notifications");
|
||||||
mBluetoothGatt.setCharacteristicNotification(characteristic, true);
|
mBluetoothGatt.setCharacteristicNotification(characteristic, true);
|
||||||
@@ -396,8 +414,9 @@ public class SdDataSourceBLE extends SdDataSource {
|
|||||||
UUID.fromString(GattAttributes.CLIENT_CHARACTERISTIC_CONFIG));
|
UUID.fromString(GattAttributes.CLIENT_CHARACTERISTIC_CONFIG));
|
||||||
descriptor.setValue(BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE);
|
descriptor.setValue(BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE);
|
||||||
mBluetoothGatt.writeDescriptor(descriptor);
|
mBluetoothGatt.writeDescriptor(descriptor);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
waitForDescriptorWrite = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -414,12 +433,3 @@ public class SdDataSourceBLE extends SdDataSource {
|
|||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -129,6 +129,9 @@ public class SdDataSourcePhone extends SdDataSource implements SensorEventListen
|
|||||||
float z = event.values[2];
|
float z = event.values[2];
|
||||||
//Log.v(TAG,"Accelerometer Data Received: x="+x+", y="+y+", z="+z);
|
//Log.v(TAG,"Accelerometer Data Received: x="+x+", y="+y+", z="+z);
|
||||||
mSdData.rawData[mSdData.mNsamp] = sqrt(x*x + y*y + z*z);
|
mSdData.rawData[mSdData.mNsamp] = sqrt(x*x + y*y + z*z);
|
||||||
|
mSdData.rawData3D[3*mSdData.mNsamp] = x;
|
||||||
|
mSdData.rawData3D[3*mSdData.mNsamp+1] = y;
|
||||||
|
mSdData.rawData3D[3*mSdData.mNsamp+2] = z;
|
||||||
mSdData.mNsamp++;
|
mSdData.mNsamp++;
|
||||||
if (mSdData.mNsamp==NSAMP) {
|
if (mSdData.mNsamp==NSAMP) {
|
||||||
// Calculate the sample frequency for this sample, but do not change mSampleFreq, which is used for
|
// Calculate the sample frequency for this sample, but do not change mSampleFreq, which is used for
|
||||||
@@ -142,6 +145,9 @@ public class SdDataSourcePhone extends SdDataSource implements SensorEventListen
|
|||||||
// FIXME - we should really do this properly rather than assume we are really receiving data at 50Hz.
|
// FIXME - we should really do this properly rather than assume we are really receiving data at 50Hz.
|
||||||
for (int i=0; i<mSdData.mNsamp; i++) {
|
for (int i=0; i<mSdData.mNsamp; i++) {
|
||||||
mSdData.rawData[i/2] = 1000.*mSdData.rawData[i]/9.81;
|
mSdData.rawData[i/2] = 1000.*mSdData.rawData[i]/9.81;
|
||||||
|
mSdData.rawData3D[i/2] = 1000.*mSdData.rawData3D[i]/9.81;
|
||||||
|
mSdData.rawData3D[i/2 +1] = 1000.*mSdData.rawData3D[i+1]/9.81;
|
||||||
|
mSdData.rawData3D[i/2 +2] = 1000.*mSdData.rawData3D[i+2]/9.81;
|
||||||
//Log.v(TAG,"i="+i+", rawData="+mSdData.rawData[i]+","+mSdData.rawData[i/2]);
|
//Log.v(TAG,"i="+i+", rawData="+mSdData.rawData[i]+","+mSdData.rawData[i/2]);
|
||||||
}
|
}
|
||||||
mSdData.mNsamp /= 2;
|
mSdData.mNsamp /= 2;
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -104,13 +104,18 @@ public class SdWebServer extends NanoHTTPD {
|
|||||||
Log.v(TAG, " files=" + files.toString());
|
Log.v(TAG, " files=" + files.toString());
|
||||||
String postData = files.get("postData");
|
String postData = files.get("postData");
|
||||||
Log.v(TAG, " postData=" + postData);
|
Log.v(TAG, " postData=" + postData);
|
||||||
// Send the data to the SdDataSource so the app can pick it up.
|
if (mSdServer.mSdDataSourceName.equals("Garmin")) {
|
||||||
if (parameters.get("dataObj") != null) {
|
// Send the data to the SdDataSource so the app can pick it up.
|
||||||
Log.v(TAG,"passing parameters to data source");
|
if (parameters.get("dataObj") != null) {
|
||||||
answer = mSdServer.mSdDataSource.updateFromJSON(parameters.get("dataObj").toString());
|
Log.v(TAG, "passing parameters to data source");
|
||||||
|
answer = mSdServer.mSdDataSource.updateFromJSON(parameters.get("dataObj").toString());
|
||||||
|
} else {
|
||||||
|
Log.v(TAG, "Passing postData to data source");
|
||||||
|
answer = mSdServer.mSdDataSource.updateFromJSON(files.get("postData"));
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
Log.v(TAG,"Passing postData to data source");
|
Log.i(TAG,"Web server received data, but datasource is not set to 'Garmin' - Ignoring");
|
||||||
answer = mSdServer.mSdDataSource.updateFromJSON(files.get("postData"));
|
mUtil.showToast("Web server received data, but datasource is not set to 'Garmin' - Ignoring");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -202,7 +207,7 @@ public class SdWebServer extends NanoHTTPD {
|
|||||||
} else {
|
} else {
|
||||||
Log.v(TAG, "WebServer.serve() - Unknown uri -" +
|
Log.v(TAG, "WebServer.serve() - Unknown uri -" +
|
||||||
uri);
|
uri);
|
||||||
answer = "{'msg' : 'Unknown URI: '}";
|
answer = "{'msg' : 'Unknown URI: "+uri+"'}";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
res = new NanoHTTPD.Response(answer);
|
res = new NanoHTTPD.Response(answer);
|
||||||
|
|||||||
@@ -24,20 +24,22 @@
|
|||||||
*/
|
*/
|
||||||
package uk.org.openseizuredetector;
|
package uk.org.openseizuredetector;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.Manifest;
|
||||||
import android.app.AlertDialog;
|
|
||||||
import android.content.ComponentName;
|
import android.content.ComponentName;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.DialogInterface;
|
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.net.Uri;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
|
import android.os.PowerManager;
|
||||||
import android.preference.PreferenceManager;
|
import android.preference.PreferenceManager;
|
||||||
|
import android.text.Html;
|
||||||
import android.text.SpannableString;
|
import android.text.SpannableString;
|
||||||
import android.text.SpannedString;
|
|
||||||
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;
|
||||||
@@ -46,6 +48,12 @@ import android.widget.Button;
|
|||||||
import android.widget.ProgressBar;
|
import android.widget.ProgressBar;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.appcompat.app.AlertDialog;
|
||||||
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
import androidx.core.app.ActivityCompat;
|
||||||
|
import androidx.core.content.ContextCompat;
|
||||||
|
import androidx.core.text.HtmlCompat;
|
||||||
|
|
||||||
import com.rohitss.uceh.UCEHandler;
|
import com.rohitss.uceh.UCEHandler;
|
||||||
|
|
||||||
import java.util.Timer;
|
import java.util.Timer;
|
||||||
@@ -56,7 +64,7 @@ import java.util.TimerTask;
|
|||||||
* for it to start and to receive data and settings from the seizure detector before exiting and
|
* for it to start and to receive data and settings from the seizure detector before exiting and
|
||||||
* starting the main activity.
|
* starting the main activity.
|
||||||
*/
|
*/
|
||||||
public class StartupActivity extends Activity {
|
public class StartupActivity extends AppCompatActivity {
|
||||||
private static String TAG = "StartupActivity";
|
private static String TAG = "StartupActivity";
|
||||||
private int okColour = Color.BLUE;
|
private int okColour = Color.BLUE;
|
||||||
private int warnColour = Color.MAGENTA;
|
private int warnColour = Color.MAGENTA;
|
||||||
@@ -74,11 +82,42 @@ public class StartupActivity extends Activity {
|
|||||||
private Handler mHandler = new Handler(); // used to update ui from mUiTimer
|
private Handler mHandler = new Handler(); // used to update ui from mUiTimer
|
||||||
private boolean mUsingPebbleDataSource = true;
|
private boolean mUsingPebbleDataSource = true;
|
||||||
private String mPebbleAppPackageName = null;
|
private String mPebbleAppPackageName = null;
|
||||||
|
private boolean mBatteryOptDialogDisplayed = false;
|
||||||
|
private AlertDialog mBatteryOptDialog;
|
||||||
|
private boolean mLocationPermissions1Requested;
|
||||||
|
private boolean mLocationPermissions2Requested;
|
||||||
|
private boolean mSmsPermissionsRequested;
|
||||||
|
private boolean mPermissionsRequested;
|
||||||
|
|
||||||
|
public final String[] REQUIRED_PERMISSIONS = {
|
||||||
|
//Manifest.permission.WRITE_EXTERNAL_STORAGE,
|
||||||
|
Manifest.permission.WAKE_LOCK,
|
||||||
|
};
|
||||||
|
|
||||||
|
public final String[] SMS_PERMISSIONS_1 = {
|
||||||
|
Manifest.permission.SEND_SMS,
|
||||||
|
Manifest.permission.READ_PHONE_STATE,
|
||||||
|
};
|
||||||
|
|
||||||
|
public final String[] LOCATION_PERMISSIONS_1 = {
|
||||||
|
Manifest.permission.SEND_SMS,
|
||||||
|
Manifest.permission.ACCESS_FINE_LOCATION,
|
||||||
|
//Manifest.permission.ACCESS_BACKGROUND_LOCATION,
|
||||||
|
Manifest.permission.READ_PHONE_STATE,
|
||||||
|
};
|
||||||
|
|
||||||
|
public final String[] LOCATION_PERMISSIONS_2 = {
|
||||||
|
Manifest.permission.ACCESS_BACKGROUND_LOCATION,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
Log.i(TAG,"onCreate()");
|
Log.i(TAG, "onCreate()");
|
||||||
|
setContentView(R.layout.startup_activity);
|
||||||
|
|
||||||
// Set our custom uncaught exception handler to report issues.
|
// Set our custom uncaught exception handler to report issues.
|
||||||
//Thread.setDefaultUncaughtExceptionHandler(new OsdUncaughtExceptionHandler(StartupActivity.this));
|
//Thread.setDefaultUncaughtExceptionHandler(new OsdUncaughtExceptionHandler(StartupActivity.this));
|
||||||
@@ -86,20 +125,6 @@ public class StartupActivity extends Activity {
|
|||||||
.addCommaSeparatedEmailAddresses("crashreports@openseizuredetector.org.uk,")
|
.addCommaSeparatedEmailAddresses("crashreports@openseizuredetector.org.uk,")
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
|
||||||
mHandler = new Handler();
|
|
||||||
mUtil = new OsdUtil(this, mHandler);
|
|
||||||
mUtil.writeToSysLogFile("");
|
|
||||||
mUtil.writeToSysLogFile("*******************************");
|
|
||||||
mUtil.writeToSysLogFile("* StartUpActivity Started *");
|
|
||||||
mUtil.writeToSysLogFile("*******************************");
|
|
||||||
|
|
||||||
// Force the screen to stay on when the app is running
|
|
||||||
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
|
|
||||||
|
|
||||||
|
|
||||||
setContentView(R.layout.startup_activity);
|
|
||||||
|
|
||||||
// Read the default settings from the xml preferences files, so we do
|
// Read the default settings from the xml preferences files, so we do
|
||||||
// not have to use the hard coded ones in the java files.
|
// not have to use the hard coded ones in the java files.
|
||||||
PreferenceManager.setDefaultValues(this, R.xml.alarm_prefs, true);
|
PreferenceManager.setDefaultValues(this, R.xml.alarm_prefs, true);
|
||||||
@@ -108,6 +133,17 @@ public class StartupActivity extends Activity {
|
|||||||
PreferenceManager.setDefaultValues(this, R.xml.pebble_datasource_prefs, true);
|
PreferenceManager.setDefaultValues(this, R.xml.pebble_datasource_prefs, true);
|
||||||
PreferenceManager.setDefaultValues(this, R.xml.seizure_detector_prefs, true);
|
PreferenceManager.setDefaultValues(this, R.xml.seizure_detector_prefs, true);
|
||||||
PreferenceManager.setDefaultValues(this, R.xml.network_passive_datasource_prefs, true);
|
PreferenceManager.setDefaultValues(this, R.xml.network_passive_datasource_prefs, true);
|
||||||
|
PreferenceManager.setDefaultValues(this, R.xml.logging_prefs, true);
|
||||||
|
|
||||||
|
mHandler = new Handler();
|
||||||
|
mUtil = new OsdUtil(getApplicationContext(), mHandler);
|
||||||
|
mUtil.writeToSysLogFile("");
|
||||||
|
mUtil.writeToSysLogFile("*******************************");
|
||||||
|
mUtil.writeToSysLogFile("* StartUpActivity Started *");
|
||||||
|
mUtil.writeToSysLogFile("*******************************");
|
||||||
|
|
||||||
|
// Force the screen to stay on when the app is running
|
||||||
|
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
|
||||||
|
|
||||||
|
|
||||||
Button b;
|
Button b;
|
||||||
@@ -142,24 +178,16 @@ public class StartupActivity extends Activity {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
mConnection = new SdServiceConnection(this);
|
mConnection = new SdServiceConnection(getApplicationContext());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onStart() {
|
protected void onStart() {
|
||||||
super.onStart();
|
super.onStart();
|
||||||
Log.i(TAG,"onStart()");
|
Log.i(TAG, "onStart()");
|
||||||
mUtil.writeToSysLogFile("StartupActivity.onStart()");
|
mUtil.writeToSysLogFile("StartupActivity.onStart()");
|
||||||
TextView tv;
|
TextView tv;
|
||||||
|
|
||||||
if (mUtil.arePermissionsOK()) {
|
|
||||||
Log.i(TAG,"onStart() - Permissions OK");
|
|
||||||
} else {
|
|
||||||
Log.i(TAG,"onStart() - Permissions Not OK - requesting them");
|
|
||||||
mUtil.requestPermissions(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
String versionName = mUtil.getAppVersionName();
|
String versionName = mUtil.getAppVersionName();
|
||||||
tv = (TextView) findViewById(R.id.appNameTv);
|
tv = (TextView) findViewById(R.id.appNameTv);
|
||||||
tv.setText("OpenSeizureDetector V" + versionName);
|
tv.setText("OpenSeizureDetector V" + versionName);
|
||||||
@@ -174,18 +202,36 @@ public class StartupActivity extends Activity {
|
|||||||
|
|
||||||
|
|
||||||
if (mUtil.isServerRunning()) {
|
if (mUtil.isServerRunning()) {
|
||||||
Log.i(TAG, "onStart() - server running - stopping it");
|
Log.i(TAG, "onStart() - server running - stopping it - isServerRunning="+mUtil.isServerRunning());
|
||||||
mUtil.writeToSysLogFile("StartupActivity.onStart() - server already running - stopping it.");
|
mUtil.writeToSysLogFile("StartupActivity.onStart() - server already running - stopping it.");
|
||||||
mUtil.stopServer();
|
mUtil.stopServer();
|
||||||
|
} else {
|
||||||
|
Log.i(TAG, "onStart() - server not running - isServerRunning="+mUtil.isServerRunning());
|
||||||
|
}
|
||||||
|
// Wait 0.1 second to give the server chance to shutdown in case we have just shut it down below, then start it
|
||||||
|
mHandler.postDelayed(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
mUtil.writeToSysLogFile("StartupActivity.onStart() - starting server after delay - isServerRunning="+mUtil.isServerRunning());
|
||||||
|
Log.i(TAG, "onStart() - starting server after delay -isServerRunning="+mUtil.isServerRunning());
|
||||||
|
mUtil.startServer();
|
||||||
|
// Bind to the service.
|
||||||
|
Log.i(TAG, "onStart() - binding to server");
|
||||||
|
mUtil.writeToSysLogFile("StartupActivity.onStart() - binding to server");
|
||||||
|
mUtil.bindToServer(getApplicationContext(), mConnection);
|
||||||
|
}
|
||||||
|
}, 100);
|
||||||
|
|
||||||
|
// Check power management settings
|
||||||
|
PowerManager powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
|
||||||
|
if (powerManager.isIgnoringBatteryOptimizations(getPackageName())) {
|
||||||
|
Log.i(TAG, "Power Management OK - we are ignoring Battery Optimizations");
|
||||||
|
mBatteryOptDialogDisplayed = false;
|
||||||
|
} else {
|
||||||
|
Log.e(TAG, "Power Management Problem - not ignoring Battery Optimisations");
|
||||||
|
//mUtil.showToast("WARNING - Phone is Optimising OpenSeizureDetector Battery Usage - this is likely to prevent it working correctly when running on battery!");
|
||||||
|
if (!mBatteryOptDialogDisplayed) showBatteryOptimisationWarningDialog();
|
||||||
}
|
}
|
||||||
mUtil.writeToSysLogFile("StartupActivity.onStart() - starting server");
|
|
||||||
Log.i(TAG,"onStart() - starting server");
|
|
||||||
mUtil.startServer();
|
|
||||||
|
|
||||||
// Bind to the service.
|
|
||||||
Log.i(TAG,"onStart() - binding to server");
|
|
||||||
mUtil.writeToSysLogFile("StartupActivity.onStart() - binding to server");
|
|
||||||
mUtil.bindToServer(this, mConnection);
|
|
||||||
|
|
||||||
// Check to see if this is the first time the app has been run, and display welcome dialog if it is.
|
// Check to see if this is the first time the app has been run, and display welcome dialog if it is.
|
||||||
checkFirstRun();
|
checkFirstRun();
|
||||||
@@ -198,7 +244,7 @@ public class StartupActivity extends Activity {
|
|||||||
mHandler.post(serverStatusRunnable);
|
mHandler.post(serverStatusRunnable);
|
||||||
//updateServerStatus();
|
//updateServerStatus();
|
||||||
}
|
}
|
||||||
}, 0, 1000);
|
}, 0, 2000);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -208,17 +254,17 @@ public class StartupActivity extends Activity {
|
|||||||
super.onStop();
|
super.onStop();
|
||||||
Log.i(TAG, "onStop() - unbinding from server");
|
Log.i(TAG, "onStop() - unbinding from server");
|
||||||
mUtil.writeToSysLogFile("StartupActivity.onStop() - unbinding from server");
|
mUtil.writeToSysLogFile("StartupActivity.onStop() - unbinding from server");
|
||||||
mUtil.unbindFromServer(this, mConnection);
|
mUtil.unbindFromServer(getApplicationContext(), mConnection);
|
||||||
mUiTimer.cancel();
|
mUiTimer.cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* serverStatusRunnable - called by updateServerStatus - updates the
|
* serverStatusRunnable - called by updateServerStatus - updates the
|
||||||
* user interface to reflect the current status received from the server.
|
* user interface to reflect the current status received from the server.
|
||||||
* If everything is ok, we close this activity and open the main user interface
|
* If everything is ok, we close this activity and open the main user interface
|
||||||
* activity.
|
* activity.
|
||||||
*/
|
*/
|
||||||
final Runnable serverStatusRunnable = new Runnable() {
|
final Runnable serverStatusRunnable = new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
Boolean allOk = true;
|
Boolean allOk = true;
|
||||||
@@ -227,23 +273,49 @@ public class StartupActivity extends Activity {
|
|||||||
boolean smsAlarmsActive = true;
|
boolean smsAlarmsActive = true;
|
||||||
boolean phoneAlarmsActive = true;
|
boolean phoneAlarmsActive = true;
|
||||||
|
|
||||||
Log.v(TAG,"serverStatusRunnable()");
|
Log.v(TAG, "serverStatusRunnable()");
|
||||||
SharedPreferences SP = PreferenceManager
|
SharedPreferences SP = PreferenceManager
|
||||||
.getDefaultSharedPreferences(getBaseContext());
|
.getDefaultSharedPreferences(getBaseContext());
|
||||||
smsAlarmsActive = SP.getBoolean("SMSAlarm", false);
|
smsAlarmsActive = SP.getBoolean("SMSAlarm", false);
|
||||||
phoneAlarmsActive = SP.getBoolean("PhoneCallAlarm", false);
|
phoneAlarmsActive = SP.getBoolean("PhoneCallAlarm", false);
|
||||||
|
|
||||||
|
// Check power management settings
|
||||||
|
PowerManager powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
|
||||||
|
if (powerManager.isIgnoringBatteryOptimizations(getPackageName())) {
|
||||||
|
Log.i(TAG, "Power Management OK - we are ignoring Battery Optimizations");
|
||||||
|
if (mBatteryOptDialogDisplayed) {
|
||||||
|
mBatteryOptDialog.cancel();
|
||||||
|
mBatteryOptDialogDisplayed = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Settings ok
|
// Settings ok
|
||||||
tv = (TextView) findViewById(R.id.textItem1);
|
tv = (TextView) findViewById(R.id.textItem1);
|
||||||
pb = (ProgressBar) findViewById(R.id.progressBar1);
|
pb = (ProgressBar) findViewById(R.id.progressBar1);
|
||||||
if (mUtil.arePermissionsOK()) {
|
if (arePermissionsOK()) {
|
||||||
if (smsAlarmsActive && !mUtil.areSMSPermissionsOK()) {
|
if (smsAlarmsActive && !areSMSPermissions1OK()) {
|
||||||
|
Log.i(TAG,"SMS permissions NOT OK");
|
||||||
tv.setText(getString(R.string.SmsPermissionWarning));
|
tv.setText(getString(R.string.SmsPermissionWarning));
|
||||||
tv.setBackgroundColor(okColour);
|
tv.setBackgroundColor(alarmColour);
|
||||||
tv.setTextColor(okTextColour);
|
tv.setTextColor(alarmTextColour);
|
||||||
pb.setIndeterminateDrawable(getResources().getDrawable(R.drawable.start_server));
|
//pb.setIndeterminateDrawable(getResources().getDrawable(R.drawable.start_server));
|
||||||
pb.setProgressDrawable(getResources().getDrawable(R.drawable.start_server));
|
//pb.setProgressDrawable(getResources().getDrawable(R.drawable.start_server));
|
||||||
mUtil.requestSMSPermissions(StartupActivity.this);
|
requestSMSPermissions();
|
||||||
|
allOk = false;
|
||||||
|
} else if (smsAlarmsActive && !areLocationPermissions1OK()) {
|
||||||
|
Log.i(TAG,"Location permissions NOT OK");
|
||||||
|
tv.setText(getString(R.string.SmsPermissionWarning));
|
||||||
|
tv.setBackgroundColor(alarmColour);
|
||||||
|
tv.setTextColor(alarmTextColour);
|
||||||
|
requestLocationPermissions1();
|
||||||
|
allOk = false;
|
||||||
|
} else if (smsAlarmsActive && !areLocationPermissions2OK()) {
|
||||||
|
Log.i(TAG,"SMS permissions2 NOT OK");
|
||||||
|
tv.setText(getString(R.string.SmsPermissionWarning));
|
||||||
|
tv.setBackgroundColor(alarmColour);
|
||||||
|
tv.setTextColor(alarmTextColour);
|
||||||
|
requestLocationPermissions2();
|
||||||
|
allOk = false;
|
||||||
} else {
|
} else {
|
||||||
tv.setText(getString(R.string.AppPermissionsOk));
|
tv.setText(getString(R.string.AppPermissionsOk));
|
||||||
tv.setBackgroundColor(okColour);
|
tv.setBackgroundColor(okColour);
|
||||||
@@ -257,7 +329,7 @@ public class StartupActivity extends Activity {
|
|||||||
tv.setTextColor(alarmTextColour);
|
tv.setTextColor(alarmTextColour);
|
||||||
pb.setIndeterminate(true);
|
pb.setIndeterminate(true);
|
||||||
allOk = false;
|
allOk = false;
|
||||||
mUtil.requestPermissions(StartupActivity.this);
|
requestPermissions(StartupActivity.this);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If phone alarms are selected, we need to have the uk.org.openseizuredetector.dialler package installed to do the actual dialling.
|
// If phone alarms are selected, we need to have the uk.org.openseizuredetector.dialler package installed to do the actual dialling.
|
||||||
@@ -305,7 +377,6 @@ public class StartupActivity extends Activity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Do we have seizure detector data?
|
// Do we have seizure detector data?
|
||||||
tv = (TextView) findViewById(R.id.textItem5);
|
tv = (TextView) findViewById(R.id.textItem5);
|
||||||
pb = (ProgressBar) findViewById(R.id.progressBar5);
|
pb = (ProgressBar) findViewById(R.id.progressBar5);
|
||||||
@@ -342,11 +413,10 @@ public class StartupActivity extends Activity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// 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
|
||||||
// user interface activity instead.
|
// user interface activity instead.
|
||||||
if (allOk) {
|
if (allOk) {
|
||||||
if (!mDialogDisplayed) {
|
if (!mDialogDisplayed && !mBatteryOptDialogDisplayed) {
|
||||||
if (!mStartedMainActivity) {
|
if (!mStartedMainActivity) {
|
||||||
Log.i(TAG, "serverStatusRunnable() - starting main activity...");
|
Log.i(TAG, "serverStatusRunnable() - starting main activity...");
|
||||||
mUtil.writeToSysLogFile("StartupActivity.serverStatusRunnable - all checks ok - starting main activity.");
|
mUtil.writeToSysLogFile("StartupActivity.serverStatusRunnable - all checks ok - starting main activity.");
|
||||||
@@ -393,42 +463,65 @@ public class StartupActivity extends Activity {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* checkFirstRun - checks to see if this is the first run of the app after installation or upgrade.
|
* checkFirstRun - checks to see if this is the first run of the app after installation or upgrade.
|
||||||
* if it is, the relevant dialog message is displayed. If not, the routine just exists so start-up can continue.
|
* if it is, the relevant dialog message is displayed. If not, the routine just exists so start-up can continue.
|
||||||
*/
|
*/
|
||||||
public void checkFirstRun() {
|
public void checkFirstRun() {
|
||||||
String storedVersionName = "";
|
String storedVersionName = "";
|
||||||
String versionName;
|
String versionName;
|
||||||
AlertDialog UpdateDialog;
|
AlertDialog UpdateDialog;
|
||||||
AlertDialog FirstRunDialog;
|
AlertDialog FirstRunDialog;
|
||||||
SharedPreferences prefs;
|
SharedPreferences prefs;
|
||||||
Log.i(TAG,"checkFirstRun()");
|
Log.i(TAG, "checkFirstRun()");
|
||||||
versionName = this.getVersionName(this, StartupActivity.class);
|
versionName = this.getVersionName(this, StartupActivity.class);
|
||||||
prefs = PreferenceManager.getDefaultSharedPreferences(this);
|
prefs = PreferenceManager.getDefaultSharedPreferences(this);
|
||||||
storedVersionName = (prefs.getString("AppVersionName", null));
|
storedVersionName = (prefs.getString("AppVersionName", null));
|
||||||
Log.v(TAG,"storedVersionName="+storedVersionName+", versionName="+versionName);
|
Log.v(TAG, "storedVersionName=" + storedVersionName + ", versionName=" + versionName);
|
||||||
|
|
||||||
// CHeck for new installation
|
// CHeck for new installation
|
||||||
|
//storedVersionName = null; // FIXME Force first run dialog for easier testing ****************************
|
||||||
if (storedVersionName == null || storedVersionName.length() == 0) {
|
if (storedVersionName == null || storedVersionName.length() == 0) {
|
||||||
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(
|
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(
|
||||||
this);
|
this);
|
||||||
final SpannableString s = new SpannableString(
|
final String s = new String(
|
||||||
getString(R.string.FirstRunDlgMsg)+getString(R.string.changelog)
|
getString(R.string.FirstRunDlgMsg));
|
||||||
);
|
|
||||||
// This makes the links display as links, but they do not respond to clicks for some reason...
|
|
||||||
Linkify.addLinks(s, Linkify.ALL);
|
|
||||||
alertDialogBuilder
|
alertDialogBuilder
|
||||||
.setTitle(getString(R.string.FirstRunDlgTitle))
|
.setTitle(getString(R.string.FirstRunDlgTitle))
|
||||||
.setMessage(s)
|
.setMessage(Html.fromHtml(s))
|
||||||
.setCancelable(false)
|
.setCancelable(false)
|
||||||
.setPositiveButton(getString(R.string.okBtnTxt), new DialogInterface.OnClickListener() {
|
.setNeutralButton(getString(R.string.closeBtnTxt), new DialogInterface.OnClickListener() {
|
||||||
public void onClick(DialogInterface dialog, int id) {
|
public void onClick(DialogInterface dialog, int id) {
|
||||||
dialog.cancel();
|
dialog.cancel();
|
||||||
mDialogDisplayed = false;
|
mDialogDisplayed = false;
|
||||||
//MainActivity.this.finish();
|
//MainActivity.this.finish();
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
|
.setPositiveButton("Privacy Policy", new DialogInterface.OnClickListener() {
|
||||||
|
public void onClick(DialogInterface dialog, int id) {
|
||||||
|
dialog.cancel();
|
||||||
|
mDialogDisplayed = false;
|
||||||
|
String url = OsdUtil.PRIVACY_POLICY_URL;
|
||||||
|
Intent i = new Intent(Intent.ACTION_VIEW);
|
||||||
|
i.setData(Uri.parse(url));
|
||||||
|
startActivity(i);
|
||||||
|
dialog.cancel();
|
||||||
|
mDialogDisplayed = false;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.setNegativeButton("Data Sharing", new DialogInterface.OnClickListener() {
|
||||||
|
public void onClick(DialogInterface dialog, int id) {
|
||||||
|
dialog.cancel();
|
||||||
|
mDialogDisplayed = false;
|
||||||
|
String url = OsdUtil.DATA_SHARING_URL;
|
||||||
|
Intent i = new Intent(Intent.ACTION_VIEW);
|
||||||
|
i.setData(Uri.parse(url));
|
||||||
|
startActivity(i);
|
||||||
|
dialog.cancel();
|
||||||
|
mDialogDisplayed = false;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
;
|
||||||
FirstRunDialog = alertDialogBuilder.create();
|
FirstRunDialog = alertDialogBuilder.create();
|
||||||
Log.i(TAG, "Displaying First Run Dialog");
|
Log.i(TAG, "Displaying First Run Dialog");
|
||||||
FirstRunDialog.show();
|
FirstRunDialog.show();
|
||||||
@@ -437,19 +530,43 @@ public class StartupActivity extends Activity {
|
|||||||
// Check for update of installed application
|
// Check for update of installed application
|
||||||
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(
|
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(
|
||||||
this);
|
this);
|
||||||
final SpannableString s = new SpannableString(
|
final String s = new String(
|
||||||
getString(R.string.UpgradeMsg)+getString(R.string.changelog)
|
getString(R.string.UpgradeMsg) + getString(R.string.changelog)
|
||||||
);
|
);
|
||||||
// This makes the links display as links, but they do not respond to clicks for some reason...
|
|
||||||
Linkify.addLinks(s, Linkify.ALL);
|
|
||||||
alertDialogBuilder
|
alertDialogBuilder
|
||||||
.setTitle(getString(R.string.UpdateDialogTitleTxt))
|
.setTitle(getString(R.string.UpdateDialogTitleTxt))
|
||||||
.setMessage(s)
|
.setMessage(Html.fromHtml(s))
|
||||||
.setCancelable(false)
|
.setCancelable(false)
|
||||||
.setPositiveButton(getString(R.string.okBtnTxt), new DialogInterface.OnClickListener() {
|
.setNeutralButton(getString(R.string.closeBtnTxt), new DialogInterface.OnClickListener() {
|
||||||
public void onClick(DialogInterface dialog, int id) {
|
public void onClick(DialogInterface dialog, int id) {
|
||||||
dialog.cancel();
|
dialog.cancel();
|
||||||
mDialogDisplayed = false;
|
mDialogDisplayed = false;
|
||||||
|
//MainActivity.this.finish();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.setPositiveButton("Privacy Policy", new DialogInterface.OnClickListener() {
|
||||||
|
public void onClick(DialogInterface dialog, int id) {
|
||||||
|
dialog.cancel();
|
||||||
|
mDialogDisplayed = false;
|
||||||
|
String url = OsdUtil.PRIVACY_POLICY_URL;
|
||||||
|
Intent i = new Intent(Intent.ACTION_VIEW);
|
||||||
|
i.setData(Uri.parse(url));
|
||||||
|
startActivity(i);
|
||||||
|
dialog.cancel();
|
||||||
|
mDialogDisplayed = false;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.setNegativeButton("Data Sharing", new DialogInterface.OnClickListener() {
|
||||||
|
public void onClick(DialogInterface dialog, int id) {
|
||||||
|
dialog.cancel();
|
||||||
|
mDialogDisplayed = false;
|
||||||
|
String url = OsdUtil.DATA_SHARING_URL;
|
||||||
|
Intent i = new Intent(Intent.ACTION_VIEW);
|
||||||
|
i.setData(Uri.parse(url));
|
||||||
|
startActivity(i);
|
||||||
|
dialog.cancel();
|
||||||
|
mDialogDisplayed = false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
UpdateDialog = alertDialogBuilder.create();
|
UpdateDialog = alertDialogBuilder.create();
|
||||||
@@ -463,4 +580,202 @@ public class StartupActivity extends Activity {
|
|||||||
prefs.edit().putString("AppVersionName", versionName).commit();
|
prefs.edit().putString("AppVersionName", versionName).commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void showBatteryOptimisationWarningDialog() {
|
||||||
|
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(
|
||||||
|
this);
|
||||||
|
final SpannableString s = new SpannableString(
|
||||||
|
getString(R.string.battery_usage_optimisation_dialog_text)
|
||||||
|
);
|
||||||
|
// This makes the links display as links, but they do not respond to clicks for some reason...
|
||||||
|
Linkify.addLinks(s, Linkify.ALL);
|
||||||
|
alertDialogBuilder
|
||||||
|
.setTitle(R.string.battery_usage_optimisation_dialog_title)
|
||||||
|
.setMessage(s)
|
||||||
|
.setCancelable(false)
|
||||||
|
.setPositiveButton(getString(R.string.okBtnTxt), new DialogInterface.OnClickListener() {
|
||||||
|
public void onClick(DialogInterface dialog, int id) {
|
||||||
|
dialog.cancel();
|
||||||
|
mBatteryOptDialogDisplayed = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
mBatteryOptDialog = alertDialogBuilder.create();
|
||||||
|
Log.i(TAG, "Displaying Update Dialog");
|
||||||
|
mBatteryOptDialog.show();
|
||||||
|
mBatteryOptDialogDisplayed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
public boolean arePermissionsOK() {
|
||||||
|
boolean allOk = true;
|
||||||
|
Log.v(TAG, "arePermissionsOK");
|
||||||
|
for (int i = 0; i < REQUIRED_PERMISSIONS.length; i++) {
|
||||||
|
if (ContextCompat.checkSelfPermission(this, REQUIRED_PERMISSIONS[i])
|
||||||
|
!= PackageManager.PERMISSION_GRANTED) {
|
||||||
|
Log.i(TAG, REQUIRED_PERMISSIONS[i] + " Permission Not Granted");
|
||||||
|
allOk = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return allOk;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean areSMSPermissions1OK() {
|
||||||
|
boolean allOk = true;
|
||||||
|
Log.v(TAG, "areSMSPermissions1 OK()");
|
||||||
|
for (int i = 0; i < SMS_PERMISSIONS_1.length; i++) {
|
||||||
|
if (ContextCompat.checkSelfPermission(this, SMS_PERMISSIONS_1[i])
|
||||||
|
!= PackageManager.PERMISSION_GRANTED) {
|
||||||
|
Log.i(TAG, "areSMSPermissions1OK: "+SMS_PERMISSIONS_1[i] + " Permission Not Granted");
|
||||||
|
allOk = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return allOk;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public boolean areLocationPermissions1OK() {
|
||||||
|
boolean allOk = true;
|
||||||
|
Log.v(TAG, "areLocationPermissions1 OK()");
|
||||||
|
for (int i = 0; i < LOCATION_PERMISSIONS_1.length; i++) {
|
||||||
|
if (ContextCompat.checkSelfPermission(this, LOCATION_PERMISSIONS_1[i])
|
||||||
|
!= PackageManager.PERMISSION_GRANTED) {
|
||||||
|
Log.i(TAG, LOCATION_PERMISSIONS_1[i] + " Permission Not Granted");
|
||||||
|
allOk = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return allOk;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean areLocationPermissions2OK() {
|
||||||
|
boolean allOk = true;
|
||||||
|
Log.v(TAG, "areSMSPermissions2OK()");
|
||||||
|
for (int i = 0; i < LOCATION_PERMISSIONS_2.length; i++) {
|
||||||
|
if (ContextCompat.checkSelfPermission(this, LOCATION_PERMISSIONS_2[i])
|
||||||
|
!= PackageManager.PERMISSION_GRANTED) {
|
||||||
|
Log.i(TAG, LOCATION_PERMISSIONS_2[i] + " Permission Not Granted");
|
||||||
|
allOk = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return allOk;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void requestPermissions(AppCompatActivity activity) {
|
||||||
|
if (mPermissionsRequested) {
|
||||||
|
Log.i(TAG, "requestPermissions() - request already sent - not doing anything");
|
||||||
|
} else {
|
||||||
|
Log.i(TAG, "requestPermissions() - requesting permissions");
|
||||||
|
for (int i = 0; i < REQUIRED_PERMISSIONS.length; i++) {
|
||||||
|
if (ActivityCompat.shouldShowRequestPermissionRationale(activity,
|
||||||
|
REQUIRED_PERMISSIONS[i])) {
|
||||||
|
Log.i(TAG, "shouldShowRationale for permission" + REQUIRED_PERMISSIONS[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ActivityCompat.requestPermissions(activity,
|
||||||
|
REQUIRED_PERMISSIONS,
|
||||||
|
42);
|
||||||
|
mPermissionsRequested = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void requestSMSPermissions() {
|
||||||
|
if (mSmsPermissionsRequested) {
|
||||||
|
Log.i(TAG, "requestSMSPermissions() - request already sent - not doing anything");
|
||||||
|
} else {
|
||||||
|
Log.i(TAG, "requestSMSPermissions() - requesting permissions");
|
||||||
|
mSmsPermissionsRequested = true;
|
||||||
|
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(
|
||||||
|
this);
|
||||||
|
alertDialogBuilder
|
||||||
|
.setTitle(R.string.permissions_required)
|
||||||
|
.setMessage(R.string.sms_permissions_rationale_1)
|
||||||
|
.setCancelable(false)
|
||||||
|
.setPositiveButton(getString(R.string.okBtnTxt), new DialogInterface.OnClickListener() {
|
||||||
|
public void onClick(DialogInterface dialog, int id) {
|
||||||
|
dialog.cancel();
|
||||||
|
Log.i(TAG,"requestSMSPermissions(): Launching ActivityCompat.requestPermissions()");
|
||||||
|
ActivityCompat.requestPermissions(StartupActivity.this,
|
||||||
|
SMS_PERMISSIONS_1,
|
||||||
|
45);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.setNegativeButton(getString(R.string.cancelBtnTxt), new DialogInterface.OnClickListener() {
|
||||||
|
public void onClick(DialogInterface dialog, int id) {
|
||||||
|
dialog.cancel();
|
||||||
|
}
|
||||||
|
}).create().show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void requestLocationPermissions1() {
|
||||||
|
if (mLocationPermissions1Requested) {
|
||||||
|
Log.i(TAG, "requestLocationPermissions1() - request already sent - not doing anything");
|
||||||
|
} else {
|
||||||
|
Log.i(TAG, "requestLocationPermissions1() - requesting permissions");
|
||||||
|
mLocationPermissions1Requested = true;
|
||||||
|
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(
|
||||||
|
this);
|
||||||
|
alertDialogBuilder
|
||||||
|
.setTitle(R.string.permissions_required)
|
||||||
|
.setMessage(R.string.location_permissions_rationale_1)
|
||||||
|
.setCancelable(false)
|
||||||
|
.setPositiveButton(getString(R.string.okBtnTxt), new DialogInterface.OnClickListener() {
|
||||||
|
public void onClick(DialogInterface dialog, int id) {
|
||||||
|
dialog.cancel();
|
||||||
|
Log.i(TAG, "requestLocationPermissions1(): Launching ActivityCompat.requestPermissions()");
|
||||||
|
ActivityCompat.requestPermissions(StartupActivity.this,
|
||||||
|
LOCATION_PERMISSIONS_1,
|
||||||
|
43);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.setNegativeButton(getString(R.string.cancelBtnTxt), new DialogInterface.OnClickListener() {
|
||||||
|
public void onClick(DialogInterface dialog, int id) {
|
||||||
|
dialog.cancel();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.create().show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void requestLocationPermissions2() {
|
||||||
|
if (mLocationPermissions2Requested) {
|
||||||
|
Log.i(TAG, "requestSMSPermissions2() - request already sent - not doing anything");
|
||||||
|
} else {
|
||||||
|
Log.i(TAG, "requestSMSPermissions2() - requesting permissions");
|
||||||
|
mLocationPermissions2Requested = true;
|
||||||
|
|
||||||
|
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(
|
||||||
|
this);
|
||||||
|
alertDialogBuilder
|
||||||
|
.setTitle(R.string.permissions_required)
|
||||||
|
.setMessage(R.string.location_permissions_2_rationale)
|
||||||
|
.setCancelable(false)
|
||||||
|
.setPositiveButton(getString(R.string.okBtnTxt), new DialogInterface.OnClickListener() {
|
||||||
|
public void onClick(DialogInterface dialog, int id) {
|
||||||
|
dialog.cancel();
|
||||||
|
Log.i(TAG,"requestSMSPermissions(): Launching ActivityCompat.requestPermissions()");
|
||||||
|
ActivityCompat.requestPermissions(StartupActivity.this,
|
||||||
|
LOCATION_PERMISSIONS_2,
|
||||||
|
44);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.setNegativeButton(getString(R.string.cancelBtnTxt), new DialogInterface.OnClickListener() {
|
||||||
|
public void onClick(DialogInterface dialog, int id) {
|
||||||
|
dialog.cancel();
|
||||||
|
}
|
||||||
|
}).create().show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onRequestPermissionsResult(int requestCode,
|
||||||
|
String permissions[], int[] grantResults) {
|
||||||
|
Log.i(TAG, "onRequestPermissionsResult - Permission" + permissions + " = " + grantResults);
|
||||||
|
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||||
|
for (int i = 0; i < permissions.length; i++) {
|
||||||
|
Log.i(TAG, "Permission " + permissions[i] + " = " + grantResults[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,234 @@
|
|||||||
|
package uk.org.openseizuredetector;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
|
import com.android.volley.AuthFailureError;
|
||||||
|
import com.android.volley.Request;
|
||||||
|
import com.android.volley.RequestQueue;
|
||||||
|
import com.android.volley.Response;
|
||||||
|
import com.android.volley.VolleyError;
|
||||||
|
import com.android.volley.VolleyLog;
|
||||||
|
import com.android.volley.toolbox.StringRequest;
|
||||||
|
import com.android.volley.toolbox.Volley;
|
||||||
|
import com.google.android.gms.tasks.OnCompleteListener;
|
||||||
|
import com.google.android.gms.tasks.OnFailureListener;
|
||||||
|
import com.google.android.gms.tasks.OnSuccessListener;
|
||||||
|
import com.google.android.gms.tasks.Task;
|
||||||
|
import com.google.firebase.auth.FirebaseAuth;
|
||||||
|
import com.google.firebase.firestore.DocumentReference;
|
||||||
|
import com.google.firebase.firestore.DocumentSnapshot;
|
||||||
|
import com.google.firebase.firestore.FirebaseFirestore;
|
||||||
|
import com.google.firebase.firestore.Query;
|
||||||
|
import com.google.firebase.firestore.QueryDocumentSnapshot;
|
||||||
|
import com.google.firebase.firestore.QuerySnapshot;
|
||||||
|
import com.google.firebase.firestore.core.OrderBy;
|
||||||
|
|
||||||
|
import org.json.JSONArray;
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.text.DateFormat;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
|
||||||
|
// This class is intended to handle all interactions with the OSD WebAPI
|
||||||
|
public abstract class WebApiConnection {
|
||||||
|
protected Context mContext;
|
||||||
|
protected OsdUtil mUtil;
|
||||||
|
private String TAG = "WebApiConnection";
|
||||||
|
private String mAuthToken;
|
||||||
|
|
||||||
|
|
||||||
|
public interface JSONObjectCallback {
|
||||||
|
public void accept(JSONObject retValObj);
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface StringCallback {
|
||||||
|
public void accept(String retValStr);
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface LongCallback {
|
||||||
|
public void accept(Long retVal);
|
||||||
|
}
|
||||||
|
|
||||||
|
public WebApiConnection(Context context) {
|
||||||
|
mContext = context;
|
||||||
|
mUtil = new OsdUtil(mContext, new Handler());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void close() {
|
||||||
|
Log.i(TAG, "stop()");
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract boolean isLoggedIn();
|
||||||
|
|
||||||
|
|
||||||
|
// Create a new event in the remote database, based on the provided parameters.
|
||||||
|
// passes the newly created documentId to function callback on successful completion, or null on error.
|
||||||
|
public abstract boolean createEvent(final int osdAlarmState, final Date eventDate, final String type, final String subType,
|
||||||
|
final String eventDesc, final String dataJSON, StringCallback callback);
|
||||||
|
|
||||||
|
// calls function callback with a JSONObject representation of the event with id 'eventId'
|
||||||
|
public abstract boolean getEvent(String eventId, JSONObjectCallback callback);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve all events accessible to the logged in user, and pass them to the callback function as a JSONObject
|
||||||
|
*
|
||||||
|
* @param callback
|
||||||
|
* @return true on success or false on failure to initiate the request.
|
||||||
|
*/
|
||||||
|
public abstract boolean getEvents(JSONObjectCallback callback);
|
||||||
|
|
||||||
|
public abstract boolean updateEvent(final JSONObject eventObj, JSONObjectCallback callback);
|
||||||
|
|
||||||
|
public abstract boolean createDatapoint(JSONObject dataObj, String eventId, StringCallback callback);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the file containing the standard event types from the server.
|
||||||
|
* Calls the specified callback function, passing a JSONObject as a parameter when the data has been received and parsed.
|
||||||
|
*
|
||||||
|
* @return true if request sent successfully or else false.
|
||||||
|
*/
|
||||||
|
public abstract boolean getEventTypes(JSONObjectCallback callback);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve a trivial file from the server to check we have a good server connection.
|
||||||
|
* sets mServerConnectionOk.
|
||||||
|
*
|
||||||
|
* @return true if request sent successfully or else false.
|
||||||
|
*/
|
||||||
|
public abstract boolean checkServerConnection();
|
||||||
|
|
||||||
|
public abstract boolean getUserProfile(JSONObjectCallback callback);
|
||||||
|
|
||||||
|
|
||||||
|
public boolean authenticate(final String uname, final String passwd, StringCallback callback) {
|
||||||
|
Log.e(TAG, "WebApiConnection.authenticate(username, password, callback) Not Implemented");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove the stored token so future calls are not authenticated.
|
||||||
|
public void logout() {
|
||||||
|
Log.v(TAG, "logout()");
|
||||||
|
setStoredToken(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void setStoredToken(String authToken) {
|
||||||
|
mAuthToken = authToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String getStoredToken() {
|
||||||
|
return (mAuthToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mark all of the events with IDs contained in eventList as unknown type.
|
||||||
|
* @param eventList list of String IDs of the events to mark as unknown.
|
||||||
|
* @return true if request sent successfully or false.
|
||||||
|
*/
|
||||||
|
private boolean markEventsAsUnknown(ArrayList<String>eventList) {
|
||||||
|
if (eventList.size()>0) {
|
||||||
|
Log.i(TAG,"markEventsAsUnknown - eventList.size()="+eventList.size());
|
||||||
|
Log.i(TAG,"markEventsAsUnknown - eventList(0) = "+eventList.get(0));
|
||||||
|
getEvent(eventList.get(0), new WebApiConnection.JSONObjectCallback() {
|
||||||
|
@Override
|
||||||
|
public void accept(JSONObject eventObj) {
|
||||||
|
Log.v(TAG, "markEventsAsUnknown.getEvent.callback: "+eventObj);
|
||||||
|
if (eventObj != null) {
|
||||||
|
Log.v(TAG, "markEventsAsUnknown.getEvent.callback: eventObj=" + eventObj.toString());
|
||||||
|
try {
|
||||||
|
eventObj.put("type", "Unknown");
|
||||||
|
String notesStr = eventObj.getString("desc");
|
||||||
|
if (notesStr == null) notesStr = new String("");
|
||||||
|
notesStr = notesStr + " Set to Unknown automatically by OSD Android App";
|
||||||
|
eventObj.put("desc", notesStr);
|
||||||
|
updateEvent(eventObj,new WebApiConnection.JSONObjectCallback() {
|
||||||
|
@Override
|
||||||
|
public void accept(JSONObject eventObj) {
|
||||||
|
if (eventObj != null) {
|
||||||
|
Log.i(TAG, "markEventsAsUnknown.updateEvent.callback" + eventObj.toString());
|
||||||
|
// Remove the first item from the list,then call this whole procedure again to modify the next one on the list.
|
||||||
|
eventList.remove(0);
|
||||||
|
markEventsAsUnknown(eventList);
|
||||||
|
} else {
|
||||||
|
Log.e(TAG, "markEventsAsUnknown.updateEvent.callback - eventObj is null");
|
||||||
|
mUtil.showToast("markEventsAsUnknown.updateEvent.callback - eventObj is null");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (JSONException e) {
|
||||||
|
Log.e(TAG,"markEventsAsUnknown.getEvent.callback: Error editing eventObj");
|
||||||
|
mUtil.showToast("markEventsAsUnknown.getEvent.callback: Error editing eventObj");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
mUtil.showToast("Failed to Retrieve Event from Remote Database");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
Log.i(TAG,"markEventsAsUnknown(): No more events to Modify");
|
||||||
|
mUtil.showToast("No more unvalidated events to modify.");
|
||||||
|
|
||||||
|
}
|
||||||
|
return(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mark all unverified events in the remote database as unknown
|
||||||
|
*
|
||||||
|
* @return true if request is successful or false.
|
||||||
|
*/
|
||||||
|
public boolean markUnverifiedEventsAsUnknown() {
|
||||||
|
if (getEvents((JSONObject remoteEventsObj) -> {
|
||||||
|
Log.v(TAG, "markUnverifiedEventsAsUnknown.getEvents.Callback()");
|
||||||
|
Boolean haveUnvalidatedEvent = false;
|
||||||
|
if (remoteEventsObj == null) {
|
||||||
|
Log.e(TAG, "markUnverifiedEventsAsUnknown.getEvents.Callback: Error Retrieving events");
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
JSONArray eventsArray = remoteEventsObj.getJSONArray("events");
|
||||||
|
ArrayList<String> unvalidatedEventsList = new ArrayList<String>();
|
||||||
|
for (int i = eventsArray.length() - 1; i >= 0; i--) {
|
||||||
|
JSONObject eventObj = eventsArray.getJSONObject(i);
|
||||||
|
String typeStr = eventObj.getString("type");
|
||||||
|
if (typeStr.equals("null") || typeStr.equals("")) {
|
||||||
|
haveUnvalidatedEvent = true;
|
||||||
|
unvalidatedEventsList.add(eventObj.getString("id"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Log.v(TAG, "markUnverifiedEventsAsUnknown.getEvents.onFinish.callback - haveUnvalidatedEvent = " +
|
||||||
|
haveUnvalidatedEvent);
|
||||||
|
markEventsAsUnknown(unvalidatedEventsList);
|
||||||
|
|
||||||
|
} catch (JSONException e) {
|
||||||
|
Log.e(TAG, "markUnverifiedEventsAsUnknown.getEvents.onFinish(): Error Parsing remoteEventsObj: " + e.getMessage());
|
||||||
|
//mUtil.showToast("Error Parsing remoteEventsObj - this should not happen!!!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})) {
|
||||||
|
Log.v(TAG, "markUnverifiedEventsAsUnknown.getEvents - requested events");
|
||||||
|
} else {
|
||||||
|
Log.v(TAG, "markUnverifiedEventsAsUnknown.getEvents - Not Logged In");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return (true);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,426 @@
|
|||||||
|
package uk.org.openseizuredetector;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
|
import com.android.volley.RequestQueue;
|
||||||
|
import com.android.volley.toolbox.Volley;
|
||||||
|
import com.google.android.gms.tasks.OnCompleteListener;
|
||||||
|
import com.google.android.gms.tasks.OnFailureListener;
|
||||||
|
import com.google.android.gms.tasks.OnSuccessListener;
|
||||||
|
import com.google.android.gms.tasks.Task;
|
||||||
|
import com.google.firebase.auth.FirebaseAuth;
|
||||||
|
import com.google.firebase.firestore.DocumentReference;
|
||||||
|
import com.google.firebase.firestore.DocumentSnapshot;
|
||||||
|
import com.google.firebase.firestore.FirebaseFirestore;
|
||||||
|
import com.google.firebase.firestore.Query;
|
||||||
|
import com.google.firebase.firestore.QueryDocumentSnapshot;
|
||||||
|
import com.google.firebase.firestore.QuerySnapshot;
|
||||||
|
|
||||||
|
import org.json.JSONArray;
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
|
||||||
|
// This class is intended to handle all interactions with the OSD WebAPI
|
||||||
|
public class WebApiConnection_firebase extends WebApiConnection {
|
||||||
|
public String retVal;
|
||||||
|
public int retCode;
|
||||||
|
public boolean mServerConnectionOk = false;
|
||||||
|
private String TAG = "WebApiConnection_firebase";
|
||||||
|
private String mAuthToken;
|
||||||
|
private Context mContext;
|
||||||
|
private OsdUtil mUtil;
|
||||||
|
FirebaseFirestore mDb;
|
||||||
|
|
||||||
|
RequestQueue mQueue;
|
||||||
|
|
||||||
|
|
||||||
|
public WebApiConnection_firebase(Context context) {
|
||||||
|
super(context);
|
||||||
|
loginToFirebase();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void loginToFirebase() {
|
||||||
|
// Check if we are already logged in
|
||||||
|
FirebaseAuth auth = FirebaseAuth.getInstance();
|
||||||
|
mDb = FirebaseFirestore.getInstance();
|
||||||
|
if (auth != null) {
|
||||||
|
if (auth.getCurrentUser() != null) {
|
||||||
|
Log.i(TAG, "Firebase Logged in OK -" + auth.getCurrentUser().getDisplayName());
|
||||||
|
} else {
|
||||||
|
Log.e(TAG, "Firebase not logged in - no current user");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Log.e(TAG, "Firebase not logged in");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void close() {
|
||||||
|
Log.i(TAG, "stop()");
|
||||||
|
mQueue.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isLoggedIn() {
|
||||||
|
FirebaseAuth auth = FirebaseAuth.getInstance();
|
||||||
|
if (auth != null) {
|
||||||
|
if (auth.getCurrentUser() != null) {
|
||||||
|
//Log.v(TAG, "isLoggedIn(): Firebase Logged in OK");
|
||||||
|
return (true);
|
||||||
|
} else {
|
||||||
|
//Log.v(TAG, "isLoggedIn(): Current user is null - Firebase not logged in");
|
||||||
|
return (false);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//Log.v(TAG, "isLoggedIn(): Firebase not logged in");
|
||||||
|
return (false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean getUserProfile(JSONObjectCallback callback) {
|
||||||
|
Log.v(TAG, "getUserProfile()");
|
||||||
|
FirebaseAuth auth = FirebaseAuth.getInstance();
|
||||||
|
if (!isLoggedIn()) {
|
||||||
|
Log.v(TAG, "not logged in - doing nothing");
|
||||||
|
return (false);
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
JSONObject retObj = new JSONObject();
|
||||||
|
retObj.put("id",auth.getCurrentUser().getUid());
|
||||||
|
retObj.put("username", auth.getCurrentUser().getDisplayName());
|
||||||
|
retObj.put("email", auth.getCurrentUser().getEmail());
|
||||||
|
callback.accept(retObj);
|
||||||
|
} catch (JSONException e) {
|
||||||
|
Log.e(TAG, "Error Creating retObjObj: " + e.getMessage());
|
||||||
|
mUtil.showToast("Error Creating retObj - this should not happen!!!");
|
||||||
|
return (false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getStoredToken() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStoredToken(String s) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Create a new event in the remote database, based on the provided parameters.
|
||||||
|
// passes the newly created documentId to function callback on successful completion, or null on error.
|
||||||
|
public boolean createEvent(final int osdAlarmState, final Date eventDate, final String type, final String subType,
|
||||||
|
final String eventDesc, final String dataJSON, StringCallback callback) {
|
||||||
|
// FIXME - save type, subtype, eventDesc and dataJSON
|
||||||
|
Log.v(TAG, "createEvent()");
|
||||||
|
String userId = null;
|
||||||
|
|
||||||
|
if (mDb == null) {
|
||||||
|
Log.w(TAG, "createEvent() - mDb is null - not doing anything");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FirebaseAuth.getInstance().getCurrentUser() == null) {
|
||||||
|
Log.e(TAG, "ERROR: createEvent() - not logged in");
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
userId = FirebaseAuth.getInstance().getCurrentUser().getUid();
|
||||||
|
}
|
||||||
|
Map<String, Object> event = new HashMap<>();
|
||||||
|
event.put("dataTime", eventDate.getTime());
|
||||||
|
event.put("osdAlarmState", osdAlarmState);
|
||||||
|
event.put("desc", eventDesc);
|
||||||
|
event.put("type", type);
|
||||||
|
event.put("subType", subType);
|
||||||
|
event.put("dataJSON", dataJSON);
|
||||||
|
event.put("userId", userId);
|
||||||
|
|
||||||
|
mDb.collection("Events")
|
||||||
|
.add(event)
|
||||||
|
.addOnSuccessListener(new OnSuccessListener<DocumentReference>() {
|
||||||
|
@Override
|
||||||
|
public void onSuccess(DocumentReference documentReference) {
|
||||||
|
Log.d(TAG, "createEvent.onSuccess() - DocumentSnapshot added with ID: " + documentReference.getId());
|
||||||
|
mServerConnectionOk = true;
|
||||||
|
callback.accept(documentReference.getId());
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.addOnFailureListener(new OnFailureListener() {
|
||||||
|
@Override
|
||||||
|
public void onFailure(@NonNull Exception e) {
|
||||||
|
Log.w(TAG, "createEvent.onFailure() - Error adding document", e);
|
||||||
|
callback.accept(null);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return (true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// calls function callback with a JSONObject representation of the event with id 'eventId'
|
||||||
|
public boolean getEvent(String eventId, JSONObjectCallback callback) {
|
||||||
|
Log.v(TAG, "getEvent()");
|
||||||
|
if (mDb == null) {
|
||||||
|
Log.w(TAG, "getEvent() - mDb is null - not doing anything");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
DocumentReference docRef = mDb
|
||||||
|
.collection("Events").document(eventId);
|
||||||
|
docRef.get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
|
||||||
|
@Override
|
||||||
|
public void onComplete(@NonNull Task<DocumentSnapshot> task) {
|
||||||
|
if (task.isSuccessful()) {
|
||||||
|
DocumentSnapshot document = task.getResult();
|
||||||
|
if (document.exists()) {
|
||||||
|
Log.d(TAG, "getEvent.onComplete(): DocumentSnapshot data: " + document.getData());
|
||||||
|
if (document.getData() == null) {
|
||||||
|
callback.accept(null);
|
||||||
|
} else
|
||||||
|
callback.accept(new JSONObject(document.getData()));
|
||||||
|
} else {
|
||||||
|
Log.d(TAG, "No such document");
|
||||||
|
callback.accept(null);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Log.d(TAG, "get failed with ", task.getException());
|
||||||
|
callback.accept(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve all events accessible to the logged in user, and pass them to the callback function as a JSONObject
|
||||||
|
*
|
||||||
|
* @param callback
|
||||||
|
* @return true on success or false on failure to initiate the request.
|
||||||
|
*/
|
||||||
|
public boolean getEvents(JSONObjectCallback callback) {
|
||||||
|
//Long eventId=Long.valueOf(285);
|
||||||
|
Log.v(TAG, "getEvents()");
|
||||||
|
if (mDb == null) {
|
||||||
|
Log.w(TAG, "getEvents() - mDb is null - not doing anything");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isLoggedIn()) {
|
||||||
|
Log.w(TAG, "getEvents() - not logged in - not doing anything");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
String userId = FirebaseAuth.getInstance().getCurrentUser().getUid();
|
||||||
|
mDb.collection("Events") //.where("userId", "==", userId)
|
||||||
|
.whereEqualTo("userId", userId)
|
||||||
|
.orderBy("dataTime", Query.Direction.ASCENDING)
|
||||||
|
.get()
|
||||||
|
.addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
|
||||||
|
@Override
|
||||||
|
public void onComplete(@NonNull Task<QuerySnapshot> task) {
|
||||||
|
if (task.isSuccessful()) {
|
||||||
|
try {
|
||||||
|
JSONObject retObj = new JSONObject();
|
||||||
|
JSONArray eventArray = new JSONArray();
|
||||||
|
Log.d(TAG, "getEvents() - returned " + task.getResult().size());
|
||||||
|
for (QueryDocumentSnapshot document : task.getResult()) {
|
||||||
|
Log.d(TAG, "getEvents() - " + document.getId() + " => " + document.getData());
|
||||||
|
JSONObject eventObj = new JSONObject(document.getData());
|
||||||
|
// Add the event id into the event data because firebase does not include it as part of the document.
|
||||||
|
eventObj.put("id", document.getId());
|
||||||
|
eventArray.put(eventObj);
|
||||||
|
}
|
||||||
|
retObj.put("events", eventArray);
|
||||||
|
callback.accept(retObj);
|
||||||
|
} catch (JSONException e) {
|
||||||
|
Log.e(TAG, "getEvents.onResponse(): Error: " + e.getMessage() + "," + e.toString());
|
||||||
|
callback.accept(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
Log.d(TAG, "Error getting documents: ", task.getException());
|
||||||
|
callback.accept(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return (true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean updateEvent(final JSONObject eventObj, JSONObjectCallback callback) {
|
||||||
|
String eventId;
|
||||||
|
Log.v(TAG, "updateEvent()");
|
||||||
|
if (mDb == null) {
|
||||||
|
Log.w(TAG, "updateEvent() - mDb is null - not doing anything");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
eventId = eventObj.getString("id");
|
||||||
|
} catch (JSONException e) {
|
||||||
|
Log.e(TAG, "updateEvent(): Error reading id from eventObj");
|
||||||
|
eventId = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
final String dataStr = eventObj.toString();
|
||||||
|
Log.v(TAG, "updateEvent - data=" + dataStr);
|
||||||
|
Map<String, Object> eventMap = new HashMap<>();
|
||||||
|
try {
|
||||||
|
eventMap.put("dataTime", eventObj.getLong("dataTime"));
|
||||||
|
eventMap.put("osdAlarmState", eventObj.getInt("osdAlarmState"));
|
||||||
|
eventMap.put("desc", eventObj.getString("desc"));
|
||||||
|
eventMap.put("type", eventObj.getString("type"));
|
||||||
|
eventMap.put("subType", eventObj.getString("subType"));
|
||||||
|
eventMap.put("userId", eventObj.getString("userId"));
|
||||||
|
} catch (JSONException e) {
|
||||||
|
Log.e(TAG, "updateEvent(): Error data from eventObj." + e.toString());
|
||||||
|
e.printStackTrace();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Log.v(TAG, "updateEvent - map=" + eventMap.toString());
|
||||||
|
|
||||||
|
try {
|
||||||
|
DocumentReference docRef = mDb.collection("Events").document(eventId);
|
||||||
|
docRef.set(eventMap)
|
||||||
|
.addOnSuccessListener(new OnSuccessListener<Void>() {
|
||||||
|
@Override
|
||||||
|
public void onSuccess(Void aVoid) {
|
||||||
|
JSONObject retObj;
|
||||||
|
try {
|
||||||
|
retObj = new JSONObject("{\"status\":\"OK\"}");
|
||||||
|
} catch (Exception e) {
|
||||||
|
retObj = null;
|
||||||
|
}
|
||||||
|
callback.accept(retObj);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.addOnFailureListener(new OnFailureListener() {
|
||||||
|
@Override
|
||||||
|
public void onFailure(@NonNull Exception e) {
|
||||||
|
Log.w(TAG, "Error updating document", e);
|
||||||
|
callback.accept(null);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return (true);
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, "updateEvent() - ERROR: " + e.toString());
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return (false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean createDatapoint(JSONObject dataObj, String eventId, StringCallback callback) {
|
||||||
|
Log.v(TAG, "createDatapoint()");
|
||||||
|
// Create a new event in the remote database, based on the provided parameters.
|
||||||
|
String userId = null;
|
||||||
|
if (FirebaseAuth.getInstance().getCurrentUser() == null) {
|
||||||
|
Log.e(TAG, "ERROR: createDatapoint() - not logged in");
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
userId = FirebaseAuth.getInstance().getCurrentUser().getUid();
|
||||||
|
}
|
||||||
|
String dataTime;
|
||||||
|
try {
|
||||||
|
dataTime = dataObj.getString("dataTime");
|
||||||
|
} catch (JSONException e) {
|
||||||
|
dataTime = "";
|
||||||
|
}
|
||||||
|
Map<String, Object> datapoint = new HashMap<>();
|
||||||
|
datapoint.put("dataTime", dataTime);
|
||||||
|
datapoint.put("dataJSON", dataObj.toString());
|
||||||
|
datapoint.put("userId", userId);
|
||||||
|
datapoint.put("eventId", userId);
|
||||||
|
|
||||||
|
mDb.collection("Datapoints")
|
||||||
|
.add(datapoint)
|
||||||
|
.addOnSuccessListener(new OnSuccessListener<DocumentReference>() {
|
||||||
|
@Override
|
||||||
|
public void onSuccess(DocumentReference documentReference) {
|
||||||
|
Log.d(TAG, "createDatapoint.onSuccess() - DocumentSnapshot added with ID: " + documentReference.getId());
|
||||||
|
mServerConnectionOk = true;
|
||||||
|
callback.accept(documentReference.getId());
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.addOnFailureListener(new OnFailureListener() {
|
||||||
|
@Override
|
||||||
|
public void onFailure(@NonNull Exception e) {
|
||||||
|
Log.w(TAG, "createDatapoint.onFailure() - Error adding document", e);
|
||||||
|
callback.accept(null);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return (true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the file containing the standard event types from the server.
|
||||||
|
* Calls the specified callback function, passing a JSONObject as a parameter when the data has been received and parsed.
|
||||||
|
*
|
||||||
|
* @return true if request sent successfully or else false.
|
||||||
|
*/
|
||||||
|
public boolean getEventTypes(JSONObjectCallback callback) {
|
||||||
|
Log.v(TAG, "getEventTypes()");
|
||||||
|
if (mDb == null) {
|
||||||
|
Log.w(TAG, "getEventTypes() - mDb is null - not doing anything");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
mDb.collection("EventTypes")
|
||||||
|
.get()
|
||||||
|
.addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
|
||||||
|
@Override
|
||||||
|
public void onComplete(@NonNull Task<QuerySnapshot> task) {
|
||||||
|
if (task.isSuccessful()) {
|
||||||
|
try {
|
||||||
|
JSONObject retObj = new JSONObject();
|
||||||
|
for (QueryDocumentSnapshot document : task.getResult()) {
|
||||||
|
Log.d(TAG, "getEventTypes.onComplete(): " + document.getId() + " => " + document.getData());
|
||||||
|
Log.v(TAG, "getEventTypes.onComplete() - subtypes=" + document.getData().get("subTypes"));
|
||||||
|
JSONArray subTypesArray = listToJSONArray((List) document.getData().get("subTypes"));
|
||||||
|
retObj.put(document.getData().get("type").toString(), subTypesArray);
|
||||||
|
}
|
||||||
|
Log.d(TAG, "getEventTypes.onComplete() - retObj=" + retObj.toString());
|
||||||
|
callback.accept(retObj);
|
||||||
|
} catch (JSONException e) {
|
||||||
|
Log.e(TAG, "getEventTypes.onResponse(): Error: " + e.getMessage() + "," + e.toString());
|
||||||
|
callback.accept(null);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Log.d(TAG, "Error getting documents: ", task.getException());
|
||||||
|
callback.accept(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return (true);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private JSONArray listToJSONArray(List<Object> list) {
|
||||||
|
JSONArray arr = new JSONArray();
|
||||||
|
for (Object obj : list) {
|
||||||
|
arr.put(obj);
|
||||||
|
}
|
||||||
|
return arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve a trivial file from the server to check we have a good server connection.
|
||||||
|
* sets mServerConnectionOk.
|
||||||
|
*
|
||||||
|
* @return true if request sent successfully or else false.
|
||||||
|
*/
|
||||||
|
public boolean checkServerConnection() {
|
||||||
|
//FIXME There must be a Firebase function for this?
|
||||||
|
mServerConnectionOk = true;
|
||||||
|
return mServerConnectionOk;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,667 @@
|
|||||||
|
package uk.org.openseizuredetector;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import com.android.volley.AuthFailureError;
|
||||||
|
import com.android.volley.Request;
|
||||||
|
import com.android.volley.RequestQueue;
|
||||||
|
import com.android.volley.Response;
|
||||||
|
import com.android.volley.VolleyError;
|
||||||
|
import com.android.volley.VolleyLog;
|
||||||
|
import com.android.volley.toolbox.StringRequest;
|
||||||
|
import com.android.volley.toolbox.Volley;
|
||||||
|
|
||||||
|
import org.json.JSONArray;
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.text.DateFormat;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
|
||||||
|
// This class is intended to handle all interactions with the OSD WebAPI
|
||||||
|
public class WebApiConnection_osdapi extends WebApiConnection {
|
||||||
|
public String retVal;
|
||||||
|
public int retCode;
|
||||||
|
public boolean mServerConnectionOk = false;
|
||||||
|
private String mUrlBase = "https://osdApi.ddns.net";
|
||||||
|
private String TAG = "WebApiConnection_osdapi";
|
||||||
|
RequestQueue mQueue;
|
||||||
|
|
||||||
|
public WebApiConnection_osdapi(Context context) {
|
||||||
|
super(context);
|
||||||
|
mQueue = Volley.newRequestQueue(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void close() {
|
||||||
|
super.close();
|
||||||
|
Log.i(TAG,"stop()");
|
||||||
|
mQueue.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempt to authenticate with the web API using user name uname and password passwd. Calls function callback with either
|
||||||
|
* the authentication token on success or null on failure.
|
||||||
|
*
|
||||||
|
* @param uname - user name
|
||||||
|
* @param passwd - password
|
||||||
|
* @param callback - call back function callback(String retVal)
|
||||||
|
* @return true if request sent, or false if failed to send request.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean authenticate(final String uname, final String passwd, StringCallback callback) {
|
||||||
|
// NOTE: the 'final' keyword is necessary for uname and passwd to be accessible to getParams below - I don't know why!
|
||||||
|
// We know that this command works, so we just need the Java equivalent:
|
||||||
|
// curl -X POST -d 'login=graham4&password=testpwd1' https://osdapi.ddns.net/api/accounts/login/
|
||||||
|
// sending the credentials as a JSONObject postData did not work, so try the method from:
|
||||||
|
// https://protocoderspoint.com/login-and-registration-form-in-android-using-volley-keeping-user-logged-in/#Login_Registration_form_in_android_using_volley_library
|
||||||
|
String urlStr = mUrlBase + "/api/accounts/login/";
|
||||||
|
Log.v(TAG, "urlStr=" + urlStr);
|
||||||
|
|
||||||
|
StringRequest req = new StringRequest(Request.Method.POST, urlStr,
|
||||||
|
new Response.Listener<String>() {
|
||||||
|
@Override
|
||||||
|
public void onResponse(String response) {
|
||||||
|
String tokenStr = null;
|
||||||
|
Log.v(TAG, "Response is: " + response);
|
||||||
|
try {
|
||||||
|
JSONObject jo = new JSONObject(response);
|
||||||
|
tokenStr = jo.getString("token");
|
||||||
|
mServerConnectionOk = true;
|
||||||
|
} catch (JSONException e) {
|
||||||
|
tokenStr = "Error Parsing Rsponse";
|
||||||
|
}
|
||||||
|
setStoredToken(tokenStr);
|
||||||
|
callback.accept(tokenStr);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
new Response.ErrorListener() {
|
||||||
|
@Override
|
||||||
|
public void onErrorResponse(VolleyError error) {
|
||||||
|
if (error != null) {
|
||||||
|
Log.e(TAG, "Login Error: " + error.toString() + ", message:" + error.getMessage());
|
||||||
|
} else {
|
||||||
|
Log.e(TAG, "Login Error: Returned null response");
|
||||||
|
}
|
||||||
|
mServerConnectionOk = false;
|
||||||
|
setStoredToken(null);
|
||||||
|
callback.accept(null);
|
||||||
|
}
|
||||||
|
}) {
|
||||||
|
// Note, this is overriding part of StringRequest, not one of the sub-classes above!
|
||||||
|
@Override
|
||||||
|
protected Map<String, String> getParams() {
|
||||||
|
Map<String, String> params = new HashMap<>();
|
||||||
|
// params.put("name",sname); // passing parameters to server
|
||||||
|
params.put("login", uname);
|
||||||
|
params.put("password", passwd);
|
||||||
|
return params;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
mQueue.add(req);
|
||||||
|
return (true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public boolean isLoggedIn() {
|
||||||
|
String authToken = getStoredToken();
|
||||||
|
Log.v(TAG, "isLoggedIn(): token=" + authToken);
|
||||||
|
if (authToken == null || authToken.length() == 0) {
|
||||||
|
Log.v(TAG, "isLogged in - not logged in");
|
||||||
|
return (false);
|
||||||
|
} else {
|
||||||
|
Log.v(TAG,"isLoggedIn - logged in ok");
|
||||||
|
return (true);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Create a new event in the remote database, based on the provided parameters.
|
||||||
|
public boolean createEvent(final int osdAlarmState, final Date eventDate, final String type, final String subType,
|
||||||
|
final String eventDesc, final String dataJSON, StringCallback callback) {
|
||||||
|
Log.v(TAG, "createEvent()");
|
||||||
|
String urlStr = mUrlBase + "/api/events/";
|
||||||
|
Log.v(TAG, "urlStr=" + urlStr);
|
||||||
|
final String authtoken = getStoredToken();
|
||||||
|
|
||||||
|
if (!isLoggedIn()) {
|
||||||
|
Log.v(TAG, "not logged in - doing nothing");
|
||||||
|
return (false);
|
||||||
|
}
|
||||||
|
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
|
||||||
|
JSONObject jsonObject = new JSONObject();
|
||||||
|
try {
|
||||||
|
jsonObject.put("osdAlarmState", String.valueOf(osdAlarmState));
|
||||||
|
jsonObject.put("dataTime", dateFormat.format(eventDate));
|
||||||
|
jsonObject.put("type", type);
|
||||||
|
jsonObject.put("subType", subType);
|
||||||
|
jsonObject.put("desc", eventDesc);
|
||||||
|
jsonObject.put("dataJSON", dataJSON);
|
||||||
|
} catch (JSONException e) {
|
||||||
|
Log.e(TAG, "Error generating event JSON string");
|
||||||
|
}
|
||||||
|
final String dataStr = jsonObject.toString();
|
||||||
|
Log.v(TAG, "createEvent - data=" + dataStr);
|
||||||
|
|
||||||
|
StringRequest req = new StringRequest(Request.Method.POST, urlStr,
|
||||||
|
new Response.Listener<String>() {
|
||||||
|
@Override
|
||||||
|
public void onResponse(String response) {
|
||||||
|
Log.v(TAG, "createEvent.onResponse - Response is: " + response);
|
||||||
|
mServerConnectionOk = true;
|
||||||
|
// we return just the eventId to be consistent with the firebase version of WebApiConnection.
|
||||||
|
String retVal = null;
|
||||||
|
try {
|
||||||
|
JSONObject retObj = new JSONObject(response);
|
||||||
|
retVal = retObj.getString("id");
|
||||||
|
} catch (JSONException e) {
|
||||||
|
Log.e(TAG, "createEvent.onResponse(): Error: " + e.getMessage() + "," + e.toString());
|
||||||
|
retVal = null;
|
||||||
|
}
|
||||||
|
callback.accept(retVal);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
new Response.ErrorListener() {
|
||||||
|
@Override
|
||||||
|
public void onErrorResponse(VolleyError error) {
|
||||||
|
mServerConnectionOk = false;
|
||||||
|
if (error != null) {
|
||||||
|
Log.e(TAG, "createEvent Error: " + error.toString() + ", message:" + error.getMessage());
|
||||||
|
callback.accept(null);
|
||||||
|
} else {
|
||||||
|
Log.e(TAG, "createEvent Error - null response");
|
||||||
|
callback.accept(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}) {
|
||||||
|
// Note, this is overriding part of StringRequest, not one of the sub-classes above!
|
||||||
|
@Override
|
||||||
|
protected Map<String, String> getParams() {
|
||||||
|
Map<String, String> params = new HashMap<>();
|
||||||
|
// params.put("name",sname); // passing parameters to server
|
||||||
|
String authToken = getStoredToken();
|
||||||
|
params.put("Authorization: Token " + authToken, authToken);
|
||||||
|
Log.v(TAG, "getParams: params=" + params.toString());
|
||||||
|
return params;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, String> getHeaders() throws AuthFailureError {
|
||||||
|
Map<String, String> params = new HashMap<String, String>();
|
||||||
|
params.put("Content-Type", "application/json; charset=UTF-8");
|
||||||
|
params.put("Authorization", "Token " + getStoredToken());
|
||||||
|
return params;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] getBody() throws AuthFailureError {
|
||||||
|
try {
|
||||||
|
return dataStr == null ? null : dataStr.getBytes("utf-8");
|
||||||
|
} catch (UnsupportedEncodingException uee) {
|
||||||
|
VolleyLog.wtf("Unsupported Encoding while trying to get the bytes of %s using %s", dataStr, "utf-8");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
mQueue.add(req);
|
||||||
|
return (true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean getEvent(String eventId, JSONObjectCallback callback) {
|
||||||
|
Log.v(TAG, "getEvent()");
|
||||||
|
String urlStr = mUrlBase + "/api/events/" + eventId;
|
||||||
|
Log.v(TAG, "getEvent(): urlStr=" + urlStr);
|
||||||
|
final String authtoken = getStoredToken();
|
||||||
|
|
||||||
|
if (!isLoggedIn()) {
|
||||||
|
Log.v(TAG, "not logged in - doing nothing");
|
||||||
|
return (false);
|
||||||
|
}
|
||||||
|
|
||||||
|
StringRequest req = new StringRequest(Request.Method.GET, urlStr,
|
||||||
|
new Response.Listener<String>() {
|
||||||
|
@Override
|
||||||
|
public void onResponse(String response) {
|
||||||
|
Log.v(TAG, "Response is: " + response);
|
||||||
|
try {
|
||||||
|
JSONObject retObj = new JSONObject(response);
|
||||||
|
retObj.put("alarmStateStr", mUtil.alarmStatusToString(retObj.getInt("osdAlarmState")));
|
||||||
|
callback.accept(retObj);
|
||||||
|
} catch (JSONException e) {
|
||||||
|
Log.e(TAG, "getEventTypes.onRespons(): Error: " + e.getMessage() + "," + e.toString());
|
||||||
|
callback.accept(null);
|
||||||
|
}
|
||||||
|
mServerConnectionOk = true;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
new Response.ErrorListener() {
|
||||||
|
@Override
|
||||||
|
public void onErrorResponse(VolleyError error) {
|
||||||
|
if (error != null) {
|
||||||
|
Log.e(TAG, "Create Event Error: " + error.toString() + ", message:" + error.getMessage());
|
||||||
|
} else {
|
||||||
|
Log.e(TAG, "Create Event Error: returned null response");
|
||||||
|
}
|
||||||
|
mServerConnectionOk = false;
|
||||||
|
callback.accept(null);
|
||||||
|
}
|
||||||
|
}) {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, String> getHeaders() throws AuthFailureError {
|
||||||
|
Map<String, String> params = new HashMap<String, String>();
|
||||||
|
params.put("Content-Type", "application/json; charset=UTF-8");
|
||||||
|
params.put("Authorization", "Token " + getStoredToken());
|
||||||
|
return params;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
mQueue.add(req);
|
||||||
|
return (true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve all events accessible to the logged in user, and pass them to the callback function as a JSONObject
|
||||||
|
*
|
||||||
|
* @param callback
|
||||||
|
* @return true on success or false on failure to initiate the request.
|
||||||
|
*/
|
||||||
|
public boolean getEvents(JSONObjectCallback callback) {
|
||||||
|
Log.v(TAG, "getEvents()");
|
||||||
|
String urlStr = mUrlBase + "/api/events/";
|
||||||
|
Log.v(TAG, "getEvents(): urlStr=" + urlStr);
|
||||||
|
final String authtoken = getStoredToken();
|
||||||
|
|
||||||
|
if (!isLoggedIn()) {
|
||||||
|
Log.v(TAG, "not logged in - doing nothing");
|
||||||
|
return (false);
|
||||||
|
}
|
||||||
|
|
||||||
|
StringRequest req = new StringRequest(Request.Method.GET, urlStr,
|
||||||
|
new Response.Listener<String>() {
|
||||||
|
@Override
|
||||||
|
public void onResponse(String response) {
|
||||||
|
Log.v(TAG, "Response is: " + response);
|
||||||
|
mServerConnectionOk = true;
|
||||||
|
try {
|
||||||
|
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());
|
||||||
|
callback.accept(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
new Response.ErrorListener() {
|
||||||
|
@Override
|
||||||
|
public void onErrorResponse(VolleyError error) {
|
||||||
|
//if ((error != null) && (error.networkResponse != null) && (error.networkResponse.data != null)) {#
|
||||||
|
mServerConnectionOk = false;
|
||||||
|
if (error != null) {
|
||||||
|
if (error.networkResponse != null) {
|
||||||
|
Log.e(TAG, "getEvents(): Error: " + error.toString() + ", message:" + error.getMessage());
|
||||||
|
} else {
|
||||||
|
Log.e(TAG, "getEvents(): Error: - request returned null networkResponse");
|
||||||
|
}
|
||||||
|
} else{
|
||||||
|
Log.e(TAG, "getEvents(): Error: - request returned null response");
|
||||||
|
}
|
||||||
|
callback.accept(null);
|
||||||
|
}
|
||||||
|
}) {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, String> getHeaders() throws AuthFailureError {
|
||||||
|
Map<String, String> params = new HashMap<String, String>();
|
||||||
|
params.put("Content-Type", "application/json; charset=UTF-8");
|
||||||
|
params.put("Authorization", "Token " + getStoredToken());
|
||||||
|
return params;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
mQueue.add(req);
|
||||||
|
return (true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public boolean updateEvent(final JSONObject eventObj, JSONObjectCallback callback) {
|
||||||
|
String eventId;
|
||||||
|
Log.v(TAG, "updateEvent()");
|
||||||
|
final String authtoken = getStoredToken();
|
||||||
|
|
||||||
|
if (!isLoggedIn()) {
|
||||||
|
Log.v(TAG, "not logged in - doing nothing");
|
||||||
|
return (false);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
eventId = eventObj.getString("id");
|
||||||
|
} catch (JSONException e) {
|
||||||
|
Log.e(TAG, "updateEvent(): Error reading id from eventObj");
|
||||||
|
eventId = null;
|
||||||
|
}
|
||||||
|
final String dataStr = eventObj.toString();
|
||||||
|
Log.v(TAG, "updateEvent - data=" + dataStr);
|
||||||
|
|
||||||
|
int reqMethod;
|
||||||
|
String urlStr;
|
||||||
|
if (eventId != null) {
|
||||||
|
Log.v(TAG, "updateEvent() - found eventId " + eventId + ", Updating event record");
|
||||||
|
urlStr = mUrlBase + "/api/events/" + eventId + "/";
|
||||||
|
Log.v(TAG, "urlStr=" + urlStr);
|
||||||
|
reqMethod = Request.Method.PUT;
|
||||||
|
} else {
|
||||||
|
Log.v(TAG, "updateEvent() - eventId not found - creating new event record");
|
||||||
|
urlStr = mUrlBase + "/api/events/";
|
||||||
|
Log.v(TAG, "urlStr=" + urlStr);
|
||||||
|
reqMethod = Request.Method.POST;
|
||||||
|
}
|
||||||
|
|
||||||
|
StringRequest req = new StringRequest(reqMethod, urlStr,
|
||||||
|
new Response.Listener<String>() {
|
||||||
|
@Override
|
||||||
|
public void onResponse(String response) {
|
||||||
|
Log.v(TAG, "Response is: " + response);
|
||||||
|
mServerConnectionOk = true;
|
||||||
|
try {
|
||||||
|
JSONObject retObj = new JSONObject(response);
|
||||||
|
callback.accept(retObj);
|
||||||
|
} catch (JSONException e) {
|
||||||
|
Log.e(TAG, "getEventTypes.onRespons(): Error: " + e.getMessage() + "," + e.toString());
|
||||||
|
callback.accept(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
new Response.ErrorListener() {
|
||||||
|
@Override
|
||||||
|
public void onErrorResponse(VolleyError error) {
|
||||||
|
mServerConnectionOk = false;
|
||||||
|
if (error != null) {
|
||||||
|
Log.e(TAG, "Create Event Error: " + error.toString() + ", message:" + error.getMessage());
|
||||||
|
} else {
|
||||||
|
Log.e(TAG, "Create Event Error - returned null response");
|
||||||
|
}
|
||||||
|
callback.accept(null);
|
||||||
|
}
|
||||||
|
}) {
|
||||||
|
// Note, this is overriding part of StringRequest, not one of the sub-classes above!
|
||||||
|
@Override
|
||||||
|
protected Map<String, String> getParams() {
|
||||||
|
Map<String, String> params = new HashMap<>();
|
||||||
|
// params.put("name",sname); // passing parameters to server
|
||||||
|
String authToken = getStoredToken();
|
||||||
|
params.put("Authorization: Token " + authToken, authToken);
|
||||||
|
Log.v(TAG, "getParams: params=" + params.toString());
|
||||||
|
//params.put("eventType", String.valueOf(eventType));
|
||||||
|
//params.put("dataTime", dateFormat.format(eventDate));
|
||||||
|
//params.put("desc", eventDesc);
|
||||||
|
return params;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, String> getHeaders() throws AuthFailureError {
|
||||||
|
Map<String, String> params = new HashMap<String, String>();
|
||||||
|
params.put("Content-Type", "application/json; charset=UTF-8");
|
||||||
|
params.put("Authorization", "Token " + getStoredToken());
|
||||||
|
return params;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] getBody() throws AuthFailureError {
|
||||||
|
try {
|
||||||
|
return dataStr == null ? null : dataStr.getBytes("utf-8");
|
||||||
|
} catch (UnsupportedEncodingException uee) {
|
||||||
|
VolleyLog.wtf("Unsupported Encoding while trying to get the bytes of %s using %s", dataStr, "utf-8");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
mQueue.add(req);
|
||||||
|
return (true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public boolean createDatapoint(JSONObject dataObj, String eventId, StringCallback callback) {
|
||||||
|
Log.v(TAG, "createDatapoint()");
|
||||||
|
// Create a new event in the remote database, based on the provided parameters.
|
||||||
|
String urlStr = mUrlBase + "/api/datapoints/";
|
||||||
|
Log.v(TAG, "urlStr=" + urlStr);
|
||||||
|
final String authtoken = getStoredToken();
|
||||||
|
|
||||||
|
if (!isLoggedIn()) {
|
||||||
|
Log.v(TAG, "not logged in - doing nothing");
|
||||||
|
return (false);
|
||||||
|
}
|
||||||
|
|
||||||
|
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
|
||||||
|
JSONObject jsonObject = new JSONObject();
|
||||||
|
try {
|
||||||
|
//jsonObject.put("userId", -1);
|
||||||
|
jsonObject.put("eventId", String.valueOf(eventId));
|
||||||
|
jsonObject.put("dataTime", dataObj.getString("dataTime"));
|
||||||
|
jsonObject.put("dataJSON", dataObj.toString());
|
||||||
|
} catch (JSONException e) {
|
||||||
|
Log.e(TAG, "Error generating event JSON string");
|
||||||
|
}
|
||||||
|
final String dataStr = jsonObject.toString();
|
||||||
|
Log.v(TAG, "createDatapoint - dataStr=" + dataStr);
|
||||||
|
|
||||||
|
|
||||||
|
StringRequest req = new StringRequest(Request.Method.POST, urlStr,
|
||||||
|
new Response.Listener<String>() {
|
||||||
|
@Override
|
||||||
|
public void onResponse(String response) {
|
||||||
|
Log.v(TAG, "Response is: " + response);
|
||||||
|
mServerConnectionOk = true;
|
||||||
|
callback.accept(response);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
new Response.ErrorListener() {
|
||||||
|
@Override
|
||||||
|
public void onErrorResponse(VolleyError error) {
|
||||||
|
mServerConnectionOk = false;
|
||||||
|
if (error != null) {
|
||||||
|
Log.e(TAG, "Create Datapoint Error: " + error.toString() + ", message:" + error.getMessage());
|
||||||
|
callback.accept(null);
|
||||||
|
} else {
|
||||||
|
Log.e(TAG, "Create Datapoint Error - returned null respones");
|
||||||
|
callback.accept(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}) {
|
||||||
|
// Note, this is overriding part of StringRequest, not one of the sub-classes above!
|
||||||
|
@Override
|
||||||
|
protected Map<String, String> getParams() {
|
||||||
|
Map<String, String> params = new HashMap<>();
|
||||||
|
// params.put("name",sname); // passing parameters to server
|
||||||
|
String authToken = getStoredToken();
|
||||||
|
params.put("Authorization: Token " + authToken, authToken);
|
||||||
|
Log.v(TAG, "getParams: params=" + params.toString());
|
||||||
|
return params;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, String> getHeaders() throws AuthFailureError {
|
||||||
|
Map<String, String> params = new HashMap<String, String>();
|
||||||
|
params.put("Content-Type", "application/json; charset=UTF-8");
|
||||||
|
params.put("Authorization", "Token " + getStoredToken());
|
||||||
|
return params;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] getBody() throws AuthFailureError {
|
||||||
|
try {
|
||||||
|
return dataStr == null ? null : dataStr.getBytes("utf-8");
|
||||||
|
} catch (UnsupportedEncodingException uee) {
|
||||||
|
VolleyLog.wtf("Unsupported Encoding while trying to get the bytes of %s using %s", dataStr, "utf-8");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
mQueue.add(req);
|
||||||
|
return (true);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retieve the user profile of the authenticated user from the server, and return it to the callback function.
|
||||||
|
* @param callback - function to be called with a JSONObject as a parameter that contains the user profile data.
|
||||||
|
* @return true if request sent successfully, or else false.
|
||||||
|
*/
|
||||||
|
public boolean getUserProfile(JSONObjectCallback callback) {
|
||||||
|
Log.v(TAG, "getUserProfile()");
|
||||||
|
String urlStr = mUrlBase + "/api/accounts/profile/";
|
||||||
|
Log.v(TAG, "getUserProfile(): urlStr=" + urlStr);
|
||||||
|
final String authtoken = getStoredToken();
|
||||||
|
|
||||||
|
if (!isLoggedIn()) {
|
||||||
|
Log.v(TAG, "not logged in - doing nothing");
|
||||||
|
return (false);
|
||||||
|
}
|
||||||
|
|
||||||
|
StringRequest req = new StringRequest(Request.Method.GET, urlStr,
|
||||||
|
new Response.Listener<String>() {
|
||||||
|
@Override
|
||||||
|
public void onResponse(String response) {
|
||||||
|
Log.v(TAG, "Response is: " + response);
|
||||||
|
try {
|
||||||
|
JSONObject retObj = new JSONObject(response);
|
||||||
|
callback.accept(retObj);
|
||||||
|
} catch (JSONException e) {
|
||||||
|
Log.e(TAG, "getUserProfile.onResponse(): Error: " + e.getMessage() + "," + e.toString());
|
||||||
|
callback.accept(null);
|
||||||
|
}
|
||||||
|
mServerConnectionOk = true;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
new Response.ErrorListener() {
|
||||||
|
@Override
|
||||||
|
public void onErrorResponse(VolleyError error) {
|
||||||
|
if (error != null) {
|
||||||
|
Log.e(TAG, "Create Event Error: " + error.toString() + ", message:" + error.getMessage());
|
||||||
|
} else {
|
||||||
|
Log.e(TAG, "Create Event Error: returned null response");
|
||||||
|
}
|
||||||
|
mServerConnectionOk = false;
|
||||||
|
callback.accept(null);
|
||||||
|
}
|
||||||
|
}) {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, String> getHeaders() throws AuthFailureError {
|
||||||
|
Map<String, String> params = new HashMap<String, String>();
|
||||||
|
params.put("Content-Type", "application/json; charset=UTF-8");
|
||||||
|
params.put("Authorization", "Token " + getStoredToken());
|
||||||
|
return params;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
mQueue.add(req);
|
||||||
|
return (true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the file containing the standard event types from the server.
|
||||||
|
* Calls the specified callback function, passing a JSONObject as a parameter when the data has been received and parsed.
|
||||||
|
*
|
||||||
|
* @return true if request sent successfully or else false.
|
||||||
|
*/
|
||||||
|
public boolean getEventTypes(JSONObjectCallback callback) {
|
||||||
|
Log.v(TAG, "getEventTypes()");
|
||||||
|
String urlStr = mUrlBase + "/static/eventTypes.json";
|
||||||
|
Log.v(TAG, "urlStr=" + urlStr);
|
||||||
|
final String authtoken = getStoredToken();
|
||||||
|
|
||||||
|
if (!isLoggedIn()) {
|
||||||
|
Log.v(TAG, "not logged in - doing nothing");
|
||||||
|
return (false);
|
||||||
|
}
|
||||||
|
|
||||||
|
StringRequest req = new StringRequest(Request.Method.GET, urlStr,
|
||||||
|
new Response.Listener<String>() {
|
||||||
|
@Override
|
||||||
|
public void onResponse(String response) {
|
||||||
|
Log.v(TAG, "getEventTypes.onResponse(): Response is: " + response);
|
||||||
|
mServerConnectionOk = true;
|
||||||
|
try {
|
||||||
|
JSONObject retObj = new JSONObject(response);
|
||||||
|
callback.accept(retObj);
|
||||||
|
} catch (JSONException e) {
|
||||||
|
Log.e(TAG, "getEventTypes.onRespons(): Error: " + e.getMessage() + "," + e.toString());
|
||||||
|
callback.accept(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
new Response.ErrorListener() {
|
||||||
|
@Override
|
||||||
|
public void onErrorResponse(VolleyError error) {
|
||||||
|
mServerConnectionOk = false;
|
||||||
|
if (error != null) {
|
||||||
|
Log.e(TAG, "getEventTypes.onErrorResponse(): " + error.toString() + ", message:" + error.getMessage());
|
||||||
|
} else {
|
||||||
|
Log.e(TAG, "getEventTypes.onErrorResponse() - returned null response");
|
||||||
|
}
|
||||||
|
callback.accept(null);
|
||||||
|
}
|
||||||
|
}) {
|
||||||
|
// Note, this is overriding part of StringRequest, not one of the sub-classes above!
|
||||||
|
@Override
|
||||||
|
public Map<String, String> getHeaders() throws AuthFailureError {
|
||||||
|
Map<String, String> params = new HashMap<String, String>();
|
||||||
|
params.put("Content-Type", "application/json; charset=UTF-8");
|
||||||
|
params.put("Authorization", "Token " + getStoredToken());
|
||||||
|
return params;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
mQueue.add(req);
|
||||||
|
return (true);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve a trivial file from the server to check we have a good server connection.
|
||||||
|
* sets mServerConnectionOk.
|
||||||
|
* @return true if request sent successfully or else false.
|
||||||
|
*/
|
||||||
|
public boolean checkServerConnection() {
|
||||||
|
Log.v(TAG, "checkServerConnection()");
|
||||||
|
String urlStr = mUrlBase + "/static/test.txt";
|
||||||
|
Log.v(TAG, "urlStr=" + urlStr);
|
||||||
|
|
||||||
|
StringRequest req = new StringRequest(Request.Method.GET, urlStr,
|
||||||
|
new Response.Listener<String>() {
|
||||||
|
@Override
|
||||||
|
public void onResponse(String response) {
|
||||||
|
Log.v(TAG, "checkServerConnection.onResponse(): Response is: " + response);
|
||||||
|
mServerConnectionOk = true;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
new Response.ErrorListener() {
|
||||||
|
@Override
|
||||||
|
public void onErrorResponse(VolleyError error) {
|
||||||
|
Log.v(TAG, "checkServerConnection.onErrorResponse");
|
||||||
|
mServerConnectionOk = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
mQueue.add(req);
|
||||||
|
return (true);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
BIN
app/src/main/res/drawable/datasharing_fault_24x24.png
Normal file
BIN
app/src/main/res/drawable/datasharing_fault_24x24.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 347 B |
BIN
app/src/main/res/drawable/datasharing_query_24x24.png
Normal file
BIN
app/src/main/res/drawable/datasharing_query_24x24.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 311 B |
BIN
app/src/main/res/drawable/star_of_life_query_24x24.png
Normal file
BIN
app/src/main/res/drawable/star_of_life_query_24x24.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 306 B |
Binary file not shown.
|
Before Width: | Height: | Size: 1.1 KiB |
@@ -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"
|
||||||
@@ -21,15 +21,5 @@
|
|||||||
android:text="@string/about_text"
|
android:text="@string/about_text"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/about_credits"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:paddingTop="20dip"
|
|
||||||
android:textSize="16sp"
|
|
||||||
android:text="@string/credits_text"
|
|
||||||
android:autoLink="web"
|
|
||||||
/>
|
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
214
app/src/main/res/layout/activity_authenticate.xml
Normal file
214
app/src/main/res/layout/activity_authenticate.xml
Normal file
@@ -0,0 +1,214 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="fill_parent"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="#FFFFFF"
|
||||||
|
android:contentDescription="@string/app_name"
|
||||||
|
android:scaleType="center"
|
||||||
|
app:srcCompat="@drawable/star_of_life_24x24" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/login_to_osdapi"
|
||||||
|
android:textAppearance="?android:attr/textAppearanceLarge" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/login_ui"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/login_osdapi_ui"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/username"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginLeft="4dp"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
|
android:layout_marginRight="4dp"
|
||||||
|
android:layout_marginBottom="4dp"
|
||||||
|
android:hint="username" />
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/password"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginLeft="4dp"
|
||||||
|
android:layout_marginTop="4dp"
|
||||||
|
android:layout_marginRight="4dp"
|
||||||
|
android:layout_marginBottom="16dp"
|
||||||
|
android:fontFamily="sans-serif"
|
||||||
|
android:hint="password"
|
||||||
|
android:inputType="textPassword" />
|
||||||
|
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/cancelBtn"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:text="@string/back" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/loginBtn"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:text="@string/authenticate" />
|
||||||
|
</LinearLayout>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/RegisterBtn"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:text="@string/register" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/ResetPasswordBtn"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:text="@string/reset_password" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/logout_ui"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textAppearance="?android:attr/textAppearanceLarge"
|
||||||
|
android:text="@string/logged_in_as_user_id" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/userIdTv"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textAppearance="?android:attr/textAppearanceLarge"
|
||||||
|
android:text="userId" />
|
||||||
|
</LinearLayout>
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textAppearance="?android:attr/textAppearanceLarge"
|
||||||
|
android:text=" (" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/usernameTv"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textAppearance="?android:attr/textAppearanceLarge"
|
||||||
|
android:text="username" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textAppearance="?android:attr/textAppearanceLarge"
|
||||||
|
android:text=")" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/logoutCancelBtn"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:text="@string/back" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/logoutBtn"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:text="@string/logout" />
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:id="@+id/divider"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="5dp"
|
||||||
|
android:background="?android:attr/listDivider" />
|
||||||
|
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/aboutDataSharingBtn"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:text="@string/about_data_sharing" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/privacyPolicyBtn"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:text="@string/privacy_policy" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
144
app/src/main/res/layout/activity_edit_event.xml
Normal file
144
app/src/main/res/layout/activity_edit_event.xml
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="fill_parent"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/cancelBtn"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:text="@string/cancel" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/loginBtn"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:text="@string/save" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
|
||||||
|
<ScrollView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="EventId: " />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/eventIdTv"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="[id]" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Event Date: "
|
||||||
|
android:textSize="20sp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/eventDateTv"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="..."
|
||||||
|
android:textSize="20sp" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Alarm State: "
|
||||||
|
android:textSize="20sp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/eventAlarmStateTv"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="..."
|
||||||
|
android:textSize="20sp" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/event_type"
|
||||||
|
android:textSize="20sp" />
|
||||||
|
|
||||||
|
<RadioGroup
|
||||||
|
android:id="@+id/eventTypeRg"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"></RadioGroup>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/event_sub_type"
|
||||||
|
android:textSize="20sp" />
|
||||||
|
|
||||||
|
|
||||||
|
<RadioGroup
|
||||||
|
android:id="@+id/eventSubTypeRg"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"></RadioGroup>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/eventNotsTv"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginLeft="4dp"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
|
android:layout_marginRight="4dp"
|
||||||
|
android:layout_marginBottom="4dp"
|
||||||
|
android:hint="notes about event" />
|
||||||
|
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
</ScrollView>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
173
app/src/main/res/layout/activity_log_manager_control.xml
Normal file
173
app/src/main/res/layout/activity_log_manager_control.xml
Normal file
@@ -0,0 +1,173 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:paddingLeft="@dimen/activity_horizontal_margin"
|
||||||
|
android:paddingTop="@dimen/activity_vertical_margin"
|
||||||
|
android:paddingRight="@dimen/activity_horizontal_margin"
|
||||||
|
android:paddingBottom="@dimen/activity_vertical_margin"
|
||||||
|
tools:context="uk.org.openseizuredetector.LogManager">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/local_database"
|
||||||
|
android:textAppearance="?android:attr/textAppearanceLarge" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/num_local_events" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/num_local_events_tv"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="000" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/num_local_datapoints" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/num_local_datapoints_tv"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="000" />
|
||||||
|
</LinearLayout>
|
||||||
|
<RadioGroup xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<RadioButton
|
||||||
|
android:id="@+id/shared_data_rb"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:checked="true"
|
||||||
|
android:onClick="onRadioButtonClicked"
|
||||||
|
android:text="@string/shared_data" />
|
||||||
|
|
||||||
|
<RadioButton
|
||||||
|
android:id="@+id/local_data_rb"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:checked="false"
|
||||||
|
android:onClick="onRadioButtonClicked"
|
||||||
|
android:text="@string/local_data" />
|
||||||
|
|
||||||
|
<RadioButton
|
||||||
|
android:id="@+id/syslog_rb"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:checked="false"
|
||||||
|
android:onClick="onRadioButtonClicked"
|
||||||
|
android:text="@string/system_logs" />
|
||||||
|
</RadioGroup>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:visibility="visible"
|
||||||
|
android:id="@+id/shared_data_ll"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/remote_database"
|
||||||
|
android:textAppearance="?android:attr/textAppearanceLarge" />
|
||||||
|
<TextView
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/check_seizures_message"
|
||||||
|
/>
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/authStatusTv"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/not_authenticated" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/auth_button"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/authenticate" />
|
||||||
|
<Button
|
||||||
|
android:id="@+id/refresh_button"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/refreshBtn" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
|
||||||
|
<ListView
|
||||||
|
android:id="@+id/remoteEventsLv"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="10dp" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:visibility="gone"
|
||||||
|
android:id="@+id/local_data_ll"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/EventsInLocalDb"
|
||||||
|
android:textAppearance="?android:attr/textAppearanceLarge" />
|
||||||
|
|
||||||
|
<ListView
|
||||||
|
android:id="@+id/eventLogListView"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="10dp" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:visibility="gone"
|
||||||
|
android:id="@+id/syslog_ll"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/system_logs"
|
||||||
|
android:textAppearance="?android:attr/textAppearanceLarge" />
|
||||||
|
|
||||||
|
<ListView
|
||||||
|
android:id="@+id/sysLogListView"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="10dp" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:orientation="vertical"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:paddingBottom="@dimen/activity_vertical_margin"
|
android:paddingBottom="@dimen/activity_vertical_margin"
|
||||||
@@ -10,36 +11,34 @@
|
|||||||
tools:context="uk.org.openseizuredetector.LogManager">
|
tools:context="uk.org.openseizuredetector.LogManager">
|
||||||
|
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textAppearance="?android:attr/textAppearanceLarge"
|
||||||
|
android:text="@string/remote_database"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal">
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:textAppearance="?android:attr/textAppearanceLarge"
|
|
||||||
android:text="@string/not_authenticated"
|
android:text="@string/not_authenticated"
|
||||||
android:id="@+id/authStatusTv"
|
android:id="@+id/authStatusTv"
|
||||||
/>
|
/>
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/authenticate_button"
|
android:id="@+id/auth_button"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_weight="1"
|
|
||||||
android:text="@string/authenticate" />
|
android:text="@string/authenticate" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
<!--
|
<WebView
|
||||||
<ListView
|
android:id="@+id/remote_db_webview"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="match_parent"
|
||||||
android:id="@+id/eventLogListView"
|
/>
|
||||||
android:layout_marginTop="97dp" />
|
|
||||||
|
|
||||||
<EditText
|
|
||||||
android:id="@+id/editText"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:ems="10"
|
|
||||||
android:inputType="textPersonName"
|
|
||||||
android:text="Name" />
|
|
||||||
-->
|
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
183
app/src/main/res/layout/activity_report_seizure.xml
Normal file
183
app/src/main/res/layout/activity_report_seizure.xml
Normal file
@@ -0,0 +1,183 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:paddingLeft="@dimen/activity_horizontal_margin"
|
||||||
|
android:paddingTop="@dimen/activity_vertical_margin"
|
||||||
|
android:paddingRight="@dimen/activity_horizontal_margin"
|
||||||
|
android:paddingBottom="@dimen/activity_vertical_margin"
|
||||||
|
tools:context="uk.org.openseizuredetector.LogManager">
|
||||||
|
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/report_seizure"
|
||||||
|
android:textAppearance="?android:attr/textAppearanceLarge" />
|
||||||
|
|
||||||
|
<ScrollView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/date" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/date_day_tv"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="dd" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:enabled="false"
|
||||||
|
android:text="/" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/date_mon_tv"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="mm" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:enabled="false"
|
||||||
|
android:text="/" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/date_year_tv"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="yyyy" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/select_date_button"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/select_date" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/time" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/time_hh_tv"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="hh" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:enabled="false"
|
||||||
|
android:text=":" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/time_mm_tv"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="mm" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/select_time_button"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/select_time" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/event_type"
|
||||||
|
android:textSize="20sp" />
|
||||||
|
|
||||||
|
<RadioGroup
|
||||||
|
android:id="@+id/eventTypeRg"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"></RadioGroup>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/event_sub_type"
|
||||||
|
android:textSize="20sp" />
|
||||||
|
|
||||||
|
|
||||||
|
<RadioGroup
|
||||||
|
android:id="@+id/eventSubTypeRg"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"></RadioGroup>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/eventNotesTv"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginLeft="4dp"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
|
android:layout_marginRight="4dp"
|
||||||
|
android:layout_marginBottom="4dp"
|
||||||
|
android:hint="notes about event" />
|
||||||
|
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/loginBtn"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/okBtnTxt" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/cancelBtn"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/cancelBtnTxt" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/msg_tv"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="msg" />
|
||||||
|
</LinearLayout>
|
||||||
|
</ScrollView>
|
||||||
|
</LinearLayout>
|
||||||
88
app/src/main/res/layout/ble_scan_activity.xml
Normal file
88
app/src/main/res/layout/ble_scan_activity.xml
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:paddingLeft="8dp"
|
||||||
|
android:paddingRight="8dp">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/ble_scan_status_tv"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textSize="16pt"
|
||||||
|
android:text="ble_scan_status_tv" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/startScanButton"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:onClick="onScanButtonClick"
|
||||||
|
android:text="Start Scan"/>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/ble_present_tv"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="ble_present_tv" />
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/ble_adapter_tv"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="ble_adapter_tv" />
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/current_ble_device_tv"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="current_ble_device_tv" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/ble_perm1_tv"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="ble_perm1_tv" />
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/ble_perm2_tv"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="ble_perm2_tv" />
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/ble_perm3_tv"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="ble_perm3_tv" />
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/ble_perm4_tv"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="ble_perm4_tv" />
|
||||||
|
|
||||||
|
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="fill_parent"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<ListView
|
||||||
|
android:id="@android:id/list"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:background="#00FF00"
|
||||||
|
android:drawSelectorOnTop="false" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@android:id/empty"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:background="#FF0000"
|
||||||
|
android:text="No data" />
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
34
app/src/main/res/layout/data_sharing_dialog_layout.xml
Normal file
34
app/src/main/res/layout/data_sharing_dialog_layout.xml
Normal 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>
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content">
|
|
||||||
<ImageView
|
|
||||||
android:src="@drawable/star_of_life_24x24"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="64dp"
|
|
||||||
android:scaleType="center"
|
|
||||||
android:background="#FFFFBB33"
|
|
||||||
android:contentDescription="@string/app_name" />
|
|
||||||
<EditText
|
|
||||||
android:id="@+id/username"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="16dp"
|
|
||||||
android:layout_marginLeft="4dp"
|
|
||||||
android:layout_marginRight="4dp"
|
|
||||||
android:layout_marginBottom="4dp"
|
|
||||||
android:hint="username" />
|
|
||||||
<EditText
|
|
||||||
android:id="@+id/password"
|
|
||||||
android:inputType="textPassword"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="4dp"
|
|
||||||
android:layout_marginLeft="4dp"
|
|
||||||
android:layout_marginRight="4dp"
|
|
||||||
android:layout_marginBottom="16dp"
|
|
||||||
android:fontFamily="sans-serif"
|
|
||||||
android:hint="password"/>
|
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:orientation="horizontal"
|
|
||||||
android:layout_width="fill_parent"
|
|
||||||
android:layout_height="wrap_content">
|
|
||||||
<Button
|
|
||||||
android:id="@+id/cancelBtn"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:text="@string/cancel" />
|
|
||||||
<Button
|
|
||||||
android:id="@+id/OKBtn"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:text="@string/authenticate" />
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
android:orientation="vertical" android:layout_width="match_parent"
|
android:orientation="vertical" android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="fill_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="horizontal">
|
android:orientation="horizontal">
|
||||||
<TextView
|
<TextView
|
||||||
@@ -11,24 +11,32 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="date"
|
android:text="date"
|
||||||
android:id="@+id/event_date" />
|
android:id="@+id/event_date" />
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text=" : "/>
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="alarm"
|
android:text="alarm"
|
||||||
android:id="@+id/event_alarmState"
|
android:id="@+id/event_alarmState"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="note"
|
android:text=" : "/>
|
||||||
android:id="@+id/event_note"
|
|
||||||
/>
|
|
||||||
</LinearLayout>
|
|
||||||
<TextView
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="uploaded"
|
||||||
|
android:id="@+id/event_uploaded"
|
||||||
|
/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
<!-- <TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="dataJSON"
|
android:text="dataJSON"
|
||||||
android:id="@+id/event_dataJSON" />
|
android:id="@+id/event_dataJSON" />
|
||||||
|
-->
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
71
app/src/main/res/layout/log_entry_layout_remote.xml
Normal file
71
app/src/main/res/layout/log_entry_layout_remote.xml
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/event_date_remote_tv"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="date"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/event_type_remote_tv"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="---"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text=" : " />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/event_subtype_remote_tv"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="---" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/event_alarmState_remote_tv"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="alarm" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/event_notes_remote_tv"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="notes"
|
||||||
|
android:textStyle="italic" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/event_id_remote_tv"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginRight="10dp"
|
||||||
|
android:textAppearance="?android:attr/textAppearanceSmall" />
|
||||||
|
android:text="eventId" />
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
||||||
@@ -20,16 +20,16 @@
|
|||||||
android:id="@+id/serverStatusTv"
|
android:id="@+id/serverStatusTv"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:gravity="center"
|
|
||||||
android:layout_weight="0.5"
|
android:layout_weight="0.5"
|
||||||
|
android:gravity="center"
|
||||||
android:text="textView1" />
|
android:text="textView1" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/serverIpTv"
|
android:id="@+id/serverIpTv"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:gravity="center"
|
|
||||||
android:layout_weight="0.5"
|
android:layout_weight="0.5"
|
||||||
|
android:gravity="center"
|
||||||
android:text="textView2" />
|
android:text="textView2" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
@@ -86,6 +86,11 @@
|
|||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/remoteDbTv"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="----" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/powerTv"
|
android:id="@+id/powerTv"
|
||||||
@@ -116,19 +121,30 @@
|
|||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content">
|
android:layout_height="wrap_content"
|
||||||
|
android:baselineAligned="false">
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/acceptAlarmButton"
|
android:id="@+id/acceptAlarmButton"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
android:text="@string/AcceptAlarmBtnTxt" />
|
android:text="@string/AcceptAlarmBtnTxt" />
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/cancelAudibleButton"
|
android:id="@+id/cancelAudibleButton"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
android:text="@string/CancelAudibleButtonTxt" />
|
android:text="@string/CancelAudibleButtonTxt" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/manualAlarmButton"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:backgroundTint="#ff0000"
|
||||||
|
android:text="@string/ManualAlarmBtnTxt" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<com.github.mikephil.charting.charts.BarChart
|
<com.github.mikephil.charting.charts.BarChart
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
@@ -15,7 +16,7 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:id="@+id/imageView"
|
android:id="@+id/imageView"
|
||||||
android:layout_gravity="center_horizontal"
|
android:layout_gravity="center_horizontal"
|
||||||
android:src="@drawable/star_of_life_48x48" />
|
app:srcCompat="@drawable/star_of_life_48x48" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
|||||||
31
app/src/main/res/layout/syslog_entry_layout.xml
Normal file
31
app/src/main/res/layout/syslog_entry_layout.xml
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/syslog_entry_date_tv"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="date" />
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/syslog_level_tv"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="---" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="date"
|
||||||
|
android:id="@+id/syslog_entry_text_tv" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
31
app/src/main/res/menu/log_manager_activity_menu.xml
Normal file
31
app/src/main/res/menu/log_manager_activity_menu.xml
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
<menu xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<group android:id="@+id/grp1">
|
||||||
|
<item
|
||||||
|
android:id="@+id/pruneDatabaseMenuItem"
|
||||||
|
app:showAsAction="never|withText"
|
||||||
|
android:title="@string/prune_database" />
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_mark_unknown"
|
||||||
|
app:showAsAction="never|withText"
|
||||||
|
android:title="@string/mark_unverified_events_as_unknown" />
|
||||||
|
</group>
|
||||||
|
|
||||||
|
<group android:id="@+id/grp3">
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_report_seizure"
|
||||||
|
android:enabled="true"
|
||||||
|
android:icon="@drawable/ic_action_settings"
|
||||||
|
app:showAsAction="never|withText"
|
||||||
|
android:title="@string/report_seizure" />
|
||||||
|
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_authenticate_api"
|
||||||
|
android:enabled="true"
|
||||||
|
android:icon="@drawable/ic_action_settings"
|
||||||
|
app:showAsAction="never|withText"
|
||||||
|
android:title="@string/data_sharing_log_in" />
|
||||||
|
|
||||||
|
</group>
|
||||||
|
</menu>
|
||||||
@@ -1,92 +1,104 @@
|
|||||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
<menu xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
<item
|
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
android:id="@+id/action_accept_alarm"
|
<group android:id="@+id/grp1">
|
||||||
android:showAsAction="never|withText"
|
<item
|
||||||
android:title="@string/accept_alarm" />
|
android:id="@+id/action_accept_alarm"
|
||||||
|
app:showAsAction="never|withText"
|
||||||
|
android:title="@string/accept_alarm" />
|
||||||
|
</group>
|
||||||
|
|
||||||
|
<group android:id="@+id/grp2">
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_start_stop"
|
||||||
|
android:icon="@drawable/stop_server"
|
||||||
|
app:showAsAction="never|withText"
|
||||||
|
android:title="@string/start_stop_server" />
|
||||||
|
</group>
|
||||||
|
<group android:id="@+id/grp3">
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_report_seizure"
|
||||||
|
android:enabled="true"
|
||||||
|
android:icon="@drawable/ic_action_settings"
|
||||||
|
app:showAsAction="never|withText"
|
||||||
|
android:title="@string/report_seizure" />
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_logmanager"
|
||||||
|
android:enabled="true"
|
||||||
|
android:icon="@drawable/ic_action_settings"
|
||||||
|
app:showAsAction="never|withText"
|
||||||
|
android:title="@string/data_log_manager" />
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_authenticate_api"
|
||||||
|
android:enabled="true"
|
||||||
|
android:icon="@drawable/ic_action_settings"
|
||||||
|
app:showAsAction="never|withText"
|
||||||
|
android:title="@string/data_sharing_log_in" />
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_about_datasharing"
|
||||||
|
android:enabled="true"
|
||||||
|
android:icon="@drawable/ic_action_settings"
|
||||||
|
app:showAsAction="never|withText"
|
||||||
|
android:title="About Data Sharing..." />
|
||||||
|
|
||||||
|
</group>
|
||||||
|
<group android:id="@+id/grp4">
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_install_watch_app"
|
||||||
|
app:showAsAction="never|withText"
|
||||||
|
android:title="@string/install_watch_app" />
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_test_alarm_beep"
|
||||||
|
android:icon="@drawable/stop_server"
|
||||||
|
app:showAsAction="never|withText"
|
||||||
|
android:title="@string/test_alarm_beep" />
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_test_warning_beep"
|
||||||
|
android:icon="@drawable/stop_server"
|
||||||
|
app:showAsAction="never|withText"
|
||||||
|
android:title="@string/test_warning_beep" />
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_test_sms_alarm"
|
||||||
|
android:icon="@drawable/stop_server"
|
||||||
|
app:showAsAction="never|withText"
|
||||||
|
android:title="@string/test_sms_alarm_notification" />
|
||||||
|
</group>
|
||||||
|
<group android:id="@+id/grp5">
|
||||||
|
<!--<item
|
||||||
|
android:id="@+id/action_logs"
|
||||||
|
android:enabled="true"
|
||||||
|
android:icon="@drawable/ic_action_settings"
|
||||||
|
android:showAsAction="never|withText"
|
||||||
|
android:title="@string/view_log_entries" /> -->
|
||||||
|
<!--
|
||||||
|
<item
|
||||||
|
android:enabled="false"
|
||||||
|
android:id="@+id/action_export"
|
||||||
|
android:icon="@drawable/ic_action_settings"
|
||||||
|
android:showAsAction="never|withText"
|
||||||
|
android:title="@string/export_data"
|
||||||
|
/>
|
||||||
|
-->
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_settings"
|
||||||
|
android:icon="@drawable/ic_action_settings"
|
||||||
|
app:showAsAction="never|withText"
|
||||||
|
android:title="@string/settings" />
|
||||||
|
|
||||||
|
</group>
|
||||||
|
|
||||||
|
<group android:id="@+id/grp6">
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_about"
|
||||||
|
app:showAsAction="never|withText"
|
||||||
|
android:title="@string/about" />
|
||||||
|
</group>
|
||||||
|
|
||||||
|
|
||||||
<item
|
</menu>
|
||||||
android:id="@+id/action_start_stop"
|
|
||||||
android:icon="@drawable/stop_server"
|
|
||||||
android:showAsAction="never|withText"
|
|
||||||
android:title="@string/start_stop_server" />
|
|
||||||
|
|
||||||
<!-- fault beep test does not work because of fault timer so don't show menu option
|
|
||||||
<item
|
|
||||||
android:id="@+id/action_test_fault_beep"
|
|
||||||
android:icon="@drawable/stop_server"
|
|
||||||
android:showAsAction="never|withText"
|
|
||||||
android:title="Test Fault Beep" />
|
|
||||||
-->
|
|
||||||
<!-- <item
|
|
||||||
android:id="@+id/action_launch_pebble_app"
|
|
||||||
android:showAsAction="never|withText"
|
|
||||||
android:title="Launch Pebble App" />
|
|
||||||
-->
|
|
||||||
<item
|
|
||||||
android:id="@+id/action_install_watch_app"
|
|
||||||
android:showAsAction="never|withText"
|
|
||||||
android:title="@string/install_watch_app" />
|
|
||||||
|
|
||||||
<item
|
|
||||||
android:id="@+id/action_test_alarm_beep"
|
|
||||||
android:icon="@drawable/stop_server"
|
|
||||||
android:showAsAction="never|withText"
|
|
||||||
android:title="@string/test_alarm_beep" />
|
|
||||||
|
|
||||||
<item
|
|
||||||
android:id="@+id/action_test_warning_beep"
|
|
||||||
android:icon="@drawable/stop_server"
|
|
||||||
android:showAsAction="never|withText"
|
|
||||||
android:title="@string/test_warning_beep" />
|
|
||||||
|
|
||||||
<item
|
|
||||||
android:id="@+id/action_test_sms_alarm"
|
|
||||||
android:icon="@drawable/stop_server"
|
|
||||||
android:showAsAction="never|withText"
|
|
||||||
android:title="@string/test_sms_alarm_notification" />
|
|
||||||
|
|
||||||
<item
|
|
||||||
android:enabled="false"
|
|
||||||
android:id="@+id/action_test_phone_alarm"
|
|
||||||
android:icon="@drawable/stop_server"
|
|
||||||
android:showAsAction="never|withText"
|
|
||||||
android:title="@string/test_phone_alarm_notification" />
|
|
||||||
|
|
||||||
<item
|
|
||||||
android:enabled="false"
|
|
||||||
android:id="@+id/action_logmanager"
|
|
||||||
android:icon="@drawable/ic_action_settings"
|
|
||||||
android:showAsAction="never|withText"
|
|
||||||
android:title="@string/data_log_manager"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<item
|
|
||||||
android:id="@+id/action_logs"
|
|
||||||
android:icon="@drawable/ic_action_settings"
|
|
||||||
android:showAsAction="never|withText"
|
|
||||||
android:title="@string/view_log_entries"
|
|
||||||
android:enabled="true"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<item
|
|
||||||
android:enabled="false"
|
|
||||||
android:id="@+id/action_export"
|
|
||||||
android:icon="@drawable/ic_action_settings"
|
|
||||||
android:showAsAction="never|withText"
|
|
||||||
android:title="@string/export_data"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<item
|
|
||||||
android:id="@+id/action_settings"
|
|
||||||
android:icon="@drawable/ic_action_settings"
|
|
||||||
android:showAsAction="never|withText"
|
|
||||||
android:title="@string/settings"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<item
|
|
||||||
android:id="@+id/action_about"
|
|
||||||
android:showAsAction="never|withText"
|
|
||||||
android:title="@string/about" />
|
|
||||||
|
|
||||||
</menu>
|
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -105,7 +105,6 @@
|
|||||||
<string name="sms_location_alarm_active">SMS Location Alarm Active</string>
|
<string name="sms_location_alarm_active">SMS Location Alarm Active</string>
|
||||||
<string name="sms_location_alarm_disabled">SMS Location Alarm Disabled</string>
|
<string name="sms_location_alarm_disabled">SMS Location Alarm Disabled</string>
|
||||||
<string name="cancel_audible_not_sending_sms">Cancel Audible Active - not sending SMS</string>
|
<string name="cancel_audible_not_sending_sms">Cancel Audible Active - not sending SMS</string>
|
||||||
<string name="sms_alarm_disabled">SMS Alarms Disabled - not doing anything!</string>
|
|
||||||
<string name="no_wifi_connection">Network State Changed - no Wifi Connection</string>
|
<string name="no_wifi_connection">Network State Changed - no Wifi Connection</string>
|
||||||
<string name="no_active_network">Network State Changed - No Active Network</string>
|
<string name="no_active_network">Network State Changed - No Active Network</string>
|
||||||
<string name="problem_parsing_preferences">Problem Parsing Preferences - Something won\'t work - Please go back to Settings and correct it!</string>
|
<string name="problem_parsing_preferences">Problem Parsing Preferences - Something won\'t work - Please go back to Settings and correct it!</string>
|
||||||
|
|||||||
@@ -120,7 +120,6 @@
|
|||||||
<string name="sms_location_alarm_active">Alarma de Localización de SMS Activa</string>
|
<string name="sms_location_alarm_active">Alarma de Localización de SMS Activa</string>
|
||||||
<string name="sms_location_alarm_disabled">Alarma de Localización de SMS Inactiva</string>
|
<string name="sms_location_alarm_disabled">Alarma de Localización de SMS Inactiva</string>
|
||||||
<string name="cancel_audible_not_sending_sms">Cancele Alarma Audible - no enviando SMS</string>
|
<string name="cancel_audible_not_sending_sms">Cancele Alarma Audible - no enviando SMS</string>
|
||||||
<string name="sms_alarm_disabled">Alarmas de SMS Incativas - No está haciendo nada ! </string>
|
|
||||||
<string name="no_wifi_connection">Cambio en el Estado de Red - Sin Conexión de Wifi</string>
|
<string name="no_wifi_connection">Cambio en el Estado de Red - Sin Conexión de Wifi</string>
|
||||||
<string name="no_active_network">Cambio en el Estado de Red - Sin Red Activa</string>
|
<string name="no_active_network">Cambio en el Estado de Red - Sin Red Activa</string>
|
||||||
<string name="problem_parsing_preferences">Problema al Interpretar las Preferencias - Algo no está Trabajando - Por favor regrese a Ajustes y corríjalo !</string>
|
<string name="problem_parsing_preferences">Problema al Interpretar las Preferencias - Algo no está Trabajando - Por favor regrese a Ajustes y corríjalo !</string>
|
||||||
|
|||||||
@@ -113,7 +113,7 @@
|
|||||||
<string name="BasicPrefSummary">Ustawienia podstawowe</string>
|
<string name="BasicPrefSummary">Ustawienia podstawowe</string>
|
||||||
<string name="accept_alarm">Zaakceptuj alarm</string>
|
<string name="accept_alarm">Zaakceptuj alarm</string>
|
||||||
<string name="start_stop_server">Włącz/wyłącz serwer</string>
|
<string name="start_stop_server">Włącz/wyłącz serwer</string>
|
||||||
<string name="install_watch_app">Zainstaluj apkę na zegarek</string>
|
<string name="install_watch_app">Pobierz apkę na zegarek</string>
|
||||||
<string name="test_alarm_beep">Test alarmu dźwiękowego</string>
|
<string name="test_alarm_beep">Test alarmu dźwiękowego</string>
|
||||||
<string name="test_warning_beep">Test dźwięku ostrzeżeń</string>
|
<string name="test_warning_beep">Test dźwięku ostrzeżeń</string>
|
||||||
<string name="test_sms_alarm_notification">Wyślij próbny alarm SMS</string>
|
<string name="test_sms_alarm_notification">Wyślij próbny alarm SMS</string>
|
||||||
@@ -128,7 +128,6 @@
|
|||||||
<string name="sms_location_alarm_active">SMS będzie zawierać lokalizację</string>
|
<string name="sms_location_alarm_active">SMS będzie zawierać lokalizację</string>
|
||||||
<string name="sms_location_alarm_disabled">SMS nie będzie zawierać lokalizacji</string>
|
<string name="sms_location_alarm_disabled">SMS nie będzie zawierać lokalizacji</string>
|
||||||
<string name="cancel_audible_not_sending_sms">Wyłączono alarmy dźwiękowe - nie wysyłam SMS</string>
|
<string name="cancel_audible_not_sending_sms">Wyłączono alarmy dźwiękowe - nie wysyłam SMS</string>
|
||||||
<string name="sms_alarm_disabled">Wyłączono alarmy SMS - nic nie zrobię!</string>
|
|
||||||
<string name="no_wifi_connection">Stan sieci zmieniony - brak połączenia Wifi</string>
|
<string name="no_wifi_connection">Stan sieci zmieniony - brak połączenia Wifi</string>
|
||||||
<string name="no_active_network">Stan sieci zmieniony - brak aktywnych sieci</string>
|
<string name="no_active_network">Stan sieci zmieniony - brak aktywnych sieci</string>
|
||||||
<string name="problem_parsing_preferences">Problem z ustawieniami - to nie zadziała - proszę wrócić do ustawień i poprawić to!</string>
|
<string name="problem_parsing_preferences">Problem z ustawieniami - to nie zadziała - proszę wrócić do ustawień i poprawić to!</string>
|
||||||
@@ -276,7 +275,7 @@
|
|||||||
<string name="AlarmFunctionalitySettingsTitle">Ustawienia alarmów</string>
|
<string name="AlarmFunctionalitySettingsTitle">Ustawienia alarmów</string>
|
||||||
<string name="AudibleAlarmSettingsTitle">Ustawienia alarmów dźwiękowych</string>
|
<string name="AudibleAlarmSettingsTitle">Ustawienia alarmów dźwiękowych</string>
|
||||||
<string name="SMSAlarmSettingsTitle">Ustawienia alarmów SMS</string>
|
<string name="SMSAlarmSettingsTitle">Ustawienia alarmów SMS</string>
|
||||||
<string name="DefaultSMSMsgText">**SPRAWDŹ PODOPIECZNEGO**</string>
|
<string name="DefaultSMSMsgText">**ALARM! SPRAWDŹ PODOPIECZNEGO!**</string>
|
||||||
<string name="AlarmLoggingTitle">Dziennik alarmów</string>
|
<string name="AlarmLoggingTitle">Dziennik alarmów</string>
|
||||||
<string name="WarnTimeSummary">Czas oczekiwania przed włączeniem ostrzeżenia (domyślnie = 5 sek)</string>
|
<string name="WarnTimeSummary">Czas oczekiwania przed włączeniem ostrzeżenia (domyślnie = 5 sek)</string>
|
||||||
<string name="WarnTimeTitle">Opóźnienie ostrzeżenia (sek)</string>
|
<string name="WarnTimeTitle">Opóźnienie ostrzeżenia (sek)</string>
|
||||||
|
|||||||
Binary file not shown.
351
app/src/main/res/values-sl/strings.xml
Normal file
351
app/src/main/res/values-sl/strings.xml
Normal file
@@ -0,0 +1,351 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<string name="app_name">OpenSeizureDetector</string>
|
||||||
|
<string name="changelog">
|
||||||
|
"V4.0 - Dodano logiranje podatkov na strežnik.
|
||||||
|
\nV3.7.0 - Dodana podpora za Garmin meritve sauturacije kisika v krvi.
|
||||||
|
\nV3.6.2 - Popravek težav s pravicami datotek logiranja na nekaterih napravah Android 10 in dodanih nekaj prevedljivih besedil vmesnika.
|
||||||
|
\nV3.6.1 - Morebiten popravek težave ugašanja sistema.
|
||||||
|
\nV3.6 - Dodan podatkovni vir senzorjev telefona za testiranje brez pametnih ur.
|
||||||
|
\nV3.5 - Dodana podpora za SMS Annunciator App
|
||||||
|
\nV3.4 - Dodana podpora za podatkovne vire BLE"</string>
|
||||||
|
<string name="UpgradeMsg">
|
||||||
|
OpenSeizureDetector ne zbira osebnih podatkov.
|
||||||
|
To pomeni, da ne morem kontaktirati uporabnikov, če naletim na težavo z aplikacijo,
|
||||||
|
ki bi se jo morali zavedati.\n
|
||||||
|
Prosim, naročite se na ažurne informacije na http://openseizuredetector.org.uk ali na https://www.facebook.com/openseizuredetector,
|
||||||
|
tako da vas lahko obvestim, če bo potrebno.\nHvala! Graham \ngraham@openseizuredetector.org.uk
|
||||||
|
\n\nSpremembe v tej verziji:
|
||||||
|
\n
|
||||||
|
</string>
|
||||||
|
<string name="FirstRunDlgMsg">
|
||||||
|
OpenSeizureDetector ne zbira osebnih podatkov.
|
||||||
|
To pomeni, da ne morem kontaktirati uporabnikov, če naletim na težavo z aplikacijo,
|
||||||
|
ki bi se jo morali zavedati.\n
|
||||||
|
Prosim, naročite se na ažurne informacije na http://openseizuredetector.org.uk ali na https://www.facebook.com/openseizuredetector,
|
||||||
|
tako da vas lahko obvestim, če bo potrebno.\nHvala! Graham \ngraham@openseizuredetector.org.uk
|
||||||
|
\n\nSpremembe v tej verziji:
|
||||||
|
</string>
|
||||||
|
<string name="ask_for_error_log">Pardon, OpenSeizureDetector se je zrušil. Prosim, pošljite ta log po elektronski pošti, da lahko ugotovimo, kako odpraviti težavo.\nHvala, Graham.</string>
|
||||||
|
<string name="email_welcome_note">Dragi OpenSeizureDetector,\n\nAplikacija se je ravnokar zrušila, prosim preverite priloženi log za podrobnosti.\n\n\n</string>
|
||||||
|
<string name="copyright_info">OpenSeizureDetector (Uporablja UCE Handler\nCopyright © 2018 Rohit Sahebrao Surwase.)</string>
|
||||||
|
<string name="okBtnTxt">OK</string>
|
||||||
|
<string name="UpdateDialogTitleTxt">Hvala za posodobitev OpenSeizureDetector</string>
|
||||||
|
<string name="FirstRunDlgTitle">Dobrodošli v OpenSeizureDetector</string>
|
||||||
|
<string name="SmsPermissionWarning">Problem z SMS dovoljenji</string>
|
||||||
|
<string name="AppPermissionsOk">App dovoljenja OK</string>
|
||||||
|
<string name="AppPermissionsWarning">Problem z App dovoljenji</string>
|
||||||
|
<string name="BoundToServiceOk">Povezava na storitev OK</string>
|
||||||
|
<string name="BindingToService">Povezovanje na storitev v ozadnju ...</string>
|
||||||
|
<string name="WatchConnectedOk">Ura povezana OK</string>
|
||||||
|
<string name="WatchNotConnected">Ura NI povezana</string>
|
||||||
|
<string name="SeizureDetectorDataReceived">Podatki detektorja napadov sprejeti OK</string>
|
||||||
|
<string name="WaitingForSeizureDetectorData">Čakanje podatkov detektorja napadov ...</string>
|
||||||
|
<string name="SeizureDetectorSettingsReceived">Nastavitve detektorja napadov sprejeti OK</string>
|
||||||
|
<string name="WaitingForSeizureDetectorSettings">Čakanje nastavitev detektorja napadov ...</string>
|
||||||
|
<string name="DataSource">Vir podatkov</string>
|
||||||
|
<string name="AppTitleText">OpenSeizureDetector Android App Verzija </string>
|
||||||
|
<string name="ServerRunningOK">Strežnik deluje OK\n</string>
|
||||||
|
<string name="AccessServerAt">Dostopanje strežnika na </string>
|
||||||
|
<string name="ServerStopped">Strežnik ustavljen</string>
|
||||||
|
<string name="Warning">OPOZORILO</string>
|
||||||
|
<string name="Mute">TIHO</string>
|
||||||
|
<string name="Alarm">**ALARM**</string>
|
||||||
|
<string name="Fall">**PADEC**</string>
|
||||||
|
<string name="HR_Equals">Srčni utrip = </string>
|
||||||
|
<string name="HRAlarmOff">Alarm Srčnega utripa IZKLJUČEN</string>
|
||||||
|
<string name="WatchAppOK">App ure OK</string>
|
||||||
|
<string name="WatchAppNotRunning">App ure NE dela</string>
|
||||||
|
<string name="WatchBatteryEquals">Baterija ure = </string>
|
||||||
|
<string name="PowerEquals">Moč = </string>
|
||||||
|
<string name="SpectrumRatioEquals">Razmerje spektra = </string>
|
||||||
|
<string name="Threshold">Prag</string>
|
||||||
|
<string name="NetFault">NAPAKA OMREŽJA</string>
|
||||||
|
<string name="WatchApp">App ure -----</string>
|
||||||
|
<string name="Dashes">------</string>
|
||||||
|
<string name="SMSWillBeSentIn">SMS bo poslan v </string>
|
||||||
|
<string name="Cancel">PREKLIC?</string>
|
||||||
|
<string name="AcceptAlarm">Sprejmi Alarm</string>
|
||||||
|
<string name="AudibleAlarmsCancelledFor">Utišano za </string>
|
||||||
|
<string name="PressToReEnable"> Obnovi</string>
|
||||||
|
<string name="CancelAudibleAlarms">Utišaj alarme</string>
|
||||||
|
<string name="AudibleAlarmsOff">Zvočni Alarmi IZKLJUČENI</string>
|
||||||
|
<string name="Fault">NAPAKA</string>
|
||||||
|
<string name="authenticate">Prijava</string>
|
||||||
|
<string name="not_authenticated">Neprijavljen</string>
|
||||||
|
<string name="cancel">Preklic</string>
|
||||||
|
<!-- Strings related to login -->
|
||||||
|
<string name="prompt_email">Email</string>
|
||||||
|
<string name="prompt_password">Geslo</string>
|
||||||
|
<string name="action_sign_in">Prijava ali registracija</string>
|
||||||
|
<string name="action_sign_in_short">Prijava</string>
|
||||||
|
<string name="welcome">"Dobrodošli!"</string>
|
||||||
|
<string name="invalid_username">Uporabniško ime ni veljavno</string>
|
||||||
|
<string name="invalid_password">Geslo mora biti >5 znakov</string>
|
||||||
|
<string name="login_failed">"Prijava neuspešna"</string>
|
||||||
|
<string name="AdvancedModeTitle">Napredni Način</string>
|
||||||
|
<string name="AdvancedModeSummary">Omogoči Napredni način (prikaže mnogo dodatnih nastavitev ...)</string>
|
||||||
|
<string name="AutoStartTitle">Samodejni Zagon</string>
|
||||||
|
<string name="AutoStartSummary">OpenSeizureDetector se samodejno zažene ob zagonu telefona</string>
|
||||||
|
<string name="DataSourceTitle">Izberi Vir Podatkov</string>
|
||||||
|
<string name="DataSourceSummary">Izberi, kaj naj se uporabi za vir podatkov detekcije napadov (ura Garmin, ura Pebble, ali omrežna povezava)</string>
|
||||||
|
<string name="LogRemoteTitle">Oddaljeno Logiranje Podatkov</string>
|
||||||
|
<string name="LogRemoteSummary">Logiranje podatkov v centralno bazo OpenSeizureDetector</string>
|
||||||
|
<string name="UseMobileTitle">Uporabi Mobilni Internet</string>
|
||||||
|
<string name="UseMobileSummary">Uporabi mobilni internet za logiranje podatkov</string>
|
||||||
|
<string name="SeizureDetectorSettingsTitle">Nastavitve Detektorja Napadov</string>
|
||||||
|
<string name="AlarmThreshTitle">Prag Alarma</string>
|
||||||
|
<string name="AlarmThreshSummary">Prag alarma (Privzeto = 100)</string>
|
||||||
|
<string name="AlarmRatioThreshTitle">Prag Razmerja Alarma</string>
|
||||||
|
<string name="AlarmRatioThreshSummary">Prag razmerja alarma (Privzeto = 50). Povečaj za zmanjšanje občutljivosti.</string>
|
||||||
|
<string name="AlarmFreqMaxTitle">Max Frekv. Alarma (Hz)</string>
|
||||||
|
<string name="AlarmFreqMaxSummary">Najvišja frekvenca ROI (Hz) (Privzeto = 8 Hz)</string>
|
||||||
|
<string name="AlarmFreqMinTitle">Min frekv. Alarma (Hz)</string>
|
||||||
|
<string name="AlarmFreqMinSummary">Najnižja frekvenca ROI (Hz) (Privzeto = 3 Hz)</string>
|
||||||
|
<string name="HRAlarmEnabledTitle">Alarm Srčnega Utripa Omogočen</string>
|
||||||
|
<string name="HRAlarmEnabledSummary" />
|
||||||
|
<string name="HRNullAlarmTitle">Obravnavaj stanje brez srčnega utripa kot alarm</string>
|
||||||
|
<string name="HRNullAlarmSummary" />
|
||||||
|
<string name="HRThreshMinTitle">Min prag Srčnega Utripa (utripov/min)</string>
|
||||||
|
<string name="HRThreshMinSummary" />
|
||||||
|
<string name="HRThreshMaxTitle">Max prag Srčnega Utripa (utripov/min)</string>
|
||||||
|
<string name="HRThreshMaxSummary" />
|
||||||
|
<string name="BasicPrefTitle">Osnovno</string>
|
||||||
|
<string name="BasicPrefSummary">Osnovne preference</string>
|
||||||
|
<string name="accept_alarm">Sprejmi Alarm</string>
|
||||||
|
<string name="start_stop_server">Start/Stop Strežnik</string>
|
||||||
|
<string name="install_watch_app">Namesti app ure</string>
|
||||||
|
<string name="test_alarm_beep">Testiraj pisk alarma</string>
|
||||||
|
<string name="test_warning_beep">Testiraj pisk opozorila</string>
|
||||||
|
<string name="test_sms_alarm_notification">Testiraj SMS opozorilo alarma</string>
|
||||||
|
<string name="data_log_manager">Upravljanje podatkov logiranja</string>
|
||||||
|
<string name="view_log_entries">Pregled podatkov logiranja</string>
|
||||||
|
<string name="export_data">Izvažanje podatkov</string>
|
||||||
|
<string name="settings">Nastavitve</string>
|
||||||
|
<string name="about">O appu ...</string>
|
||||||
|
<string name="about_text">OpenSeizureDetector je detektor epileptičnih (konvulzivnih) napadov in sistem alarmov. Uporablja pametno uro za detekcijo tresenja povezanega z napadom, nakar sproži glasovna in SMS opozorila za skrbnike. Sistem je brezplačen in odprtokoden - več na http://openseizuredetector.org.uk. Prosim sporočite težave na graham@openseizuredetector.org.uk\n ali prijavite težavo na github projektu odprte kode, repozitorij - https://github.com/OpenSeizureDetector</string> <!-- preveri "konvulzivnost" z Grahamom -->
|
||||||
|
<string name="credits_text">App glavne ure in Android App \n copyright Graham Jones, 2015.\n Uporabljene so sledeče knjižnice :\n - SYLT-FFT - https://github.com/stg/SYLT-FFT by D. Taylor.\n - NanoHTTPD - https://github.com/NanoHttpd/nanohttpd\n - jQuery - http://jquery.org\n - jBeep - http://www.ultraduz.com.br\n - Chartjs - http://www.chartjs.org\n - MPAndroidChart - https://github.com/PhilJay/MPAndroidChart\n - UCE-Handler - https://github.com/RohitSurwase/UCE-Handler\n \n Logotip temelji na Star of life2, avtorja Verdy P, \n Licensed under Public Domain via\n Wikimedia Commons (http://commons.wikimedia.org/wiki/File:Star_of_life2.svg#mediaviewer/File:Star_of_life2.svg).</string>
|
||||||
|
<string name="edit_settings">Urejanje nastavitev</string>
|
||||||
|
<string name="sms_location_alarm_active">SMS alarm lokacije Aktiven</string>
|
||||||
|
<string name="sms_location_alarm_disabled">SMS alarm lokacije Neaktiven</string>
|
||||||
|
<string name="cancel_audible_not_sending_sms">Cancel Audible Active - not sending SMS</string> <!-- HMMM, what does it mean?? -->
|
||||||
|
<!--<string name="sms_alarm_disabled">SMS alarmi Onemogočeni - ne javlja nič!</string>-->
|
||||||
|
<string name="no_wifi_connection">Spremenjeno stanje omrežja - ni Wifi povezave</string>
|
||||||
|
<string name="no_active_network">Spremenjeno stanje omrežja - Ni aktivne povezave</string>
|
||||||
|
<string name="problem_parsing_preferences">Težava pri razčlenjevanju nastavitev - Nekaj ne bo delalo - Prosim vrnite se v nastavitve in popravite!</string>
|
||||||
|
<string name="send_sms_last_location">Pošiljanje SMS - zadnja lokacija je </string>
|
||||||
|
<string name="failed_to_send_sms">NAPAKA: POŠILJANJE SMS NEUSPEŠNO</string>
|
||||||
|
<string name="sms_alarms_disabled">SMS alarmi Onemogočeni - ne javlja nič!</string>
|
||||||
|
<string name="phone_alarm_disabled">Alarmi telefona Onemogočeni</string>
|
||||||
|
<string name="test_phone_alarm_notification">Testni alarm telefona</string>
|
||||||
|
<string name="DiallerNotInstalledWarning"><a href="https://github.com/OpenSeizureDetector/Dialler/tree/master/app/release/app-release.apk">OpenSeizureDetector Dialer App</a> Ni inštaliran - Potreben je za opozorilne klice.</string>
|
||||||
|
<string name="title_devices">BLE Naprave</string>
|
||||||
|
<string name="ble_not_supported">BLE ni podprto</string>
|
||||||
|
<string name="error_bluetooth_not_supported">Bluetooth ni podprt</string>
|
||||||
|
<string name="menu_stop">STOP</string>
|
||||||
|
<string name="menu_scan">IŠČI</string>
|
||||||
|
<string name="unknown_device">Neznana naprava</string>
|
||||||
|
<string name="select_ble_device_title">Izberi BLE Napravo (samo za Bluetooth kot podatkovni vir)</string>
|
||||||
|
<string name="select_ble_device_desc">Izberi napravo Bluetooth Low Energy (BLE) za pridobitev podatkov o napadih (pospešek in srčni utrip) data) pri uporabi Bluetooth naprave kot podatkovnega vira.</string>
|
||||||
|
<string name="basic_settings_title">Osnovno</string>
|
||||||
|
<string name="basic_settings_summary">Osnovne Nastavitve</string>
|
||||||
|
<string name="general_settings_title">General</string>
|
||||||
|
<string name="general_settings_summary">Splošne preference</string>
|
||||||
|
<string name="alarms_settings_title">Alarmi</string>
|
||||||
|
<string name="alarms_settings_summary">Preference alarmov</string>
|
||||||
|
<string name="seizure_detector_settings_title">Detektor Napadov</string>
|
||||||
|
<string name="seizure_detector_settings_summary">Preference detektorja napadov</string>
|
||||||
|
<string name="pebble_datasource_summary">Preference podatkovnega vira Pebble</string>
|
||||||
|
<string name="network_datasource_title">Vir Podatkov Omrežje</string>
|
||||||
|
<string name="network_datasource_summary">Preference podatkovnega vira Omrežje</string>
|
||||||
|
<string name="pebble_datasource_title">Vir Podatkov Pebble</string>
|
||||||
|
<string name="select_datasource_title">Izberi Podatkovni Vir</string>
|
||||||
|
<string name="select_datasource_summary">Izberi želeni podatkovni vir detektorja napadov.</string>
|
||||||
|
<string name="log_alarms_summary">Logiranje alarmov v pomnilnik telefona</string>
|
||||||
|
<string name="log_alarms_title">Log Alarmnih Dogodkov</string>
|
||||||
|
<string name="log_data_summary">Logiranje podatkov v pomnilnik telefona</string>
|
||||||
|
<string name="log_data_title">Podatki Logiranja</string>
|
||||||
|
<string name="log_data_remote_summary">Deljenje podatkov z OpenSeizureDetector</string>
|
||||||
|
<string name="log_data_remote_title">Deljenje Podatkov</string>
|
||||||
|
<string name="log_data_remote_mobile_summary">Uporabi mobilni internet za delitev podatkov</string>
|
||||||
|
<string name="log_data_remote_mobile_title">Uporabi Mobilni Internet</string>
|
||||||
|
<string name="remote_uname_title">Uporabniško Ime</string>
|
||||||
|
<string name="remote_uname_summary">Uporabniško ime za deljenje podatkov</string>
|
||||||
|
<string name="remote_passwd_summary">Geslo za deljenje podatkov</string>
|
||||||
|
<string name="remote_passwd_title">Geslo</string>
|
||||||
|
<string name="wearer_id_summary">ID uporabnika</string>
|
||||||
|
<string name="wearer_id_title">ID uporabnika, ki uporablja pametno uro (iz OSD Web API)</string>
|
||||||
|
<string name="remote_url_summary">URL za oddaljeno logiranje podatkov.</string>
|
||||||
|
<string name="remote_url_title">Oddaljeni URL</string>
|
||||||
|
<string name="prevent_sleep_summary">Prepreči ugašanje zaslona med delovanjem aplikacije.</string>
|
||||||
|
<string name="prevent_sleep_title">Prepreči Ugašanje Zaslona</string>
|
||||||
|
<string name="data_update_period_summary">Prikaži periodo osveževanja v milisekundah.</string>
|
||||||
|
<string name="data_update_period_title">Prikaži periodo osveževanja (ms).</string>
|
||||||
|
<string name="auto_start_summary">Samodejno zaženi App ob zagonu naprave</string>
|
||||||
|
<string name="auto_start_title">Samodejno Zaženi App ob Zagonu</string>
|
||||||
|
<string name="app_version_summary">Verzija aplikacije - uporabljeno za odločanje o prikazu sporočila dobrodošlice.</string>
|
||||||
|
<string name="app_version_title">Verzija Aplikacije</string>
|
||||||
|
<string name="latch_alarms_summary">Require manual reset of alarms to reset them to silence them.</string>
|
||||||
|
<string name="latch_alarms_title">Trajanje Alarmov</string>
|
||||||
|
<string name="latch_timer_period_title">Trajanje Alarmov (sek)</string>
|
||||||
|
<string name="latch_timer_period_summary">Koliko sekund bodo alarmi opozarjali, preden se samodejno utišajo.</string>
|
||||||
|
<string name="enable_audible_alarm_summary">Sproži zvočni alarm, če datektor napadov zazna alarmno stanje.</string>
|
||||||
|
<string name="enable_audible_alarm_title">Omogoči Zvočni Alarm</string>
|
||||||
|
<string name="enable_audible_warning_summary">Sproži zvočni alarm, če datektor napadov zazna opozorilno (pred-alarmno) stanje.</string>
|
||||||
|
<string name="enable_audible_warning_title">Omogoči Zvočna Opozorila</string>
|
||||||
|
<string name="enable_audible_fault_summary">Sproži zvočni alarm, če sistem zazna napako (npr. ni komunikacije s pametno uro).</string>
|
||||||
|
<string name="enable_audible_fault_title">Omogoči Zvočna Opozorila Napak Sistema</string>
|
||||||
|
<string name="fault_timer_period_title">Časovnik Trajanja Napake (sek)</string>
|
||||||
|
<string name="fault_timer_period_summary">Trajanje zakasnitve alarmiranja o napakah sistema (preden se sprožijo).</string>
|
||||||
|
<string name="use_mp3_alarm_summary">Predvajaj MP3 datoteko za predvajanje opozorilnih alarmov (namesto privzetega generatorja tonov).</string>
|
||||||
|
<string name="use_mp3_alarm_title">Uporabi MP3 Zvok Alarma</string>
|
||||||
|
<string name="enable_sms_alarm_summary">Pošlji SMS alarm, če detektor napadov zazna alarmno stanje. OPOZORILO: SPOROČILO BO VSEBOVALO LOKACIJO UPORABNIKA. Onemogoči to izbiro, če deljenje lokacije vzbuja skrbi.</string>
|
||||||
|
<string name="enable_sms_alarm_title">Omogoči SMS Alarm</string>
|
||||||
|
<string name="sms_numbers_summary">Telefonske št. (1 ali več) za obveščanje z SMS Alarmi (ločene z vejico).</string>
|
||||||
|
<string name="sms_numbers_title">Telefonske št. SMS Alarmov</string>
|
||||||
|
<string name="sms_message_summary">SMS sporočilo za pošiljanje kadar je zaznan napad.</string>
|
||||||
|
<string name="sms_message_title">SMS Sporočilo</string>
|
||||||
|
<string name="server_ip_summary">IP naslov strežnika OpenSeizureDetector (npr. 192.168.1.175).</string>
|
||||||
|
<string name="server_ip_title">IP Naslov Strežnika.</string>
|
||||||
|
<string name="network_update_period_summary">Perioda med strežniškimi zahtevami v milisekundah.</string>
|
||||||
|
<string name="network_update_period_title">Perioda Posodobitve Podatkov (ms)</string>
|
||||||
|
<string name="connection_timeout_summary" />
|
||||||
|
<string name="connection_timeout_title">Timeout Povezovanja (ms)</string>
|
||||||
|
<string name="read_timeout_summary" />
|
||||||
|
<string name="read_timeout_title">Timeout Branja (ms)</string>
|
||||||
|
<string name="ble_device_settings_title">Nastavitve Naprave BLE</string>
|
||||||
|
<string name="ble_mac_addr_summary">MAC naslov naprave BLE kot podatkovnega vira</string>
|
||||||
|
<string name="ble_mac_addr_title">MAC Naslov Naprave</string>
|
||||||
|
<string name="ble_device_name_summary">Ime naprave BLE kot podatkovnega vira</string>
|
||||||
|
<string name="ble_device_name_title">Ime Naprave</string>
|
||||||
|
<string name="user_interface_settings_title">Nastavitve Uporabniškega Vmesnika</string>
|
||||||
|
<string name="pebble_update_period_summary">Časovna perioda pošiljanja podatkov telefonu (ne vpliva na frekvenco analize - tisto je v nastavitvi Perioda Vzorčenja)</string>
|
||||||
|
<string name="mute_period_summary">Trajanje utišanja alarmov po dolgem pritisku gumba GOR</string>
|
||||||
|
<string name="pebble_update_period_title">Perioda Prenosa Podatkov (sek)</string>
|
||||||
|
<string name="mute_period_title">Perioda Utišanja (sek)</string>
|
||||||
|
<string name="manual_alarm_period_summary">Trajanje zvonjenja ročnih alarmov po dolgem pritisku gumba DOL</string>
|
||||||
|
<string name="manual_alarm_period_title">Perioda Ročnega Alarma (sek)</string>
|
||||||
|
<string name="warn_time_summary">Trajanje pred začetkom opozarjanja (privzeto = 5 sek)</string>
|
||||||
|
<string name="warn_time_title">Čas do Opozarjanja (sek)</string>
|
||||||
|
<string name="alarm_time_summary">Trajanje pred začetkom alarmiranja (privzeto = 10 sek)</string>
|
||||||
|
<string name="alarm_time_title">Čas do Alarmiranja (sek)</string>
|
||||||
|
<string name="alarm_threshold_summary">Prag za proženje Alarma (privzeto = 100)</string>
|
||||||
|
<string name="alarm_threshold_title">Prag Alarma</string>
|
||||||
|
<string name="alarm_ratio_thresh_summary">Prag razmerja alarma (privzeto = 50). Povečaj to vrednost za zmanjšanje občutljivosti, če so lažni alarmi problem.</string>
|
||||||
|
<string name="alarm_ratio_thresh_title">Prag Razmerja Alarma</string>
|
||||||
|
<string name="alarm_freq_min_summary">Minimum za Območje Zanimanja, t.j. ROI (privzeto = 3 Hz)</string>
|
||||||
|
<string name="alarm_freq_min_title">Min. Frekvenca Alarma (Hz)</string>
|
||||||
|
<string name="alarm_freq_max_summary">Maksimum za Območje Zanimanja, t.j. ROI (privzeto = 10 Hz)</string>
|
||||||
|
<string name="alarm_freq_max_title">Max Frekvenca Alarma (Hz)</string>
|
||||||
|
<string name="sample_period_summary">Perioda med analizami podatkov (v sekundah)</string>
|
||||||
|
<string name="sample_period_title">Perioda Vzorčenja (sek)</string>
|
||||||
|
<string name="seizure_detect_mode_summary">Izberi enega od treh načinov delovanja.</string>
|
||||||
|
<string name="seizure_detect_mode_title">Način Detekcije Napadov</string>
|
||||||
|
<string name="sample_freq_summary">Višja frekvenca je bolj natančna, ampak porabi več baterije.</string>
|
||||||
|
<string name="sample_freq_title">Izberi Frekvenco Vzorca</string>
|
||||||
|
<string name="fall_detect_title">Nastavitve Detektorja Padcev</string>
|
||||||
|
<string name="fall_detect_active_title">Vključi Funkcijo Detekcije Padcev</string>
|
||||||
|
<string name="fall_thresh_min_title">Spodnji Prag Detekcije Padcev (milli-g)</string>
|
||||||
|
<string name="fall_thresh_max_title">Zgornji Prag Detekcije Padcev (milli-g)</string>
|
||||||
|
<string name="fall_window_title">Časovno Okno Detekcije Padcev (mili sekund)</string>
|
||||||
|
<string name="watch_comms_title">Nastavitve Komunikacije Ure</string>
|
||||||
|
<string name="debug_mode_summary">Vključi ali Izključi odkrivanje napak.</string>
|
||||||
|
<string name="debug_mode_title">Odkrivanje Napak Detektorja Napadov</string>
|
||||||
|
<string name="app_restart_timeout_summary">Perioda čakanja na podatke iz ure preden predpostavimo, da ne dela, in ponovno zaženemo aplikacijo na uri.</string>
|
||||||
|
<string name="app_restart_timeout_title">Perioda čakanja podatkov (v sekundah) pred ponovnim zagonom aplikacije na uri.</string>
|
||||||
|
<string name="display_spectrum_mode_title">Select Display Spectrum Mode</string> <!-- what is this -->
|
||||||
|
<string name="display_spectrum_mode_summary">Vključi ali Izključi Display Spectrum.</string> <!-- what is this -->
|
||||||
|
<string name="analysis_prefs_title">Analiza</string>
|
||||||
|
<string name="watch_comms_settings_title">Nastavitve Komunikacije z Uro</string>
|
||||||
|
<string name="ParsePreferenceWarning">Problem Parsing Preferences - Something won\'t work - Please go back to Settings and correct it!</string> <!-- same as line 135? -->
|
||||||
|
<string name="ErrorWritingLogFileWarning">NAPAKA pisanja v datoteko Logiranja</string>
|
||||||
|
<string name="RestartingServerMsg">Dovoljenja spremenjena - ponovno zaženi strežnik</string>
|
||||||
|
<string name="ErrorReleasingWakelockMsg">Napaka pri sprostitvi Wakelock mehanizma</string>
|
||||||
|
<string name="SMSAlarmAlreadySentMsg">SMS Alarm že poslan - ni ponovnega pošiljanja</string>
|
||||||
|
<string name="SMSAlarmDisabledNotSendingMsg">SMS Alarmi Onemogočeni - SMS opozorila se ne pošiljajo</string>
|
||||||
|
<string name="PleaseForceStopOSDorRebootMsg">NAPAKA - OpenSizureDetector se ni pravilno zagnal - prosim Prisilno zaustavi OpenSeizureDetector ali ponovno zaženi telefon.</string>
|
||||||
|
<string name="SMSPermissionsDeniedMsg">NAPAKA - Dovoljenje za SMS ali Lokacijo zavrnjeno - SMS se ne pošiljajo</string>
|
||||||
|
<string name="DatasourceTitle">\"Podatkovni vir\"</string>
|
||||||
|
<string name="DefaultingToPhoneMsg">\" ni prepoznan - Privzeto nastavljen na Telefon\"</string>
|
||||||
|
<string name="SMSAlarmCancelledMsg">SMS Alarm Preklican</string>
|
||||||
|
<string name="StopServerTitle">Ustavi Strežnik</string>
|
||||||
|
<string name="StartServerTitle">Startaj Strežnik</string>
|
||||||
|
<string name="StartingTitle">Starting......</string>
|
||||||
|
<string name="AcceptAlarmBtnTxt">Sprejmi Alarm</string>
|
||||||
|
<string name="CancelAudibleButtonTxt">Prekliči Zvoke (začasno)</string>
|
||||||
|
<string name="DataLoggingSettingsTitle">Nastavitve Logiranja podatkov</string>
|
||||||
|
<string name="HeartRateAlarmSettingsTitle">Nastavitve Alarmov Srčnega Utripa</string>
|
||||||
|
<string name="AlarmFunctionalitySettingsTitle">Nastavitve Alarmov</string>
|
||||||
|
<string name="AudibleAlarmSettingsTitle">Nastavitve Zvočnih Alarmov</string>
|
||||||
|
<string name="SMSAlarmSettingsTitle">Nastavitve SMS Alarmov</string>
|
||||||
|
<string name="DefaultSMSMsgText">**NAPAD ZAZNAN**</string>
|
||||||
|
<string name="AlarmLoggingTitle">Logiranje Alarmov</string>
|
||||||
|
<string name="WarnTimeSummary">Perioda čakanja preden se prožijo opozorila (privzeto = 5 sek)</string> <!-- lines 283..286 already in 228...231 -->
|
||||||
|
<string name="WarnTimeTitle">Zamik Opozoril (sek)</string>
|
||||||
|
<string name="AlarmTimeSummary">Perioda čakanja preden se prožijo alarmi (privzeto = 10 sek)</string>
|
||||||
|
<string name="AlarmTimeTitle">Zamik Alarmov (sek)</string>
|
||||||
|
<string name="O2SatSettingsTitle">Nastavitve Alarmov Sauturacije Kisika v Krvi</string>
|
||||||
|
<string name="O2Sat_enabled_summary">O2Sat_enabled_summary</string> <!-- Missing "human string"? -->
|
||||||
|
<string name="O2Sat_enabled_title">Omogoči Alarme Saturacije Kisika</string>
|
||||||
|
<string name="O2SatNullAlarmSummary">Obravnavaj napako (stanje brez meritev saturacije) kot alarm</string>
|
||||||
|
<string name="O2SatNullAlarmTitle">Obravnavaj stanje brez Saturacije kot alarm</string>
|
||||||
|
<string name="O2SatThreshMinTitle">Min. Saturacije kisika za Alarm (%)</string>
|
||||||
|
<string name="O2SatThreshMinSummary">Spodnja meja Saturacije kisika za proženje Alarmov (%)</string>
|
||||||
|
<string name="title_activity_authenticate">Prijava v Deljenje Podatkov OpenSeizureDetector</string>
|
||||||
|
<string name="logout">Odjava</string>
|
||||||
|
<string name="logged_in_with_token">Prijavljen v\nDeljenje Podatkov</string>
|
||||||
|
<string name="local_database">Upravitelj Podatkov Logiranja</string>
|
||||||
|
<string name="remote_database">Deljeni Podatki</string>
|
||||||
|
<string name="num_local_events">Št. Dogodkov Shranjenih na Telefonu: </string>
|
||||||
|
<string name="num_local_datapoints">"Št. Podatkovnih Točk Shranjenih na Telefonu: "</string>
|
||||||
|
<string name="view_remote_db_btn">Ogled Podatkov Oddaljene Baze</string>
|
||||||
|
<string name="report_seizure">Prijavi Napad</string>
|
||||||
|
<string name="date">"Datum: "</string>
|
||||||
|
<string name="select_date">Izberi Datum</string>
|
||||||
|
<string name="time">"Čas: "</string>
|
||||||
|
<string name="cancelBtnTxt">Preklic</string>
|
||||||
|
<string name="select_time">Izberi Čas</string>
|
||||||
|
<string name="EventsInLocalDb">Dogodki Shranjeni na Telefonu</string>
|
||||||
|
<string name="createdNewEvent">Ustvarjen nov Ročni Alarm</string>
|
||||||
|
<string name="DatapointNotFound">Podatkovna točka ni najdena - nič ni zabeleženo</string>
|
||||||
|
<string name="logging_settings_title">Nastavitve Logiranja podatkov</string>
|
||||||
|
<string name="logging_settings_summary">Nastavitve za upravljanje, kako so podatki shranjeni na telefonu in naloženi v Podatkovno bazo OpenSeizure</string>
|
||||||
|
<string name="eventDurationSummary">Trajanje (v sekundah) pred in po napadu, za katerega se beležijo podatki.</string>
|
||||||
|
<string name="eventDurationTitle">Trajanje Dogodka (v sekundah)</string>
|
||||||
|
<string name="dataRetentionPeriodTitle">Obdobje Hranjenja Podatkov (v dneh)</string>
|
||||||
|
<string name="dataRetentionPeriodSummary">Št. dni za katere se hrani podatke in so zaščiteni pred možnostjo \'Oklesti Bazo podatkov\' Option.</string>
|
||||||
|
<string name="AutoPruneDbTitle">Samodejno Oklesti Bazo podatkov</string>
|
||||||
|
<string name="AutoPruneDbSummary">Samodejno periodično Oklesti Bazo podatkov, da se prepreči pretiranjo zasedanje pomnilniškega prostora (spomina).</string>
|
||||||
|
<string name="remoteLogPeriodSummary">Perioda (v sekundah) med poizkusi nalaganja podatkov na oddljeni strežnik. Vsak poizkus naloži samo en dogodek, ne vseh rapoložljivih podatkov.</string>
|
||||||
|
<string name="remoteLogPeriodTitle">Perioda Logiranja Podatkov (v sekundah)</string>
|
||||||
|
<string name="ManualAlarmBtnTxt">Sproži Alarm</string>
|
||||||
|
<string name="save">Shrani</string>
|
||||||
|
<string name="event_type">Tip dogodka:</string>
|
||||||
|
<string name="event_sub_type">"Pod-tip dogodka: "</string>
|
||||||
|
<string name="selectFromOptionselow">"-- izberi možnost --"</string>
|
||||||
|
<string name="waitingForData">...čakanje na podatke...</string>
|
||||||
|
<string name="refreshBtn">Osveži</string>
|
||||||
|
<string name="back">Nazaj</string>
|
||||||
|
<string name="unvalidatedEventsTitle">Nepotrjeni Dogodki Napadov</string>
|
||||||
|
<string name="register">Registriraj Novega Uporabnika</string>
|
||||||
|
<string name="reset_password">Ponastavi Geslo</string>
|
||||||
|
<string name="login_to_osdapi">Prijava za Deljenje Podatkov</string>
|
||||||
|
<string name="login">Prijava</string>
|
||||||
|
<string name="data_sharing_status">Deljenje Podatkov</string>
|
||||||
|
<string name="not_logging_data">Ni deljenja Podatkov</string>
|
||||||
|
<string name="not_sharing_logged_data">Ni deljenja Logiranih Podatkov</string>
|
||||||
|
<string name="not_logged_in">Neprijavljen</string>
|
||||||
|
<string name="data_sharing_setup_ok">Nastavitev Deljenja Podatkov je OK</string>
|
||||||
|
<string name="please_confirm_seizure_events">Prosim preveri svoje Deljene dogodke Napadov</string>
|
||||||
|
<string name="data_sharing_log_in">Prijava za Deljenje Podatkov</string>
|
||||||
|
<string name="not_updating_mobile">Ni uporabe Mobilnega Interneta</string>
|
||||||
|
<string name="not_updating_no_network">Ni Podatkovne Povezave</string>
|
||||||
|
<string name="error_connecting_to_server">Napaka Povezovanje na Strežnik</string>
|
||||||
|
<string name="battery_usage_optimisation_dialog_title">OPOZORILO: Optimizacija Rabe Baterije</string>
|
||||||
|
<string name="battery_usage_optimisation_dialog_text">OPOZORILO: Android sistemske Nastavitve Optimizacija Baterije so nastavljene na \'Optimiraj\' OpenSeizureDetector. To pomeni, da bo aplikacija najverjetneje prisilno ustavljena, kadar naprava ni priklopljena na polnjenje, in ne bo delovala. \n\nProsim, da v Nastavitvah Telefona poiščete \'Optimizacija Baterije\' in nastavite, da OpenSeizureDetector NI optimiziran</string>
|
||||||
|
<string name="local_data">Lokalni podatki</string>
|
||||||
|
<string name="shared_data">Deljeni podatki</string>
|
||||||
|
<string name="prune_database">Oklesti bazo podatkov</string>
|
||||||
|
<string name="check_seizures_message">Prosim izberi dogodke označene z roza za določanje, ali so to pravi napadi ali lažni alarmi</string>
|
||||||
|
<string name="error_server_not_running">NAPAKA: OpenSeizureDetector Strežnik ne dela - prosim ponovno ga zaženi</string>
|
||||||
|
</resources>
|
||||||
@@ -119,7 +119,6 @@
|
|||||||
<string name="sms_location_alarm_active">SMS positionslarm PÅ</string>
|
<string name="sms_location_alarm_active">SMS positionslarm PÅ</string>
|
||||||
<string name="sms_location_alarm_disabled">SMS positionslarm AV</string>
|
<string name="sms_location_alarm_disabled">SMS positionslarm AV</string>
|
||||||
<string name="cancel_audible_not_sending_sms">Stäng av ljudlarm - skicka inte SMS</string>
|
<string name="cancel_audible_not_sending_sms">Stäng av ljudlarm - skicka inte SMS</string>
|
||||||
<string name="sms_alarm_disabled">SMS-larm avstängt- ingen åtgärd</string>
|
|
||||||
<string name="no_wifi_connection">Nätverksstatus ändrad - ingen uppkoppling</string>
|
<string name="no_wifi_connection">Nätverksstatus ändrad - ingen uppkoppling</string>
|
||||||
<string name="no_active_network">Nätverksstatus ändrad - inga aktiva nätverk</string>
|
<string name="no_active_network">Nätverksstatus ändrad - inga aktiva nätverk</string>
|
||||||
<string name="problem_parsing_preferences">Något gick fel! Problem med inställningarna - justera dessa.</string>
|
<string name="problem_parsing_preferences">Något gick fel! Problem med inställningarna - justera dessa.</string>
|
||||||
|
|||||||
@@ -3,6 +3,4 @@
|
|||||||
<dimen name="activity_horizontal_margin">16dp</dimen>
|
<dimen name="activity_horizontal_margin">16dp</dimen>
|
||||||
<dimen name="activity_vertical_margin">16dp</dimen>
|
<dimen name="activity_vertical_margin">16dp</dimen>
|
||||||
<!-- Default screen margins, per the Android Design guidelines. -->
|
<!-- Default screen margins, per the Android Design guidelines. -->
|
||||||
<dimen name="fragment_horizontal_margin">16dp</dimen>
|
|
||||||
<dimen name="fragment_vertical_margin">16dp</dimen>
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -2,35 +2,41 @@
|
|||||||
<resources>
|
<resources>
|
||||||
<string name="app_name">OpenSeizureDetector</string>
|
<string name="app_name">OpenSeizureDetector</string>
|
||||||
<string name="changelog">
|
<string name="changelog">
|
||||||
"V3.6.2 - Fix of issue with log file permissions on some Android 10 devices and added more translatable strings with polish translation.
|
"\n
|
||||||
\nV3.6.1 - Possible fix for issue with shutting down system and expanded Polish translation to all settings screens.
|
\nV4.0.5 - fixed issue with O2 saturation data not being recorded to data sharing database.
|
||||||
\nV3.6 - Added phone sensor data source for testing without a watches
|
\nV4.0.4
|
||||||
\nV3.5 - Added support for SMS Annunciator App
|
- Introduced the <b>Data Sharing</b> feature to allow users to share their seizure and false alarm data
|
||||||
\nV3.4 - Added support for BLE Data Source "</string>
|
with researchers to help improve the system.<br/>
|
||||||
|
- Fixed <b>SMS Location Alerts</b> on Android V10+ (new permissions screens)<br/>
|
||||||
|
- Added explicit link to the <b>Privacy Policy</b> <br/>
|
||||||
|
"</string>
|
||||||
<string name="UpgradeMsg">
|
<string name="UpgradeMsg">
|
||||||
OpenSeizureDetector does not collect any personal data.
|
Please enable the new <b>Data Sharing</b> feature to help improve OpenSeizureDetector!<br/>
|
||||||
This does mean that it is not possible for me to contact users if I find an
|
(see below for details)<br/><br/>
|
||||||
issue with the app that you should be aware of. \nPlease subscribe to updates at
|
|
||||||
http://openseizuredetector.org.uk, or the app Facebook page at https://www.facebook.com/openseizuredetector.
|
Please subscribe to updates at <b>www.openseizuredetector.org.uk</b>
|
||||||
so I can get in touch if necessary.\nThank you! Graham \ngraham@openseizuredetector.org.uk
|
so we can inform you of any issues.
|
||||||
\n\nChanges in this version:
|
<br/><br/>
|
||||||
\n
|
<b>Changes in this version:</b><br/>
|
||||||
</string>
|
</string>
|
||||||
<string name="FirstRunDlgMsg">
|
<string name="FirstRunDlgMsg">
|
||||||
OpenSeizureDetector does not collect any personal data.
|
For details of how OpenSeizure Detector collects and uses
|
||||||
This does mean that it is not possible for me to contact users if I find an
|
your personal data, please refer to the <b>Privacy Policy below</b>.<br/><br/>
|
||||||
issue with the app that you should be aware of. \nPlease subscribe to updates at
|
|
||||||
http://openseizuredetector.org.uk, or the app Facebook page at https://www.facebook.com/openseizuredetector.
|
Please enable <b>Data Sharing</b> to help improve OpenSeizureDetector!<br/>
|
||||||
so I can get in touch if necessary.\nThank you! Graham \ngraham@openseizuredetector.org.uk
|
(see below for details)<br/><br/>
|
||||||
\n\nChanges in this version:
|
|
||||||
|
Please subscribe to updates at <b>www.openseizuredetector.org.uk</b>
|
||||||
|
so we can inform you of any issues.
|
||||||
</string>
|
</string>
|
||||||
<string name="ask_for_error_log">Sorry, OpenSeizureDetector Has Crashed. Please Email this log file to us so we can work out what happened and fix it.\nThanks, Graham.</string>
|
<string name="ask_for_error_log">Sorry, OpenSeizureDetector Has Crashed. Please Email this log file to us so we can work out what happened and fix it.\nThanks, Graham.</string>
|
||||||
<string name="email_welcome_note">Dear OpenSeizureDetector,\n\nApplication is just crashed, please check following error log for more details.\n\n\n</string>
|
<string name="email_welcome_note">Dear OpenSeizureDetector,\n\nApplication is just crashed, please check following error log for more details.\n\n\n</string>
|
||||||
<string name="copyright_info">OpenSeizureDetector (Using UCE Handler\nCopyright © 2018 Rohit Sahebrao Surwase.)</string>
|
<string name="copyright_info">OpenSeizureDetector (Using UCE Handler\nCopyright © 2018 Rohit Sahebrao Surwase.)</string>
|
||||||
<string name="okBtnTxt">OK</string>
|
<string name="okBtnTxt">OK</string>
|
||||||
|
<string name="closeBtnTxt">Close</string>
|
||||||
<string name="UpdateDialogTitleTxt">Thank you for Updating OpenSeizureDetector</string>
|
<string name="UpdateDialogTitleTxt">Thank you for Updating OpenSeizureDetector</string>
|
||||||
<string name="FirstRunDlgTitle">Welcome to OpenSeizureDetector</string>
|
<string name="FirstRunDlgTitle">Welcome to OpenSeizureDetector</string>
|
||||||
<string name="SmsPermissionWarning">Problem with SMS Permissions</string>
|
<string name="SmsPermissionWarning">Problem with SMS Permissions\n(please check phone settings -> Apps -> OpenSeizureDetector -> Permissions</string>
|
||||||
<string name="AppPermissionsOk">App Permissions OK</string>
|
<string name="AppPermissionsOk">App Permissions OK</string>
|
||||||
<string name="AppPermissionsWarning">Problem with App Permissions</string>
|
<string name="AppPermissionsWarning">Problem with App Permissions</string>
|
||||||
<string name="BoundToServiceOk">Bound to Service OK</string>
|
<string name="BoundToServiceOk">Bound to Service OK</string>
|
||||||
@@ -64,13 +70,13 @@
|
|||||||
<string name="SMSWillBeSentIn">SMS Will Be Sent in </string>
|
<string name="SMSWillBeSentIn">SMS Will Be Sent in </string>
|
||||||
<string name="Cancel">CANCEL?</string>
|
<string name="Cancel">CANCEL?</string>
|
||||||
<string name="AcceptAlarm">Accept Alarm</string>
|
<string name="AcceptAlarm">Accept Alarm</string>
|
||||||
<string name="AudibleAlarmsCancelledFor">Audible Alarms Cancelled for </string>
|
<string name="AudibleAlarmsCancelledFor">Muted for </string>
|
||||||
<string name="PressToReEnable"> Press to re-enable</string>
|
<string name="PressToReEnable"> Restore</string>
|
||||||
<string name="CancelAudibleAlarms">Cancel Audible Alarms (temporarily)</string>
|
<string name="CancelAudibleAlarms">Mute Alarms</string>
|
||||||
<string name="AudibleAlarmsOff">Audible Alarms OFF</string>
|
<string name="AudibleAlarmsOff">Audible Alarms OFF</string>
|
||||||
<string name="Fault">FAULT</string>
|
<string name="Fault">FAULT</string>
|
||||||
<string name="authenticate">Authenticate</string>
|
<string name="authenticate">Log In</string>
|
||||||
<string name="not_authenticated">Not Authenticated</string>
|
<string name="not_authenticated">Not Logged In</string>
|
||||||
<string name="cancel">Cancel</string>
|
<string name="cancel">Cancel</string>
|
||||||
<!-- Strings related to login -->
|
<!-- Strings related to login -->
|
||||||
<string name="prompt_email">Email</string>
|
<string name="prompt_email">Email</string>
|
||||||
@@ -121,13 +127,27 @@
|
|||||||
<string name="export_data">Export Data</string>
|
<string name="export_data">Export Data</string>
|
||||||
<string name="settings">Settings</string>
|
<string name="settings">Settings</string>
|
||||||
<string name="about">About...</string>
|
<string name="about">About...</string>
|
||||||
<string name="about_text">OpenSeizureDetector epileptic\n (tonic-clonic) seizure detector and \n alarm system. Uses a Pebble Smart\n watch to detect the shaking \n associated with a seizure, \n then raises audible and text\n message (SMS) alerts for carers.\n The system is free and open source - see \n http://openseizuredetector.org.uk for details. Please report any issues to graham@openseizuredetector.org.uk\n or raise an issue on the project github source code \n repository - https://github.com/OpenSeizureDetector</string>
|
<string name="about_text">OpenSeizureDetector epileptic\n
|
||||||
<string name="credits_text">Main Watch App and Android App \n copyright Graham Jones, 2015.\n The following libraries are used:\n - SYLT-FFT - https://github.com/stg/SYLT-FFT by D. Taylor.\n - NanoHTTPD - https://github.com/NanoHttpd/nanohttpd\n - jQuery - http://jquery.org\n - jBeep - http://www.ultraduz.com.br\n - Chartjs - http://www.chartjs.org\n - MPAndroidChart - https://github.com/PhilJay/MPAndroidChart\n - UCE-Handler - https://github.com/RohitSurwase/UCE-Handler\n \n The Logo is based on Star of life2 by Verdy P, \n Licensed under Public Domain via\n Wikimedia Commons (http://commons.wikimedia.org/wiki/File:Star_of_life2.svg#mediaviewer/File:Star_of_life2.svg).</string>
|
(tonic-clonic) seizure detector and alarm
|
||||||
|
system. Uses a Smart
|
||||||
|
watch to detect the shaking
|
||||||
|
associated with a seizure,
|
||||||
|
then raises audible and text
|
||||||
|
message (SMS) location alerts for carers.\n\n
|
||||||
|
The system is free and open source - see
|
||||||
|
openseizuredetector.org.uk for details.\n\n
|
||||||
|
Please report any issues by raising an issue on the source code repository - https://github.com/OpenSeizureDetector/Android_Pebble_SD/issues
|
||||||
|
or email graham@openseizuredetector.org.uk\n\n
|
||||||
|
Android App and Garmin Watch App,
|
||||||
|
copyright Graham Jones, 2015-2022.\n
|
||||||
|
|
||||||
|
</string>
|
||||||
|
<string name="credits_text"></string>
|
||||||
<string name="edit_settings">Edit Settings</string>
|
<string name="edit_settings">Edit Settings</string>
|
||||||
<string name="sms_location_alarm_active">SMS Location Alarm Active</string>
|
<string name="sms_location_alarm_active">SMS Location Alarm Active</string>
|
||||||
<string name="sms_location_alarm_disabled">SMS Location Alarm Disabled</string>
|
<string name="sms_location_alarm_disabled">SMS Location Alarm Disabled</string>
|
||||||
<string name="cancel_audible_not_sending_sms">Cancel Audible Active - not sending SMS</string>
|
<string name="cancel_audible_not_sending_sms">Cancel Audible Active - not sending SMS</string>
|
||||||
<string name="sms_alarm_disabled">SMS Alarms Disabled - not doing anything!</string>
|
<!--<string name="sms_alarm_disabled">SMS Alarms Disabled - not doing anything!</string>-->
|
||||||
<string name="no_wifi_connection">Network State Changed - no Wifi Connection</string>
|
<string name="no_wifi_connection">Network State Changed - no Wifi Connection</string>
|
||||||
<string name="no_active_network">Network State Changed - No Active Network</string>
|
<string name="no_active_network">Network State Changed - No Active Network</string>
|
||||||
<string name="problem_parsing_preferences">Problem Parsing Preferences - Something won\'t work - Please go back to Settings and correct it!</string>
|
<string name="problem_parsing_preferences">Problem Parsing Preferences - Something won\'t work - Please go back to Settings and correct it!</string>
|
||||||
@@ -159,18 +179,18 @@
|
|||||||
<string name="pebble_datasource_title">Pebble Datasource</string>
|
<string name="pebble_datasource_title">Pebble Datasource</string>
|
||||||
<string name="select_datasource_title">Select Data Source</string>
|
<string name="select_datasource_title">Select Data Source</string>
|
||||||
<string name="select_datasource_summary">Select the seizure detector data source to use.</string>
|
<string name="select_datasource_summary">Select the seizure detector data source to use.</string>
|
||||||
<string name="log_alarms_summary">Log Alarm events to SD Card</string>
|
<string name="log_alarms_summary">Log Alarm events to Phone Storage</string>
|
||||||
<string name="log_alarms_title">Log Alarm events to SD Card</string>
|
<string name="log_alarms_title">Log Alarm Events</string>
|
||||||
<string name="log_data_summary">Log Data to SD Card Regularly</string>
|
<string name="log_data_summary">Log Data to Phone Storage</string>
|
||||||
<string name="log_data_title">Log Data to SD Card</string>
|
<string name="log_data_title">Log Data</string>
|
||||||
<string name="log_data_remote_summary">Log Data to Central OpenSeizureDetector Database</string>
|
<string name="log_data_remote_summary">Share Data with OpenSeizureDetector</string>
|
||||||
<string name="log_data_remote_title">Log Data Remotely</string>
|
<string name="log_data_remote_title">Share Data</string>
|
||||||
<string name="log_data_remote_mobile_summary">Use mobile internet to log remote data</string>
|
<string name="log_data_remote_mobile_summary">Use mobile internet to share data</string>
|
||||||
<string name="log_data_remote_mobile_title">Use Mobile Internet</string>
|
<string name="log_data_remote_mobile_title">Use Mobile Internet</string>
|
||||||
<string name="remote_uname_title">Username for remote data logging.</string>
|
<string name="remote_uname_title">Username</string>
|
||||||
<string name="remote_uname_summary">Remote Username</string>
|
<string name="remote_uname_summary">Username for data sharing</string>
|
||||||
<string name="remote_passwd_summary">Password for remote data logging.</string>
|
<string name="remote_passwd_summary">Password for data sharing</string>
|
||||||
<string name="remote_passwd_title">Remote Password</string>
|
<string name="remote_passwd_title">Password</string>
|
||||||
<string name="wearer_id_summary">Wearer ID</string>
|
<string name="wearer_id_summary">Wearer ID</string>
|
||||||
<string name="wearer_id_title">Wearer ID of the person wearing the watch (from OSD Web API)</string>
|
<string name="wearer_id_title">Wearer ID of the person wearing the watch (from OSD Web API)</string>
|
||||||
<string name="remote_url_summary">URL for remote data logging.</string>
|
<string name="remote_url_summary">URL for remote data logging.</string>
|
||||||
@@ -191,7 +211,7 @@
|
|||||||
<string name="enable_audible_alarm_title">Enable Audible Alarm</string>
|
<string name="enable_audible_alarm_title">Enable Audible Alarm</string>
|
||||||
<string name="enable_audible_warning_summary">Issue an audible alarm if the seizure detector enters a warning (pre-alarm) condition.</string>
|
<string name="enable_audible_warning_summary">Issue an audible alarm if the seizure detector enters a warning (pre-alarm) condition.</string>
|
||||||
<string name="enable_audible_warning_title">Enable Audible Warnings</string>
|
<string name="enable_audible_warning_title">Enable Audible Warnings</string>
|
||||||
<string name="enable_audible_fault_summary">Issue an audible alarm if the system detects a fault (e.g. can not talk to Pebble).</string>
|
<string name="enable_audible_fault_summary">Issue an audible alarm if the system detects a fault (e.g. can not talk to watch).</string>
|
||||||
<string name="enable_audible_fault_title">Enable Audible System FaultWarnings</string>
|
<string name="enable_audible_fault_title">Enable Audible System FaultWarnings</string>
|
||||||
<string name="fault_timer_period_title">Fault Timer Duration (sec)</string>
|
<string name="fault_timer_period_title">Fault Timer Duration (sec)</string>
|
||||||
<string name="fault_timer_period_summary">Duration that fault alarms are muted before initiating.</string>
|
<string name="fault_timer_period_summary">Duration that fault alarms are muted before initiating.</string>
|
||||||
@@ -282,4 +302,139 @@
|
|||||||
<string name="WarnTimeTitle">WarnTime (sec)</string>
|
<string name="WarnTimeTitle">WarnTime (sec)</string>
|
||||||
<string name="AlarmTimeSummary">Time to wait before initiating alarm (Default = 10 sec)</string>
|
<string name="AlarmTimeSummary">Time to wait before initiating alarm (Default = 10 sec)</string>
|
||||||
<string name="AlarmTimeTitle">AlarmTime (sec)</string>
|
<string name="AlarmTimeTitle">AlarmTime (sec)</string>
|
||||||
|
<string name="O2SatSettingsTitle">Blood Oxygen Saturation Alarm Settigs</string>
|
||||||
|
<string name="O2Sat_enabled_summary">O2Sat_enabled_summary</string>
|
||||||
|
<string name="O2Sat_enabled_title">Enable O2 Saturation Alarm</string>
|
||||||
|
<string name="O2SatNullAlarmSummary">Treat an error condition (null value of oxygen saturation reading) as an alarm condition</string>
|
||||||
|
<string name="O2SatNullAlarmTitle">Treat Null Value as Alarm</string>
|
||||||
|
<string name="O2SatThreshMinTitle">Oxygen Saturation Low Alarm Level (%)</string>
|
||||||
|
<string name="O2SatThreshMinSummary">O2 Saturation Low Alarm Level (%)</string>
|
||||||
|
<string name="title_activity_authenticate">Log in to OpenSeizureDetector Data Sharing</string>
|
||||||
|
<string name="logout">Log Out</string>
|
||||||
|
<string name="logged_in_with_token">Logged in to\nData Sharing</string>
|
||||||
|
<string name="local_database">Logged Data Manager</string>
|
||||||
|
<string name="remote_database">Shared Data</string>
|
||||||
|
<string name="num_local_events">Number of Events Stored on Phone: </string>
|
||||||
|
<string name="num_local_datapoints">"Number of Datapoints Stored on Phone: "</string>
|
||||||
|
<string name="view_remote_db_btn">View Remote DB Data</string>
|
||||||
|
<string name="report_seizure">Report Seizure</string>
|
||||||
|
<string name="date">"Date: "</string>
|
||||||
|
<string name="select_date">Select Date</string>
|
||||||
|
<string name="time">"Time: "</string>
|
||||||
|
<string name="cancelBtnTxt">Cancel</string>
|
||||||
|
<string name="select_time">Select Time</string>
|
||||||
|
<string name="EventsInLocalDb">Events Stored on Phone</string>
|
||||||
|
<string name="createdNewEvent">Created new Manual Alarm Event</string>
|
||||||
|
<string name="DatapointNotFound">Datapoint not found - not doing anything</string>
|
||||||
|
<string name="logging_settings_title">Data Logging Settings</string>
|
||||||
|
<string name="logging_settings_summary">Settings that control how data is recorded on the phone and uploaded to the Open Seizure Database</string>
|
||||||
|
<string name="eventDurationSummary">The time (in seconds) before and after a seizure event that we record data.</string>
|
||||||
|
<string name="eventDurationTitle">Event Duration (seconds)</string>
|
||||||
|
<string name="dataRetentionPeriodTitle">Data Retention Period (days)</string>
|
||||||
|
<string name="dataRetentionPeriodSummary">The period (in days) that data will be retained and is protected from deletion by the \'Prune Database\' Option.</string>
|
||||||
|
<string name="AutoPruneDbTitle">Automatically Prune (Trim) Database</string>
|
||||||
|
<string name="AutoPruneDbSummary">Automatically Prune (Trim) the Database periodically to prevent excessive storage capacity (memory) usage.</string>
|
||||||
|
<string name="remoteLogPeriodSummary">The period (in seconds) between attempts to upload data to the remote server. Each attempt only uploads a single event, not all the available data.</string>
|
||||||
|
<string name="remoteLogPeriodTitle">Remote Log Period (seconds)</string>
|
||||||
|
<string name="ManualAlarmBtnTxt">Raise Alarm</string>
|
||||||
|
<string name="save">Save</string>
|
||||||
|
<string name="event_type">Event Type:</string>
|
||||||
|
<string name="event_sub_type">"Event Sub-Type: "</string>
|
||||||
|
<string name="selectFromOptionselow">"-- select option --"</string>
|
||||||
|
<string name="waitingForData">...waiting for data...</string>
|
||||||
|
<string name="refreshBtn">Refresh</string>
|
||||||
|
<string name="back">Back</string>
|
||||||
|
<string name="unvalidatedEventsTitle">Un-Confirmed Seizure Events</string>
|
||||||
|
<string name="register">Register New User</string>
|
||||||
|
<string name="reset_password">Reset Password</string>
|
||||||
|
<string name="login_to_osdapi">Log in to Share Data</string>
|
||||||
|
<string name="login">Log In</string>
|
||||||
|
<string name="data_sharing_status">Data Sharing</string>
|
||||||
|
<string name="not_logging_data">Not Logging Data</string>
|
||||||
|
<string name="not_sharing_logged_data">Not Sharing Logged Data</string>
|
||||||
|
<string name="not_logged_in">Not Logged In</string>
|
||||||
|
<string name="data_sharing_setup_ok">Data Sharing Setup OK</string>
|
||||||
|
<string name="please_confirm_seizure_events">Please Check your Shared Seizure Events</string>
|
||||||
|
<string name="data_sharing_log_in">Data Sharing Log-In</string>
|
||||||
|
<string name="not_updating_mobile">Not Updating using Mobile Internet</string>
|
||||||
|
<string name="not_updating_no_network">No Network Connection</string>
|
||||||
|
<string name="error_connecting_to_server">Error Connecting to Server</string>
|
||||||
|
<string name="battery_usage_optimisation_dialog_title">WARNING: Battery Usage Optimisation</string>
|
||||||
|
<string name="battery_usage_optimisation_dialog_text">
|
||||||
|
<b>WARNING: The Android System Battery Optimisation Settings are configured to \'Optimise\' OpenSeizureDetector.</b>\n\n
|
||||||
|
This means it is likely to be shutdown when operating on battery power, so will not work correctly\n\n
|
||||||
|
Please go into the Phone Settings and select <b>Apps->OpenSeizureDetector->Battery->Optimise battery usage</b> and set it so that OpenSeizureDetector is NOT optimised</string>
|
||||||
|
<string name="local_data">Local Data</string>
|
||||||
|
<string name="shared_data">Shared Data</string>
|
||||||
|
<string name="prune_database">Prune Database</string>
|
||||||
|
<string name="check_seizures_message">Please select the events highlighted in pink to say if they are real seizures or false alarms</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="logged_in_as_user_id">Logged in as: </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>
|
||||||
|
<string name="sms_permissions_rationale_1">
|
||||||
|
OpenSeizureDetector needs permission to <b>read your phone state and send SMS messages</b> to enable it to send SMS alerts when it detects a seizure.\n\n
|
||||||
|
With this permission enabled the App will <b>send an SMS message to the phone numbers you enter on th Alarm settings page of the app when it detects a seizure</b>.\n\n
|
||||||
|
Please grant the permissions in the following screens after pressing \'OK\' below....\n\n
|
||||||
|
You can change this later by going into the phone settings and selecting Apps->OpenSeizureDetector->Permissions
|
||||||
|
</string>
|
||||||
|
<string name="location_permissions_rationale_1">
|
||||||
|
OpenSeizureDetector <b>collects location data</b>
|
||||||
|
to enable the <b>SMS Location Alarms</b> feature
|
||||||
|
to include your location in the alarm message
|
||||||
|
<b>when the app is closed or not in use</b>.\n\n
|
||||||
|
This means that it will be able to send <b>SMS text messages</b> containing
|
||||||
|
<b>your location</b>
|
||||||
|
to the <b>phone numbers you enter</b> on the Alarm settings page of the app
|
||||||
|
when it detects a seizure, by running in the <b>background</b>,
|
||||||
|
even <b>when the app is closed</b>.\n
|
||||||
|
It does not store your location or share it with anyone other than the phone numbers
|
||||||
|
you specify\n\n
|
||||||
|
|
||||||
|
Please grant the permissions in the following screen by selecting
|
||||||
|
<b>While using the app</b>
|
||||||
|
if you wish to use SMS Location Alarms\n\n
|
||||||
|
You can change this later by going into the phone settings and selecting
|
||||||
|
<b>Apps->OpenSeizureDetector->Permissions</b>.
|
||||||
|
</string>
|
||||||
|
<string name="location_permissions_2_rationale">
|
||||||
|
OpenSeizureDetector <b>collects location data</b>
|
||||||
|
to enable the <b>SMS Location Alarms</b> feature
|
||||||
|
to include your location in the alarm message
|
||||||
|
<b>when the app is closed or not in use</b>.\n\n
|
||||||
|
This means that it will be able to send <b>SMS text messages</b> containing
|
||||||
|
<b>your location</b>
|
||||||
|
to the <b>phone numbers you enter</b> on the Alarm settings page of the app
|
||||||
|
when it detects a seizure, by running in the <b>background</b>,
|
||||||
|
even <b>when the app is closed</b>.\n
|
||||||
|
It does not store your location or share it with anyone other than the phone numbers
|
||||||
|
you specify.\n\n
|
||||||
|
Please grant the required permission by selecting <b>Allow all the time</b>
|
||||||
|
on the next screen, if you wish to use SMS Location Alarms\n\n
|
||||||
|
You can change this later by going into the phone settings
|
||||||
|
and selecting <b>Apps->OpenSeizureDetector->Permissions</b>.
|
||||||
|
</string>
|
||||||
|
<string name="permissions_required">Permissions Disclosure</string>
|
||||||
|
<string name="about_data_sharing">About Data Sharing</string>
|
||||||
|
<string name="privacy_policy">Privacy Policy</string>
|
||||||
|
<string name="mark_unverified_events_as_unknown">Mark Unverified Events as Unknown</string>
|
||||||
|
<string name="mark_unverified_events_unknown_dialog_title">Mark All Unverified Events as Unknown?</string>
|
||||||
|
<string name="mark_unverified_events_unknown_dialog_message">Please confirm that all genuine seizure events have been verified before marking all unverified events as type \'unknown\'. \n\nContinue to mark unverified events as Unknown?</string>
|
||||||
|
<string name="not_logged_in_dialog_title">Not Logged in to Data Sharing</string>
|
||||||
|
<string name="not_logged_in_dialog_message">You must be logged in to the Data Sharing system to be able to report seizures.</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -7,11 +7,5 @@
|
|||||||
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
|
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
|
||||||
<item name="colorAccent">@color/colorAccent</item>
|
<item name="colorAccent">@color/colorAccent</item>
|
||||||
</style>
|
</style>
|
||||||
<style name="AppTheme.NoActionBar">
|
|
||||||
<item name="windowActionBar">false</item>
|
|
||||||
<item name="windowNoTitle">true</item>
|
|
||||||
</style>
|
|
||||||
<style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />
|
|
||||||
<style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" />
|
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -70,6 +70,7 @@
|
|||||||
android:title="Enable Phone Call Alarm" />
|
android:title="Enable Phone Call Alarm" />
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
-->
|
-->
|
||||||
|
<!--
|
||||||
<PreferenceCategory android:title="@string/AlarmLoggingTitle">
|
<PreferenceCategory android:title="@string/AlarmLoggingTitle">
|
||||||
<CheckBoxPreference
|
<CheckBoxPreference
|
||||||
android:defaultValue="true"
|
android:defaultValue="true"
|
||||||
@@ -82,4 +83,5 @@
|
|||||||
android:summary="@string/log_data_summary"
|
android:summary="@string/log_data_summary"
|
||||||
android:title="@string/log_data_title"/>
|
android:title="@string/log_data_title"/>
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
|
-->
|
||||||
</PreferenceScreen>
|
</PreferenceScreen>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
<CheckBoxPreference
|
<CheckBoxPreference
|
||||||
android:defaultValue="false"
|
android:defaultValue="true"
|
||||||
android:enabled="true"
|
android:enabled="true"
|
||||||
android:key="advancedMode"
|
android:key="advancedMode"
|
||||||
android:summary="@string/AdvancedModeSummary"
|
android:summary="@string/AdvancedModeSummary"
|
||||||
|
|||||||
@@ -6,14 +6,9 @@
|
|||||||
android:summary="@string/select_datasource_summary"
|
android:summary="@string/select_datasource_summary"
|
||||||
android:entries="@array/datasource_list"
|
android:entries="@array/datasource_list"
|
||||||
android:entryValues="@array/datasource_list_values"
|
android:entryValues="@array/datasource_list_values"
|
||||||
android:defaultValue="Garmin"
|
android:defaultValue="Phone"
|
||||||
android:dialogTitle="@string/select_datasource_title" />
|
android:dialogTitle="@string/select_datasource_title" />
|
||||||
<Preference
|
<!--
|
||||||
android:key="SelectBLEDevice"
|
|
||||||
android:title="@string/select_ble_device_title"
|
|
||||||
android:summary="@string/select_ble_device_desc"
|
|
||||||
android:widgetLayout="@layout/pref_select_ble_device_button"
|
|
||||||
/>
|
|
||||||
<CheckBoxPreference
|
<CheckBoxPreference
|
||||||
android:defaultValue="true"
|
android:defaultValue="true"
|
||||||
android:key="LogAlarms"
|
android:key="LogAlarms"
|
||||||
@@ -55,16 +50,18 @@
|
|||||||
android:key="OSDUrl"
|
android:key="OSDUrl"
|
||||||
android:summary="@string/remote_url_summary"
|
android:summary="@string/remote_url_summary"
|
||||||
android:title="@string/remote_url_title" />
|
android:title="@string/remote_url_title" />
|
||||||
|
-->
|
||||||
|
|
||||||
<CheckBoxPreference
|
<CheckBoxPreference
|
||||||
android:defaultValue="false"
|
android:defaultValue="false"
|
||||||
android:key="PreventSleep"
|
android:key="PreventSleep"
|
||||||
android:summary="@string/prevent_sleep_summary"
|
android:summary="@string/prevent_sleep_summary"
|
||||||
android:title="@string/prevent_sleep_title" />
|
android:title="@string/prevent_sleep_title" />
|
||||||
<EditTextPreference
|
<!--<EditTextPreference
|
||||||
android:defaultValue="1000"
|
android:defaultValue="1000"
|
||||||
android:key="UpdatePeriod"
|
android:key="UpdatePeriod"
|
||||||
android:summary="@string/data_update_period_summary"
|
android:summary="@string/data_update_period_summary"
|
||||||
android:title="@string/data_update_period_title" />
|
android:title="@string/data_update_period_title" />-->
|
||||||
<CheckBoxPreference
|
<CheckBoxPreference
|
||||||
android:defaultValue="false"
|
android:defaultValue="false"
|
||||||
android:key="AutoStart"
|
android:key="AutoStart"
|
||||||
@@ -72,6 +69,12 @@
|
|||||||
android:title="@string/auto_start_title"
|
android:title="@string/auto_start_title"
|
||||||
android:enabled="true"
|
android:enabled="true"
|
||||||
/>
|
/>
|
||||||
|
<Preference
|
||||||
|
android:key="SelectBLEDevice"
|
||||||
|
android:title="@string/select_ble_device_title"
|
||||||
|
android:summary="@string/select_ble_device_desc"
|
||||||
|
android:widgetLayout="@layout/pref_select_ble_device_button"
|
||||||
|
/>
|
||||||
|
|
||||||
<EditTextPreference
|
<EditTextPreference
|
||||||
android:defaultValue=""
|
android:defaultValue=""
|
||||||
|
|||||||
51
app/src/main/res/xml/logging_prefs.xml
Normal file
51
app/src/main/res/xml/logging_prefs.xml
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<!--<CheckBoxPreference
|
||||||
|
android:defaultValue="true"
|
||||||
|
android:key="LogAlarms"
|
||||||
|
android:summary="@string/log_alarms_summary"
|
||||||
|
android:title="@string/log_alarms_title" />
|
||||||
|
<CheckBoxPreference
|
||||||
|
android:defaultValue="true"
|
||||||
|
android:key="LogData"
|
||||||
|
android:summary="@string/log_data_summary"
|
||||||
|
android:title="@string/log_data_title" /> -->
|
||||||
|
<EditTextPreference
|
||||||
|
android:defaultValue="150"
|
||||||
|
android:key="EventDurationSec"
|
||||||
|
android:summary="@string/eventDurationSummary"
|
||||||
|
android:title="@string/eventDurationTitle" />
|
||||||
|
<CheckBoxPreference
|
||||||
|
android:defaultValue="true"
|
||||||
|
android:key="AutoPruneDb"
|
||||||
|
android:summary="@string/AutoPruneDbSummary"
|
||||||
|
android:title="@string/AutoPruneDbTitle" />
|
||||||
|
<EditTextPreference
|
||||||
|
android:defaultValue="28"
|
||||||
|
android:key="DataRetentionPeriod"
|
||||||
|
android:summary="@string/dataRetentionPeriodSummary"
|
||||||
|
android:title="@string/dataRetentionPeriodTitle" />
|
||||||
|
<!--<CheckBoxPreference
|
||||||
|
android:defaultValue="true"
|
||||||
|
android:key="LogDataRemote"
|
||||||
|
android:summary="@string/log_data_remote_summary"
|
||||||
|
android:title="@string/log_data_remote_title" /> -->
|
||||||
|
<CheckBoxPreference
|
||||||
|
android:defaultValue="false"
|
||||||
|
android:key="LogDataRemoteMobile"
|
||||||
|
android:summary="@string/log_data_remote_mobile_summary"
|
||||||
|
android:title="@string/log_data_remote_mobile_title" />
|
||||||
|
<!--<EditTextPreference
|
||||||
|
android:defaultValue="60"
|
||||||
|
android:key="RemoteLogPeriod"
|
||||||
|
android:summary="@string/remoteLogPeriodSummary"
|
||||||
|
android:title="@string/remoteLogPeriodTitle" />-->
|
||||||
|
|
||||||
|
<!--<EditTextPreference
|
||||||
|
android:defaultValue="https://osdapi.ddns.net/"
|
||||||
|
android:key="OSDUrl"
|
||||||
|
android:summary="@string/remote_url_summary"
|
||||||
|
android:title="@string/remote_url_title" /> -->
|
||||||
|
|
||||||
|
|
||||||
|
</PreferenceScreen>
|
||||||
@@ -1,59 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<EditTextPreference
|
|
||||||
android:defaultValue="https://osd.dynu.net/"
|
|
||||||
android:key="serverUrl"
|
|
||||||
android:title="@string/remote_url_title"
|
|
||||||
android:summary="@string/remote_url_summary"
|
|
||||||
/>
|
|
||||||
<CheckBoxPreference
|
|
||||||
android:defaultValue="true"
|
|
||||||
android:key="LogToServer"
|
|
||||||
android:summary="@string/log_data_remote_summary"
|
|
||||||
android:title="@string/log_data_remote_title" />
|
|
||||||
<CheckBoxPreference
|
|
||||||
android:defaultValue="false"
|
|
||||||
android:key="UploadOverMobileNetwork"
|
|
||||||
android:summary="@string/UseMobileSummary"
|
|
||||||
android:title="@string/UseMobileTitle" />
|
|
||||||
<EditTextPreference
|
|
||||||
android:defaultValue="password"
|
|
||||||
android:key="OSDPasswd"
|
|
||||||
android:summary="@string/remote_passwd_summary"
|
|
||||||
android:title="@string/remote_passwd_title" />
|
|
||||||
|
|
||||||
<CheckBoxPreference
|
|
||||||
android:defaultValue="false"
|
|
||||||
android:key="PreventSleep"
|
|
||||||
android:summary="@string/prevent_sleep_summary"
|
|
||||||
android:title="@string/prevent_sleep_title" />
|
|
||||||
<EditTextPreference
|
|
||||||
android:defaultValue="1000"
|
|
||||||
android:key="UpdatePeriod"
|
|
||||||
android:summary="@string/data_update_period_summary"
|
|
||||||
android:title="@string/data_update_period_title" />
|
|
||||||
<CheckBoxPreference
|
|
||||||
android:defaultValue="false"
|
|
||||||
android:key="AutoStart"
|
|
||||||
android:summary="@string/auto_start_summary"
|
|
||||||
android:title="@string/auto_start_title"
|
|
||||||
android:enabled="true"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<EditTextPreference
|
|
||||||
android:defaultValue=""
|
|
||||||
android:key="AppVersionName"
|
|
||||||
android:summary="@string/app_version_summary"
|
|
||||||
android:title="@string/app_version_title" />
|
|
||||||
<!--
|
|
||||||
<CheckBoxPreference
|
|
||||||
android:defaultValue="false"
|
|
||||||
android:key="UseIpCamera"
|
|
||||||
android:summary="Use IP Camera to View Images"
|
|
||||||
android:title="Enable IP Camera"
|
|
||||||
android:enabled="false"
|
|
||||||
/>
|
|
||||||
-->
|
|
||||||
|
|
||||||
|
|
||||||
</PreferenceScreen>
|
|
||||||
@@ -2,10 +2,10 @@
|
|||||||
<preference-headers
|
<preference-headers
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
|
||||||
<header android:fragment="uk.org.openseizuredetector.PrefActivity$BasicPrefsFragment"
|
<!--<header android:fragment="uk.org.openseizuredetector.PrefActivity$BasicPrefsFragment"
|
||||||
android:icon="@drawable/icon_24x24"
|
android:icon="@drawable/icon_24x24"
|
||||||
android:title="@string/basic_settings_title"
|
android:title="@string/basic_settings_title"
|
||||||
android:summary="@string/basic_settings_summary" />
|
android:summary="@string/basic_settings_summary" />-->
|
||||||
|
|
||||||
<header android:fragment="uk.org.openseizuredetector.PrefActivity$GeneralPrefsFragment"
|
<header android:fragment="uk.org.openseizuredetector.PrefActivity$GeneralPrefsFragment"
|
||||||
android:icon="@drawable/icon_24x24"
|
android:icon="@drawable/icon_24x24"
|
||||||
@@ -17,6 +17,11 @@
|
|||||||
android:title="@string/alarms_settings_title"
|
android:title="@string/alarms_settings_title"
|
||||||
android:summary="@string/alarms_settings_summary" />
|
android:summary="@string/alarms_settings_summary" />
|
||||||
|
|
||||||
|
<header android:fragment="uk.org.openseizuredetector.PrefActivity$LoggingPrefsFragment"
|
||||||
|
android:icon="@drawable/icon_24x24"
|
||||||
|
android:title="@string/logging_settings_title"
|
||||||
|
android:summary="@string/logging_settings_summary" />
|
||||||
|
|
||||||
<header android:fragment="uk.org.openseizuredetector.PrefActivity$SeizureDetectorPrefsFragment"
|
<header android:fragment="uk.org.openseizuredetector.PrefActivity$SeizureDetectorPrefsFragment"
|
||||||
android:icon="@drawable/icon_24x24"
|
android:icon="@drawable/icon_24x24"
|
||||||
android:title="@string/seizure_detector_settings_title"
|
android:title="@string/seizure_detector_settings_title"
|
||||||
|
|||||||
@@ -1,129 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<CheckBoxPreference
|
|
||||||
android:key="LatchAlarms"
|
|
||||||
android:title="@string/latch_alarms_title"
|
|
||||||
android:summary="@string/latch_alarms_summary"
|
|
||||||
android:defaultValue="false" />
|
|
||||||
|
|
||||||
<CheckBoxPreference
|
|
||||||
android:key="AudibleAlarm"
|
|
||||||
android:title="@string/enable_audible_alarm_title"
|
|
||||||
android:summary="@string/enable_audible_alarm_summary"
|
|
||||||
android:defaultValue="true" />
|
|
||||||
<CheckBoxPreference
|
|
||||||
android:key="AudibleWarning"
|
|
||||||
android:title="@string/enable_audible_warning_title"
|
|
||||||
android:summary="@string/enable_audible_warning_summary"
|
|
||||||
android:defaultValue="true" />
|
|
||||||
<CheckBoxPreference
|
|
||||||
android:key="SMSAlarm"
|
|
||||||
android:title="@string/enable_sms_alarm_title"
|
|
||||||
android:summary="@string/enable_sms_alarm_summary"
|
|
||||||
android:defaultValue="false" />
|
|
||||||
<EditTextPreference
|
|
||||||
android:key="SMSNumbers"
|
|
||||||
android:title="@string/sms_numbers_title"
|
|
||||||
android:summary="@string/sms_numbers_summary"
|
|
||||||
android:defaultValue="" />
|
|
||||||
<EditTextPreference
|
|
||||||
android:key="SMSMsg"
|
|
||||||
android:title="@string/sms_message_title"
|
|
||||||
android:summary="@string/sms_message_summary"
|
|
||||||
android:defaultValue="**SEIZURE DETECTED**" />
|
|
||||||
|
|
||||||
<CheckBoxPreference
|
|
||||||
android:key="AudibleFaultWarning"
|
|
||||||
android:title="@string/enable_audible_fault_title"
|
|
||||||
android:summary="@string/enable_audible_fault_summary"
|
|
||||||
android:defaultValue="true" />
|
|
||||||
|
|
||||||
<CheckBoxPreference
|
|
||||||
android:key="LogAlarms"
|
|
||||||
android:title="@string/log_alarms_title"
|
|
||||||
android:summary="@string/log_alarms_summary"
|
|
||||||
android:defaultValue="true" />
|
|
||||||
<CheckBoxPreference
|
|
||||||
android:key="LogData"
|
|
||||||
android:title="@string/log_data_title"
|
|
||||||
android:summary="@string/log_data_summary"
|
|
||||||
android:defaultValue="false" />
|
|
||||||
<!-- <CheckBoxPreference
|
|
||||||
android:key="PreventSleep"
|
|
||||||
android:title="Prevent the screen from blanking."
|
|
||||||
android:summary="Prevent the screen from blanking while the application is running."
|
|
||||||
android:defaultValue="false" />
|
|
||||||
<EditTextPreference
|
|
||||||
android:key="UpdatePeriod"
|
|
||||||
android:title="Display Update Period (ms)."
|
|
||||||
android:summary="Display update period in miliseconds."
|
|
||||||
android:defaultValue="1000" />
|
|
||||||
-->
|
|
||||||
<EditTextPreference
|
|
||||||
android:key="AlarmFreqMin"
|
|
||||||
android:title="@string/alarm_freq_min_title"
|
|
||||||
android:summary="@string/alarm_freq_min_summary"
|
|
||||||
android:defaultValue="5" />
|
|
||||||
<EditTextPreference
|
|
||||||
android:key="AlarmFreqMax"
|
|
||||||
android:title="@string/alarm_freq_max_title"
|
|
||||||
android:summary="@string/alarm_freq_max_summary"
|
|
||||||
android:defaultValue="10" />
|
|
||||||
<EditTextPreference
|
|
||||||
android:key="WarnTime"
|
|
||||||
android:title="@string/warn_time_title"
|
|
||||||
android:summary="@string/warn_time_summary"
|
|
||||||
android:defaultValue="5" />
|
|
||||||
<EditTextPreference
|
|
||||||
android:key="AlarmTime"
|
|
||||||
android:title="@string/alarm_time_title"
|
|
||||||
android:summary="@string/alarm_time_summary"
|
|
||||||
android:defaultValue="10" />
|
|
||||||
<EditTextPreference
|
|
||||||
android:key="AlarmThresh"
|
|
||||||
android:title="@string/alarm_threshold_title"
|
|
||||||
android:summary="@string/alarm_threshold_summary"
|
|
||||||
android:defaultValue="100" />
|
|
||||||
<EditTextPreference
|
|
||||||
android:key="AlarmRatioThresh"
|
|
||||||
android:title="@string/alarm_ratio_thresh_title"
|
|
||||||
android:summary="@string/alarm_ratio_thresh_summary"
|
|
||||||
android:defaultValue="30" />
|
|
||||||
|
|
||||||
<CheckBoxPreference
|
|
||||||
android:key="FallActive"
|
|
||||||
android:title="@string/fall_detect_active_title"
|
|
||||||
android:summary=""
|
|
||||||
android:defaultValue="false" />
|
|
||||||
<EditTextPreference
|
|
||||||
android:key="FallThreshMin"
|
|
||||||
android:title="@string/fall_thresh_min_title"
|
|
||||||
android:summary=""
|
|
||||||
android:defaultValue="200" />
|
|
||||||
<EditTextPreference
|
|
||||||
android:key="FallThreshMax"
|
|
||||||
android:title="@string/fall_thresh_max_title"
|
|
||||||
android:summary=""
|
|
||||||
android:defaultValue="1200" />
|
|
||||||
<EditTextPreference
|
|
||||||
android:key="FallWindow"
|
|
||||||
android:title="@string/fall_window_title"
|
|
||||||
android:summary=""
|
|
||||||
android:defaultValue="1500" />
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<EditTextPreference
|
|
||||||
android:key="AppRestartTimeout"
|
|
||||||
android:title="@string/app_restart_timeout_title"
|
|
||||||
android:summary="@string/app_restart_timeout_summary"
|
|
||||||
android:numeric="integer"
|
|
||||||
android:defaultValue="10" />
|
|
||||||
<EditTextPreference
|
|
||||||
android:key="FaultTimerPeriod"
|
|
||||||
android:title="@string/fault_timer_period_title"
|
|
||||||
android:summary="@string/fault_timer_period_summary"
|
|
||||||
android:numeric="integer"
|
|
||||||
android:defaultValue="30" />
|
|
||||||
|
|
||||||
</PreferenceScreen>
|
|
||||||
@@ -19,7 +19,7 @@
|
|||||||
android:summary="@string/AlarmThreshSummary"
|
android:summary="@string/AlarmThreshSummary"
|
||||||
android:title="@string/AlarmThreshTitle" />
|
android:title="@string/AlarmThreshTitle" />
|
||||||
<EditTextPreference
|
<EditTextPreference
|
||||||
android:defaultValue="50"
|
android:defaultValue="57"
|
||||||
android:key="AlarmRatioThresh"
|
android:key="AlarmRatioThresh"
|
||||||
android:summary="@string/AlarmRatioThreshSummary"
|
android:summary="@string/AlarmRatioThreshSummary"
|
||||||
android:title="@string/AlarmRatioThreshTitle" />
|
android:title="@string/AlarmRatioThreshTitle" />
|
||||||
@@ -30,7 +30,7 @@
|
|||||||
android:summary="@string/AlarmFreqMinSummary"
|
android:summary="@string/AlarmFreqMinSummary"
|
||||||
android:title="@string/AlarmFreqMinTitle" />
|
android:title="@string/AlarmFreqMinTitle" />
|
||||||
<EditTextPreference
|
<EditTextPreference
|
||||||
android:defaultValue="10"
|
android:defaultValue="8"
|
||||||
android:key="AlarmFreqMax"
|
android:key="AlarmFreqMax"
|
||||||
android:summary="@string/AlarmFreqMaxSummary"
|
android:summary="@string/AlarmFreqMaxSummary"
|
||||||
android:title="@string/AlarmFreqMaxTitle" />
|
android:title="@string/AlarmFreqMaxTitle" />
|
||||||
@@ -65,6 +65,24 @@
|
|||||||
android:title="@string/HRThreshMaxTitle" />
|
android:title="@string/HRThreshMaxTitle" />
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
|
|
||||||
|
<PreferenceCategory android:title="@string/O2SatSettingsTitle">
|
||||||
|
<CheckBoxPreference
|
||||||
|
android:defaultValue="false"
|
||||||
|
android:key="O2SatAlarmActive"
|
||||||
|
android:summary="@string/O2Sat_enabled_summary"
|
||||||
|
android:title="@string/O2Sat_enabled_title" />
|
||||||
|
<CheckBoxPreference
|
||||||
|
android:defaultValue="false"
|
||||||
|
android:key="O2SatNullAsAlarm"
|
||||||
|
android:summary="@string/O2SatNullAlarmSummary"
|
||||||
|
android:title="@string/O2SatNullAlarmTitle" />
|
||||||
|
<EditTextPreference
|
||||||
|
android:defaultValue="80"
|
||||||
|
android:key="O2SatThreshMin"
|
||||||
|
android:summary="@string/O2SatThreshMinSummary"
|
||||||
|
android:title="@string/O2SatThreshMinTitle" />
|
||||||
|
</PreferenceCategory>
|
||||||
|
|
||||||
<PreferenceCategory android:title="@string/fall_detect_title">
|
<PreferenceCategory android:title="@string/fall_detect_title">
|
||||||
<CheckBoxPreference
|
<CheckBoxPreference
|
||||||
android:defaultValue="false"
|
android:defaultValue="false"
|
||||||
|
|||||||
@@ -0,0 +1,95 @@
|
|||||||
|
package uk.org.openseizuredetector;
|
||||||
|
|
||||||
|
import android.os.Build;
|
||||||
|
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.robolectric.RobolectricTestRunner;
|
||||||
|
import org.robolectric.RuntimeEnvironment;
|
||||||
|
import org.robolectric.annotation.Config;
|
||||||
|
|
||||||
|
import java.util.TimeZone;
|
||||||
|
|
||||||
|
@RunWith(RobolectricTestRunner.class)
|
||||||
|
@Config(sdk = {Build.VERSION_CODES.O_MR1}, packageName = "uk.org.openseizuredetector")
|
||||||
|
public class LogManagerTest extends TestCase {
|
||||||
|
|
||||||
|
|
||||||
|
public void tearDown() throws Exception {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
SdData getFakeSdData() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testWriteToLocalDb() {
|
||||||
|
//SdData sd1 = getFakeSdData();
|
||||||
|
//mLm.writeToLocalDb(sd1);
|
||||||
|
assertTrue(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetDatapointById() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testSetDatapointToUploaded() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testSetDatapointStatus() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetDatapointsByDate() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetEventsList() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testPruneLocalDb() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetNextEventToUpload() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetNearestDatapointToDate() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetLocalEventsCount() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetLocalDatapointsCount() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testWriteToRemoteServer() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testUploadSdData() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAuthCallback() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testFinishUpload() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testEventCallback() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testUploadNextDatapoint() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testDatapointCallback() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testClose() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testStopRemoteLogTimer() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testStopAutoPruneTimer() {
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
package uk.org.openseizuredetector;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by graham on 01/01/16.
|
|
||||||
*/
|
|
||||||
public class MainActivityTest {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testOnCreate() throws Exception {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testOnCreateOptionsMenu() throws Exception {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testOnOptionsItemSelected() throws Exception {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testOnStart() throws Exception {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testOnStop() throws Exception {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testOnPause() throws Exception {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testOnResume() throws Exception {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,143 +0,0 @@
|
|||||||
package uk.org.openseizuredetector;
|
|
||||||
|
|
||||||
import org.junit.After;
|
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.junit.runner.RunWith;
|
|
||||||
import org.robolectric.RobolectricTestRunner;
|
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
|
||||||
|
|
||||||
@RunWith(RobolectricTestRunner.class)
|
|
||||||
public class SdAnalyserTest {
|
|
||||||
public SdAnalyser sda;
|
|
||||||
|
|
||||||
public String alarmJSON = "{ 'dataType': 'raw', " +
|
|
||||||
"'data': [" +
|
|
||||||
"1644, 1316, 1144, 1332, 1716, 1716, 1392, 1148, 1276, 1660, " +
|
|
||||||
"1716, 1496, 1196, 1232, 1572, 1684, 1552, 1236, 1228, 1528, " +
|
|
||||||
"1648, 1572, 1268, 1208, 1492, 1680, 1596, 1272, 1192, 1424, " +
|
|
||||||
"1668, 1636, 1300, 1200, 1356, 1652, 1684, 1420, 1208, 1304, " +
|
|
||||||
"1620, 1672, 1448, 1232, 1248, 1536, 1676, 1540, 1256, 1244, " +
|
|
||||||
"1544, 1644, 1512, 1252, 1236, 1504, 1684, 1540, 1252, 1200, " +
|
|
||||||
"1436, 1664, 1624, 1344, 1204, 1396, 1616, 1596, 1344, 1216, " +
|
|
||||||
"1368, 1648, 1660, 1388, 1220, 1316, 1588, 1672, 1460, 1232, " +
|
|
||||||
"1256, 1580, 1672, 1500, 1256, 1288, 1540, 1688, 1516, 1252, " +
|
|
||||||
"1212, 1464, 1684, 1584, 1288, 1224, 1468, 1692, 1616, 1316, " +
|
|
||||||
"1188, 1360, 1680, 1724, 1424, 1192, 1224, 1556, 1744, 1588, " +
|
|
||||||
"1260, 1220, 1472, 1692, 1608, 1328, 1192, 1412, 1668, 1656, " +
|
|
||||||
"1356, 1216, 1304, 1636, 1712], " +
|
|
||||||
"'HR':54, " +
|
|
||||||
"'Mute':0 " +
|
|
||||||
"}";
|
|
||||||
|
|
||||||
private String okJSON = "{ " +
|
|
||||||
"\"dataType\": \"raw\", " +
|
|
||||||
"\"data\": [" +
|
|
||||||
"1140, 1188, 1144, 1172, 1228, 1212, 1236, 1236, 1256, 1320, " +
|
|
||||||
"1316, 1280, 1240, 1280, 1324, 1284, 1292, 1268, 1284, 1276, " +
|
|
||||||
"1296, 1324, 1308, 1288, 1304, 1276, 1304, 1304, 1276, 1296, " +
|
|
||||||
"1280, 1284, 1296, 1300, 1284, 1288, 1296, 1284, 1300, 1280, " +
|
|
||||||
"1300, 1292, 1276, 1304, 1276, 1316, 1280, 1288, 1296, 1280, " +
|
|
||||||
"1284, 1272, 1300, 1284, 1288, 1292, 1276, 1296, 1276, 1292, " +
|
|
||||||
"1280, 1284, 1284, 1284, 1284, 1284, 1288, 1284, 1304, 1284, " +
|
|
||||||
"1288, 1280, 1296, 1284, 1292, 1296, 1280, 1276, 1288, 1296, " +
|
|
||||||
"1276, 1292, 1288, 1276, 1288, 1276, 1272, 1272, 1292, 1284, " +
|
|
||||||
"1292, 1288, 1280, 1284, 1284, 1268, 1288, 1268, 1276, 1300, " +
|
|
||||||
"1268, 1292, 1292, 1304, 1288, 1284, 1280, 1276, 1288, 1280, " +
|
|
||||||
"1300, 1288, 1320, 1268, 1288, 1280, 1304, 1280, 1280, 1288, " +
|
|
||||||
"1292, 1308, 1268, 1292, 1280], " +
|
|
||||||
"\"HR\":57, " +
|
|
||||||
"\"Mute\":0 " +
|
|
||||||
"}";
|
|
||||||
|
|
||||||
@Before
|
|
||||||
public void setUp() throws Exception {
|
|
||||||
sda = new SdAnalyser(25.0,
|
|
||||||
3.0,
|
|
||||||
8.0,
|
|
||||||
5.0,
|
|
||||||
5.0,
|
|
||||||
100.0,
|
|
||||||
54.0
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@After
|
|
||||||
public void tearDown() throws Exception {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testFreq2fftBin() {
|
|
||||||
int n;
|
|
||||||
n = sda.freq2fftBin(0.0);
|
|
||||||
assertEquals(0,n);
|
|
||||||
n = sda.freq2fftBin(5.0);
|
|
||||||
assertEquals(25,n);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testGetMagnitude() {
|
|
||||||
double[] fft = {1, 1,
|
|
||||||
2, 1,
|
|
||||||
2, 2};
|
|
||||||
double m;
|
|
||||||
m = sda.getMagnitude(fft,0);
|
|
||||||
assertEquals(2.0, m, m * 1e-4);
|
|
||||||
m = sda.getMagnitude(fft,1);
|
|
||||||
assertEquals(5.0, m, m * 1e-4);
|
|
||||||
m = sda.getMagnitude(fft,2);
|
|
||||||
assertEquals(8.0, m, m * 1e-4);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testGetAccelDataFromJson() {
|
|
||||||
double[] retVal;
|
|
||||||
|
|
||||||
retVal = sda.getAccelDataFromJSON(okJSON);
|
|
||||||
assertNotNull(retVal);
|
|
||||||
assertEquals(125,retVal.length);
|
|
||||||
assertEquals(1140,retVal[0],0.001);
|
|
||||||
assertEquals(1280,retVal[124],0.001);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testGetSpectrumRatio() {
|
|
||||||
double[] okRawVals;
|
|
||||||
double[] alarmRawVals;
|
|
||||||
okRawVals = sda.getAccelDataFromJSON(okJSON);
|
|
||||||
alarmRawVals = sda.getAccelDataFromJSON(alarmJSON);
|
|
||||||
|
|
||||||
double okRatio;
|
|
||||||
double alarmRatio;
|
|
||||||
|
|
||||||
okRatio = sda.getSpectrumRatio(okRawVals);
|
|
||||||
alarmRatio = sda.getSpectrumRatio(alarmRawVals);
|
|
||||||
|
|
||||||
assertTrue("Check Spectrum Ratio for OK data "+okRatio+" is <="+sda.mAlarmRatioThresh,
|
|
||||||
okRatio <= sda.mAlarmRatioThresh);
|
|
||||||
assertTrue("Check Spectrum Ratio for ALARM data "+alarmRatio+" is >"+sda.mAlarmRatioThresh,
|
|
||||||
alarmRatio > sda.mAlarmRatioThresh);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testgetAlarmState() {
|
|
||||||
double[] okRawVals;
|
|
||||||
double[] alarmRawVals;
|
|
||||||
okRawVals = sda.getAccelDataFromJSON(okJSON);
|
|
||||||
alarmRawVals = sda.getAccelDataFromJSON(alarmJSON);
|
|
||||||
|
|
||||||
int okAlarmState;
|
|
||||||
int alarmAlarmState;
|
|
||||||
|
|
||||||
okAlarmState = sda.getAlarmState(okRawVals);
|
|
||||||
alarmAlarmState = sda.getAlarmState(alarmRawVals);
|
|
||||||
|
|
||||||
assertEquals("check OK start detected from raw data",0, okAlarmState);
|
|
||||||
assertEquals("check alarm state detected from raw data",1, alarmAlarmState);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
package uk.org.openseizuredetector;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by graham on 01/01/16.
|
|
||||||
*/
|
|
||||||
public class SdDataSourceNetworkTest {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testStart() throws Exception {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testStop() throws Exception {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testUpdatePrefs() throws Exception {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testDownloadSdData() throws Exception {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testReadInputStream() throws Exception {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
package uk.org.openseizuredetector;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by graham on 01/01/16.
|
|
||||||
*/
|
|
||||||
public class SdDataSourcePebbleTest {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testStart() throws Exception {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testStop() throws Exception {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testUpdatePrefs() throws Exception {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testStopPebbleServer() throws Exception {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testStartWatchApp() throws Exception {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testStopWatchApp() throws Exception {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testGetPebbleSdSettings() throws Exception {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testGetPebbleStatus() throws Exception {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
45
app/src/test/java/uk/org/openseizuredetector/SdDataTest.java
Normal file
45
app/src/test/java/uk/org/openseizuredetector/SdDataTest.java
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
package uk.org.openseizuredetector;
|
||||||
|
|
||||||
|
import android.os.Build;
|
||||||
|
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.robolectric.RobolectricTestRunner;
|
||||||
|
import org.robolectric.annotation.Config;
|
||||||
|
|
||||||
|
import java.util.TimeZone;
|
||||||
|
|
||||||
|
@RunWith(RobolectricTestRunner.class)
|
||||||
|
@Config(sdk = {Build.VERSION_CODES.O_MR1}, packageName = "uk.org.openseizuredetector")
|
||||||
|
public class SdDataTest extends TestCase {
|
||||||
|
public void setUp() throws Exception {
|
||||||
|
super.setUp();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void tearDown() throws Exception {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testConstructor() {
|
||||||
|
SdData sd = new SdData();
|
||||||
|
assertTrue(true);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testFromJSON() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testTestToString() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testToJSON() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testToDataString() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testToCSVString() {
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,141 +0,0 @@
|
|||||||
package uk.org.openseizuredetector;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by graham on 01/01/16.
|
|
||||||
*/
|
|
||||||
public class SdServerTest {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testOnBind() throws Exception {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testOnCreate() throws Exception {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testOnStartCommand() throws Exception {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testOnDestroy() throws Exception {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testOnSdDataReceived() throws Exception {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testOnSdDataFault() throws Exception {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testFaultWarningBeep() throws Exception {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testAlarmBeep() throws Exception {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testWarningBeep() throws Exception {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testSendSMSAlarm() throws Exception {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testAcceptAlarm() throws Exception {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testCancelAudible() throws Exception {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testIsAudibleCancelled() throws Exception {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testCancelAudibleTimeRemaining() throws Exception {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testIsLatchAlarms() throws Exception {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testStartWebServer() throws Exception {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testStopWebServer() throws Exception {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testLogData() throws Exception {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testUpdatePrefs() throws Exception {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testIsExternalStorageWritable() throws Exception {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testGetDataStorageDir() throws Exception {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testWriteAlarmToSD() throws Exception {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testWriteToSD() throws Exception {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testWriteToSD1() throws Exception {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testStartFaultTimer() throws Exception {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testStopFaultTimer() throws Exception {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
package uk.org.openseizuredetector;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by graham on 01/01/16.
|
|
||||||
*/
|
|
||||||
public class SdServiceConnectionTest {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testOnServiceConnected() throws Exception {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testOnServiceDisconnected() throws Exception {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testHasSdData() throws Exception {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testHasSdSettings() throws Exception {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testPebbleConnected() throws Exception {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testPebbleAppRunning() throws Exception {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
package uk.org.openseizuredetector;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
|
import androidx.test.core.app.ApplicationProvider;
|
||||||
|
import androidx.test.platform.app.InstrumentationRegistry;
|
||||||
|
|
||||||
|
import com.google.firebase.FirebaseApp;
|
||||||
|
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.robolectric.RobolectricTestRunner;
|
||||||
|
|
||||||
|
|
||||||
|
@RunWith(RobolectricTestRunner.class)
|
||||||
|
public class WebApiConnectionTest {
|
||||||
|
WebApiConnection mWac;
|
||||||
|
@Before
|
||||||
|
public void setUp() throws Exception {
|
||||||
|
Context context = ApplicationProvider.getApplicationContext();
|
||||||
|
FirebaseApp.initializeApp(context);
|
||||||
|
mWac = new WebApiConnection(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void tearDown() throws Exception {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void isLoggedIn() {
|
||||||
|
assertTrue(mWac.isLoggedIn());
|
||||||
|
assertFalse(mWac.isLoggedIn());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void createEvent() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getEvent() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getEvents() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void updateEvent() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void createDatapoint() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getUserProfile() {
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,7 +9,8 @@ buildscript {
|
|||||||
google()
|
google()
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:4.1.1'
|
classpath 'com.android.tools.build:gradle:7.1.0'
|
||||||
|
classpath 'com.google.gms:google-services:4.3.10'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
allprojects {
|
allprojects {
|
||||||
@@ -19,8 +20,12 @@ allprojects {
|
|||||||
url 'https://maven.google.com/'
|
url 'https://maven.google.com/'
|
||||||
name 'Google'
|
name 'Google'
|
||||||
}
|
}
|
||||||
|
google()
|
||||||
//maven { url 'https://jitpack.io' }
|
//maven { url 'https://jitpack.io' }
|
||||||
}
|
}
|
||||||
|
tasks.withType(JavaCompile) {
|
||||||
|
options.compilerArgs << "-Xlint:unchecked" << "-Xlint:deprecation"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
BIN
doc/Event_Log_Workflow.pptx
Normal file
BIN
doc/Event_Log_Workflow.pptx
Normal file
Binary file not shown.
BIN
doc/Installation_Instructions_1.0.pptx
Normal file
BIN
doc/Installation_Instructions_1.0.pptx
Normal file
Binary file not shown.
BIN
doc/Installation_Instructions_1C.pptx
Normal file
BIN
doc/Installation_Instructions_1C.pptx
Normal file
Binary file not shown.
BIN
doc/Star_of_life.png
Normal file
BIN
doc/Star_of_life.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 33 KiB |
8
doc/Star_of_life.svg
Normal file
8
doc/Star_of_life.svg
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="198" height="192" version="1.0">
|
||||||
|
<path fill="#fff" stroke="#00f" stroke-linecap="round" stroke-width="1.70000005" d="M71.9375 6.84375v44.25l-38.3125-22.125L8 73.375l38.3125 22.09375L8 117.59375l25.625 44.4375 38.3125-22.125v44.25H123.25V139.9375l38.28125 22.09375 25.65625-44.4375L148.875 95.5l38.3125-22.125-25.65625-44.40625L123.25 51.0625V6.84375H71.9375z"/>
|
||||||
|
<path fill="#00f" d="M75.09375 10v46.53125L34.78125 33.25l-22.5 38.96875L52.59375 95.5l-40.3125 23.25 22.5 38.96875 40.3125-23.28125V181h45v-46.53125l40.28125 23.25 22.5-38.96875-40.3125-23.25 40.3125-23.28125-22.5-38.96875-40.28125 23.25V10h-45z"/>
|
||||||
|
<path fill="#fff" fill-rule="evenodd" stroke="#395475" stroke-width=".60000002" d="M92.517151 28.749341c-.108165-3.261868 2.846951-6.304555 6.005075-6.304555 2.259464 0 5.041684 1.718721 4.976294 4.583927-.79015 34.623955-2.89385 104.866307-3.688654 139.820577-.02403 1.05701-1.35523.58854-1.403534-.49573-1.544423-34.6672-4.725868-102.522697-5.889181-137.604219z"/>
|
||||||
|
<path fill="#fff" fill-rule="evenodd" stroke="#395475" stroke-width=".60000002" d="M94.036939 33.435356c2.505623 0 3.630713 1.523558 5.180778 2.864011 1.497323 1.294839 2.671463 2.479523 2.671463 3.753403 0 1.338764-.98273.937612-2.024023 1.429304-.54852.259006-.499572.818718-1.3955.818718-2.153558 0-3.010987-2.026386-5.952507-2.026386-2.424111 0-5.572559 2.904739-5.572559 8.23219 0 8.046089 3.102902 11.651715 6.775725 14.437995l.379947 9.562005c-3.926121-1.646437-14.058047-10.575123-14.058047-22.986807 0-10.801673 7.013011-16.084433 13.994723-16.084433z"/>
|
||||||
|
<path fill="#00f" fill-rule="evenodd" d="M94.986808 36.126649c1.791288-.283965 1.611109.792182 2.406332 1.488126-1.838434.054636-2.245762-.71647-2.406332-1.488126z"/>
|
||||||
|
<path fill="#fff" fill-rule="evenodd" stroke="#395475" stroke-width=".60000002" d="M102.52243 66.934037l-.2533 9.118733c0 5.57445-14.754618 15.354654-14.754618 25.32982 0 7.68205 6.174143 12.60158 8.453826 13.74142l-.284961-8.04222s-2.786279-1.87903-2.786279-5.06596c0-4.509672 16.970972-16.124154 16.970972-25.013191 0-6.302706-4.30606-8.654354-7.34564-10.068602zM101.35093 111.54617s5.79419 3.83072 5.79419 8.6438c0 4.11749-3.15748 7.88415-6.8875 11.77934-4.357416 4.55037-5.277587 10.2467-2.706168 16.21011l.221635 4.87598c-1.868074-1.51979-4.812665-6.26671-4.812665-14.18469 0-9.53083 8.168868-12.39813 8.168868-21.18205l.22164-6.14249zM100.21108 151.25066s2.6913 1.44795 2.6913 5.22427c0 3.55465-4.450779 6.80063-5.129293 7.28233-.657297.46664-.909218-.14107-.379947-.63325.546479-.50818 2.78628-3.50978 2.78628-6.9657l.03166-4.90765z"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 2.6 KiB |
@@ -1 +1,16 @@
|
|||||||
android.useAndroidX = true
|
## For more details on how to configure your build environment visit
|
||||||
|
# http://www.gradle.org/docs/current/userguide/build_environment.html
|
||||||
|
#
|
||||||
|
# Specifies the JVM arguments used for the daemon process.
|
||||||
|
# The setting is particularly useful for tweaking memory settings.
|
||||||
|
# Default value: -Xmx1024m -XX:MaxPermSize=256m
|
||||||
|
# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
|
||||||
|
#
|
||||||
|
# When configured, Gradle will run in incubating parallel mode.
|
||||||
|
# This option should only be used with decoupled projects. More details, visit
|
||||||
|
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
|
||||||
|
# org.gradle.parallel=true
|
||||||
|
#Tue Apr 12 22:12:16 BST 2022
|
||||||
|
org.gradle.jvmargs=-Xmx1536M -Dkotlin.daemon.jvm.options\="-Xmx1536M"
|
||||||
|
android.enableJetifier=true
|
||||||
|
android.useAndroidX=true
|
||||||
|
|||||||
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
|
|||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-all.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-all.zip
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user