mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge.git
synced 2026-07-31 07:44:24 +02:00
Zepp OS: Music upload (unstable)
- Only works in some regions apparently (eg. uk) - Very unstable for files larger than 2MB
This commit is contained in:
+13
@@ -67,6 +67,7 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.service
|
|||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.services.ZeppOsPhoneService;
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.services.ZeppOsPhoneService;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.services.ZeppOsRemindersService;
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.services.ZeppOsRemindersService;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.services.ZeppOsShortcutCardsService;
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.services.ZeppOsShortcutCardsService;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.services.filetransfer.ZeppOsFileTransferImpl;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.util.FileUtils;
|
import nodomain.freeyourgadget.gadgetbridge.util.FileUtils;
|
||||||
|
|
||||||
public abstract class ZeppOsCoordinator extends HuamiCoordinator {
|
public abstract class ZeppOsCoordinator extends HuamiCoordinator {
|
||||||
@@ -122,6 +123,11 @@ public abstract class ZeppOsCoordinator extends HuamiCoordinator {
|
|||||||
return mapsInstallHandler;
|
return mapsInstallHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final ZeppOsMusicInstallHandler musicInstallHandler = new ZeppOsMusicInstallHandler(uri, context);
|
||||||
|
if (musicInstallHandler.isValid()) {
|
||||||
|
return musicInstallHandler;
|
||||||
|
}
|
||||||
|
|
||||||
final ZeppOsFwInstallHandler fwInstallHandler = new ZeppOsFwInstallHandler(
|
final ZeppOsFwInstallHandler fwInstallHandler = new ZeppOsFwInstallHandler(
|
||||||
uri,
|
uri,
|
||||||
context,
|
context,
|
||||||
@@ -600,6 +606,13 @@ public abstract class ZeppOsCoordinator extends HuamiCoordinator {
|
|||||||
return supportsDisplayItem(device, "map");
|
return supportsDisplayItem(device, "map");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean supportsMusicUpload(final GBDevice device) {
|
||||||
|
return supportsDisplayItem(device, "music") &&
|
||||||
|
getPrefs(device)
|
||||||
|
.getStringSet(ZeppOsFileTransferImpl.PREF_SUPPORTED_SERVICES, Collections.emptySet())
|
||||||
|
.contains("music");
|
||||||
|
}
|
||||||
|
|
||||||
private boolean supportsConfig(final GBDevice device, final ZeppOsConfigService.ConfigArg config) {
|
private boolean supportsConfig(final GBDevice device, final ZeppOsConfigService.ConfigArg config) {
|
||||||
return ZeppOsConfigService.deviceHasConfig(getPrefs(device), config);
|
return ZeppOsConfigService.deviceHasConfig(getPrefs(device), config);
|
||||||
}
|
}
|
||||||
|
|||||||
+136
@@ -0,0 +1,136 @@
|
|||||||
|
/* Copyright (C) 2025 José Rebelo
|
||||||
|
|
||||||
|
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.huami.zeppos;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.net.Uri;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.io.BufferedInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.activities.InstallActivity;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.devices.DeviceCoordinator;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.devices.InstallHandler;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.model.GenericItem;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.util.FileUtils;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.util.UriHelper;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.util.audio.AudioInfo;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.util.audio.MusicUtils;
|
||||||
|
|
||||||
|
public class ZeppOsMusicInstallHandler implements InstallHandler {
|
||||||
|
private static final Logger LOG = LoggerFactory.getLogger(ZeppOsMusicInstallHandler.class);
|
||||||
|
|
||||||
|
protected final Context mContext;
|
||||||
|
private final Uri mUri;
|
||||||
|
private final AudioInfo mAudioInfo;
|
||||||
|
|
||||||
|
public ZeppOsMusicInstallHandler(final Uri uri, final Context context) {
|
||||||
|
this.mContext = context;
|
||||||
|
this.mUri = uri;
|
||||||
|
this.mAudioInfo = MusicUtils.audioInfoFromUri(context, uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isValid() {
|
||||||
|
return mAudioInfo != null &&
|
||||||
|
"audio/mpeg".equals(mAudioInfo.getMimeType()) &&
|
||||||
|
mAudioInfo.getExtension().equals("mp3");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void validateInstallation(final InstallActivity installActivity, final GBDevice device) {
|
||||||
|
if (device.isBusy()) {
|
||||||
|
installActivity.setInfoText(device.getBusyTask());
|
||||||
|
installActivity.setInstallEnabled(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final DeviceCoordinator coordinator = device.getDeviceCoordinator();
|
||||||
|
if (!(coordinator instanceof ZeppOsCoordinator)) {
|
||||||
|
LOG.warn("Coordinator is not a ZeppOsCoordinator: {}", coordinator.getClass());
|
||||||
|
installActivity.setInfoText(mContext.getString(R.string.fwapp_install_device_not_supported));
|
||||||
|
installActivity.setInstallEnabled(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final ZeppOsCoordinator zeppOsCoordinator = (ZeppOsCoordinator) coordinator;
|
||||||
|
if (!zeppOsCoordinator.supportsMusicUpload(device)) {
|
||||||
|
installActivity.setInfoText(mContext.getString(R.string.fwapp_install_device_not_supported));
|
||||||
|
installActivity.setInstallEnabled(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!device.isInitialized()) {
|
||||||
|
installActivity.setInfoText(mContext.getString(R.string.fwapp_install_device_not_ready));
|
||||||
|
installActivity.setInstallEnabled(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final GenericItem fwItem = createInstallItem(device);
|
||||||
|
fwItem.setIcon(coordinator.getDefaultIconResource());
|
||||||
|
|
||||||
|
installActivity.setInfoText(mContext.getString(R.string.fw_upgrade_notice, mContext.getString(R.string.menuitem_music)));
|
||||||
|
installActivity.setInstallItem(fwItem);
|
||||||
|
installActivity.setInstallEnabled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStartInstall(final GBDevice device) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public AudioInfo getAudioInfo() {
|
||||||
|
return mAudioInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public byte[] readFileBytes() {
|
||||||
|
final UriHelper uriHelper;
|
||||||
|
try {
|
||||||
|
uriHelper = UriHelper.get(mUri, mContext);
|
||||||
|
} catch (final IOException e) {
|
||||||
|
LOG.error("Failed to get uri", e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
try (InputStream in = new BufferedInputStream(uriHelper.openInputStream())) {
|
||||||
|
// FIXME we should be able to stream this
|
||||||
|
return FileUtils.readAll(in, 50 * 1024 * 1024); // 50MB
|
||||||
|
} catch (final Exception e) {
|
||||||
|
LOG.error("Failed to read music file", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private GenericItem createInstallItem(final GBDevice device) {
|
||||||
|
DeviceCoordinator coordinator = device.getDeviceCoordinator();
|
||||||
|
final String firmwareName = mContext.getString(
|
||||||
|
R.string.installhandler_firmware_name,
|
||||||
|
mContext.getString(coordinator.getDeviceNameResource()),
|
||||||
|
mContext.getString(R.string.menuitem_music),
|
||||||
|
mAudioInfo.getFileName()
|
||||||
|
);
|
||||||
|
return new GenericItem(firmwareName);
|
||||||
|
}
|
||||||
|
}
|
||||||
+22
@@ -90,6 +90,7 @@ import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventScreenshot
|
|||||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventSilentMode;
|
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventSilentMode;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventUpdatePreferences;
|
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventUpdatePreferences;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.huami.zeppos.ZeppOsMapsInstallHandler;
|
import nodomain.freeyourgadget.gadgetbridge.devices.huami.zeppos.ZeppOsMapsInstallHandler;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.devices.huami.zeppos.ZeppOsMusicInstallHandler;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.SleepAsAndroidSender;
|
import nodomain.freeyourgadget.gadgetbridge.service.SleepAsAndroidSender;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiFWHelper;
|
import nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiFWHelper;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.huami.zeppos.ZeppOsCoordinator;
|
import nodomain.freeyourgadget.gadgetbridge.devices.huami.zeppos.ZeppOsCoordinator;
|
||||||
@@ -129,6 +130,7 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.operations.upd
|
|||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.operations.ZeppOsFirmwareUpdateOperation;
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.operations.ZeppOsFirmwareUpdateOperation;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.operations.ZeppOsAgpsUpdateOperation;
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.operations.ZeppOsAgpsUpdateOperation;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.operations.ZeppOsGpxRouteUploadOperation;
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.operations.ZeppOsGpxRouteUploadOperation;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.operations.ZeppOsMusicUploadOperation;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.services.ZeppOsAgpsService;
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.services.ZeppOsAgpsService;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.services.ZeppOsAlarmsService;
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.services.ZeppOsAlarmsService;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.services.ZeppOsAssistantService;
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.services.ZeppOsAssistantService;
|
||||||
@@ -739,6 +741,26 @@ public class ZeppOsSupport extends HuamiSupport implements ZeppOsFileTransferSer
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final ZeppOsMusicInstallHandler musicHandler = new ZeppOsMusicInstallHandler(uri, getContext());
|
||||||
|
if (musicHandler.isValid()) {
|
||||||
|
try {
|
||||||
|
final byte[] musicBytes = musicHandler.readFileBytes();
|
||||||
|
if (musicBytes == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
new ZeppOsMusicUploadOperation(
|
||||||
|
this,
|
||||||
|
musicHandler.getAudioInfo(),
|
||||||
|
musicBytes,
|
||||||
|
fileTransferService
|
||||||
|
).perform();
|
||||||
|
} catch (final Exception e) {
|
||||||
|
GB.toast(getContext(), "Music install error: " + e.getMessage(), Toast.LENGTH_LONG, GB.ERROR, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
final ZeppOsMapsInstallHandler mapsHandler = new ZeppOsMapsInstallHandler(uri, getContext());
|
final ZeppOsMapsInstallHandler mapsHandler = new ZeppOsMapsInstallHandler(uri, getContext());
|
||||||
if (mapsHandler.isValid()) {
|
if (mapsHandler.isValid()) {
|
||||||
mapsService.upload(mapsHandler.getFile());
|
mapsService.upload(mapsHandler.getFile());
|
||||||
|
|||||||
+114
@@ -0,0 +1,114 @@
|
|||||||
|
/* Copyright (C) 2023-2024 José Rebelo
|
||||||
|
|
||||||
|
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.huami.zeppos.operations;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.service.btle.AbstractBTLEOperation;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.service.btle.actions.SetProgressAction;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.ZeppOsSupport;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.services.ZeppOsFileTransferService;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.miband.operations.OperationStatus;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.util.audio.AudioInfo;
|
||||||
|
|
||||||
|
public class ZeppOsMusicUploadOperation extends AbstractBTLEOperation<ZeppOsSupport>
|
||||||
|
implements ZeppOsFileTransferService.Callback {
|
||||||
|
private static final Logger LOG = LoggerFactory.getLogger(ZeppOsMusicUploadOperation.class);
|
||||||
|
|
||||||
|
private final AudioInfo audioInfo;
|
||||||
|
private final byte[] fileBytes;
|
||||||
|
|
||||||
|
private final ZeppOsFileTransferService fileTransferService;
|
||||||
|
|
||||||
|
public ZeppOsMusicUploadOperation(final ZeppOsSupport support,
|
||||||
|
final AudioInfo audioInfo,
|
||||||
|
final byte[] fileBytes,
|
||||||
|
final ZeppOsFileTransferService fileTransferService) {
|
||||||
|
super(support);
|
||||||
|
this.audioInfo = audioInfo;
|
||||||
|
this.fileBytes = fileBytes;
|
||||||
|
this.fileTransferService = fileTransferService;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doPerform() throws IOException {
|
||||||
|
fileTransferService.sendFile(
|
||||||
|
String.format(
|
||||||
|
Locale.ROOT,
|
||||||
|
"music://file?songName=%s&singer=%s&end=1",
|
||||||
|
audioInfo.getTitle(),
|
||||||
|
audioInfo.getArtist()
|
||||||
|
),
|
||||||
|
audioInfo.getFileName(),
|
||||||
|
fileBytes,
|
||||||
|
false,
|
||||||
|
this
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void operationFinished() {
|
||||||
|
operationStatus = OperationStatus.FINISHED;
|
||||||
|
if (getDevice() != null && getDevice().isConnected()) {
|
||||||
|
unsetBusy();
|
||||||
|
getDevice().sendDeviceUpdateIntent(getContext());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFileUploadFinish(final boolean success) {
|
||||||
|
LOG.info("Finished music upload operation, success={}", success);
|
||||||
|
|
||||||
|
final String notificationMessage = success ?
|
||||||
|
getContext().getString(R.string.music_upload_complete) :
|
||||||
|
getContext().getString(R.string.music_upload_failed);
|
||||||
|
|
||||||
|
GB.updateInstallNotification(notificationMessage, false, 100, getContext());
|
||||||
|
|
||||||
|
operationFinished();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFileUploadProgress(final int progress) {
|
||||||
|
LOG.trace("Music upload operation progress: {}", progress);
|
||||||
|
|
||||||
|
final int progressPercent = (int) ((((float) (progress)) / fileBytes.length) * 100);
|
||||||
|
updateProgress(progressPercent);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFileDownloadFinish(final String url, final String filename, final byte[] data) {
|
||||||
|
LOG.warn("Received unexpected file: url={} filename={} length={}", url, filename, data.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateProgress(final int progressPercent) {
|
||||||
|
try {
|
||||||
|
final TransactionBuilder builder = performInitialized("send music upload progress");
|
||||||
|
builder.add(new SetProgressAction(getContext().getString(R.string.music_upload_in_progress), true, progressPercent, getContext()));
|
||||||
|
builder.queue(getQueue());
|
||||||
|
} catch (final Exception e) {
|
||||||
|
LOG.error("Failed to update progress notification", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+7
@@ -11,11 +11,13 @@ import java.io.ByteArrayOutputStream;
|
|||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.ByteOrder;
|
import java.nio.ByteOrder;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.zip.DataFormatException;
|
import java.util.zip.DataFormatException;
|
||||||
import java.util.zip.Deflater;
|
import java.util.zip.Deflater;
|
||||||
import java.util.zip.Inflater;
|
import java.util.zip.Inflater;
|
||||||
|
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventUpdatePreferences;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiService;
|
import nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiService;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
|
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.ZeppOsSupport;
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.zeppos.ZeppOsSupport;
|
||||||
@@ -39,6 +41,8 @@ public abstract class ZeppOsFileTransferImpl {
|
|||||||
protected static final byte FLAG_LAST_CHUNK = 0x02;
|
protected static final byte FLAG_LAST_CHUNK = 0x02;
|
||||||
protected static final byte FLAG_CRC = 0x04;
|
protected static final byte FLAG_CRC = 0x04;
|
||||||
|
|
||||||
|
public static final String PREF_SUPPORTED_SERVICES = "zepp_os_file_transfer_supported_service";
|
||||||
|
|
||||||
protected final ZeppOsFileTransferService mFileTransferService;
|
protected final ZeppOsFileTransferService mFileTransferService;
|
||||||
protected final ZeppOsSupport mSupport;
|
protected final ZeppOsSupport mSupport;
|
||||||
|
|
||||||
@@ -108,6 +112,7 @@ public abstract class ZeppOsFileTransferImpl {
|
|||||||
for (int i = 0; i < numServices; i++) {
|
for (int i = 0; i < numServices; i++) {
|
||||||
supportedServices.add(StringUtils.untilNullTerminator(buf));
|
supportedServices.add(StringUtils.untilNullTerminator(buf));
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: 3 unknown bytes for v3
|
// TODO: 3 unknown bytes for v3
|
||||||
|
|
||||||
final TransactionBuilder builder = mSupport.createTransactionBuilder("enable file transfer v3 notifications");
|
final TransactionBuilder builder = mSupport.createTransactionBuilder("enable file transfer v3 notifications");
|
||||||
@@ -116,6 +121,8 @@ public abstract class ZeppOsFileTransferImpl {
|
|||||||
builder.queue(mSupport.getQueue());
|
builder.queue(mSupport.getQueue());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mSupport.evaluateGBDeviceEvent(new GBDeviceEventUpdatePreferences(PREF_SUPPORTED_SERVICES, new HashSet<>(supportedServices)));
|
||||||
|
|
||||||
LOG.info(
|
LOG.info(
|
||||||
"Got file transfer service: version={}, chunkSize={}, compressedChunkSize={}, supportedServices=[{}]",
|
"Got file transfer service: version={}, chunkSize={}, compressedChunkSize={}, supportedServices=[{}]",
|
||||||
mVersion,
|
mVersion,
|
||||||
|
|||||||
+2
@@ -41,6 +41,8 @@ public class ZeppOsFileTransferV3 extends ZeppOsFileTransferImpl {
|
|||||||
|
|
||||||
private static final byte CMD_DATA_V3_SEND = 0x12;
|
private static final byte CMD_DATA_V3_SEND = 0x12;
|
||||||
private static final byte CMD_DATA_V3_ACK = 0x13;
|
private static final byte CMD_DATA_V3_ACK = 0x13;
|
||||||
|
private static final byte CMD_CANCEL_TRANSFER_REQ = 0x20; // 20:01
|
||||||
|
private static final byte CMD_CANCEL_TRANSFER_ACK = 0x21; // 21:01:00
|
||||||
|
|
||||||
private static final long TRANSFER_TIMEOUT_THRESHOLD_MILLIS = 5_000L;
|
private static final long TRANSFER_TIMEOUT_THRESHOLD_MILLIS = 5_000L;
|
||||||
|
|
||||||
|
|||||||
@@ -952,6 +952,9 @@
|
|||||||
<string name="map_upload_failed">Map upload failed</string>
|
<string name="map_upload_failed">Map upload failed</string>
|
||||||
<string name="map_upload_complete">Map upload complete</string>
|
<string name="map_upload_complete">Map upload complete</string>
|
||||||
<string name="map_upload_in_progress">Uploading map</string>
|
<string name="map_upload_in_progress">Uploading map</string>
|
||||||
|
<string name="music_upload_failed">Music upload failed</string>
|
||||||
|
<string name="music_upload_complete">Music upload complete</string>
|
||||||
|
<string name="music_upload_in_progress">Uploading music</string>
|
||||||
<string name="updatefirmwareoperation_failed_low_mtu">Current MTU of %1$d is too low, please enable high MTU in the device settings and disconnect/re-connect the device.</string>
|
<string name="updatefirmwareoperation_failed_low_mtu">Current MTU of %1$d is too low, please enable high MTU in the device settings and disconnect/re-connect the device.</string>
|
||||||
<string name="chart_steps">Steps</string>
|
<string name="chart_steps">Steps</string>
|
||||||
<string name="calories">Calories</string>
|
<string name="calories">Calories</string>
|
||||||
|
|||||||
Reference in New Issue
Block a user