mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge
synced 2024-06-01 19:06:06 +02:00
Compare commits
13 Commits
b09d00d555
...
85178d8d40
Author | SHA1 | Date | |
---|---|---|---|
|
85178d8d40 | ||
|
b92e1ff947 | ||
|
00faf1be6b | ||
|
e97d699c6f | ||
|
13cf48a6c5 | ||
|
2bfbb75c0b | ||
|
598549b1f5 | ||
|
7dcefd1815 | ||
|
f932dabc72 | ||
|
36911b890f | ||
|
1a07ad8ff1 | ||
|
19095caa6e | ||
|
533ce0441f |
|
@ -79,6 +79,7 @@ import nodomain.freeyourgadget.gadgetbridge.model.StressSample;
|
|||
import nodomain.freeyourgadget.gadgetbridge.model.TemperatureSample;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.ServiceDeviceSupport;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.SleepAsAndroidSender;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.FileUtils;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.GBPrefs;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
|
||||
|
||||
|
@ -290,6 +291,18 @@ public abstract class AbstractDeviceCoordinator implements DeviceCoordinator {
|
|||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getWritableExportDirectory(final GBDevice device) throws IOException {
|
||||
File dir;
|
||||
dir = new File(FileUtils.getExternalFilesDir() + File.separator + device.getAddress());
|
||||
if (!dir.isDirectory()) {
|
||||
if (!dir.mkdir()) {
|
||||
throw new IOException("Cannot create device specific directory for " + device.getName());
|
||||
}
|
||||
}
|
||||
return dir;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAppCacheSortFilename() {
|
||||
return null;
|
||||
|
|
|
@ -442,6 +442,11 @@ public interface DeviceCoordinator {
|
|||
*/
|
||||
File getAppCacheDir() throws IOException;
|
||||
|
||||
/**
|
||||
* Returns the dedicated writable export directory for this device.
|
||||
*/
|
||||
File getWritableExportDirectory(GBDevice device) throws IOException;
|
||||
|
||||
/**
|
||||
* Returns a String containing the device app sort order filename.
|
||||
*/
|
||||
|
|
|
@ -101,6 +101,12 @@ public abstract class GarminCoordinator extends AbstractBLEDeviceCoordinator {
|
|||
return new Prefs(GBApplication.getDeviceSpecificSharedPrefs(device.getAddress()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsUnicodeEmojis() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InstallHandler findInstallHandler(final Uri uri, final Context context) {
|
||||
if (supportsAgpsUpdates()) {
|
||||
final GarminAgpsInstallHandler agpsInstallHandler = new GarminAgpsInstallHandler(uri, context);
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
package nodomain.freeyourgadget.gadgetbridge.devices.garmin.instinctcrossover;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.garmin.GarminCoordinator;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class GarminInstinctCrossoverCoordinator extends GarminCoordinator {
|
||||
@Override
|
||||
protected Pattern getSupportedDeviceName() {
|
||||
return Pattern.compile("Instinct Crossover");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDeviceNameResource() {
|
||||
return R.string.devicetype_garmin_instinct_crossover;
|
||||
}
|
||||
}
|
|
@ -54,6 +54,7 @@ import nodomain.freeyourgadget.gadgetbridge.devices.garmin.instinctsolar.GarminI
|
|||
import nodomain.freeyourgadget.gadgetbridge.devices.garmin.instinct2s.GarminInstinct2SCoordinator;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.garmin.instinct2solar.GarminInstinct2SolarCoordinator;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.garmin.instinct2soltac.GarminInstinct2SolTacCoordinator;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.garmin.instinctcrossover.GarminInstinctCrossoverCoordinator;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.garmin.venu3.GarminVenu3Coordinator;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.garmin.vivoactive4s.GarminVivoActive4SCoordinator;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.garmin.vivoactive5.GarminVivoActive5Coordinator;
|
||||
|
@ -335,6 +336,7 @@ public enum DeviceType {
|
|||
GARMIN_INSTINCT_2S(GarminInstinct2SCoordinator.class),
|
||||
GARMIN_INSTINCT_2_SOLAR(GarminInstinct2SolarCoordinator.class),
|
||||
GARMIN_INSTINCT_2_SOLTAC(GarminInstinct2SolTacCoordinator.class),
|
||||
GARMIN_INSTINCT_CROSSOVER(GarminInstinctCrossoverCoordinator.class),
|
||||
GARMIN_VIVOMOVE_STYLE(GarminVivomoveStyleCoordinator.class),
|
||||
GARMIN_VENU_3(GarminVenu3Coordinator.class),
|
||||
GARMIN_VIVOACTIVE_4S(GarminVivoActive4SCoordinator.class),
|
||||
|
|
|
@ -336,6 +336,12 @@ public class FileTransferHandler implements MessageHandler {
|
|||
}
|
||||
|
||||
public String getFileName() {
|
||||
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss");
|
||||
String dateString = dateFormat.format(fileDate);
|
||||
return getFiletype().name() + "_" + dateString + "_" + getFileIndex() + (getFiletype().isFitFile() ? ".fit" : ".bin");
|
||||
}
|
||||
|
||||
public String getLegacyFileName() {
|
||||
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss");
|
||||
String dateString = dateFormat.format(fileDate);
|
||||
return getFiletype().name() + "_" + getFileIndex() + "_" + dateString + (getFiletype().isFitFile() ? ".fit" : ".bin");
|
||||
|
|
|
@ -452,6 +452,9 @@ public class GarminSupport extends AbstractBTLEDeviceSupport implements ICommuni
|
|||
}
|
||||
|
||||
private void processDownloadQueue() {
|
||||
|
||||
moveFilesFromLegacyCache(); //TODO: remove before merging
|
||||
|
||||
if (!filesToDownload.isEmpty() && !fileTransferHandler.isDownloading()) {
|
||||
if (!gbDevice.isBusy()) {
|
||||
GB.updateTransferNotification(getContext().getString(R.string.busy_task_fetch_activity_data), "", true, 0, getContext());
|
||||
|
@ -461,7 +464,7 @@ public class GarminSupport extends AbstractBTLEDeviceSupport implements ICommuni
|
|||
|
||||
try {
|
||||
FileTransferHandler.DirectoryEntry directoryEntry = filesToDownload.remove();
|
||||
while (checkFileExists(directoryEntry.getFileName())) {
|
||||
while (checkFileExists(directoryEntry.getFileName()) || checkFileExists(directoryEntry.getLegacyFileName())) {
|
||||
LOG.debug("File: {} already downloaded, not downloading again.", directoryEntry.getFileName());
|
||||
if (!getKeepActivityDataOnDevice()) // delete file from watch if already downloaded
|
||||
sendOutgoingMessage(new SetFileFlagsMessage(directoryEntry.getFileIndex(), SetFileFlagsMessage.FileFlags.ARCHIVE));
|
||||
|
@ -491,6 +494,36 @@ public class GarminSupport extends AbstractBTLEDeviceSupport implements ICommuni
|
|||
}
|
||||
}
|
||||
|
||||
private void moveFilesFromLegacyCache() { //TODO: remove before merging
|
||||
File legacyDir;
|
||||
try {
|
||||
legacyDir = new File(FileUtils.getExternalFilesDir() + "/" + FileUtils.makeValidFileName(getDevice().getName() + "_" + getDevice().getAddress()));
|
||||
|
||||
if (legacyDir.isDirectory()) {
|
||||
final File newDir = getWritableExportDirectory();
|
||||
File[] files = legacyDir.listFiles();
|
||||
|
||||
for (File file : files) {
|
||||
if (file.isFile()) {
|
||||
File destFile = new File(newDir, file.getName());
|
||||
boolean success = file.renameTo(destFile);
|
||||
if (!success) {
|
||||
LOG.error("Failed to move file {}", file.getName());
|
||||
} else {
|
||||
LOG.info("Moved file {} to new cache directory", file.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
boolean removed = legacyDir.delete();
|
||||
if (!removed) {
|
||||
LOG.error("Failed to remove legacy directory: {}", legacyDir);
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
LOG.error(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private void enableBatteryLevelUpdate() {
|
||||
final ProtobufMessage batteryLevelProtobufRequest = protocolBufferHandler.prepareProtobufRequest(GdiSmartProto.Smart.newBuilder()
|
||||
.setDeviceStatusService(
|
||||
|
@ -626,14 +659,7 @@ public class GarminSupport extends AbstractBTLEDeviceSupport implements ICommuni
|
|||
}
|
||||
|
||||
public File getWritableExportDirectory() throws IOException {
|
||||
File dir;
|
||||
dir = new File(FileUtils.getExternalFilesDir() + "/" + FileUtils.makeValidFileName(getDevice().getName() + "_" + getDevice().getAddress()));
|
||||
if (!dir.isDirectory()) {
|
||||
if (!dir.mkdir()) {
|
||||
throw new IOException("Cannot create device specific directory for " + getDevice().getName());
|
||||
}
|
||||
}
|
||||
return dir;
|
||||
return getDevice().getDeviceCoordinator().getWritableExportDirectory(getDevice());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -84,6 +84,11 @@ public class NotificationsHandler implements MessageHandler {
|
|||
callNotificationSpec.type = NotificationType.GENERIC_PHONE;
|
||||
callNotificationSpec.body = StringUtils.isEmpty(callSpec.name) ? callSpec.number : callSpec.name;
|
||||
|
||||
// add an empty bogus action to toggle the hasActions boolean. The actions are hardcoded on the watch in case of incoming calls.
|
||||
callNotificationSpec.attachedActions = new ArrayList<>();
|
||||
callNotificationSpec.attachedActions.add(0, new NotificationSpec.Action());
|
||||
|
||||
|
||||
return onNotification(callNotificationSpec);
|
||||
} else {
|
||||
if (callSpec.number != null) // this happens in debug screen
|
||||
|
@ -180,6 +185,8 @@ public class NotificationsHandler implements MessageHandler {
|
|||
final GBDeviceEventCallControl deviceEvtCallControl = new GBDeviceEventCallControl();
|
||||
switch (message.getNotificationAction()) {
|
||||
case REPLY_INCOMING_CALL:
|
||||
deviceEvtCallControl.event = GBDeviceEventCallControl.Event.REJECT;
|
||||
message.addGbDeviceEvent(deviceEvtCallControl);
|
||||
case REPLY_MESSAGES:
|
||||
deviceEvtNotificationControl.event = GBDeviceEventNotificationControl.Event.REPLY;
|
||||
deviceEvtNotificationControl.reply = message.getActionString();
|
||||
|
@ -188,23 +195,23 @@ public class NotificationsHandler implements MessageHandler {
|
|||
} else {
|
||||
deviceEvtNotificationControl.handle = mNotificationReplyAction.lookup(notificationSpec.getId()); //handle of wearable action is needed
|
||||
}
|
||||
message.setDeviceEvent(deviceEvtNotificationControl);
|
||||
message.addGbDeviceEvent(deviceEvtNotificationControl);
|
||||
break;
|
||||
case ACCEPT_INCOMING_CALL:
|
||||
deviceEvtCallControl.event = GBDeviceEventCallControl.Event.ACCEPT;
|
||||
message.setDeviceEvent(deviceEvtCallControl);
|
||||
message.addGbDeviceEvent(deviceEvtCallControl);
|
||||
break;
|
||||
case REJECT_INCOMING_CALL:
|
||||
deviceEvtCallControl.event = GBDeviceEventCallControl.Event.REJECT;
|
||||
message.setDeviceEvent(deviceEvtCallControl);
|
||||
message.addGbDeviceEvent(deviceEvtCallControl);
|
||||
break;
|
||||
case DISMISS_NOTIFICATION:
|
||||
deviceEvtNotificationControl.event = GBDeviceEventNotificationControl.Event.DISMISS;
|
||||
message.setDeviceEvent(deviceEvtNotificationControl);
|
||||
message.addGbDeviceEvent(deviceEvtNotificationControl);
|
||||
break;
|
||||
case BLOCK_APPLICATION:
|
||||
deviceEvtNotificationControl.event = GBDeviceEventNotificationControl.Event.MUTE;
|
||||
message.setDeviceEvent(deviceEvtNotificationControl);
|
||||
message.addGbDeviceEvent(deviceEvtNotificationControl);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -365,7 +365,7 @@ public class ProtocolBufferHandler implements MessageHandler {
|
|||
);
|
||||
} else {
|
||||
builder.setStatus(GdiSmsNotification.SmsNotificationService.ResponseStatus.GENERIC_ERROR);
|
||||
LOG.error("Missing canned messages data for type {}", requestedType);
|
||||
LOG.info("Missing canned messages data for type {}", requestedType);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -192,7 +192,7 @@ public class FitFile {
|
|||
if (hasCRC) {
|
||||
int incomingCrc = garminByteBufferReader.readShort();
|
||||
|
||||
if (incomingCrc != ChecksumCalculator.computeCrc(garminByteBufferReader.asReadOnlyBuffer(), 0, headerSize - 2)) {
|
||||
if (incomingCrc != 0 && incomingCrc != ChecksumCalculator.computeCrc(garminByteBufferReader.asReadOnlyBuffer(), 0, headerSize - 2)) {
|
||||
throw new IllegalArgumentException("Wrong CRC for header in FIT file");
|
||||
}
|
||||
// LOG.info("Fit File Header didn't have CRC, no check performed.");
|
||||
|
|
|
@ -138,7 +138,7 @@ public class FieldDefinitionWeatherCondition extends FieldDefinition {
|
|||
case 902: //hurricane
|
||||
case 962: //hurricane
|
||||
default:
|
||||
throw new IllegalArgumentException("Unknown weather code " + openWeatherCode);
|
||||
return 255; //invalid
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.messages;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
|
@ -21,7 +22,7 @@ public class NotificationControlMessage extends GFDIMessage {
|
|||
private NotificationsHandler.LegacyNotificationAction legacyNotificationAction;
|
||||
private NotificationsHandler.NotificationAction notificationAction;
|
||||
private String actionString;
|
||||
private GBDeviceEvent deviceEvent;
|
||||
private List<GBDeviceEvent> gbDeviceEventList;
|
||||
|
||||
public NotificationControlMessage(GarminMessage garminMessage, NotificationsHandler.NotificationCommand command, int notificationId, NotificationsHandler.NotificationAction notificationAction, String actionString) {
|
||||
this.garminMessage = garminMessage;
|
||||
|
@ -108,13 +109,17 @@ public class NotificationControlMessage extends GFDIMessage {
|
|||
return actionString;
|
||||
}
|
||||
|
||||
public void setDeviceEvent(GBDeviceEvent deviceEvent) {
|
||||
this.deviceEvent = deviceEvent;
|
||||
public void addGbDeviceEvent(GBDeviceEvent gbDeviceEvent) {
|
||||
if (null == this.gbDeviceEventList)
|
||||
this.gbDeviceEventList = new ArrayList<>();
|
||||
this.gbDeviceEventList.add(gbDeviceEvent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<GBDeviceEvent> getGBDeviceEvent() {
|
||||
return Collections.singletonList(deviceEvent);
|
||||
if (null == this.gbDeviceEventList)
|
||||
return Collections.emptyList();
|
||||
return gbDeviceEventList;
|
||||
}
|
||||
|
||||
public NotificationsHandler.LegacyNotificationAction getLegacyNotificationAction() {
|
||||
|
|
|
@ -1486,15 +1486,16 @@
|
|||
<string name="devicetype_amazfit_gts2e">Amazfit GTS 2e</string>
|
||||
<string name="devicetype_amazfit_x">Amazfit X</string>
|
||||
<string name="devicetype_zepp_e">Zepp E</string>
|
||||
<string name="devicetype_garmin_vivomove_hr">Garmin Vivomove HR</string>
|
||||
<string name="devicetype_garmin_vivomove_style">Vívomove Style</string>
|
||||
<string name="devicetype_garmin_vivomove_hr">Garmin Vívomove HR</string>
|
||||
<string name="devicetype_garmin_vivomove_style">Garmin Vívomove Style</string>
|
||||
<string name="devicetype_garmin_instinct_solar">Garmin Instinct Solar</string>
|
||||
<string name="devicetype_garmin_instinct_2s">Garmin Instinct 2S</string>
|
||||
<string name="devicetype_garmin_instinct_2_solar">Garmin Instinct 2 Solar</string>
|
||||
<string name="devicetype_garmin_instinct_2_soltac">Instinct 2 SolTac</string>
|
||||
<string name="devicetype_garmin_instinct_2_soltac">Garmin Instinct 2 SolTac</string>
|
||||
<string name="devicetype_garmin_instinct_crossover">Garmin Instinct Crossover</string>
|
||||
<string name="devicetype_garmin_forerunner_245">Garmin Forerunner 245</string>
|
||||
<string name="devicetype_garmin_vivoactive_4s">Vívoactive 4S</string>
|
||||
<string name="devicetype_garmin_vivoactive_5">Vivoactive 5</string>
|
||||
<string name="devicetype_garmin_vivoactive_4s">Garmin Vívoactive 4S</string>
|
||||
<string name="devicetype_garmin_vivoactive_5">Garmin Vívoactive 5</string>
|
||||
<string name="devicetype_vibratissimo">Vibratissimo</string>
|
||||
<string name="devicetype_um25">UM-25</string>
|
||||
<string name="devicetype_liveview">LiveView</string>
|
||||
|
|
Loading…
Reference in New Issue
Block a user