mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge.git
synced 2026-07-31 07:44:24 +02:00
Huawei: ECG activation support. No sync.
This commit is contained in:
+1
-1
@@ -117,7 +117,7 @@ public final class HuaweiConstants {
|
||||
public static final String PREF_HUAWEI_ARRHYTHMIA_SWITCH = "pref_huawei_arrhythmia_switch";
|
||||
public static final String PREF_HUAWEI_ARRHYTHMIA_AUTOMATIC = "pref_huawei_arrhythmia_automatic";
|
||||
public static final String PREF_HUAWEI_ARRHYTHMIA_ALERT = "pref_huawei_arrhythmia_alert";
|
||||
|
||||
public static final String PREF_HUAWEI_ECG_SWITCH = "pref_huawei_ecg_switch";
|
||||
|
||||
public static final String PKG_NAME = "com.huawei.devicegroupmanage";
|
||||
}
|
||||
|
||||
+21
-2
@@ -321,11 +321,12 @@ public class HuaweiCoordinator {
|
||||
if(supportsAutoStress()) {
|
||||
deviceSpecificSettings.addRootScreen(DeviceSpecificSettingsScreen.HEALTH, R.xml.devicesettings_huawei_stress);
|
||||
}
|
||||
|
||||
if(supportsArrhythmia() && isShowForceCountrySpecificFeatures(device)) {
|
||||
deviceSpecificSettings.addRootScreen(DeviceSpecificSettingsScreen.HEALTH, R.xml.devicesettings_huawei_arrhythmia);
|
||||
}
|
||||
|
||||
if(supportsECG() && isShowForceCountrySpecificFeatures(device)) {
|
||||
deviceSpecificSettings.addRootScreen(DeviceSpecificSettingsScreen.HEALTH, R.xml.devicesettings_huawei_ecg);
|
||||
}
|
||||
if(supportsThreeCircle() || supportsThreeCircleLite()) {
|
||||
deviceSpecificSettings.addRootScreen(DeviceSpecificSettingsScreen.HEALTH, R.xml.devicesettings_huawei_activity_reminders);
|
||||
}
|
||||
@@ -923,6 +924,24 @@ public class HuaweiCoordinator {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean supportsECG() {
|
||||
if (supportsExpandCapability())
|
||||
return supportsExpandCapability(106); // 226
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean supportsECGOpen() {
|
||||
if (supportsExpandCapability())
|
||||
return supportsExpandCapability(27);
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean supportsECGNotification() {
|
||||
if (supportsExpandCapability())
|
||||
return supportsExpandCapability(138);
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean supportsPromptPushMessage () {
|
||||
// do not ask for capabilities under specific condition
|
||||
// if (deviceType == 10 && deviceVersion == 73617766697368 && deviceSoftVersion == 372E312E31) -> leo device
|
||||
|
||||
+2
@@ -50,6 +50,7 @@ import static nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiConstant
|
||||
import static nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiConstants.PREF_HUAWEI_ARRHYTHMIA_SWITCH;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiConstants.PREF_HUAWEI_DEBUG_REQUEST;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiConstants.PREF_HUAWEI_CONTINUOUS_SKIN_TEMPERATURE_MEASUREMENT;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiConstants.PREF_HUAWEI_ECG_SWITCH;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiConstants.PREF_HUAWEI_HEART_RATE_HIGH_ALERT;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiConstants.PREF_HUAWEI_HEART_RATE_LOW_ALERT;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiConstants.PREF_HUAWEI_HEART_RATE_REALTIME_MODE;
|
||||
@@ -135,6 +136,7 @@ public class HuaweiSettingsCustomizer implements DeviceSpecificSettingsCustomize
|
||||
handler.addPreferenceHandlerFor(PREF_HUAWEI_SPO_LOW_ALERT);
|
||||
handler.addPreferenceHandlerFor(PREF_HUAWEI_STRESS_SWITCH);
|
||||
handler.addPreferenceHandlerFor(PREF_HUAWEI_STRESS_CALIBRATE);
|
||||
handler.addPreferenceHandlerFor(PREF_HUAWEI_ECG_SWITCH);
|
||||
|
||||
handler.addPreferenceHandlerFor(PREF_HUAWEI_ACTIVITY_REMINDER_STAND);
|
||||
handler.addPreferenceHandlerFor(PREF_HUAWEI_ACTIVITY_REMINDER_PROGRESS);
|
||||
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
/* Copyright (C) 2025 Me7c7
|
||||
|
||||
This file is part of Gadgetbridge.
|
||||
|
||||
Gadgetbridge is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Gadgetbridge is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
package nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiPacket;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiTLV;
|
||||
|
||||
public class ECG {
|
||||
public static final byte id = 0x23;
|
||||
|
||||
public static class SetECGOpen {
|
||||
public static final byte id = 0x10;
|
||||
|
||||
public static class Request extends HuaweiPacket {
|
||||
public Request(ParamsProvider paramsProvider, byte state) {
|
||||
super(paramsProvider);
|
||||
|
||||
this.serviceId = ECG.id;
|
||||
this.commandId = id;
|
||||
|
||||
this.tlv = new HuaweiTLV().put(0x1, state);
|
||||
|
||||
this.isEncrypted = true;
|
||||
this.complete = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
@@ -36,6 +36,7 @@ public class FileDownloadService2C {
|
||||
RRI,
|
||||
GPS,
|
||||
SEQUENCE_DATA,
|
||||
ECG_ANALYSIS_DATA,
|
||||
UNKNOWN; // Never use this as input
|
||||
|
||||
static byte fileTypeToByte(FileType fileType) {
|
||||
@@ -45,6 +46,7 @@ public class FileDownloadService2C {
|
||||
case RRI -> (byte) 0x10;
|
||||
case GPS -> (byte) 0x11;
|
||||
case SEQUENCE_DATA -> (byte) 0x16;
|
||||
case ECG_ANALYSIS_DATA -> (byte) 0x18;
|
||||
default -> throw new RuntimeException();
|
||||
};
|
||||
}
|
||||
@@ -56,6 +58,7 @@ public class FileDownloadService2C {
|
||||
case 0x10 -> FileType.RRI;
|
||||
case 0x11 -> FileType.GPS;
|
||||
case 0x16 -> FileType.SEQUENCE_DATA;
|
||||
case 0x18 -> FileType.ECG_ANALYSIS_DATA;
|
||||
default -> FileType.UNKNOWN;
|
||||
};
|
||||
}
|
||||
|
||||
+7
-1
@@ -124,6 +124,7 @@ public class HuaweiFileDownloadManager {
|
||||
RRI,
|
||||
GPS,
|
||||
SEQUENCE_DATA,
|
||||
ECG_ANALYSIS_DATA,
|
||||
UNKNOWN // Never for input!
|
||||
}
|
||||
|
||||
@@ -183,9 +184,14 @@ public class HuaweiFileDownloadManager {
|
||||
}
|
||||
|
||||
public static FileRequest rriFileRequest(boolean supportsRriNewSync, int startTime, int endTime, FileDownloadCallback fileDownloadCallback) {
|
||||
return new FileRequest("rrisqi_data.bin", FileType.RRI, supportsRriNewSync, startTime, endTime,fileDownloadCallback);
|
||||
return new FileRequest("rrisqi_data.bin", FileType.RRI, supportsRriNewSync, startTime, endTime, fileDownloadCallback);
|
||||
}
|
||||
|
||||
public static FileRequest ecgAnalysisFileRequest(int startTime, int endTime, FileDownloadCallback fileDownloadCallback) {
|
||||
return new FileRequest("ecg_analysis_data.bin", FileType.ECG_ANALYSIS_DATA, true, startTime, endTime, fileDownloadCallback);
|
||||
}
|
||||
|
||||
|
||||
private FileRequest(String filename, FileType fileType, int startTime, int endTime, int dictId, FileDownloadCallback fileDownloadCallback) {
|
||||
this.filename = filename;
|
||||
this.fileType = fileType;
|
||||
|
||||
+24
-3
@@ -136,6 +136,7 @@ import nodomain.freeyourgadget.gadgetbridge.model.RecordedDataTypes;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.WeatherSpec;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.datasync.HuaweiDataSyncArrhythmia;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.datasync.HuaweiDataSyncEcg;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.datasync.HuaweiDataSyncFeatureManager;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.datasync.HuaweiDataSyncEmotion;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.datasync.HuaweiDataSyncFindDevice;
|
||||
@@ -174,6 +175,7 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.Send
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.SendSetContactsRequest;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.SendNotifyHeartRateCapabilityRequest;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.SendNotifyRestHeartRateCapabilityRequest;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.SendSetECGOpenRequest;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.SendSleepBreathRequest;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.SetAutomaticHeartrateRequest;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.SetAutomaticSpoRequest;
|
||||
@@ -308,6 +310,8 @@ public class HuaweiSupportProvider {
|
||||
|
||||
private HuaweiDataSyncArrhythmia huaweiDataSyncArrhythmia = null;
|
||||
|
||||
private HuaweiDataSyncEcg huaweiDataSyncEcg = null;
|
||||
|
||||
protected HuaweiOTAManager huaweiOTAManager = new HuaweiOTAManager(this);
|
||||
|
||||
HuaweiStressCalibration stressCalibration = null;
|
||||
@@ -872,6 +876,9 @@ public class HuaweiSupportProvider {
|
||||
if (getHuaweiCoordinator().supportsArrhythmia() && getHuaweiCoordinator().isShowForceCountrySpecificFeatures(getCoordinator().getDevice())) {
|
||||
huaweiDataSyncArrhythmia = new HuaweiDataSyncArrhythmia(HuaweiSupportProvider.this);
|
||||
}
|
||||
if (getHuaweiCoordinator().supportsECG() && getHuaweiCoordinator().isShowForceCountrySpecificFeatures(getCoordinator().getDevice())) {
|
||||
huaweiDataSyncEcg = new HuaweiDataSyncEcg(HuaweiSupportProvider.this);
|
||||
}
|
||||
|
||||
// All of the below check that they are supported and otherwise they skip themselves
|
||||
final List<Request> initRequestQueue = new ArrayList<>();
|
||||
@@ -919,6 +926,7 @@ public class HuaweiSupportProvider {
|
||||
initRequestQueue.add(new GetOTAChangeLog(this));
|
||||
initRequestQueue.add(new SendCountryCodeRequest(this));
|
||||
initRequestQueue.add(new GetWorkoutCapability(this));
|
||||
initRequestQueue.add(new SendSetECGOpenRequest(this));
|
||||
initRequestQueue.add(new GetEventAlarmList(this));
|
||||
initRequestQueue.add(new GetSmartAlarmList(this));
|
||||
|
||||
@@ -972,7 +980,7 @@ public class HuaweiSupportProvider {
|
||||
appIconService.register();
|
||||
}
|
||||
}
|
||||
if(getHuaweiCoordinator().supportsContactsSync()) {
|
||||
if (getHuaweiCoordinator().supportsContactsSync()) {
|
||||
if (HuaweiP2PContactsService.getRegisteredInstance(huaweiP2PManager) == null) {
|
||||
HuaweiP2PContactsService contactsService = new HuaweiP2PContactsService(huaweiP2PManager);
|
||||
contactsService.register();
|
||||
@@ -1214,6 +1222,8 @@ public class HuaweiSupportProvider {
|
||||
break;
|
||||
case HuaweiConstants.PREF_HUAWEI_ARRHYTHMIA_ALERT:
|
||||
setArrhythmiaAlert();
|
||||
case HuaweiConstants.PREF_HUAWEI_ECG_SWITCH:
|
||||
setECG();
|
||||
break;
|
||||
case DeviceSettingsPreferenceConst.PREF_FORCE_ENABLE_SMART_ALARM:
|
||||
getAlarms();
|
||||
@@ -2482,6 +2492,17 @@ public class HuaweiSupportProvider {
|
||||
}
|
||||
}
|
||||
|
||||
private void setECG() {
|
||||
boolean ecgEnabled = GBApplication
|
||||
.getDeviceSpecificSharedPrefs(getDevice().getAddress())
|
||||
.getBoolean(HuaweiConstants.PREF_HUAWEI_ECG_SWITCH, false);
|
||||
if (huaweiDataSyncEcg != null) {
|
||||
if (!huaweiDataSyncEcg.changeECGState(ecgEnabled)) {
|
||||
LOG.error("Error to set ECG");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void storeLastStressData(HuaweiStressParser.StressData data) {
|
||||
String str = HuaweiStressParser.stressDataToJsonStr(data);
|
||||
if (TextUtils.isEmpty(str)) {
|
||||
@@ -2772,13 +2793,13 @@ public class HuaweiSupportProvider {
|
||||
}
|
||||
|
||||
public void onSetContacts(ArrayList<? extends Contact> contacts) {
|
||||
if(getHuaweiCoordinator().supportsContactsSync()) {
|
||||
if (getHuaweiCoordinator().supportsContactsSync()) {
|
||||
HuaweiP2PContactsService P2PContactsService = HuaweiP2PContactsService.getRegisteredInstance(huaweiP2PManager);
|
||||
|
||||
if (P2PContactsService != null) {
|
||||
P2PContactsService.startSync();
|
||||
}
|
||||
} else if(getHuaweiCoordinator().supportsContacts()) {
|
||||
} else if (getHuaweiCoordinator().supportsContacts()) {
|
||||
SendSetContactsRequest sendSetContactsRequest = new SendSetContactsRequest(
|
||||
this,
|
||||
contacts,
|
||||
|
||||
+92
@@ -0,0 +1,92 @@
|
||||
/* Copyright (C) 2025 Me7c7
|
||||
|
||||
This file is part of Gadgetbridge.
|
||||
|
||||
Gadgetbridge is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Gadgetbridge is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
package nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.datasync;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiTLV;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.HuaweiSupportProvider;
|
||||
|
||||
public class HuaweiDataSyncEcg implements HuaweiDataSyncCommon.DataCallback {
|
||||
private final Logger LOG = LoggerFactory.getLogger(HuaweiDataSyncEcg.class);
|
||||
|
||||
private final HuaweiSupportProvider support;
|
||||
|
||||
public static final String SRC_PKG_NAME = "hw.health.ecganalysis";
|
||||
public static final String PKG_NAME = "hw.watch.health.ecganalysis";
|
||||
|
||||
public HuaweiDataSyncEcg(HuaweiSupportProvider support) {
|
||||
LOG.info("HuaweiDataSyncEcg");
|
||||
this.support = support;
|
||||
this.support.getHuaweiDataSyncManager().registerCallback(PKG_NAME, this);
|
||||
}
|
||||
|
||||
private boolean sendCommonConfig(int configId, byte configAction, byte[] configData) {
|
||||
LOG.info("HuaweiDataSyncEcg sendCommonConfig");
|
||||
HuaweiDataSyncCommon.ConfigCommandData data = new HuaweiDataSyncCommon.ConfigCommandData();
|
||||
HuaweiDataSyncCommon.ConfigData ecgConfigData = new HuaweiDataSyncCommon.ConfigData();
|
||||
ecgConfigData.configId = configId;
|
||||
ecgConfigData.configAction = configAction;
|
||||
ecgConfigData.configData = configData;
|
||||
List<HuaweiDataSyncCommon.ConfigData> list = new ArrayList<>();
|
||||
list.add(ecgConfigData);
|
||||
data.setConfigDataList(list);
|
||||
return this.support.getHuaweiDataSyncManager().sendConfigCommand(SRC_PKG_NAME, PKG_NAME, data);
|
||||
}
|
||||
|
||||
public boolean changeECGState(boolean state) {
|
||||
HuaweiTLV tlv = new HuaweiTLV().put(0x01, (byte) (state ? 1 : 0)).put(0x02, "hw.health.ecganalysis");
|
||||
return sendCommonConfig(900300005, (byte) 1, tlv.serialize());
|
||||
}
|
||||
|
||||
public boolean activateECG() {
|
||||
return sendCommonConfig(900300006, (byte) 2, new byte[0]);
|
||||
}
|
||||
|
||||
// TODO:
|
||||
public boolean sendNotifications(boolean state) {
|
||||
HuaweiTLV tlv = new HuaweiTLV()
|
||||
.put(0x01, (byte)0) // 1 - enable, 0 - disable
|
||||
.put(0x02, (byte)0) // days as bits sun,mon,tue,wed,thu,fri,sat. 1 is set. ex. 0100001 - mon and sat. CAn be wrong, not tested.
|
||||
.put(0x03, (byte)0) // hours
|
||||
.put(0x04, (byte)0); // minutes
|
||||
return sendCommonConfig(900300014, (byte) 1, tlv.serialize());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onConfigCommand(HuaweiDataSyncCommon.ConfigCommandData data) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEventCommand(HuaweiDataSyncCommon.EventCommandData data) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDataCommand(HuaweiDataSyncCommon.DataCommandData data) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDictDataCommand(HuaweiDataSyncCommon.DictDataCommandData data) {
|
||||
}
|
||||
}
|
||||
+2
@@ -58,6 +58,7 @@ public class GetFileDownloadInitRequest extends Request {
|
||||
case RRI -> FileDownloadService2C.FileType.RRI;
|
||||
case GPS -> FileDownloadService2C.FileType.GPS;
|
||||
case SEQUENCE_DATA -> FileDownloadService2C.FileType.SEQUENCE_DATA;
|
||||
case ECG_ANALYSIS_DATA -> FileDownloadService2C.FileType.ECG_ANALYSIS_DATA;
|
||||
default -> FileDownloadService2C.FileType.UNKNOWN;
|
||||
};
|
||||
}
|
||||
@@ -69,6 +70,7 @@ public class GetFileDownloadInitRequest extends Request {
|
||||
case RRI -> HuaweiFileDownloadManager.FileType.RRI;
|
||||
case GPS -> HuaweiFileDownloadManager.FileType.GPS;
|
||||
case SEQUENCE_DATA -> HuaweiFileDownloadManager.FileType.SEQUENCE_DATA;
|
||||
case ECG_ANALYSIS_DATA -> HuaweiFileDownloadManager.FileType.ECG_ANALYSIS_DATA;
|
||||
default -> HuaweiFileDownloadManager.FileType.UNKNOWN;
|
||||
};
|
||||
}
|
||||
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
package nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiPacket;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.ECG;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.HuaweiSupportProvider;
|
||||
|
||||
public class SendSetECGOpenRequest extends Request {
|
||||
|
||||
public SendSetECGOpenRequest(HuaweiSupportProvider support) {
|
||||
super(support);
|
||||
this.serviceId = ECG.id;
|
||||
this.commandId = ECG.SetECGOpen.id;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean requestSupported() {
|
||||
return supportProvider.getHuaweiCoordinator().supportsECGOpen();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<byte[]> createRequest() throws Request.RequestCreationException {
|
||||
|
||||
try {
|
||||
return new ECG.SetECGOpen.Request(paramsProvider, (byte) 0).serialize();
|
||||
} catch (HuaweiPacket.CryptoException e) {
|
||||
throw new Request.RequestCreationException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480L480,480Q480,480 480,480Q480,480 480,480L480,480Q480,480 480,480Q480,480 480,480L480,480Q480,480 480,480Q480,480 480,480ZM80,360L80,240Q80,207 103.5,183.5Q127,160 160,160L800,160Q833,160 856.5,183.5Q880,207 880,240L880,480L800,480L800,240Q800,240 800,240Q800,240 800,240L160,240Q160,240 160,240Q160,240 160,240L160,360L80,360ZM160,800Q127,800 103.5,776.5Q80,753 80,720L80,600L160,600L160,720Q160,720 160,720Q160,720 160,720L440,720Q440,740 440,760Q440,780 440,800L160,800ZM720,900L659,848Q571,773 545.5,739.5Q520,706 520,670Q520,625 552,592.5Q584,560 630,560Q656,560 679.5,572Q703,584 720,607L720,607L720,607Q736,584 759.5,572Q783,560 810,560Q855,560 887.5,592.5Q920,625 920,670Q920,706 894,739.5Q868,773 780,848L720,900ZM720,794L748,771Q804,723 822,703.5Q840,684 840,670Q840,658 831,649Q822,640 810,640Q802,640 795.5,643.5Q789,647 780,655L720,712L659,655Q650,647 643.5,643.5Q637,640 630,640Q617,640 608.5,649Q600,658 600,670Q600,684 617.5,703.5Q635,723 691,771L720,794ZM280,680Q268,680 258.5,674.5Q249,669 244,658L175,520L80,520L80,440L200,440Q211,440 220.5,446Q230,452 235,462L280,551L404,302Q409,292 419,287Q429,282 440,282Q451,282 461,287Q471,292 476,302L544,440L680,440L680,520L520,520Q508,520 498.5,514.5Q489,509 484,498L440,410L315,658Q310,669 300.5,674.5Q291,680 280,680ZM720,717L720,717Q720,717 720,717Q720,717 720,717Q720,717 720,717Q720,717 720,717Q720,717 720,717Q720,717 720,717L720,717L720,717Q720,717 720,717Q720,717 720,717Q720,717 720,717Q720,717 720,717Q720,717 720,717Q720,717 720,717Z"/>
|
||||
</vector>
|
||||
@@ -4390,4 +4390,7 @@
|
||||
<string name="pref_huawei_pulse_wave_arrhythmia_automatic_summary">The device will automatically monitor your heart rate.</string>
|
||||
<string name="pref_huawei_pulse_wave_arrhythmia_alert_title">Arrhythmia alert</string>
|
||||
<string name="pref_huawei_pulse_wave_arrhythmia_alert_summary">Receive alert when your heart rate is abnormal</string>
|
||||
<string name="pref_screen_ecg">ECG</string>
|
||||
<string name="pref_huawei_ecg_activate_title">Activate ECG</string>
|
||||
<string name="pref_huawei_ecg_activate_summary">Activate or deactivate ECG on the device</string>
|
||||
</resources>
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.preference.PreferenceScreen
|
||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<PreferenceScreen
|
||||
android:icon="@drawable/ic_ecg"
|
||||
android:key="screen_huawei_ecg"
|
||||
android:persistent="false"
|
||||
android:title="@string/pref_screen_ecg">
|
||||
|
||||
<SwitchPreferenceCompat
|
||||
android:defaultValue="false"
|
||||
android:icon="@drawable/ic_ecg"
|
||||
android:key="pref_huawei_ecg_switch"
|
||||
android:layout="@layout/preference_checkbox"
|
||||
android:title="@string/pref_huawei_ecg_activate_title"
|
||||
android:summary="@string/pref_huawei_ecg_activate_summary" />
|
||||
|
||||
</PreferenceScreen>
|
||||
</androidx.preference.PreferenceScreen>
|
||||
Reference in New Issue
Block a user