From 6cbd6e892cd4398268778106e190f6c7265cd8df Mon Sep 17 00:00:00 2001 From: Arjan Schrijver Date: Thu, 8 Jan 2026 22:32:14 +0100 Subject: [PATCH] InfiniTime: Improve user feedback on uploading resources --- .../devices/pinetime/PineTimeJFConstants.java | 2 + .../btle/profiles/adablefs/AdaBleFsProfile.kt | 38 +++++++++++++----- .../devices/pinetime/PineTimeJFSupport.java | 39 +++++++++++-------- app/src/main/res/values/strings.xml | 2 + 4 files changed, 56 insertions(+), 25 deletions(-) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/pinetime/PineTimeJFConstants.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/pinetime/PineTimeJFConstants.java index bc10e5bbab..eff3573006 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/pinetime/PineTimeJFConstants.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/pinetime/PineTimeJFConstants.java @@ -64,4 +64,6 @@ public class PineTimeJFConstants { public static final UUID UUID_CHARACTERISTIC_HEART_RATE_MEASUREMENT = UUID.fromString("00002a37-0000-1000-8000-00805f9b34fb"); public static final String ACTION_UPLOAD_PROGRESS = "PINETIME_UPLOAD_PROGRESS"; + public static final String ACTION_UPLOAD_FINISHED = "PINETIME_UPLOAD_FINISHED"; + public static final String ACTION_UPLOAD_ERROR = "PINETIME_UPLOAD_ERROR"; } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/profiles/adablefs/AdaBleFsProfile.kt b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/profiles/adablefs/AdaBleFsProfile.kt index d265cae97c..b6571ed3f5 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/profiles/adablefs/AdaBleFsProfile.kt +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/profiles/adablefs/AdaBleFsProfile.kt @@ -169,7 +169,7 @@ class AdaBleFsProfile(support: T) : Abstrac try { currentAction = adaBleFsQueue.removeFirst() } catch (e: NoSuchElementException) { - notify(createIntent(false)) + notify(createSuccessIntent()) return } currentActionNr++ @@ -187,6 +187,17 @@ class AdaBleFsProfile(support: T) : Abstrac builder.notify(UUID_CHARACTERISTIC_FS_TRANSFER, enable) } + override fun onCharacteristicWrite( + gatt: BluetoothGatt?, + characteristic: BluetoothGattCharacteristic?, + status: Int + ): Boolean { + if (status == 0x08) { // BluetoothGatt.GATT_INSUFFICIENT_AUTHORIZATION + notify(createErrorIntent(context.getString(R.string.infinitime_filesystem_access_disabled))) + } + return super.onCharacteristicWrite(gatt, characteristic, status) + } + override fun onCharacteristicChanged( gatt: BluetoothGatt?, characteristic: BluetoothGattCharacteristic?, @@ -294,7 +305,7 @@ class AdaBleFsProfile(support: T) : Abstrac bytesWritten = 0 LOG.info("Sending start packet for ${currentAction!!.filenameorpath} (${currentAction!!.data.size} bytes)") - notify(createIntent(true)) + notify(createProgressIntent()) currentBuilder = performInitialized("Upload file start") currentBuilder?.write(UUID_CHARACTERISTIC_FS_TRANSFER, *buffer.array()) currentBuilder?.queue() @@ -315,7 +326,7 @@ class AdaBleFsProfile(support: T) : Abstrac bytesProgress += toSendSize val percentage = ((bytesProgress.toFloat() / bytesTotal.toFloat()) * 100).roundToInt() LOG.info("Sending chunk of $toSendSize bytes for ${currentAction!!.filenameorpath}, at offset $bytesWritten") - notify(createIntent(true)) + notify(createProgressIntent()) currentBuilder = performInitialized("Upload file chunk") currentBuilder?.write(UUID_CHARACTERISTIC_FS_TRANSFER, *buffer.array()) currentBuilder?.setProgress(R.string.uploading_resources, true, percentage) @@ -337,7 +348,7 @@ class AdaBleFsProfile(support: T) : Abstrac buffer.putShort(pathBytes.size.toShort()) buffer.put(pathBytes) - notify(createIntent(true)) + notify(createProgressIntent()) currentBuilder = performInitialized("Delete file or directory: ${currentAction!!.filenameorpath}") currentBuilder?.write(UUID_CHARACTERISTIC_FS_TRANSFER, *buffer.array()) currentBuilder?.queue() @@ -355,7 +366,7 @@ class AdaBleFsProfile(support: T) : Abstrac buffer.putLong(unixTime) buffer.put(pathBytes) - notify(createIntent(true)) + notify(createProgressIntent()) currentBuilder = performInitialized("Create directory") currentBuilder?.write(UUID_CHARACTERISTIC_FS_TRANSFER, *buffer.array()) currentBuilder?.queue() @@ -374,7 +385,7 @@ class AdaBleFsProfile(support: T) : Abstrac buffer.put(PADDING_BYTE) buffer.put(secondPathBytes) - notify(createIntent(true)) + notify(createProgressIntent()) currentBuilder = performInitialized("Move file or directory") currentBuilder?.write(UUID_CHARACTERISTIC_FS_TRANSFER, *buffer.array()) currentBuilder?.queue() @@ -390,15 +401,14 @@ class AdaBleFsProfile(support: T) : Abstrac buffer.putShort(pathBytes.size.toShort()) buffer.put(pathBytes) - notify(createIntent(true)) + notify(createProgressIntent()) currentBuilder = performInitialized("List directory") currentBuilder?.write(UUID_CHARACTERISTIC_FS_TRANSFER, *buffer.array()) currentBuilder?.queue() } - private fun createIntent(ongoing: Boolean): Intent { + private fun createProgressIntent(): Intent { val intent = Intent(PineTimeJFConstants.ACTION_UPLOAD_PROGRESS) - intent.putExtra("ongoing", ongoing) intent.putExtra("filename", currentAction!!.filenameorpath) intent.putExtra("currentAction", currentAction!!.method.toString()) intent.putExtra("currentActionNr", currentActionNr) @@ -406,4 +416,14 @@ class AdaBleFsProfile(support: T) : Abstrac return intent } + private fun createSuccessIntent(): Intent { + val intent = Intent(PineTimeJFConstants.ACTION_UPLOAD_FINISHED) + return intent + } + + private fun createErrorIntent(errorMsg: String): Intent { + val intent = Intent(PineTimeJFConstants.ACTION_UPLOAD_ERROR) + intent.putExtra("errorMsg", errorMsg) + return intent + } } \ No newline at end of file diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pinetime/PineTimeJFSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pinetime/PineTimeJFSupport.java index 420b93b3de..e5d114a4ee 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pinetime/PineTimeJFSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pinetime/PineTimeJFSupport.java @@ -269,26 +269,33 @@ public class PineTimeJFSupport extends AbstractBTLESingleDeviceSupport implement addSupportedService(AdaBleFsProfile.UUID_SERVICE_FS); IntentListener mListener = intent -> { + LocalBroadcastManager manager = LocalBroadcastManager.getInstance(getContext()); String action = intent.getAction(); if (DeviceInfoProfile.ACTION_DEVICE_INFO.equals(action)) { handleDeviceInfo(intent.getParcelableExtra(DeviceInfoProfile.EXTRA_DEVICE_INFO)); } else if (BatteryInfoProfile.ACTION_BATTERY_INFO.equals(action)) { handleBatteryInfo(intent.getParcelableExtra(BatteryInfoProfile.EXTRA_BATTERY_INFO)); } else if (PineTimeJFConstants.ACTION_UPLOAD_PROGRESS.equals(action)) { - LocalBroadcastManager manager = LocalBroadcastManager.getInstance(getContext()); - boolean ongoing = intent.getBooleanExtra("ongoing", true); - String progressText = ""; - if (ongoing) { - String filename = intent.getStringExtra("filename"); - String currentAction = intent.getStringExtra("currentAction"); - int currentActionNr = intent.getIntExtra("currentActionNr", 0); - int allActionsCount = intent.getIntExtra("allActionsCount", 0); - progressText = String.format("Performing action %d of %d\n%s %s", currentActionNr, allActionsCount, currentAction, filename); - } else { - progressText = getContext().getString(R.string.devicestatus_upload_completed); - gbDevice.unsetBusyTask(); - } + String filename = intent.getStringExtra("filename"); + String currentAction = intent.getStringExtra("currentAction"); + int currentActionNr = intent.getIntExtra("currentActionNr", 0); + int allActionsCount = intent.getIntExtra("allActionsCount", 0); + String progressText = String.format(getContext().getString(R.string.infinitime_resource_upload_progress_status), currentActionNr, allActionsCount, currentAction, filename); manager.sendBroadcast(new Intent(GB.ACTION_SET_PROGRESS_TEXT).putExtra(GB.DISPLAY_MESSAGE_MESSAGE, progressText)); + } else if (PineTimeJFConstants.ACTION_UPLOAD_FINISHED.equals(action)) { + String progressText = getContext().getString(R.string.devicestatus_upload_completed); + manager.sendBroadcast(new Intent(GB.ACTION_SET_PROGRESS_TEXT).putExtra(GB.DISPLAY_MESSAGE_MESSAGE, progressText)); + manager.sendBroadcast(new Intent(GB.ACTION_SET_PROGRESS_BAR).putExtra(GB.PROGRESS_BAR_INDETERMINATE, false)); + manager.sendBroadcast(new Intent(GB.ACTION_SET_PROGRESS_BAR).putExtra(GB.PROGRESS_BAR_PROGRESS, 100)); + GB.updateInstallNotification(progressText, false, 0, getContext()); + gbDevice.unsetBusyTask(); + } else if (PineTimeJFConstants.ACTION_UPLOAD_ERROR.equals(action)) { + String errorMsg = intent.getStringExtra("errorMsg"); + manager.sendBroadcast(new Intent(GB.ACTION_SET_PROGRESS_TEXT).putExtra(GB.DISPLAY_MESSAGE_MESSAGE, errorMsg)); + manager.sendBroadcast(new Intent(GB.ACTION_SET_PROGRESS_BAR).putExtra(GB.PROGRESS_BAR_INDETERMINATE, false)); + manager.sendBroadcast(new Intent(GB.ACTION_SET_PROGRESS_BAR).putExtra(GB.PROGRESS_BAR_PROGRESS, 0)); + GB.updateInstallNotification(getContext().getString(R.string.devicestatus_upload_failed), false, 0, getContext()); + gbDevice.unsetBusyTask(); } }; @@ -406,8 +413,8 @@ public class PineTimeJFSupport extends AbstractBTLESingleDeviceSupport implement iconname = "uturn"; break; case NavigationInfoSpec.ACTION_ROUNDABOUT_RIGHT: - iconname = "roundabout-right"; - break; + iconname = "roundabout-right"; + break; case NavigationInfoSpec.ACTION_ROUNDABOUT_LEFT: iconname = "roundabout-left"; break; @@ -522,7 +529,7 @@ public class PineTimeJFSupport extends AbstractBTLESingleDeviceSupport implement } else { LocalBroadcastManager.getInstance(getContext()).sendBroadcast(new Intent(GB.ACTION_SET_PROGRESS_TEXT) .putExtra(GB.DISPLAY_MESSAGE_MESSAGE, getContext().getString(R.string.fwinstaller_firmware_not_compatible_to_device))); - } + } } catch (Exception ex) { GB.toast(getContext(), getContext().getString(R.string.updatefirmwareoperation_write_failed) + ":" + ex.getLocalizedMessage(), Toast.LENGTH_LONG, GB.ERROR, ex); if (gbDevice.isBusy() && gbDevice.getBusyTask().equals("firmware upgrade")) { diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 99cba16dc4..8665ccf74b 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -4623,4 +4623,6 @@ Permission denied: %1$s. Please check Health Connect permissions. Sleep Session from %1$s Sleep data from Gadgetbridge device: %1$s. + Filesystem access is disabled in InfiniTime + Performing action %d of %d\n%s %s