add Heart icon (trigger heart measurement) to device action icons

This commit is contained in:
vanous 2021-08-08 11:11:05 +02:00
parent 1092d1bc05
commit e6ae5e357e
7 changed files with 348 additions and 0 deletions

View File

@ -51,6 +51,7 @@ import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.android.material.navigation.NavigationView;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
@ -64,6 +65,8 @@ import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.adapter.GBDeviceAdapterv2;
import nodomain.freeyourgadget.gadgetbridge.devices.DeviceManager;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample;
import nodomain.freeyourgadget.gadgetbridge.model.DeviceService;
import nodomain.freeyourgadget.gadgetbridge.util.AndroidUtils;
import nodomain.freeyourgadget.gadgetbridge.util.GB;
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
@ -99,10 +102,33 @@ public class ControlCenterv2 extends AppCompatActivity
case DeviceManager.ACTION_DEVICES_CHANGED:
refreshPairedDevices();
break;
case DeviceService.ACTION_REALTIME_SAMPLES:
handleRealtimeSample(intent.getSerializableExtra(DeviceService.EXTRA_REALTIME_SAMPLE));
break;
}
}
};
private boolean pesterWithPermissions = true;
private ActivitySample currentHRSample;
public ActivitySample getCurrentHRSample() {
return currentHRSample;
}
private void setCurrentHRSample(ActivitySample sample) {
if (HeartRateUtils.getInstance().isValidHeartRateValue(sample.getHeartRate())) {
currentHRSample = sample;
refreshPairedDevices();
}
}
private void handleRealtimeSample(Serializable extra) {
if (extra instanceof ActivitySample) {
ActivitySample sample = (ActivitySample) extra;
setCurrentHRSample(sample);
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
@ -185,6 +211,7 @@ public class ControlCenterv2 extends AppCompatActivity
filterLocal.addAction(GBApplication.ACTION_LANGUAGE_CHANGE);
filterLocal.addAction(GBApplication.ACTION_QUIT);
filterLocal.addAction(DeviceManager.ACTION_DEVICES_CHANGED);
filterLocal.addAction(DeviceService.ACTION_REALTIME_SAMPLES);
LocalBroadcastManager.getInstance(this).registerReceiver(mReceiver, filterLocal);
refreshPairedDevices();

View File

@ -0,0 +1,128 @@
package nodomain.freeyourgadget.gadgetbridge.activities;
import android.app.Dialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.Serializable;
import java.util.Objects;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample;
import nodomain.freeyourgadget.gadgetbridge.model.DeviceService;
public class HeartRateDialog extends Dialog {
protected static final Logger LOG = LoggerFactory.getLogger(HeartRateDialog.class);
LinearLayout heart_rate_dialog_results_layout;
RelativeLayout heart_rate_dialog_loading_layout;
TextView heart_rate_widget_hr_value;
TextView heart_rate_widget_spo2_value;
TextView heart_rate_widget_pressure_value;
LinearLayout heart_rate_hr;
LinearLayout heart_rate_spo2;
LinearLayout heart_rate_pressure;
TextView heart_rate_dialog_label;
final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
switch (Objects.requireNonNull(intent.getAction())) {
case DeviceService.ACTION_REALTIME_SAMPLES:
setMeasurementResults(intent.getSerializableExtra(DeviceService.EXTRA_REALTIME_SAMPLE));
break;
default:
LOG.info("ignoring intent action " + intent.getAction());
break;
}
}
};
public HeartRateDialog(@NonNull Context context) {
super(context);
}
private void setMeasurementResults(Serializable result) {
heart_rate_dialog_results_layout.setVisibility(View.VISIBLE);
heart_rate_dialog_loading_layout.setVisibility(View.GONE);
heart_rate_dialog_label.setText(getContext().getString(R.string.heart_rate_result));
if (result instanceof ActivitySample) {
ActivitySample sample = (ActivitySample) result;
heart_rate_hr.setVisibility(View.VISIBLE);
if (HeartRateUtils.getInstance().isValidHeartRateValue(sample.getHeartRate()))
heart_rate_widget_hr_value.setText(String.valueOf(sample.getHeartRate()));
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
IntentFilter filter = new IntentFilter();
filter.addAction(DeviceService.ACTION_REALTIME_SAMPLES);
LocalBroadcastManager.getInstance(getContext()).registerReceiver(mReceiver, filter);
getContext().registerReceiver(mReceiver, filter);
setContentView(R.layout.heart_rate_dialog);
heart_rate_dialog_results_layout = findViewById(R.id.heart_rate_dialog_results_layout);
heart_rate_dialog_loading_layout = findViewById(R.id.heart_rate_dialog_loading_layout);
heart_rate_hr = findViewById(R.id.heart_rate_measurements1);
heart_rate_spo2 = findViewById(R.id.heart_rate_measurements2);
heart_rate_pressure = findViewById(R.id.heart_rate_measurements3);
TextView heart_rate_widget_hr_title = heart_rate_hr.findViewById(R.id.generic_widget_title);
TextView heart_rate_widget_spo2_title = heart_rate_spo2.findViewById(R.id.generic_widget_title);
TextView heart_rate_widget_pressure_title = heart_rate_pressure.findViewById(R.id.generic_widget_title);
heart_rate_widget_hr_value = heart_rate_hr.findViewById(R.id.generic_widget_value);
heart_rate_widget_spo2_value = heart_rate_spo2.findViewById(R.id.generic_widget_value);
heart_rate_widget_pressure_value = heart_rate_pressure.findViewById(R.id.generic_widget_value);
ImageView heart_rate_widget_hr_icon = heart_rate_hr.findViewById(R.id.generic_widget_icon);
ImageView heart_rate_widget_spo2_icon = heart_rate_spo2.findViewById(R.id.generic_widget_icon);
ImageView heart_rate_widget_pressure_icon = heart_rate_pressure.findViewById(R.id.generic_widget_icon);
heart_rate_widget_hr_icon.setImageResource(R.drawable.ic_heart);
heart_rate_widget_spo2_icon.setImageResource(R.drawable.ic_circle);
heart_rate_widget_pressure_icon.setImageResource(R.drawable.ic_heartrate);
heart_rate_hr.setVisibility(View.VISIBLE);
heart_rate_spo2.setVisibility(View.GONE);
heart_rate_pressure.setVisibility(View.GONE);
heart_rate_widget_hr_title.setText(R.string.heart_rate);
heart_rate_widget_spo2_title.setText(R.string.menuitem_spo2);
heart_rate_widget_pressure_title.setText(R.string.blood_pressure);
heart_rate_dialog_label = findViewById(R.id.heart_rate_dialog_title);
heart_rate_dialog_results_layout.setVisibility(View.GONE);
heart_rate_dialog_loading_layout.setVisibility(View.VISIBLE);
setOnCancelListener(new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialogInterface) {
LocalBroadcastManager.getInstance(getContext()).unregisterReceiver(mReceiver);
getContext().unregisterReceiver(mReceiver);
}
});
}
}

