diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/ResourceUploadProgressListener.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/ResourceUploadProgressListener.java
deleted file mode 100644
index 8e4cf30131..0000000000
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/ResourceUploadProgressListener.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/* Copyright (C) 2016-2022 Andreas Shimokawa, Carsten Pfeiffer, JF, Sebastian
- Kranz, Taavi Eomäe
-
- 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 . */
-package nodomain.freeyourgadget.gadgetbridge.service.btle;
-
-public class ResourceUploadProgressListener {
- public void onDeviceConnecting(final String mac) { }
- public void onDeviceConnected(final String mac) { }
- public void onUploadStarting(final String mac) { }
- public void onDeviceDisconnecting(final String mac) { }
- public void onDeviceDisconnected(final String mac) { }
- public void onUploadCompleted(final String mac) { }
- public void onUploadAborted(final String mac) { }
- public void onError(final String mac, int error, int errorType, final String message) { }
- public void onProgressChanged(final String mac,
- int percent,
- float speed,
- float averageSpeed,
- int segment,
- int totalSegments) { }
-}
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 09ad1faddd..d265cae97c 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
@@ -21,6 +21,7 @@ import android.bluetooth.BluetoothGattCharacteristic
import android.content.Context
import android.content.Intent
import android.net.Uri
+import com.google.protobuf.LazyStringArrayList.emptyList
import nodomain.freeyourgadget.gadgetbridge.R
import nodomain.freeyourgadget.gadgetbridge.devices.pinetime.PineTimeJFConstants
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice
@@ -29,7 +30,6 @@ import nodomain.freeyourgadget.gadgetbridge.service.btle.BtLEQueue
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder
import nodomain.freeyourgadget.gadgetbridge.service.btle.profiles.AbstractBleProfile
import nodomain.freeyourgadget.gadgetbridge.util.GBZipFile
-import nodomain.freeyourgadget.gadgetbridge.util.RemoteFileSystemCache
import nodomain.freeyourgadget.gadgetbridge.util.UriHelper
import nodomain.freeyourgadget.gadgetbridge.util.ZipFileException
import org.json.JSONObject
@@ -74,35 +74,79 @@ class AdaBleFsProfile(support: T) : Abstrac
private var currentBuilder: TransactionBuilder? = null
private var device: GBDevice? = null
private val adaBleFsQueue: ArrayDeque = ArrayDeque()
- private var offsetToWriteTo = 0
- private var chunkSize = 240 // Maximum possible within MTU
- private val remoteFs = RemoteFileSystemCache()
+ private var currentAction: AdaBleFsAction? = null
+ private var bytesWritten = 0
+ private var bytesProgress = 0
+ private var bytesTotal = 0
+ private var chunkSize = 235 // Maximum possible within MTU
+ private var watchFsContents: MutableList = ArrayList()
private var listingDirectory: List = emptyList()
private var allActionsCount = 0
private var currentActionNr = 0
fun loadResources(uri: Uri, context: Context, queue: BtLEQueue) {
btleQueue = queue
+ watchFsContents = ArrayList()
try {
+ // Retrieve directory listing for finding and deleting existing files
+ adaBleFsQueue.addFirst(
+ AdaBleFsAction(
+ AdaBleFsAction.Method.LIST_DIRECTORY,
+ "/"
+ )
+ )
+ allActionsCount++
val uriHelper = UriHelper.get(uri, context)
val zipPackage = GBZipFile(uriHelper.openInputStream())
val resourcesManifest = JSONObject(String(zipPackage.getFileFromZip("resources.json")))
- val resources = resourcesManifest.getJSONArray("resources")
- // TODO: add support for deleting files in the obsolete_files array
+ // Delete files declared obsolete in the manifest
+ var resources = resourcesManifest.getJSONArray("obsolete_files")
for (i in 0 until resources.length()) {
val fileItem = resources.getJSONObject(i)
val filePath = fileItem.getString("path")
- val fileName = fileItem.getString("filename")
- LOG.info("Adding to queue: UPLOAD, $fileName, $filePath")
+ LOG.info("Adding to queue: DELETE (obsolete), $filePath")
adaBleFsQueue.add(
AdaBleFsAction(
- AdaBleFsAction.Method.UPLOAD,
- filePath,
- zipPackage.getFileFromZip(fileName)
+ AdaBleFsAction.Method.DELETE,
+ filePath
)
)
allActionsCount += 1
}
+ // Upload new/updated resource files
+ resources = resourcesManifest.getJSONArray("resources")
+ for (i in 0 until resources.length()) {
+ val fileItem = resources.getJSONObject(i)
+ val filePath = fileItem.getString("path")
+ val fileName = fileItem.getString("filename")
+ LOG.info("Adding to queue: DELETE, $filePath")
+ adaBleFsQueue.add(
+ AdaBleFsAction(
+ AdaBleFsAction.Method.DELETE,
+ filePath
+ )
+ )
+ allActionsCount += 1
+ val fileData = zipPackage.getFileFromZip(fileName)
+ bytesTotal += fileData.size
+ LOG.info("Adding to queue: UPLOAD, $fileName, $filePath, ${fileData.size} bytes")
+ adaBleFsQueue.add(
+ AdaBleFsAction(
+ AdaBleFsAction.Method.UPLOAD,
+ filePath,
+ fileData
+ )
+ )
+ allActionsCount += 1
+ }
+ // This directory listing is only useful to get some data in the log
+ adaBleFsQueue.add(
+ AdaBleFsAction(
+ AdaBleFsAction.Method.LIST_DIRECTORY,
+ "/"
+ )
+ )
+ allActionsCount++
} catch (e: ZipFileException) {
LOG.error("Unable to read the zip file.", e)
} catch (e: FileNotFoundException) {
@@ -122,17 +166,19 @@ class AdaBleFsProfile(support: T) : Abstrac
@Throws(IOException::class)
private fun startNextAdaFsAction() {
- val nextAction = adaBleFsQueue.firstOrNull()// ?: return
- if (nextAction == null) {
- notify(createIntent("", false))
+ try {
+ currentAction = adaBleFsQueue.removeFirst()
+ } catch (e: NoSuchElementException) {
+ notify(createIntent(false))
return
}
currentActionNr++
- when (nextAction.method) {
+ when (currentAction!!.method) {
AdaBleFsAction.Method.UPLOAD -> uploadFileStart()
AdaBleFsAction.Method.DELETE -> deleteFile()
+ AdaBleFsAction.Method.LIST_DIRECTORY -> listDirectoryFromQueue()
else -> {
- LOG.warn("Skipping unimplemented AdaBleFsAction method ${nextAction.method}")
+ LOG.warn("Skipping unimplemented AdaBleFsAction method ${currentAction!!.method}")
}
}
}
@@ -176,7 +222,6 @@ class AdaBleFsProfile(support: T) : Abstrac
else -> LOG.warn("Unknown BLE FS response: ${returned[0]}")
}
if (actionResult) {
- adaBleFsQueue.removeFirst()
startNextAdaFsAction()
}
}
@@ -199,7 +244,21 @@ class AdaBleFsProfile(support: T) : Abstrac
val fileSize = returned.sliceArray(24..27).foldIndexed(0) { i, acc, b -> acc or ((b.toInt() and 0xFF) shl (8 * i)) }
val path = String(returned.copyOfRange(28, 28 + pathLength), Charsets.UTF_8)
- remoteFs.updateEntry(path, AdaFsEntry(path, isDirectory, fileSize, timestamp, flags))
+ val absPath = "/" + (listingDirectory + path).filter { it.isNotEmpty() }.joinToString("/")
+ LOG.debug("LISTDIR: $absPath, $fileSize bytes")
+ if (path.isNotEmpty() && path != "." && path != "..") {
+ watchFsContents.add(absPath)
+ if (isDirectory) {
+ LOG.info("Adding to queue: LISTDIR, $absPath")
+ adaBleFsQueue.addFirst(
+ AdaBleFsAction(
+ AdaBleFsAction.Method.LIST_DIRECTORY,
+ absPath
+ )
+ )
+ allActionsCount++
+ }
+ }
return entryNum == totalEntries
}
@@ -210,28 +269,32 @@ class AdaBleFsProfile(support: T) : Abstrac
@Throws(IOException::class)
private fun checkContinueFileUpload(returned: ByteArray): Boolean {
checkStatus(returned[1])
- offsetToWriteTo = ByteBuffer.wrap(returned, 4, 4).order(ByteOrder.LITTLE_ENDIAN).int
+ val offset = ByteBuffer.wrap(returned, 4, 4).order(ByteOrder.LITTLE_ENDIAN).int
val sizeLeft = ByteBuffer.wrap(returned, 16, 4).order(ByteOrder.LITTLE_ENDIAN).int
- LOG.debug("Status from watch: ${returned[1]}, offset=$offsetToWriteTo, sizeLeft=$sizeLeft")
- if (sizeLeft > 0) uploadNextFileChunk()
- return sizeLeft == 0
+ LOG.debug("Status from watch: ${returned[1]}, offset=$offset, sizeLeft=$sizeLeft")
+ if (bytesWritten < currentAction!!.data.size) {
+ uploadNextFileChunk()
+ return false
+ }
+ return true
}
@Throws(IOException::class)
private fun uploadFileStart() {
- val nextAction = adaBleFsQueue.first()
val unixTime = System.currentTimeMillis() / 1000L
- val pathBytes = nextAction.filenameorpath.toByteArray()
+ val pathBytes = currentAction!!.filenameorpath.toByteArray()
val buffer = ByteBuffer.allocate(1 + 1 + 2 + 4 + 8 + 4 + pathBytes.size).order(ByteOrder.LITTLE_ENDIAN)
buffer.put(REQUEST_WRITE_FILE_START)
buffer.put(PADDING_BYTE)
buffer.putShort(pathBytes.size.toShort())
buffer.putInt(0)
buffer.putLong(unixTime)
- buffer.putInt(nextAction.data.size)
+ buffer.putInt(currentAction!!.data.size)
buffer.put(pathBytes)
- LOG.info("Sending start packet for ${nextAction.filenameorpath} (${nextAction.data.size} bytes)")
+ bytesWritten = 0
+ LOG.info("Sending start packet for ${currentAction!!.filenameorpath} (${currentAction!!.data.size} bytes)")
+ notify(createIntent(true))
currentBuilder = performInitialized("Upload file start")
currentBuilder?.write(UUID_CHARACTERISTIC_FS_TRANSFER, *buffer.array())
currentBuilder?.queue()
@@ -239,46 +302,51 @@ class AdaBleFsProfile(support: T) : Abstrac
@Throws(IOException::class)
private fun uploadNextFileChunk() {
- val nextAction = adaBleFsQueue.first()
- val toSendSize = minOf(chunkSize, nextAction.data.size - offsetToWriteTo)
+ val toSendSize = minOf(chunkSize, currentAction!!.data.size - bytesWritten)
val buffer = ByteBuffer.allocate(2 + 2 + 4 + 4 + toSendSize).order(ByteOrder.LITTLE_ENDIAN)
buffer.put(REQUEST_WRITE_FILE_DATA)
buffer.put(REQUEST_CONTINUED)
buffer.put(PADDING_BYTE)
buffer.put(PADDING_BYTE)
- buffer.putInt(offsetToWriteTo + toSendSize) // next chunk offset
+ buffer.putInt(bytesWritten)
buffer.putInt(toSendSize)
- buffer.put(nextAction.data, offsetToWriteTo, toSendSize)
+ buffer.put(currentAction!!.data, bytesWritten, toSendSize)
- val percentage = (((offsetToWriteTo+toSendSize).toFloat() / nextAction.data.size.toFloat()) * 100).roundToInt()
- LOG.info("Sending chunk of $toSendSize bytes ($percentage%) for ${nextAction.filenameorpath}, next chunk starts at offset $offsetToWriteTo")
- notify(createIntent(nextAction.filenameorpath, true))
+ 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))
currentBuilder = performInitialized("Upload file chunk")
currentBuilder?.write(UUID_CHARACTERISTIC_FS_TRANSFER, *buffer.array())
currentBuilder?.setProgress(R.string.uploading_resources, true, percentage)
currentBuilder?.queue()
+ bytesWritten += toSendSize
}
@Throws(IOException::class)
private fun deleteFile() {
- val nextAction = adaBleFsQueue.first()
- val pathBytes = nextAction.filenameorpath.toByteArray()
+ if (!watchFsContents.contains(currentAction!!.filenameorpath)) {
+ LOG.info("Not deleting non-existent file: ${currentAction!!.filenameorpath}")
+ startNextAdaFsAction()
+ return
+ }
+ val pathBytes = currentAction!!.filenameorpath.toByteArray()
val buffer = ByteBuffer.allocate(2 + 2 + pathBytes.size).order(ByteOrder.LITTLE_ENDIAN)
buffer.put(REQUEST_DELETE_FILE)
buffer.put(PADDING_BYTE)
buffer.putShort(pathBytes.size.toShort())
buffer.put(pathBytes)
- currentBuilder = performInitialized("Delete file or directory")
+ notify(createIntent(true))
+ currentBuilder = performInitialized("Delete file or directory: ${currentAction!!.filenameorpath}")
currentBuilder?.write(UUID_CHARACTERISTIC_FS_TRANSFER, *buffer.array())
currentBuilder?.queue()
}
@Throws(IOException::class)
private fun makeDirectory() {
- val nextAction = adaBleFsQueue.first()
val unixTime = System.currentTimeMillis() / 1000L
- val pathBytes = nextAction.filenameorpath.toByteArray()
+ val pathBytes = currentAction!!.filenameorpath.toByteArray()
val buffer = ByteBuffer.allocate(2 + 2 + 4 + 8 + pathBytes.size).order(ByteOrder.LITTLE_ENDIAN)
buffer.put(REQUEST_MAKE_DIRECTORY)
buffer.put(PADDING_BYTE)
@@ -287,6 +355,7 @@ class AdaBleFsProfile(support: T) : Abstrac
buffer.putLong(unixTime)
buffer.put(pathBytes)
+ notify(createIntent(true))
currentBuilder = performInitialized("Create directory")
currentBuilder?.write(UUID_CHARACTERISTIC_FS_TRANSFER, *buffer.array())
currentBuilder?.queue()
@@ -294,9 +363,8 @@ class AdaBleFsProfile(support: T) : Abstrac
@Throws(IOException::class)
private fun moveFileOrDirectory() {
- val nextAction = adaBleFsQueue.first()
- val firstPathBytes = nextAction.filenameorpath.toByteArray()
- val secondPathBytes = nextAction.secondFilenameorpath.toByteArray()
+ val firstPathBytes = currentAction!!.filenameorpath.toByteArray()
+ val secondPathBytes = currentAction!!.secondFilenameorpath.toByteArray()
val buffer = ByteBuffer.allocate(2 + 4 + firstPathBytes.size + secondPathBytes.size).order(ByteOrder.LITTLE_ENDIAN)
buffer.put(REQUEST_MOVE_FILE_DIRECTORY)
buffer.put(PADDING_BYTE)
@@ -306,31 +374,33 @@ class AdaBleFsProfile(support: T) : Abstrac
buffer.put(PADDING_BYTE)
buffer.put(secondPathBytes)
+ notify(createIntent(true))
currentBuilder = performInitialized("Move file or directory")
currentBuilder?.write(UUID_CHARACTERISTIC_FS_TRANSFER, *buffer.array())
currentBuilder?.queue()
}
@Throws(IOException::class)
- private fun requestListDirectory(path: String) {
- val pathBytes = path.toByteArray()
+ private fun listDirectoryFromQueue() {
+ listingDirectory = currentAction!!.filenameorpath.split("/").filter { it.isNotEmpty() }
+ val pathBytes = currentAction!!.filenameorpath.toByteArray()
val buffer = ByteBuffer.allocate(2 + 2 + pathBytes.size).order(ByteOrder.LITTLE_ENDIAN)
buffer.put(REQUEST_LIST_DIRECTORY)
buffer.put(PADDING_BYTE)
buffer.putShort(pathBytes.size.toShort())
buffer.put(pathBytes)
+ notify(createIntent(true))
currentBuilder = performInitialized("List directory")
currentBuilder?.write(UUID_CHARACTERISTIC_FS_TRANSFER, *buffer.array())
currentBuilder?.queue()
-
- listingDirectory = path.split("/")
}
- private fun createIntent(filename: String, ongoing: Boolean): Intent {
+ private fun createIntent(ongoing: Boolean): Intent {
val intent = Intent(PineTimeJFConstants.ACTION_UPLOAD_PROGRESS)
intent.putExtra("ongoing", ongoing)
- intent.putExtra("filename", filename)
+ intent.putExtra("filename", currentAction!!.filenameorpath)
+ intent.putExtra("currentAction", currentAction!!.method.toString())
intent.putExtra("currentActionNr", currentActionNr)
intent.putExtra("allActionsCount", allActionsCount)
return intent
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/profiles/adablefs/AdaFsEntry.kt b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/profiles/adablefs/AdaFsEntry.kt
deleted file mode 100644
index a839ddcc61..0000000000
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/profiles/adablefs/AdaFsEntry.kt
+++ /dev/null
@@ -1,25 +0,0 @@
-/* Copyright (C) 2025 Arjan Schrijver
-
- 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 . */
-package nodomain.freeyourgadget.gadgetbridge.service.btle.profiles.adablefs
-
-data class AdaFsEntry(
- val path: String,
- val isDirectory: Boolean,
- val fileSize: Int,
- val timestamp: Long,
- val flags: Int
-)
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/profiles/adablefs/RemoteFileSystemCache.kt b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/profiles/adablefs/RemoteFileSystemCache.kt
deleted file mode 100644
index a648808eb2..0000000000
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/profiles/adablefs/RemoteFileSystemCache.kt
+++ /dev/null
@@ -1,67 +0,0 @@
-package nodomain.freeyourgadget.gadgetbridge.util
-
-import nodomain.freeyourgadget.gadgetbridge.service.btle.profiles.adablefs.AdaFsEntry
-
-/**
- * Type-safe cache for remote filesystem.
- * Directories are maps, files are AdaFsEntry objects.
- */
-class RemoteFileSystemCache {
-
- private val root = mutableMapOf()
-
- fun updateEntry(path: String, entry: AdaFsEntry) {
- val parts = path.trim('/').split("/")
- var current: MutableMap = root
- for ((index, part) in parts.withIndex()) {
- if (index == parts.lastIndex) {
- current[part] = entry
- } else {
- current = (current[part] as? MutableMap) ?: mutableMapOf().also {
- current[part] = it
- }
- }
- }
- }
-
- fun directoryExists(path: String): Boolean {
- val parts = path.trim('/').split("/")
- var current: Map = root
- for (part in parts) {
- val next = current[part] ?: return false
- current = next as? Map ?: return false
- }
- return true
- }
-
- fun getEntry(path: String): AdaFsEntry? {
- val parts = path.trim('/').split("/")
- var current: Any = root
- for (part in parts) {
- current = (current as? Map<*, *>)?.get(part) ?: return null
- }
- return current as? AdaFsEntry
- }
-
- fun removeEntry(path: String) {
- val parts = path.trim('/').split("/")
- var current: MutableMap = root
- for ((index, part) in parts.withIndex()) {
- if (index == parts.lastIndex) {
- current.remove(part)
- } else {
- current = (current[part] as? MutableMap) ?: return
- }
- }
- }
-
- fun listDirectory(path: String): List {
- val parts = path.trim('/').split("/")
- var current: Any = root
- for (part in parts) {
- current = (current as? Map)?.get(part) ?: return emptyList()
- }
- val dir = current as? Map ?: return emptyList()
- return dir.values.mapNotNull { it as? AdaFsEntry }
- }
-}
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 5b1c789245..420b93b3de 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
@@ -95,7 +95,6 @@ import nodomain.freeyourgadget.gadgetbridge.service.btle.AbstractBTLESingleDevic
import nodomain.freeyourgadget.gadgetbridge.service.btle.BLETypeConversions;
import nodomain.freeyourgadget.gadgetbridge.service.btle.GattCharacteristic;
import nodomain.freeyourgadget.gadgetbridge.service.btle.GattService;
-import nodomain.freeyourgadget.gadgetbridge.service.btle.ResourceUploadProgressListener;
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
import nodomain.freeyourgadget.gadgetbridge.service.btle.profiles.IntentListener;
import nodomain.freeyourgadget.gadgetbridge.service.btle.profiles.adablefs.AdaBleFsProfile;
@@ -114,7 +113,6 @@ public class PineTimeJFSupport extends AbstractBTLESingleDeviceSupport implement
private final DeviceInfoProfile deviceInfoProfile;
private final BatteryInfoProfile batteryInfoProfile;
-
private final AdaBleFsProfile adaBleFsProfile;
private final int MaxNotificationLength = 100;
@@ -255,102 +253,6 @@ public class PineTimeJFSupport extends AbstractBTLESingleDeviceSupport implement
}
};
- private final ResourceUploadProgressListener resourceUploadProgressListener = new ResourceUploadProgressListener() {
- private final LocalBroadcastManager manager = LocalBroadcastManager.getInstance(getContext());
-
- /**
- * Sets the progress bar to indeterminate or not, also makes it visible
- *
- * @param indeterminate if indeterminate
- */
- public void setIndeterminate(boolean indeterminate) {
- manager.sendBroadcast(new Intent(GB.ACTION_SET_PROGRESS_BAR).putExtra(GB.PROGRESS_BAR_INDETERMINATE, indeterminate));
- }
-
- /**
- * Sets the status text and logs it
- */
- public void setProgress(int progress) {
- manager.sendBroadcast(new Intent(GB.ACTION_SET_PROGRESS_BAR).putExtra(GB.PROGRESS_BAR_PROGRESS, progress));
- }
-
- /**
- * Sets the text that describes progress
- *
- * @param progressText text to display
- */
- public void setProgressText(String progressText) {
- manager.sendBroadcast(new Intent(GB.ACTION_SET_PROGRESS_TEXT).putExtra(GB.DISPLAY_MESSAGE_MESSAGE, progressText));
- }
-
- @Override
- public void onDeviceConnecting(final String mac) {
- this.setIndeterminate(true);
- this.setProgressText(getContext().getString(R.string.devicestatus_connecting));
- }
-
- @Override
- public void onDeviceConnected(final String mac) {
- this.setIndeterminate(true);
- this.setProgressText(getContext().getString(R.string.devicestatus_connected));
- }
-
- @Override
- public void onUploadStarting(final String mac) {
- this.setIndeterminate(true);
- this.setProgressText(getContext().getString(R.string.devicestatus_upload_starting));
- }
-
- @Override
- public void onDeviceDisconnecting(final String mac) {
- this.setProgressText(getContext().getString(R.string.devicestatus_disconnecting));
- }
-
- @Override
- public void onDeviceDisconnected(final String mac) {
- this.setIndeterminate(true);
- this.setProgressText(getContext().getString(R.string.devicestatus_disconnected));
- }
-
- @Override
- public void onUploadCompleted(final String mac) {
- this.setProgressText(getContext().getString(R.string.devicestatus_upload_completed));
- this.setIndeterminate(false);
- this.setProgress(100);
-
- handler = null;
- controller = null;
- gbDevice.unsetBusyTask();
- // TODO: Request reconnection
- }
-
- @Override
- public void onUploadAborted(final String mac) {
- this.setProgressText(getContext().getString(R.string.devicestatus_upload_aborted));
- gbDevice.unsetBusyTask();
- }
-
- @Override
- public void onError(final String mac, int error, int errorType, final String message) {
- this.setProgressText(getContext().getString(R.string.devicestatus_upload_failed));
- gbDevice.unsetBusyTask();
- }
-
- @Override
- public void onProgressChanged(final String mac,
- int percent,
- float speed,
- float averageSpeed,
- int segment,
- int totalSegments) {
- this.setProgress(percent);
- this.setIndeterminate(false);
- this.setProgressText(String.format(Locale.ENGLISH,
- getContext().getString(R.string.firmware_update_progress),
- percent, speed, averageSpeed, segment, totalSegments));
- }
- };
-
public PineTimeJFSupport() {
super(LOG);
addSupportedService(GattService.UUID_SERVICE_ALERT_NOTIFICATION);
@@ -366,30 +268,27 @@ public class PineTimeJFSupport extends AbstractBTLESingleDeviceSupport implement
addSupportedService(PineTimeJFConstants.UUID_SERVICE_HEART_RATE);
addSupportedService(AdaBleFsProfile.UUID_SERVICE_FS);
- IntentListener mListener = new IntentListener() {
- @Override
- public void notify(Intent intent) {
- String action = intent.getAction();
- LOG.info("IntentListener received an intent with ACTION={}", action);
- 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");
- int currentActionNr = intent.getIntExtra("currentActionNr", 0);
- int allActionsCount = intent.getIntExtra("allActionsCount", 0);
- progressText = String.format("Performing action %d of %d\nCurrent filename: %s", currentActionNr, allActionsCount, filename);
- } else {
- progressText = getContext().getString(R.string.devicestatus_upload_completed);
- gbDevice.unsetBusyTask();
- }
- manager.sendBroadcast(new Intent(GB.ACTION_SET_PROGRESS_TEXT).putExtra(GB.DISPLAY_MESSAGE_MESSAGE, progressText));
+ IntentListener mListener = intent -> {
+ 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();
}
+ manager.sendBroadcast(new Intent(GB.ACTION_SET_PROGRESS_TEXT).putExtra(GB.DISPLAY_MESSAGE_MESSAGE, progressText));
}
};