Merge branch 'beta'

This commit is contained in:
Graham Jones
2025-09-08 21:54:42 +01:00
33 changed files with 1085 additions and 629 deletions

View File

@@ -1,5 +1,9 @@
OpenSeizureDetector Android App - Change Log
============================================
V4.3.1 - Fixed corrupted user interface issues on Android 15 and Android 16.
V4.3.0 - 2025-07-16
- Added support for Android 15 (API 35) to allow publishing on Play Store.
- Improved the data sharing screen to show grouped events to reduce the number of events that need to be edited.
V4.2.12 - Fixed crash when pressing 'Install Watch App' button by hiding the button if the Pebble data source is not selected
- Added a 'Help' and 'Troubleshooting' button and menu item to draw users' attention to the web site instructions.
V4.2.11 - Updated permissions handling to support Android 14 (needed to publish on Play Store)

View File

@@ -1,13 +1,14 @@
apply plugin: 'com.android.application'
apply plugin: 'com.google.gms.google-services'
android {
compileSdk 34 // Android 14
compileSdk 36
// Android 14
useLibrary 'org.apache.http.legacy'
defaultConfig {
applicationId "uk.org.openseizuredetector"
minSdkVersion 23 // Android 6
targetSdkVersion 34 // Android 14 = 34
targetSdkVersion 35 // Android 15 = 35
multiDexEnabled true
}

View File

@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:versionCode="151"
android:versionName="4.2.12">
android:versionCode="154"
android:versionName="4.3.1">
<!-- android:allowBackup="false" -->
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>

View File

@@ -5,10 +5,13 @@ import android.os.Bundle;
import android.os.Handler;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.TextView;
@@ -38,6 +41,7 @@ public class EditEventActivity extends AppCompatActivity {
private String mEventTypeStr = null;
private String mEventSubTypeStr = null;
private String mEventId;
private ArrayList<String> mEventIds; // For group editing
private String mEventNotes = "";
//private Date mEventDateTime;
private RadioGroup mEventTypeRg;
@@ -52,6 +56,22 @@ public class EditEventActivity extends AppCompatActivity {
Log.v(TAG, "onCreate()");
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_edit_event);
// Handle system window insets for all API levels
View rootView = findViewById(R.id.root_layout_edit_event);
ViewCompat.setOnApplyWindowInsetsListener(rootView, (v, insets) -> {
// Get the system bar insets
int top = insets.getInsets(WindowInsetsCompat.Type.systemBars()).top;
int bottom = insets.getInsets(WindowInsetsCompat.Type.systemBars()).bottom;
// Apply padding to your main content view
LinearLayout content = findViewById(R.id.edit_event_content_layout);
content.setPadding(0, top, 0, bottom);
// Return the insets so they keep propagating
return WindowInsetsCompat.CONSUMED;
});
mUtil = new OsdUtil(getApplicationContext(), serverStatusHandler);
mConnection = new SdServiceConnection(getApplicationContext());
@@ -61,8 +81,15 @@ public class EditEventActivity extends AppCompatActivity {
Bundle extras = getIntent().getExtras();
if (extras != null) {
String eventId = extras.getString("eventId");
mEventId = eventId;
mEventIds = extras.getStringArrayList("eventIds");
if (mEventIds != null && !mEventIds.isEmpty()) {
Log.v(TAG, "onCreate - Group Edit - eventIds=" + mEventIds.toString());
mEventId = mEventIds.get(0);
} else {
Log.v(TAG, "onCreate - Single Edit - eventId=" + extras.getString("eventId"));
mEventId = extras.getString("eventId");
mEventIds = null;
}
Log.v(TAG, "onCreate - mEventId=" + mEventId);
}
@@ -297,6 +324,7 @@ public class EditEventActivity extends AppCompatActivity {
}
Log.v(TAG, "onOK() - eventObj=" + mEventObj.toString());
// First we just save the open event, irrespective of whether it is a group edit or not.
try {
mWac.updateEvent(mEventObj, new WebApiConnection.JSONObjectCallback() {
@Override
@@ -320,9 +348,58 @@ public class EditEventActivity extends AppCompatActivity {
mUtil.showToast("Error Updating Event");
updateUi();
}
// If this is a group edit, we need to update the other events in the group.
if (mEventIds != null && mEventIds.size() > 1) {
Log.v(TAG, "onOK() - Group Edit - updating other events in group");
updateGroupEventsSequentially(0);
}
}
};
private void updateGroupEventsSequentially(final int index) {
if (mEventIds == null || index >= mEventIds.size()) {
Log.v(TAG, "updateGroupEventsSequentially - All events updated");
return;
}
final String eventId = mEventIds.get(index);
mWac.getEvent(eventId, new WebApiConnection.JSONObjectCallback() {
@Override
public void accept(JSONObject eventObj) {
if (eventObj == null) {
Log.e(TAG, "updateGroupEventsSequentially - ERROR: could not retrieve event " + eventId);
mUtil.showToast("Error Retrieving Event " + eventId);
updateGroupEventsSequentially(index + 1);
return;
}
try {
eventObj.put("id", eventId);
eventObj.put("type", mEventObj.getString("type"));
eventObj.put("subType", mEventObj.getString("subType"));
eventObj.put("desc", mEventObj.getString("desc"));
} catch (JSONException e) {
Log.e(TAG, "updateGroupEventsSequentially - ERROR: " + e.getMessage());
updateGroupEventsSequentially(index + 1);
return;
}
mWac.updateEvent(eventObj, new WebApiConnection.JSONObjectCallback() {
@Override
public void accept(JSONObject updatedObj) {
if (updatedObj == null) {
Log.e(TAG, "updateGroupEventsSequentially - ERROR: update failed for " + eventId);
mUtil.showToast("Error Updating Event " + eventId);
} else {
Log.v(TAG, "updateGroupEventsSequentially - Updated event " + eventId + " OK");
mUtil.showToast("Event " + eventId + " Updated OK");
}
updateGroupEventsSequentially(index + 1);
}
});
}
});
}
RadioGroup.OnCheckedChangeListener onEventTypeChange =
new RadioGroup.OnCheckedChangeListener() {

View File

@@ -13,6 +13,8 @@ import android.os.AsyncTask;
import android.os.Handler;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;
import android.os.Bundle;
import android.os.IBinder;
@@ -22,6 +24,7 @@ import android.view.View;
import android.widget.Button;
import android.widget.DatePicker;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TimePicker;
import android.os.ParcelFileDescriptor;
@@ -83,6 +86,21 @@ public class ExportDataActivity extends AppCompatActivity
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_dbquery);
// Handle system window insets for all API levels
View rootView = findViewById(R.id.root_layout_export_data);
ViewCompat.setOnApplyWindowInsetsListener(rootView, (v, insets) -> {
// Get the system bar insets
int top = insets.getInsets(WindowInsetsCompat.Type.systemBars()).top;
int bottom = insets.getInsets(WindowInsetsCompat.Type.systemBars()).bottom;
// Apply padding to your main content view
LinearLayout content = findViewById(R.id.export_data_content_layout);
content.setPadding(0, top, 0, bottom);
// Return the insets so they keep propagating
return WindowInsetsCompat.CONSUMED;
});
mHandler = new Handler();
mUtil = new OsdUtil(this, mHandler);

View File

@@ -12,11 +12,15 @@ import android.os.CountDownTimer;
import android.os.Handler;
import android.os.IBinder;
import androidx.core.graphics.Insets;
import androidx.core.view.MenuCompat;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
@@ -42,13 +46,17 @@ import java.lang.reflect.Field;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
public class LogManagerControlActivity extends AppCompatActivity {
private String TAG = "LogManagerControlActivity";
private static final long GROUPING_WINDOW_MINUTES = 3;
private static final long GROUPING_WINDOW_MS = GROUPING_WINDOW_MINUTES * 60 * 1000;
private LogManager mLm;
private Context mContext;
private UiTimer mUiTimer;
@@ -63,6 +71,7 @@ public class LogManagerControlActivity extends AppCompatActivity {
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 Menu mMenu;
private CheckBox mGroupEventsCb; // Declare the CheckBox member
//private Integer UI_MODE_LOCAL = 0;
//private Integer UI_MODE_SHARED = 1;
//private Integer mUiMode = UI_MODE_SHARED;
@@ -84,6 +93,20 @@ public class LogManagerControlActivity extends AppCompatActivity {
setContentView(R.layout.activity_log_manager_control);
// Handle system window insets for all API levels
View rootView = findViewById(R.id.root_layout_log_manager_control);
ViewCompat.setOnApplyWindowInsetsListener(rootView, (v, insets) -> {
// Get the system bar insets
int top = insets.getInsets(WindowInsetsCompat.Type.systemBars()).top;
int bottom = insets.getInsets(WindowInsetsCompat.Type.systemBars()).bottom;
// Apply padding to your main content view
LinearLayout content = findViewById(R.id.log_manager_control_content_layout); // Add this ID to your LinearLayout
content.setPadding(0, top, 0, bottom);
// Return the insets so they keep propagating
return WindowInsetsCompat.CONSUMED;
});
/* Force display of overflow menu - from stackoverflow
* "how to force use of..."
*/
@@ -118,6 +141,21 @@ public class LogManagerControlActivity extends AppCompatActivity {
(CheckBox) findViewById(R.id.include_nda_cb);
includeNDACb.setOnCheckedChangeListener(onIncludeNDACb);
mGroupEventsCb = findViewById(R.id.group_events_cb);
mGroupEventsCb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
// When the checkbox state changes, re-process and update the UI
if (mRemoteEventsList != null && !mRemoteEventsList.isEmpty()) {
if (isChecked) {
createGroupedEventsList();
}
updateUi(); // Update UI to reflect grouped or non-grouped list
}
}
});
ListView lv = (ListView) findViewById(R.id.eventLogListView);
lv.setOnItemClickListener(onEventListClick);
@@ -219,7 +257,7 @@ public class LogManagerControlActivity extends AppCompatActivity {
updateUi();
});
} else {
Log.e(TAG,"ERROR: initialiseServiceConnection() - mLm is null");
Log.e(TAG, "ERROR: initialiseServiceConnection() - mLm is null");
mUtil.showToast(getString(R.string.error_failed_to_start_log_manager));
}
}
@@ -227,6 +265,7 @@ public class LogManagerControlActivity extends AppCompatActivity {
private void getRemoteEvents(boolean includeWarnings, boolean includeNDA) {
mRemoteEventsList = null; // clear existing data
mGroupedRemoteEventsList = null;
// Retrieve events from remote database
mLm.mWac.getEvents((JSONObject remoteEventsObj) -> {
Log.v(TAG, "getRemoteEvents()");
@@ -253,7 +292,7 @@ public class LogManagerControlActivity extends AppCompatActivity {
String dataTime = "null";
if (!eventObj.isNull("dataTime")) {
dataTime = eventObj.getString("dataTime");
Log.v(TAG, "getRemoteEvents() - dataTime=" + dataTime);
//Log.v(TAG, "getRemoteEvents() - dataTime=" + dataTime);
}
String typeStr = "null";
if (!eventObj.isNull("type")) {
@@ -282,27 +321,141 @@ public class LogManagerControlActivity extends AppCompatActivity {
Log.v(TAG, "getRemoteEvents - skipping warning or NDA record");
}
}
createGroupedEventsList();
Log.v(TAG, "getRemoteEvents() - set mRemoteEventsList(). Updating UI");
// Sort the remote events list by date, descending (newest first)
Log.v(TAG, "getRemoteEvents() - Sorting mRemoteEventsList by date");
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX", Locale.getDefault()); // Adjust format if needed
Collections.sort(mRemoteEventsList, (event1, event2) -> {
try {
String dt1Str = event1.get("dataTime");
String dt2Str = event2.get("dataTime");
if (
dt1Str == null
|| dt2Str == null
|| dt1Str.equals("null")
|| dt2Str.equals("null"))
return 0;
Date date1 = sdf.parse(dt1Str);
Date date2 = sdf.parse(dt2Str);
return date2.compareTo(date1); // Descending
} catch (ParseException e) {
Log.e(TAG, "Error parsing date for sorting: " + e.getMessage());
return 0;
}
});
if (mGroupEventsCb.isChecked()) { // Check if grouping is enabled
createGroupedEventsList();
Log.v(TAG, "getRemoteEvents() - created grouped events. Updating UI");
} else {
mGroupedRemoteEventsList = null; // Ensure grouped list is cleared if not used
Log.v(TAG, "getRemoteEvents() - grouping disabled. Updating UI with flat list.");
}
updateUi();
} catch (JSONException e) {
Log.e(TAG, "getRemoteEvents(): Error Parsing remoteEventsObj: " + e.getMessage());
mUtil.showToast("Error Parsing remoteEventsObj - this should not happen!!!");
mRemoteEventsList = null;
mGroupedRemoteEventsList = null;
updateUi(); // Update UI to show error state
}
//Log.v(TAG, "getRemoteEvents(): mRemoteEventsList = " + mRemoteEventsList.toString());
}
});
}
/**
* createGroupedEventsList()
* Reads the complete list of remote events mRemoteEventsList and creates a new list mGroupedRemoteEventsList
* where each item is a list of events that comprise a group based on time (all events within a 3 minute period are grouped together).
*/
private void createGroupedEventsList() {
/**
* Reads the complete list of remote events mRemoteEventsList and creates a new list mGroupedRemoteEventsList
* where each item is a list of events that comprise a group based on time (all events within a 3 minute period are grouped together).
*/
Log.i(TAG, "createGroupedEventsList()");
mGroupedRemoteEventsList = new ArrayList<ArrayList<HashMap<String,String>>>();
// FIXME - Make this do something!
/**
* createGroupedEventsList()
* Reads the complete list of remote events mRemoteEventsList (sorted newest first)
* and creates a new list mGroupedRemoteEventsList
* where each item is a list of events that comprise a group based on time.
*/
mGroupedRemoteEventsList = new ArrayList<>();
if (mRemoteEventsList == null || mRemoteEventsList.isEmpty()) {
Log.i(TAG, "createGroupedEventsList() - mRemoteEventsList is null or empty.");
return;
}
// Helper to parse date strings to long timestamps.
// Adjust the SimpleDateFormat pattern to match your "dataTime" format.
// If "dataTime" is already a timestamp (long), you can use it directly.
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX", Locale.getDefault()); // Example format
ArrayList<HashMap<String, String>> currentGroup = null;
long lastEventTimeInGroup = 0;
for (HashMap<String, String> event : mRemoteEventsList) {
String dataTimeString = event.get("dataTime");
if (dataTimeString == null || dataTimeString.equals("null")) {
Log.w(TAG, "Event has null or invalid dataTime: " + event.get("id"));
continue; // Skip events with no valid time
}
long currentEventTime;
try {
Date eventDate = sdf.parse(dataTimeString);
if (eventDate == null) {
Log.w(TAG, "Could not parse dataTime: " + dataTimeString + " for event: " + event.get("id"));
continue;
}
currentEventTime = eventDate.getTime();
} catch (ParseException e) {
Log.e(TAG, "Error parsing date string: " + dataTimeString + " - " + e.getMessage());
continue; // Skip if date can't be parsed
}
if (currentGroup == null || (lastEventTimeInGroup - currentEventTime) > GROUPING_WINDOW_MS) {
// Start a new group
if (currentGroup != null) {
moveFirstAlarmToFront(currentGroup); // Move the first ALARM event to the front of the group)
mGroupedRemoteEventsList.add(currentGroup);
}
currentGroup = new ArrayList<>();
currentGroup.add(event);
lastEventTimeInGroup = currentEventTime;
} else {
// Add to the current group
currentGroup.add(event);
// lastEventTimeInGroup remains the time of the first event added to this group (newest)
}
}
// Add the last group if it exists
if (currentGroup != null && !currentGroup.isEmpty()) {
moveFirstAlarmToFront(currentGroup); // Move the first ALARM event to the front of the group
mGroupedRemoteEventsList.add(currentGroup);
}
Log.i(TAG, "createGroupedEventsList() - Grouped " + mRemoteEventsList.size() +
" events into " + mGroupedRemoteEventsList.size() + " groups.");
}
/**
* moveFirstAlarmToFront() - This method checks the group for the first
* event with an ALARM state (osdAlarmState = 2) and makes that event the
* first in the list.
*
* @param group An ArrayList of HashMaps representing a group of events.
*/
private void moveFirstAlarmToFront(ArrayList<HashMap<String, String>> group) {
//Log.i(TAG, "moveFirstAlarmToFront() - Checking group of size: " + group.size());
for (int i = 0; i < group.size(); i++) {
HashMap<String, String> event = group.get(i);
String alarmStateStr = event.get("osdAlarmState");
if (alarmStateStr != null && alarmStateStr.equals("2")) { // ALARM is 2
//Log.v(TAG," moveFirstAlarmToFront() - Found ALARM event at index: " + i);
if (i != 0) {
group.remove(i);
group.add(0, event);
}
break;
}
}
}
private void updateUi() {
@@ -353,13 +506,27 @@ public class LogManagerControlActivity extends AppCompatActivity {
pb.setIndeterminate(false);
pb.setVisibility(View.INVISIBLE);
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));
if (mGroupEventsCb.isChecked() && mGroupedRemoteEventsList != null) {
// Show only the first event of each group
ArrayList<HashMap<String, String>> displayList = new ArrayList<>();
for (ArrayList<HashMap<String, String>> group : mGroupedRemoteEventsList) {
displayList.add(group.get(0));
}
ListAdapter adapter = new RemoteEventsAdapter(LogManagerControlActivity.this, displayList, 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);
} else if (mRemoteEventsList != null) {
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);
} else {
Log.i(TAG, "UpdateUi: No Remote Events");
}
} else {
//mUtil.showToast("No Remote Events");
Log.i(TAG, "UpdateUi: No Remote Events");
@@ -656,15 +823,26 @@ public class LogManagerControlActivity extends AppCompatActivity {
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) {
if (mGroupEventsCb.isChecked() && mGroupedRemoteEventsList != null) {
Log.v(TAG,"onItemClickListener() - Creating Grouped Events List from Position=" + position);
// Get the group for this position
ArrayList<HashMap<String, String>> group = mGroupedRemoteEventsList.get(position);
ArrayList<String> eventIds = new ArrayList<>();
for (HashMap<String, String> event : group) {
Log.v(TAG,"onItemClickListener() - Adding event to edit list: " + event.get("id"));
eventIds.add(event.get("id"));
}
Intent i = new Intent(getApplicationContext(), EditEventActivity.class);
i.putStringArrayListExtra("eventIds", eventIds);
startActivity(i);
} else {
Log.v(TAG,"onItemClickListener() - Editing Single event at Position=" + position);
HashMap<String, String> eventObj = (HashMap<String, String>) adapter.getItemAtPosition(position);
String eventId = eventObj.get("id");
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");
}
}
};
@@ -673,13 +851,31 @@ public class LogManagerControlActivity extends AppCompatActivity {
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);
Log.v(TAG, "onItemClickListener() - Position=" + position + ", id=" + id);// Confirmation dialog based on: https://stackoverflow.com/a/12213536/2104584
if (mGroupEventsCb.isChecked() && mGroupedRemoteEventsList != null) {
Log.v(TAG,"onItemClickListener() - Creating Grouped Events List from Position=" + position);
// Get the group for this position
ArrayList<HashMap<String, String>> group = mGroupedRemoteEventsList.get(position);
ArrayList<String> eventIds = new ArrayList<>();
for (HashMap<String, String> event : group) {
Log.v(TAG,"onItemClickListener() - Adding event to edit list: " + event.get("id"));
eventIds.add(event.get("id"));
}
Intent i = new Intent(getApplicationContext(), EditEventActivity.class);
i.putStringArrayListExtra("eventIds", eventIds);
startActivity(i);
} else {
Log.v(TAG,"onItemClickListener() - Editing Single event at Position=" + position);
HashMap<String, String> eventObj = (HashMap<String, String>) adapter.getItemAtPosition(position);
String eventId = eventObj.get("id");
Intent i = new Intent(getApplicationContext(), EditEventActivity.class);
i.putExtra("eventId", eventId);
startActivity(i);
}
}
};
@@ -787,6 +983,7 @@ public class LogManagerControlActivity extends AppCompatActivity {
}
}
private void showDataSharingDialog() {
mUtil.writeToSysLogFile("MainActivity.showDataSharingDialog()");
View aboutView = getLayoutInflater().inflate(R.layout.data_sharing_dialog_layout, null, false);

View File

@@ -2,7 +2,9 @@ package uk.org.openseizuredetector;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.view.WindowInsetsCompat;
import androidx.core.view.MenuCompat;
import androidx.core.view.ViewCompat;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.viewpager2.adapter.FragmentStateAdapter;
@@ -18,11 +20,13 @@ import android.os.Bundle;
import android.os.Handler;
import android.preference.PreferenceManager;
import android.util.Log;
import android.util.TypedValue;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.rohitss.uceh.UCEHandler;
@@ -53,6 +57,22 @@ public class MainActivity2 extends AppCompatActivity {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
// Handle system window insets for all API levels
View rootView = findViewById(R.id.activity_main2_root_layout);
ViewCompat.setOnApplyWindowInsetsListener(rootView, (v, insets) -> {
// Get the system bar insets
int top = insets.getInsets(WindowInsetsCompat.Type.systemBars()).top;
int bottom = insets.getInsets(WindowInsetsCompat.Type.systemBars()).bottom;
// Apply padding to your main content view
LinearLayout content = findViewById(R.id.activity_main2_content_layout);
content.setPadding(0, top, 0, bottom);
// Return the insets so they keep propagating
return WindowInsetsCompat.CONSUMED;
});
Log.i(TAG, "onCreate()");
// Set our custom uncaught exception handler to report issues.

View File

@@ -12,11 +12,14 @@ import android.os.Handler;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.DatePicker;
import android.widget.LinearLayout;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.TextView;
@@ -78,6 +81,21 @@ public class ReportSeizureActivity extends AppCompatActivity {
mConnection = new SdServiceConnection(getApplicationContext());
setContentView(R.layout.activity_report_seizure);
// Handle system window insets for all API levels
View rootView = findViewById(R.id.root_layout_report_seizure);
ViewCompat.setOnApplyWindowInsetsListener(rootView, (v, insets) -> {
// Get the system bar insets
int top = insets.getInsets(WindowInsetsCompat.Type.systemBars()).top;
int bottom = insets.getInsets(WindowInsetsCompat.Type.systemBars()).bottom;
// Apply padding to your main content view
LinearLayout content = findViewById(R.id.report_seizure_content_layout);
content.setPadding(0, top, 0, bottom);
// Return the insets so they keep propagating
return WindowInsetsCompat.CONSUMED;
});
mEventTypeRg = findViewById(R.id.eventTypeRg);
mEventTypeRg.setOnCheckedChangeListener(onEventTypeChange);

View File

@@ -369,13 +369,13 @@ public class WebApiConnection_osdapi extends WebApiConnection {
new Response.Listener<String>() {
@Override
public void onResponse(String response) {
Log.v(TAG, "Response is: " + response);
Log.v(TAG, "updateEvent.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());
Log.e(TAG, "updateEvent.onResponse(): Error: " + e.getMessage() + "," + e.toString());
callback.accept(null);
}
}
@@ -385,9 +385,9 @@ public class WebApiConnection_osdapi extends WebApiConnection {
public void onErrorResponse(VolleyError error) {
mServerConnectionOk = false;
if (error != null) {
Log.e(TAG, "Create Event Error: " + error.toString() + ", message:" + error.getMessage());
Log.e(TAG, "updateEvent.onErrorResponse(): Error: " + error.toString() + ", message:" + error.getMessage());
} else {
Log.e(TAG, "Create Event Error - returned null response");
Log.e(TAG, "updateEvent.onErrorResponse(): Error - returned null response");
}
callback.accept(null);
}

View File

@@ -1,91 +1,102 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/root_layout_export_data"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Export Local Data"
android:textStyle="bold" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="End Date/Time (dd-mm-yyyy hh:mm)" />
android:fitsSystemWindows="true"
tools:context="uk.org.openseizuredetector.LogManager">
<LinearLayout
android:id="@+id/export_data_content_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Export Local Data"
android:textStyle="bold" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="End Date/Time (dd-mm-yyyy hh:mm)" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<EditText
android:id="@+id/endDateText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ems="10"
android:text="(end date)" />
<Button
android:id="@+id/dateBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Select Date" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<EditText
android:id="@+id/endTimeText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ems="10"
android:text="(end time)" />
<Button
android:id="@+id/timeBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Select Time" />
</LinearLayout>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Duration (hrs)" />
<EditText
android:id="@+id/endDateText"
android:id="@+id/durationText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ems="10"
android:text="(end date)" />
android:inputType="numberDecimal"
android:text="1.0" />
<Button
android:id="@+id/dateBtn"
android:layout_width="wrap_content"
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Select Date" />
android:orientation="horizontal">
<Button
android:id="@+id/exportBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Export Data" />
<ProgressBar
android:id="@+id/exportPb"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:visibility="invisible" />
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<EditText
android:id="@+id/endTimeText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ems="10"
android:text="(end time)" />
<Button
android:id="@+id/timeBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Select Time" />
</LinearLayout>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Duration (hrs)" />
<EditText
android:id="@+id/durationText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ems="10"
android:inputType="numberDecimal"
android:text="1.0" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="@+id/exportBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Export Data" />
<ProgressBar
android:id="@+id/exportPb"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:visibility="invisible" />
</LinearLayout>
</LinearLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@@ -1,170 +1,184 @@
<?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">
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/root_layout_edit_event"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context="uk.org.openseizuredetector.LogManager">
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
<LinearLayout
android:id="@+id/edit_event_content_layout"
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">
android:layout_height="fill_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
android:orientation="horizontal">
<LinearLayout
android:layout_width="fill_parent"
<Button
android:id="@+id/cancelBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
android:layout_weight="1"
android:text="@string/cancel" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/eventid" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=": " />
<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"
<Button
android:id="@+id/loginBtn"
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:text="@string/event_date"
android:textSize="20sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=": "
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="@string/alarm_state"
android:textSize="20sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=": "
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" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=": "
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" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=": "
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="@string/notes_about_event" />
android:layout_weight="1"
android:text="@string/save" />
</LinearLayout>
</ScrollView>
</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="@string/eventid" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=": " />
<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="@string/event_date"
android:textSize="20sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=": "
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="@string/alarm_state"
android:textSize="20sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=": "
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" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=": "
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" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=": "
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="@string/notes_about_event" />
</LinearLayout>
</ScrollView>
</LinearLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@@ -1,218 +1,248 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/root_layout_log_manager_control"
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"
android:fitsSystemWindows="true"
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>
-->
<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/NDATimeRemaining" />
<TextView
android:id="@+id/nda_time_remaining_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:id="@+id/shared_data_ll"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_height="match_parent"
android:orientation="vertical"
android:visibility="visible">
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
android:id="@+id/log_manager_control_content_layout"
tools:context="uk.org.openseizuredetector.LogManager">
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/remote_database"
android:text="@string/local_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" />
android:text="@string/num_local_events" />
<Button
android:id="@+id/auth_button"
<TextView
android:id="@+id/num_local_events_tv"
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" />
<ProgressBar
android:id="@+id/remoteAccessPb"
android:layout_width="wrap_content"
android:layout_height="match_parent" />
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>
-->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<CheckBox
android:id="@+id/include_warnings_cb"
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/include_warnings"></CheckBox>
android:text="@string/NDATimeRemaining" />
<CheckBox
android:id="@+id/include_nda_cb"
<TextView
android:id="@+id/nda_time_remaining_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/include_nda"></CheckBox>
android:text="000" />
</LinearLayout>
<ListView
android:id="@+id/remoteEventsLv"
<RadioGroup xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp" />
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:id="@+id/shared_data_ll"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:visibility="visible">
<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:gravity="center_vertical"
android:orientation="horizontal">
<TextView
android:id="@+id/authStatusTv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:text="@string/not_authenticated" /> <!-- Space after TextView -->
<Button
android:id="@+id/auth_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:text="@string/authenticate" /> <!-- Space after this button -->
<Button
android:id="@+id/refresh_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:text="@string/refreshBtn" /> <!-- Space before this button -->
<!-- No marginEnd needed if ProgressBar is last and you want it close,
or add marginEnd if you want space before ProgressBar too -->
<ProgressBar
android:id="@+id/remoteAccessPb"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginStart="8dp" /> <!-- Space before ProgressBar -->
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal">
<CheckBox
android:id="@+id/group_events_cb"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:checked="true"
android:text="@string/group_remote_events" />
<CheckBox
android:id="@+id/include_warnings_cb"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/include_warnings" />
<CheckBox
android:id="@+id/include_nda_cb"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/include_nda" />
</LinearLayout>
<ListView
android:id="@+id/remoteEventsLv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp" />
</LinearLayout>
<LinearLayout
android:id="@+id/local_data_ll"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:visibility="gone">
<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:id="@+id/syslog_ll"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:visibility="gone">
<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>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
<LinearLayout
android:id="@+id/local_data_ll"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:visibility="gone">
<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:id="@+id/syslog_ll"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:visibility="gone">
<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>

View File

@@ -1,26 +1,36 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main2_root_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context="uk.org.openseizuredetector.LogManager">
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<LinearLayout
android:id="@+id/activity_main2_content_layout"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<TextView
android:id="@+id/versionTv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/app_name" />
<TextView
android:id="@+id/versionTv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/app_name" />
<androidx.fragment.app.FragmentContainerView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/fragment_common_container_view"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<androidx.fragment.app.FragmentContainerView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/fragment_common_container_view"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/fragment_pager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/fragment_pager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@@ -1,183 +1,193 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/root_layout_report_seizure"
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"
android:fitsSystemWindows="true"
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
<LinearLayout
android:id="@+id/report_seizure_content_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content">
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">
<LinearLayout
android:layout_width="match_parent"
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
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="horizontal">
android:orientation="vertical">
<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"
<LinearLayout
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" />
android:orientation="horizontal">
<Button
android:id="@+id/cancelBtn"
android:layout_width="wrap_content"
<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:text="@string/cancelBtnTxt" />
</LinearLayout>
android:orientation="horizontal">
<TextView
android:id="@+id/msg_tv"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="msg" />
</LinearLayout>
</ScrollView>
</LinearLayout>
<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>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@@ -0,0 +1,42 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<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"
android:id="@+id/group_event_time_tv" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=" : "/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="alarm"
android:id="@+id/group_event_alarmState_tv"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=" : "/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="uploaded"
android:id="@+id/group_event_uploaded"
/>
</LinearLayout>
<!-- <TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="dataJSON"
android:id="@+id/event_dataJSON" />
-->
</LinearLayout>

View File

@@ -3,7 +3,10 @@
<string name="app_name">OpenSeizureDetector</string>
<string name="changelog">
"\n
\nV4.2.12 - Added butons and menu items for 'Help' and 'Troubleshooting' to point users to the web page instructoins.
\nV4.3.1 - Fixed user interface issues on Android-15 and Android-16
\nV4.3.0 - Added support for Android 15 (API 35) and above.
\n - Simplified data sharing editor by grouping events for editing.
\nV4.2.12 - Added buttons and menu items for 'Help' and 'Troubleshooting' to point users to the web page instructions.
\nV4.2 - Added support for PineTime and BangleJS Watches using Bluetooth data source.
\n - Added support for Version 2 of the Garmin watch app, which reduces battery drain
\n - Added new, swipeable user interface to simplify the main screen.
@@ -588,4 +591,5 @@
<string name="DefaultSMSFalseAlarmMsgText">False Alarm, Sorry!</string>
<string name="sms_false_alarm_message_summary">Text of \'False Alarm\' SMS message</string>
<string name="sms_false_alarm_message_title">SMS False Alarm Message</string>
<string name="group_remote_events">Group Remote Events</string>
</resources>

View File

@@ -10,7 +10,7 @@ buildscript {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:8.4.1'
classpath 'com.android.tools.build:gradle:8.8.0'
classpath 'com.google.gms:google-services:4.3.15'
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 192 KiB

View File

@@ -1,6 +1,6 @@
#Thu Oct 10 20:04:34 BST 2024
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.