View File

@ -59,6 +59,8 @@ import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.activities.ActivitySummariesActivity;
import nodomain.freeyourgadget.gadgetbridge.activities.BatteryInfoActivity;
import nodomain.freeyourgadget.gadgetbridge.activities.ConfigureAlarms;
import nodomain.freeyourgadget.gadgetbridge.activities.ControlCenterv2;
import nodomain.freeyourgadget.gadgetbridge.activities.HeartRateDialog;
import nodomain.freeyourgadget.gadgetbridge.activities.VibrationActivity;
import nodomain.freeyourgadget.gadgetbridge.activities.charts.ChartsActivity;
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsActivity;
@ -69,6 +71,7 @@ import nodomain.freeyourgadget.gadgetbridge.devices.DeviceManager;
import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession;
import nodomain.freeyourgadget.gadgetbridge.entities.Device;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample;
import nodomain.freeyourgadget.gadgetbridge.model.BatteryState;
import nodomain.freeyourgadget.gadgetbridge.model.DeviceType;
import nodomain.freeyourgadget.gadgetbridge.model.RecordedDataTypes;
@ -173,6 +176,25 @@ public class GBDeviceAdapterv2 extends RecyclerView.Adapter<GBDeviceAdapterv2.Vi
}
);
holder.heartRateStatusBox.setVisibility((device.isInitialized() && coordinator.supportsHeartRateMeasurement(device)) ? View.VISIBLE : View.GONE);
if (parent.getContext() instanceof ControlCenterv2) {
ActivitySample sample = ((ControlCenterv2) parent.getContext()).getCurrentHRSample();
if (sample != null) {
holder.heartRateStatusLabel.setText(String.valueOf(sample.getHeartRate()));
} else {
holder.heartRateStatusLabel.setText("");
}
}
holder.heartRateStatusBox.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
GBApplication.deviceService().onHeartRateTest();
HeartRateDialog dialog = new HeartRateDialog(context);
dialog.show();
}
}
);
//device specific settings
holder.deviceSpecificSettingsView.setVisibility(coordinator.getSupportedDeviceSpecificSettings(device) != null ? View.VISIBLE : View.GONE);
@ -581,6 +603,10 @@ public class GBDeviceAdapterv2 extends RecyclerView.Adapter<GBDeviceAdapterv2.Vi
ImageView showActivityGraphs;
ImageView showActivityTracks;
ImageView calibrateDevice;
LinearLayout heartRateStatusBox;
ImageView heartRateIcon;
TextView heartRateStatusLabel;
ImageView deviceInfoView;
//overflow
@ -626,6 +652,9 @@ public class GBDeviceAdapterv2 extends RecyclerView.Adapter<GBDeviceAdapterv2.Vi
fmFrequencyBox = view.findViewById(R.id.device_fm_frequency_box);
fmFrequencyLabel = view.findViewById(R.id.fm_frequency);
ledColor = view.findViewById(R.id.device_led_color);
heartRateStatusBox = view.findViewById(R.id.device_heart_rate_status_box);
heartRateStatusLabel = view.findViewById(R.id.heart_rate_status);
heartRateIcon = view.findViewById(R.id.device_heart_rate_status);
}
}

