InfiniTime: Improve user feedback on uploading resources

This commit is contained in:
Arjan Schrijver
2026-01-17 21:10:31 +01:00
committed by Arjan Schrijver
parent 2765d78899
commit 6cbd6e892c
4 changed files with 56 additions and 25 deletions
@@ -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";
}
@@ -169,7 +169,7 @@ class AdaBleFsProfile<T : AbstractBTLESingleDeviceSupport>(support: T) : Abstrac
try {
currentAction = adaBleFsQueue.removeFirst()
} catch (e: NoSuchElementException) {
notify(createIntent(false))
notify(createSuccessIntent())
return
}
currentActionNr++
@@ -187,6 +187,17 @@ class AdaBleFsProfile<T : AbstractBTLESingleDeviceSupport>(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<T : AbstractBTLESingleDeviceSupport>(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<T : AbstractBTLESingleDeviceSupport>(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<T : AbstractBTLESingleDeviceSupport>(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<T : AbstractBTLESingleDeviceSupport>(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<T : AbstractBTLESingleDeviceSupport>(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<T : AbstractBTLESingleDeviceSupport>(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<T : AbstractBTLESingleDeviceSupport>(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
}
}
@@ -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")) {
+2
View File
@@ -4623,4 +4623,6 @@
<string name="health_connect_permission_denied">Permission denied: %1$s. Please check Health Connect permissions.</string>
<string name="health_connect_sleep_session_title">Sleep Session from %1$s</string>
<string name="health_connect_sleep_session_notes">Sleep data from Gadgetbridge device: %1$s.</string>
<string name="infinitime_filesystem_access_disabled">Filesystem access is disabled in InfiniTime</string>
<string name="infinitime_resource_upload_progress_status">Performing action %d of %d\n%s %s</string>
</resources>