mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge
synced 2024-12-25 10:05:49 +01:00
add Heart icon (trigger heart measurement) to device action icons
This commit is contained in:
parent
1092d1bc05
commit
e6ae5e357e
@ -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();
|
||||
|
@ -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);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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>
|
||||
|
||||
|
84
app/src/main/res/layout/heart_rate_dialog.xml
Normal file
84
app/src/main/res/layout/heart_rate_dialog.xml
Normal 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>
|
45
app/src/main/res/layout/layout_widget_generic.xml
Normal file
45
app/src/main/res/layout/layout_widget_generic.xml
Normal 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>
|
@ -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>
|
||||
|
Loading…
Reference in New Issue
Block a user