View File

@ -368,6 +368,38 @@
android:scaleType="fitXY"
card_view:srcCompat="@drawable/ic_activity_unknown"
card_view:tint="@color/secondarytext" />
<LinearLayout
android:id="@+id/device_heart_rate_status_box"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_margin="3dp"
android:orientation="vertical">
<ImageView
android:id="@+id/device_heart_rate_status"
android:layout_width="40dp"
android:layout_height="40dp"
android:padding="3dp"
android:scaleType="fitXY"
card_view:srcCompat="@drawable/ic_heart"
card_view:tint="@color/secondarytext" />
<TextView
android:id="@+id/heart_rate_status"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:minWidth="36dp"
android:textColor="@color/secondarytext"
android:textStyle="bold"
tools:text="100%" />
</LinearLayout>
</com.google.android.flexbox.FlexboxLayout>
</RelativeLayout>

View File

@ -0,0 +1,84 @@
<?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:id="@+id/activity_battery_info_master_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="0dp"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:gravity="center|center_vertical"
android:minWidth="1000dp"
android:orientation="vertical">
<TextView
android:id="@+id/heart_rate_dialog_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:maxLines="2"
android:scrollHorizontally="false"
android:text="@string/getting_heart_rate"
android:textAllCaps="true"
android:textColor="@color/accent"
android:textStyle="bold" />
<RelativeLayout
android:id="@+id/heart_rate_dialog_loading_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:gravity="center"
android:orientation="vertical">
<ImageView
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_marginStart="35dp"
android:layout_marginTop="35dp"
android:contentDescription="@string/app_name"
app:srcCompat="@drawable/gadgetbridge_img" />
<ProgressBar
android:layout_width="171dp"
android:layout_height="171dp"
android:indeterminate="true" />
</RelativeLayout>
<LinearLayout
android:id="@+id/heart_rate_dialog_results_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:layout_marginBottom="30dp"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="0dp"
android:layout_marginBottom="10dp"
android:baselineAligned="false"
android:gravity="bottom|center"
android:orientation="horizontal">
<include
android:id="@+id/heart_rate_measurements1"
layout="@layout/layout_widget_generic" />
<include
android:id="@+id/heart_rate_measurements2"
layout="@layout/layout_widget_generic" />
<include
android:id="@+id/heart_rate_measurements3"
layout="@layout/layout_widget_generic" />
</LinearLayout>
</LinearLayout>
</LinearLayout>

View File

@ -0,0 +1,45 @@
<?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:id="@+id/line_layout_step"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center|top"
android:layout_marginStart="1dp"
android:layout_marginEnd="1dp"
android:layout_weight="1"
android:gravity="center|top"
android:orientation="vertical">
<ImageView
android:id="@+id/generic_widget_icon"
android:layout_width="19dp"
android:layout_height="19dp"
android:layout_gravity="center"
android:contentDescription="@string/candidate_item_device_image"
app:srcCompat="@drawable/ic_shoe_print" />
<TextView
android:id="@+id/generic_widget_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:maxLines="2"
android:scrollHorizontally="false"
android:textAllCaps="true"
android:textColor="@color/accent"
android:textStyle="bold" />
<TextView
android:id="@+id/generic_widget_value"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:fontFamily="sans-serif-black"
android:gravity="center"
android:maxLines="1"
android:scrollHorizontally="false"
android:text=""
android:textSize="24sp" />
</LinearLayout>

View File

@ -511,6 +511,9 @@
<string name="distance">Distance</string>
<string name="clock">Clock</string>
<string name="heart_rate">Heart rate</string>
<string name="blood_pressure">Blood pressure</string>
<string name="getting_heart_rate">Measuring</string>
<string name="heart_rate_result">Measurement results</string>
<string name="movement_intensity">Movement intensity</string>
<string name="battery">Battery</string>
<string name="no_limit">No limit</string>