From 36b85975f72bb84de0f2c67c89a4aec440e1948c Mon Sep 17 00:00:00 2001 From: Armin Date: Mon, 15 Jul 2024 16:06:27 +0200 Subject: [PATCH 1/6] Upgrade uploader --- .../cyface/synchronization/MockedUploader.kt | 15 +-- .../synchronization/SyncPerformerTest.kt | 56 ++++++---- .../de/cyface/synchronization/SyncAdapter.kt | 104 +++++++++++------- .../cyface/synchronization/SyncPerformer.kt | 59 +++++----- 4 files changed, 132 insertions(+), 102 deletions(-) diff --git a/synchronization/src/androidTest/kotlin/de/cyface/synchronization/MockedUploader.kt b/synchronization/src/androidTest/kotlin/de/cyface/synchronization/MockedUploader.kt index 29c0a8ceb..898679c45 100644 --- a/synchronization/src/androidTest/kotlin/de/cyface/synchronization/MockedUploader.kt +++ b/synchronization/src/androidTest/kotlin/de/cyface/synchronization/MockedUploader.kt @@ -1,5 +1,5 @@ /* - * Copyright 2023 Cyface GmbH + * Copyright 2023-2024 Cyface GmbH * * This file is part of the Cyface SDK for Android. * @@ -30,8 +30,6 @@ import java.net.URL * An [Uploader] that does not actually connect to the server, for testing. * * @author Armin Schnabel - * @version 2.0.0 - * @since 7.7.0 */ internal class MockedUploader : Uploader { @@ -43,9 +41,9 @@ internal class MockedUploader : Uploader { } } - override fun attachmentsEndpoint(measurementId: Long): URL { + override fun attachmentsEndpoint(deviceId: String, measurementId: Long): URL { return try { - URL("https://mocked.cyface.de/api/v123/measurements/ID/attachments") + URL("https://mocked.cyface.de/api/v123/measurements/did/mid/attachments") } catch (e: MalformedURLException) { throw IllegalStateException(e) } @@ -53,7 +51,7 @@ internal class MockedUploader : Uploader { override fun uploadMeasurement( jwtToken: String, - metaData: RequestMetaData, + metaData: RequestMetaData, file: File, progressListener: UploadProgressListener ): Result { @@ -63,8 +61,7 @@ internal class MockedUploader : Uploader { override fun uploadAttachment( jwtToken: String, - metaData: RequestMetaData, - measurementId: Long, + metaData: RequestMetaData, file: File, fileName: String, progressListener: UploadProgressListener @@ -72,4 +69,4 @@ internal class MockedUploader : Uploader { progressListener.updatedProgress(1.0f) // 100% return Result.UPLOAD_SUCCESSFUL } -} \ No newline at end of file +} diff --git a/synchronization/src/androidTest/kotlin/de/cyface/synchronization/SyncPerformerTest.kt b/synchronization/src/androidTest/kotlin/de/cyface/synchronization/SyncPerformerTest.kt index 382ae7358..8ece3d10c 100644 --- a/synchronization/src/androidTest/kotlin/de/cyface/synchronization/SyncPerformerTest.kt +++ b/synchronization/src/androidTest/kotlin/de/cyface/synchronization/SyncPerformerTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2023 Cyface GmbH + * Copyright 2018-2024 Cyface GmbH * * This file is part of the Cyface SDK for Android. * @@ -76,8 +76,6 @@ import java.nio.file.Path * * @author Klemens Muthmann * @author Armin Schnabel - * @version 1.1.0 - * @since 7.7.0 */ @RunWith(AndroidJUnit4::class) @LargeTest @@ -140,7 +138,15 @@ class SyncPerformerTest { MatcherAssert.assertThat(loadedStatus, CoreMatchers.equalTo(MeasurementStatus.FINISHED)) val compressedTransferTempFile = loadSerializedCompressed(persistence, measurementId) val metaData = - loadMetaData(persistence, measurement, locationCount, logCount, imageCount, videoCount, filesSize) + loadMetaData( + persistence, + measurement, + locationCount, + logCount, + imageCount, + videoCount, + filesSize + ) val progressListener = object : UploadProgressListener { override fun updatedProgress(percent: Float) { Log.d(TAG, String.format("Upload Progress %f", percent)) @@ -178,12 +184,12 @@ class SyncPerformerTest { @Test @Throws(CursorIsNullException::class, NoSuchMeasurementException::class) fun testSendData() = runBlocking { - performSendDataTest( - point3DCount = 600 * 1000, - locationCount = 3 * 1000, - 0, 0, 0, 0 - ) - } + performSendDataTest( + point3DCount = 600 * 1000, + locationCount = 3 * 1000, + 0, 0, 0, 0 + ) + } /** * Tests the basic transmission with a measurement with attached files. @@ -264,20 +270,27 @@ class SyncPerformerTest { val lastTrack = tracks[tracks.size - 1].geoLocations val endLocation = lastTrack[lastTrack.size - 1]!! val deviceId = "testDevi-ce00-42b6-a840-1b70d30094b8" // Must be a valid UUID - val startRecord = RequestMetaData.GeoLocation( + val startRecord = RequestMetaData.MeasurementMetaData.GeoLocation( startLocation.timestamp, startLocation.lat, startLocation.lon ) - val endRecord = RequestMetaData.GeoLocation( + val endRecord = RequestMetaData.MeasurementMetaData.GeoLocation( endLocation.timestamp, endLocation.lat, endLocation.lon ) val metaData = RequestMetaData( - deviceId, measurementIdentifier.toString(), - "testOsVersion", "testDeviceType", "testAppVersion", - distance, locationCount.toLong(), startRecord, endRecord, - Modality.BICYCLE.databaseIdentifier, 3, 0, 0, 0, 0 + RequestMetaData.MeasurementIdentifier(deviceId, measurementIdentifier.toString()), + RequestMetaData.DeviceMetaData("testOsVersion", "testDeviceType"), + RequestMetaData.ApplicationMetaData("testAppVersion", 3), + RequestMetaData.MeasurementMetaData( + distance, + locationCount.toLong(), + startRecord, + endRecord, + Modality.BICYCLE.databaseIdentifier, + ), + RequestMetaData.AttachmentMetaData(0, 0, 0, 0), ) val progressListener = object : UploadProgressListener { override fun updatedProgress(percent: Float) { @@ -285,7 +298,7 @@ class SyncPerformerTest { } } val fileName = - "${metaData.deviceIdentifier}_${metaData.measurementIdentifier}.${SyncAdapter.COMPRESSED_TRANSFER_FILE_EXTENSION}" + "${metaData.identifier.deviceId}_${metaData.identifier.measurementId}.${SyncAdapter.COMPRESSED_TRANSFER_FILE_EXTENSION}" // Mock the actual post request val mockedUploader = object : Uploader { @@ -293,13 +306,13 @@ class SyncPerformerTest { return URL("https://mocked.cyface.de/api/v123/measurements") } - override fun attachmentsEndpoint(measurementId: Long): URL { - return URL("https://mocked.cyface.de/api/v123/measurements/$measurementId/attachments") + override fun attachmentsEndpoint(deviceId: String, measurementId: Long): URL { + return URL("https://mocked.cyface.de/api/v123/measurements/$deviceId/$measurementId/attachments") } override fun uploadMeasurement( jwtToken: String, - metaData: RequestMetaData, + metaData: RequestMetaData, file: File, progressListener: UploadProgressListener ): Result { @@ -308,8 +321,7 @@ class SyncPerformerTest { override fun uploadAttachment( jwtToken: String, - metaData: RequestMetaData, - measurementId: Long, + metaData: RequestMetaData, file: File, fileName: String, progressListener: UploadProgressListener diff --git a/synchronization/src/main/kotlin/de/cyface/synchronization/SyncAdapter.kt b/synchronization/src/main/kotlin/de/cyface/synchronization/SyncAdapter.kt index 2e474e287..526719896 100644 --- a/synchronization/src/main/kotlin/de/cyface/synchronization/SyncAdapter.kt +++ b/synchronization/src/main/kotlin/de/cyface/synchronization/SyncAdapter.kt @@ -1,5 +1,5 @@ /* - * Copyright 2017-2023 Cyface GmbH + * Copyright 2017-2024 Cyface GmbH * * This file is part of the Cyface SDK for Android. * @@ -31,7 +31,6 @@ import android.content.pm.PackageManager import android.os.Build import android.os.Bundle import android.util.Log -import de.cyface.model.RequestMetaData import de.cyface.persistence.DefaultPersistenceBehaviour import de.cyface.persistence.DefaultPersistenceLayer import de.cyface.persistence.exception.NoSuchMeasurementException @@ -45,12 +44,23 @@ import de.cyface.synchronization.ErrorHandler.ErrorCode import de.cyface.uploader.Result import de.cyface.uploader.Uploader import de.cyface.uploader.exception.SynchronizationInterruptedException +import de.cyface.uploader.model.Attachment +import de.cyface.uploader.model.AttachmentIdentifier +import de.cyface.uploader.model.MeasurementIdentifier +import de.cyface.uploader.model.Uploadable +import de.cyface.uploader.model.metadata.ApplicationMetaData +import de.cyface.uploader.model.metadata.ApplicationMetaData.Companion.CURRENT_TRANSFER_FILE_FORMAT_VERSION +import de.cyface.uploader.model.metadata.AttachmentMetaData +import de.cyface.uploader.model.metadata.DeviceMetaData +import de.cyface.uploader.model.metadata.GeoLocation +import de.cyface.uploader.model.metadata.MeasurementMetaData import de.cyface.utils.CursorIsNullException import de.cyface.utils.Validate import kotlinx.coroutines.CompletableDeferred import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.runBlocking import java.io.File +import java.util.UUID /** * An Android SyncAdapter implementation to transmit data to a Cyface server. @@ -60,8 +70,6 @@ import java.io.File * * @author Armin Schnabel * @author Klemens Muthmann - * @version 4.1.1 - * @since 2.0.0 * @property authenticator The authenticator to use for synchronization. * @property uploader The uploader to use for synchronization. */ @@ -73,7 +81,7 @@ class SyncAdapter private constructor( private val uploader: Uploader ) : AbstractThreadedSyncAdapter(context, autoInitialize, allowParallelSyncs) { - private val progressListeners: MutableCollection + private val progressListeners: MutableCollection = HashSet() /** * When this is set to true the [.isConnected] method always returns true. @@ -103,7 +111,6 @@ class SyncAdapter private constructor( ) init { - progressListeners = HashSet() addConnectionListener(CyfaceConnectionStatusListener(context)) } @@ -241,8 +248,10 @@ class SyncAdapter private constructor( val measurement = measurements[index] validateMeasurementFormat(measurement) - val metaData = loadMetaData(measurement, persistence, deviceId, context) - val attachmentCount = metaData.logCount + metaData.imageCount + metaData.videoCount + val measurementMeta = loadMeasurementMeta(measurement, persistence, deviceId, context) + val attachmentCount = measurementMeta.attachmentMetaData.logCount + + measurementMeta.attachmentMetaData.imageCount + + measurementMeta.attachmentMetaData.videoCount Log.d(TAG, "Preparing to upload Measurement (id ${measurement.id}) with $attachmentCount attachments.") @@ -258,7 +267,7 @@ class SyncAdapter private constructor( val progressListener = DefaultUploadProgressListener(measurementCount, index, measurement.id, attachmentCount, indexWithinMeasurement, progressListeners) error = !syncMeasurement( measurement, - metaData, + measurementMeta, compressedTransferTempFile, syncPerformer, syncResult, @@ -301,9 +310,9 @@ class SyncAdapter private constructor( indexWithinMeasurement, progressListeners ) + val attachmentMeta = attachmentMeta(measurementMeta, attachment.id) error = !syncAttachment( - attachment.id, - metaData, + attachmentMeta, syncPerformer, transferTempFile, syncResult, @@ -347,7 +356,7 @@ class SyncAdapter private constructor( private suspend fun syncMeasurement( measurement: Measurement, - metaData: RequestMetaData, + uploadable: de.cyface.uploader.model.Measurement, compressedTransferTempFile: File?, syncPerformer: SyncPerformer, syncResult: SyncResult, @@ -370,11 +379,11 @@ class SyncAdapter private constructor( resultDeferred.complete(false) } else { val fileName = - "${metaData.deviceIdentifier}_${metaData.measurementIdentifier}.${COMPRESSED_TRANSFER_FILE_EXTENSION}" + "${uploadable.identifier.deviceIdentifier}_${uploadable.identifier.measurementIdentifier}.${COMPRESSED_TRANSFER_FILE_EXTENSION}" val result = syncPerformer.sendData( uploader, syncResult, - metaData, + uploadable, compressedTransferTempFile!!, progressListener, accessToken!!, @@ -423,8 +432,7 @@ class SyncAdapter private constructor( } private suspend fun syncAttachment( - attachmentId: Long, - metaData: RequestMetaData, + attachment: Attachment, syncPerformer: SyncPerformer, transferFile: File?, syncResult: SyncResult, @@ -446,12 +454,13 @@ class SyncAdapter private constructor( ) resultDeferred.complete(false) } else { + val attachmentId = attachment.identifier.attachmentIdentifier val fileName = - "${metaData.deviceIdentifier}_${metaData.measurementIdentifier}_$attachmentId.${TRANSFER_FILE_EXTENSION}" + "${attachment.identifier.deviceIdentifier}_${attachment.identifier.measurementIdentifier}_$attachmentId.${TRANSFER_FILE_EXTENSION}" val result = syncPerformer.sendData( uploader, syncResult, - metaData, + attachment, transferFile!!, progressListener, accessToken!!, @@ -582,15 +591,16 @@ class SyncAdapter private constructor( * @param persistence The [DefaultPersistenceLayer] to load track data required * @param deviceId The device identifier generated for this device * @param context The `Context` to load the version name of this SDK - * @return The [RequestMetaData] loaded + * @return The [Uploadable] loaded * @throws CursorIsNullException when accessing the `ContentProvider` failed */ @Throws(CursorIsNullException::class) - private fun loadMetaData( + private fun loadMeasurementMeta( measurement: Measurement, - persistence: DefaultPersistenceLayer, deviceId: String, + persistence: DefaultPersistenceLayer, + deviceId: String, context: Context - ): RequestMetaData { + ): de.cyface.uploader.model.Measurement { // If there is only one location captured, start and end locations are identical val tracks = persistence.loadTracks(measurement.id) @@ -604,15 +614,15 @@ class SyncAdapter private constructor( ) val lastTrack: List? = if (tracks.isNotEmpty()) tracks[tracks.size - 1].geoLocations else null - var startLocation: RequestMetaData.GeoLocation? = null + var startLocation: GeoLocation? = null if (tracks.isNotEmpty()) { val l = tracks[0].geoLocations[0]!! - startLocation = RequestMetaData.GeoLocation(l.timestamp, l.lat, l.lon) + startLocation = GeoLocation(l.timestamp, l.lat, l.lon) } - var endLocation: RequestMetaData.GeoLocation? = null + var endLocation: GeoLocation? = null if (lastTrack != null) { val l = lastTrack[lastTrack.size - 1] - endLocation = RequestMetaData.GeoLocation(l!!.timestamp, l.lat, l.lon) + endLocation = GeoLocation(l!!.timestamp, l.lat, l.lon) } return runBlocking { @@ -639,26 +649,36 @@ class SyncAdapter private constructor( } catch (e: PackageManager.NameNotFoundException) { throw IllegalStateException(e) } - return@runBlocking RequestMetaData( - deviceId, - measurement.id.toString(), - osVersion, - deviceType, - appVersion, - measurement.distance, - locationCount.toLong(), - startLocation, - endLocation, - measurement.modality.databaseIdentifier, - RequestMetaData.CURRENT_TRANSFER_FILE_FORMAT_VERSION, - logCount, - imageCount, - 0, - filesSize + return@runBlocking de.cyface.uploader.model.Measurement( + MeasurementIdentifier(UUID.fromString(deviceId), measurement.id), + DeviceMetaData(osVersion, deviceType), + ApplicationMetaData(appVersion, CURRENT_TRANSFER_FILE_FORMAT_VERSION), + MeasurementMetaData( + measurement.distance, + locationCount.toLong(), + startLocation, + endLocation, + measurement.modality.databaseIdentifier, + ), + AttachmentMetaData(logCount, imageCount, 0, filesSize), ) } } + private fun attachmentMeta(measurement: de.cyface.uploader.model.Measurement, attachmentId: Long): Attachment { + return Attachment( + AttachmentIdentifier( + measurement.identifier.deviceIdentifier, + measurement.identifier.measurementIdentifier, + attachmentId, + ), + measurement.deviceMetaData, + measurement.applicationMetaData, + measurement.measurementMetaData, + measurement.attachmentMetaData, + ) + } + private fun getFolderSize(folder: File): Long { var size: Long = 0 val files = folder.listFiles() diff --git a/synchronization/src/main/kotlin/de/cyface/synchronization/SyncPerformer.kt b/synchronization/src/main/kotlin/de/cyface/synchronization/SyncPerformer.kt index 9728d98b1..6a48d728d 100644 --- a/synchronization/src/main/kotlin/de/cyface/synchronization/SyncPerformer.kt +++ b/synchronization/src/main/kotlin/de/cyface/synchronization/SyncPerformer.kt @@ -1,5 +1,5 @@ /* - * Copyright 2017-2023 Cyface GmbH + * Copyright 2017-2024 Cyface GmbH * * This file is part of the Cyface SDK for Android. * @@ -21,7 +21,6 @@ package de.cyface.synchronization import android.content.Context import android.content.SyncResult import android.util.Log -import de.cyface.model.RequestMetaData import de.cyface.serializer.DataSerializable import de.cyface.synchronization.ErrorHandler.ErrorCode import de.cyface.uploader.Result @@ -43,6 +42,9 @@ import de.cyface.uploader.exception.UnauthorizedException import de.cyface.uploader.exception.UnexpectedResponseCode import de.cyface.uploader.exception.UploadFailed import de.cyface.uploader.exception.UploadSessionExpired +import de.cyface.uploader.model.Attachment +import de.cyface.uploader.model.Measurement +import de.cyface.uploader.model.Uploadable import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.async @@ -56,8 +58,6 @@ import java.net.MalformedURLException * * @author Klemens Muthmann * @author Armin Schnabel - * @version 8.1.0 - * @since 2.0.0 * @property context The Android `Context` to use for setting the correct server certification information. * @property fromBackground `true` if the error was caused without user interaction, e.g. to avoid * disturbing the user while he is not using the app. @@ -75,7 +75,7 @@ internal class SyncPerformer(private val context: Context, private val fromBackg * * @param uploader The uploader to use for transmission * @param syncResult The [SyncResult] used to store sync error information. - * @param metaData The [RequestMetaData] required for the Multipart request. + * @param uploadable The [Uploadable] which describes the data to be uploaded. * @param file The compressed transfer file containing the data to transmit * @param progressListener The [UploadProgressListener] to be informed about the upload progress. * @param jwtAuthToken A valid JWT auth token to authenticate the transmission @@ -86,7 +86,7 @@ internal class SyncPerformer(private val context: Context, private val fromBackg fun sendData( uploader: Uploader, syncResult: SyncResult, - metaData: RequestMetaData, + uploadable: Uploadable, file: File, progressListener: UploadProgressListener, jwtAuthToken: String, @@ -98,32 +98,33 @@ internal class SyncPerformer(private val context: Context, private val fromBackg return runBlocking { val deferredResult = CoroutineScope(Dispatchers.IO).async { - val measurementId = metaData.measurementIdentifier.toLong() - val endpoint = - if (uploadType == UploadType.MEASUREMENT) uploader.measurementsEndpoint() - else uploader.attachmentsEndpoint(measurementId) val result = try { - Log.i(TAG, "Uploading $fileName to $endpoint") - - @Suppress("REDUNDANT_ELSE_IN_WHEN") when (uploadType) { - UploadType.MEASUREMENT -> uploader.uploadMeasurement( - jwtAuthToken, - metaData, - file, - progressListener - ) - - UploadType.ATTACHMENT -> uploader.uploadAttachment( - jwtAuthToken, - metaData, - measurementId, - file, - fileName, - progressListener - ) + UploadType.MEASUREMENT -> { + val endpoint = uploader.measurementsEndpoint() + Log.i(TAG, "Uploading $fileName to $endpoint.") + uploader.uploadMeasurement( + jwtAuthToken, + uploadable as Measurement, + file, + progressListener + ) + } - else -> throw IllegalArgumentException("Unsupported upload type: $uploadType") + UploadType.ATTACHMENT -> { + val attachment = uploadable as Attachment + val measurementId = attachment.identifier.measurementIdentifier + val deviceId = uploadable.identifier.deviceIdentifier.toString() + val endpoint = uploader.attachmentsEndpoint(deviceId, measurementId) + Log.i(TAG, "Uploading $fileName to $endpoint.") + uploader.uploadAttachment( + jwtAuthToken, + attachment, + file, + fileName, + progressListener + ) + } } } catch (e: UploadFailed) { return@async handleUploadFailed(e, syncResult) From 523d59fff5f7538d2d2fca46ddb16847752ae882 Mon Sep 17 00:00:00 2001 From: Armin Date: Mon, 15 Jul 2024 16:07:16 +0200 Subject: [PATCH 2/6] Upgrade dependencies to pre-versions --- build.gradle | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index 99006752d..b2b8de187 100644 --- a/build.gradle +++ b/build.gradle @@ -51,11 +51,11 @@ ext { // Cyface dependencies cyfaceUtilsVersion = "4.0.7" - // (!) Match versions `android-app`, `SDK` and `camera-service`. + // (!) Match versions `android-app`, `SDK` and `camera-service`. - FIXME !! // When `android-app` is checkout out, `rootProject.uploaderVersion` in the submodules will point // to `android-app/build.gradle` instead of `submodule/build.gradle`. - cyfaceSerializationVersion = "3.2.0" - cyfaceUploaderVersion = "1.3.0" + cyfaceSerializationVersion = "3.4.0" + cyfaceUploaderVersion = "1.4.0-alpha9" // FIXME // Android SDK versions minSdkVersion = 21 // device support From b6e51e205bbda3b99ee8d244a926e326dc36fc16 Mon Sep 17 00:00:00 2001 From: Armin Date: Mon, 15 Jul 2024 16:47:14 +0200 Subject: [PATCH 3/6] Fix build --- .github/workflows/gradle_build.yml | 2 -- .github/workflows/gradle_connected-tests.yml | 2 -- .github/workflows/gradle_publish.yml | 2 -- build.gradle | 4 +--- testutils/build.gradle | 4 +--- .../kotlin/de/cyface/testutils/SharedTestUtils.kt | 14 +------------- 6 files changed, 3 insertions(+), 25 deletions(-) diff --git a/.github/workflows/gradle_build.yml b/.github/workflows/gradle_build.yml index 1cf8004f1..c55493522 100644 --- a/.github/workflows/gradle_build.yml +++ b/.github/workflows/gradle_build.yml @@ -1,8 +1,6 @@ # This workflow ensures the building step works # # @author Armin Schnabel -# @version 1.0.3 -# @since 5.0.0 name: Gradle Build on: diff --git a/.github/workflows/gradle_connected-tests.yml b/.github/workflows/gradle_connected-tests.yml index a4bd48cc4..f1f14592b 100644 --- a/.github/workflows/gradle_connected-tests.yml +++ b/.github/workflows/gradle_connected-tests.yml @@ -1,8 +1,6 @@ # This workflow ensures the connected tests keep working # # @author Armin Schnabel -# @version 1.0.0 -# @since 7.4.0 name: Gradle Connected Tests on: diff --git a/.github/workflows/gradle_publish.yml b/.github/workflows/gradle_publish.yml index b9a3e8139..9d75b36ba 100644 --- a/.github/workflows/gradle_publish.yml +++ b/.github/workflows/gradle_publish.yml @@ -1,8 +1,6 @@ # This workflow publishes a new version to the Github Registry. # # @author Armin Schnabel -# @version 1.1.0 -# @since 5.0.0 name: Gradle Publish on: diff --git a/build.gradle b/build.gradle index b2b8de187..14bb2afb3 100644 --- a/build.gradle +++ b/build.gradle @@ -1,5 +1,5 @@ /* - * Copyright 2017-2023 Cyface GmbH + * Copyright 2017-2024 Cyface GmbH * * This file is part of the Cyface SDK for Android. * @@ -21,8 +21,6 @@ * * @author Armin Schnabel * @author Klemens Muthmann - * @version 2.11.0 - * @since 1.0.0 */ buildscript { diff --git a/testutils/build.gradle b/testutils/build.gradle index 5eaf66bf8..4938877ec 100644 --- a/testutils/build.gradle +++ b/testutils/build.gradle @@ -1,5 +1,5 @@ /* - * Copyright 2019-2023 Cyface GmbH + * Copyright 2019-2024 Cyface GmbH * * This file is part of the Cyface SDK for Android. * @@ -20,8 +20,6 @@ * Gradle's build file for the module which contains cross cutting code used by all other modules. * * @author Armin Schnabel - * @version 1.3.0 - * @since 3.0.0 */ plugins { id 'com.android.library' diff --git a/testutils/src/main/kotlin/de/cyface/testutils/SharedTestUtils.kt b/testutils/src/main/kotlin/de/cyface/testutils/SharedTestUtils.kt index 577cb6615..af557d3f4 100644 --- a/testutils/src/main/kotlin/de/cyface/testutils/SharedTestUtils.kt +++ b/testutils/src/main/kotlin/de/cyface/testutils/SharedTestUtils.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2023 Cyface GmbH + * Copyright 2018-2024 Cyface GmbH * * This file is part of the Cyface SDK for Android. * @@ -27,7 +27,6 @@ import android.util.Log import com.google.protobuf.ByteString import com.google.protobuf.InvalidProtocolBufferException import de.cyface.model.Point3DImpl -import de.cyface.model.RequestMetaData import de.cyface.persistence.Constants import de.cyface.persistence.Database import de.cyface.persistence.DefaultPersistenceLayer @@ -64,8 +63,6 @@ import java.util.UUID * It's located in the main folder to be compiled and imported as dependency in the testImplementations. * * @author Armin Schnabel - * @version 9.0.0 - * @since 3.0.0 */ object SharedTestUtils { /** @@ -159,15 +156,6 @@ object SharedTestUtils { ) } - @JvmStatic - fun generateRequestMetaDataGeoLocation( - distanceFromBase: Int, - timestamp: Long - ): RequestMetaData.GeoLocation { - val location = generateGeoLocation(distanceFromBase, timestamp) - return RequestMetaData.GeoLocation(location.timestamp, location.lat, location.lon) - } - /** * Inserts a test [de.cyface.persistence.model.ParcelablePoint3D] into the database content provider accessed by the test. * From 2940cdc69855e1641bed8089b8a40ed84e39e5d9 Mon Sep 17 00:00:00 2001 From: Armin Date: Mon, 15 Jul 2024 16:53:29 +0200 Subject: [PATCH 4/6] Upgrade uploader to 1.4.0 --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 14bb2afb3..f890690bd 100644 --- a/build.gradle +++ b/build.gradle @@ -49,11 +49,11 @@ ext { // Cyface dependencies cyfaceUtilsVersion = "4.0.7" - // (!) Match versions `android-app`, `SDK` and `camera-service`. - FIXME !! + // (!) Match versions `android-app`, `SDK` and `camera-service`. // When `android-app` is checkout out, `rootProject.uploaderVersion` in the submodules will point // to `android-app/build.gradle` instead of `submodule/build.gradle`. cyfaceSerializationVersion = "3.4.0" - cyfaceUploaderVersion = "1.4.0-alpha9" // FIXME + cyfaceUploaderVersion = "1.4.0" // Android SDK versions minSdkVersion = 21 // device support From 4c63dfd88e00ab242713ac2b2bae6ea43c695afc Mon Sep 17 00:00:00 2001 From: Armin Date: Mon, 15 Jul 2024 17:15:19 +0200 Subject: [PATCH 5/6] Fix build --- .../datacapturing/DataCapturingServiceTest.kt | 8 +--- .../cyface/synchronization/MockedUploader.kt | 7 ++-- .../synchronization/SyncPerformerTest.kt | 35 ++++++++++------- .../SyncPerformerTest_withoutAuth.kt | 7 +--- .../de/cyface/synchronization/TestUtils.kt | 39 +++++++++++-------- 5 files changed, 52 insertions(+), 44 deletions(-) diff --git a/datacapturing/src/androidTest/kotlin/de/cyface/datacapturing/DataCapturingServiceTest.kt b/datacapturing/src/androidTest/kotlin/de/cyface/datacapturing/DataCapturingServiceTest.kt index 96324c001..93818ab51 100644 --- a/datacapturing/src/androidTest/kotlin/de/cyface/datacapturing/DataCapturingServiceTest.kt +++ b/datacapturing/src/androidTest/kotlin/de/cyface/datacapturing/DataCapturingServiceTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2017-2023 Cyface GmbH + * Copyright 2017-2024 Cyface GmbH * * This file is part of the Cyface SDK for Android. * @@ -46,13 +46,11 @@ import de.cyface.persistence.model.Measurement import de.cyface.persistence.model.MeasurementStatus import de.cyface.persistence.model.Modality import de.cyface.synchronization.CyfaceAuthenticator -import de.cyface.synchronization.settings.DefaultSynchronizationSettings import de.cyface.testutils.SharedTestUtils.clearPersistenceLayer import de.cyface.utils.Validate import kotlinx.coroutines.runBlocking import org.hamcrest.CoreMatchers import org.hamcrest.MatcherAssert.assertThat -import org.json.JSONObject import org.junit.After import org.junit.Before import org.junit.Ignore @@ -70,8 +68,6 @@ import java.util.concurrent.locks.ReentrantLock * * @author Klemens Muthmann * @author Armin Schnabel - * @version 5.7.8 - * @since 2.0.0 */ @RunWith(AndroidJUnit4::class) @LargeTest @@ -224,7 +220,7 @@ class DataCapturingServiceTest { * @throws DataCapturingException If the asynchronous background service did not start successfully or no valid * Android context was available. * @throws MissingPermissionException If no Android `ACCESS_FINE_LOCATION` has been granted. You may - * register a [de.cyface.datacapturing.ui.UIListener] to ask the user for this permission and prevent the + * register a `de.cyface.datacapturing.ui.UIListener` to ask the user for this permission and prevent the * `Exception`. If the `Exception` was thrown the service does not start. */ @Throws( diff --git a/synchronization/src/androidTest/kotlin/de/cyface/synchronization/MockedUploader.kt b/synchronization/src/androidTest/kotlin/de/cyface/synchronization/MockedUploader.kt index 898679c45..5abcca4ee 100644 --- a/synchronization/src/androidTest/kotlin/de/cyface/synchronization/MockedUploader.kt +++ b/synchronization/src/androidTest/kotlin/de/cyface/synchronization/MockedUploader.kt @@ -18,10 +18,11 @@ */ package de.cyface.synchronization -import de.cyface.model.RequestMetaData import de.cyface.uploader.Result import de.cyface.uploader.UploadProgressListener import de.cyface.uploader.Uploader +import de.cyface.uploader.model.Attachment +import de.cyface.uploader.model.Measurement import java.io.File import java.net.MalformedURLException import java.net.URL @@ -51,7 +52,7 @@ internal class MockedUploader : Uploader { override fun uploadMeasurement( jwtToken: String, - metaData: RequestMetaData, + uploadable: Measurement, file: File, progressListener: UploadProgressListener ): Result { @@ -61,7 +62,7 @@ internal class MockedUploader : Uploader { override fun uploadAttachment( jwtToken: String, - metaData: RequestMetaData, + uploadable: Attachment, file: File, fileName: String, progressListener: UploadProgressListener diff --git a/synchronization/src/androidTest/kotlin/de/cyface/synchronization/SyncPerformerTest.kt b/synchronization/src/androidTest/kotlin/de/cyface/synchronization/SyncPerformerTest.kt index 8ece3d10c..1b62eba85 100644 --- a/synchronization/src/androidTest/kotlin/de/cyface/synchronization/SyncPerformerTest.kt +++ b/synchronization/src/androidTest/kotlin/de/cyface/synchronization/SyncPerformerTest.kt @@ -24,7 +24,6 @@ import android.util.Log import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.LargeTest import androidx.test.platform.app.InstrumentationRegistry -import de.cyface.model.RequestMetaData import de.cyface.persistence.DefaultPersistenceBehaviour import de.cyface.persistence.DefaultPersistenceLayer import de.cyface.persistence.exception.NoSuchMeasurementException @@ -56,6 +55,13 @@ import de.cyface.uploader.exception.UnauthorizedException import de.cyface.uploader.exception.UnexpectedResponseCode import de.cyface.uploader.exception.UploadFailed import de.cyface.uploader.exception.UploadSessionExpired +import de.cyface.uploader.model.Attachment +import de.cyface.uploader.model.MeasurementIdentifier +import de.cyface.uploader.model.metadata.ApplicationMetaData +import de.cyface.uploader.model.metadata.AttachmentMetaData +import de.cyface.uploader.model.metadata.DeviceMetaData +import de.cyface.uploader.model.metadata.GeoLocation +import de.cyface.uploader.model.metadata.MeasurementMetaData import de.cyface.utils.CursorIsNullException import kotlinx.coroutines.runBlocking import org.hamcrest.CoreMatchers @@ -68,6 +74,7 @@ import java.io.File import java.net.URL import java.nio.file.Files import java.nio.file.Path +import java.util.UUID /** * Tests the data transmission code. @@ -153,7 +160,7 @@ class SyncPerformerTest { } } val fileName = - "${metaData.deviceIdentifier}_${metaData.measurementIdentifier}.${SyncAdapter.COMPRESSED_TRANSFER_FILE_EXTENSION}" + "${metaData.identifier.deviceIdentifier}_${metaData.identifier.measurementIdentifier}.${SyncAdapter.COMPRESSED_TRANSFER_FILE_EXTENSION}" val uploader = MockedUploader() // Prepare transmission @@ -269,28 +276,28 @@ class SyncPerformerTest { val startLocation = tracks[0].geoLocations[0]!! val lastTrack = tracks[tracks.size - 1].geoLocations val endLocation = lastTrack[lastTrack.size - 1]!! - val deviceId = "testDevi-ce00-42b6-a840-1b70d30094b8" // Must be a valid UUID - val startRecord = RequestMetaData.MeasurementMetaData.GeoLocation( + val deviceId = UUID.randomUUID() + val startRecord = GeoLocation( startLocation.timestamp, startLocation.lat, startLocation.lon ) - val endRecord = RequestMetaData.MeasurementMetaData.GeoLocation( + val endRecord = GeoLocation( endLocation.timestamp, endLocation.lat, endLocation.lon ) - val metaData = RequestMetaData( - RequestMetaData.MeasurementIdentifier(deviceId, measurementIdentifier.toString()), - RequestMetaData.DeviceMetaData("testOsVersion", "testDeviceType"), - RequestMetaData.ApplicationMetaData("testAppVersion", 3), - RequestMetaData.MeasurementMetaData( + val metaData = de.cyface.uploader.model.Measurement( + MeasurementIdentifier(deviceId, measurementIdentifier), + DeviceMetaData("testOsVersion", "testDeviceType"), + ApplicationMetaData("testAppVersion", 3), + MeasurementMetaData( distance, locationCount.toLong(), startRecord, endRecord, Modality.BICYCLE.databaseIdentifier, ), - RequestMetaData.AttachmentMetaData(0, 0, 0, 0), + AttachmentMetaData(0, 0, 0, 0), ) val progressListener = object : UploadProgressListener { override fun updatedProgress(percent: Float) { @@ -298,7 +305,7 @@ class SyncPerformerTest { } } val fileName = - "${metaData.identifier.deviceId}_${metaData.identifier.measurementId}.${SyncAdapter.COMPRESSED_TRANSFER_FILE_EXTENSION}" + "${metaData.identifier.deviceIdentifier}_${metaData.identifier.measurementIdentifier}.${SyncAdapter.COMPRESSED_TRANSFER_FILE_EXTENSION}" // Mock the actual post request val mockedUploader = object : Uploader { @@ -312,7 +319,7 @@ class SyncPerformerTest { override fun uploadMeasurement( jwtToken: String, - metaData: RequestMetaData, + uploadable: de.cyface.uploader.model.Measurement, file: File, progressListener: UploadProgressListener ): Result { @@ -321,7 +328,7 @@ class SyncPerformerTest { override fun uploadAttachment( jwtToken: String, - metaData: RequestMetaData, + uploadable: Attachment, file: File, fileName: String, progressListener: UploadProgressListener diff --git a/synchronization/src/androidTest/kotlin/de/cyface/synchronization/SyncPerformerTest_withoutAuth.kt b/synchronization/src/androidTest/kotlin/de/cyface/synchronization/SyncPerformerTest_withoutAuth.kt index 89c4406da..b9c329649 100644 --- a/synchronization/src/androidTest/kotlin/de/cyface/synchronization/SyncPerformerTest_withoutAuth.kt +++ b/synchronization/src/androidTest/kotlin/de/cyface/synchronization/SyncPerformerTest_withoutAuth.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2023 Cyface GmbH + * Copyright 2018-2024 Cyface GmbH * * This file is part of the Cyface SDK for Android. * @@ -23,7 +23,6 @@ import android.content.Context import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.LargeTest import androidx.test.platform.app.InstrumentationRegistry -import de.cyface.model.RequestMetaData import de.cyface.persistence.DefaultPersistenceBehaviour import de.cyface.persistence.DefaultPersistenceLayer import de.cyface.persistence.exception.NoSuchMeasurementException @@ -72,8 +71,6 @@ import java.io.IOException * * @author Klemens Muthmann * @author Armin Schnabel - * @version 2.1.3 - * @since 2.0.0 * @see [Testing documentation](http://d.android.com/tools/testing) */ @RunWith(AndroidJUnit4::class) @@ -148,7 +145,7 @@ class SyncPerformerTestWithoutAuth { ) ) file = loadSerializedCompressed(persistence, measurementIdentifier) - val metaData: RequestMetaData = + val metaData = loadMetaData(persistence, measurement, locationCount, 0, 0, 0, 0) val url = "$TEST_API_URL/api/v3/measurements" diff --git a/synchronization/src/androidTest/kotlin/de/cyface/synchronization/TestUtils.kt b/synchronization/src/androidTest/kotlin/de/cyface/synchronization/TestUtils.kt index 4639d5582..1cbcc4879 100644 --- a/synchronization/src/androidTest/kotlin/de/cyface/synchronization/TestUtils.kt +++ b/synchronization/src/androidTest/kotlin/de/cyface/synchronization/TestUtils.kt @@ -1,5 +1,5 @@ /* - * Copyright 2019 Cyface GmbH + * Copyright 2019-2024 Cyface GmbH * * This file is part of the Cyface SDK for Android. * @@ -19,24 +19,25 @@ package de.cyface.synchronization import android.util.Log -import de.cyface.model.MeasurementIdentifier -import de.cyface.model.RequestMetaData import de.cyface.persistence.DefaultPersistenceLayer import de.cyface.persistence.model.Measurement import de.cyface.persistence.model.Modality import de.cyface.persistence.serialization.MeasurementSerializer import de.cyface.serializer.DataSerializable +import de.cyface.uploader.model.metadata.ApplicationMetaData +import de.cyface.uploader.model.metadata.AttachmentMetaData +import de.cyface.uploader.model.metadata.DeviceMetaData +import de.cyface.uploader.model.metadata.GeoLocation +import de.cyface.uploader.model.metadata.MeasurementMetaData import de.cyface.utils.CursorIsNullException import java.io.File -import kotlin.math.log +import java.util.UUID /** * Contains utility methods and constants required by the tests within the synchronization project. * * @author Klemens Muthmann * @author Armin Schnabel - * @version 2.4.2 - * @since 2.1.0 */ object TestUtils { /** @@ -85,27 +86,33 @@ object TestUtils { imageCount: Int, videoCount: Int, filesSize: Long - ): RequestMetaData { + ): de.cyface.uploader.model.Measurement { // Load meta data val tracks = persistence.loadTracks(measurement.id) val startLocation = tracks[0].geoLocations[0]!! val lastTrack = tracks[tracks.size - 1].geoLocations val endLocation = lastTrack[lastTrack.size - 1]!! - val deviceId = "testDevi-ce00-42b6-a840-1b70d30094b8" // Must be a valid UUID - val id = MeasurementIdentifier(deviceId, measurement.id) - val startRecord = RequestMetaData.GeoLocation( + val deviceId = UUID.randomUUID() + val startRecord = GeoLocation( startLocation.timestamp, startLocation.lat, startLocation.lon ) - val endRecord = RequestMetaData.GeoLocation( + val endRecord = GeoLocation( endLocation.timestamp, endLocation.lat, endLocation.lon ) - return RequestMetaData( - deviceId, id.measurementIdentifier.toString(), - "testOsVersion", "testDeviceType", "testAppVersion", - measurement.distance, locationCount.toLong(), startRecord, endRecord, - Modality.BICYCLE.databaseIdentifier, 3, logCount, imageCount, videoCount, filesSize + return de.cyface.uploader.model.Measurement( + de.cyface.uploader.model.MeasurementIdentifier(deviceId, measurement.id), + DeviceMetaData("testOsVersion", "testDeviceType"), + ApplicationMetaData("testAppVersion", 3), + MeasurementMetaData( + measurement.distance, + locationCount.toLong(), + startRecord, + endRecord, + Modality.BICYCLE.databaseIdentifier, + ), + AttachmentMetaData(logCount, imageCount, videoCount, filesSize), ) } From 381f683c6e703eedc9f6652f4b85651e91bf0ba3 Mon Sep 17 00:00:00 2001 From: Armin Date: Tue, 16 Jul 2024 09:48:47 +0200 Subject: [PATCH 6/6] Upgrade uploader to 1.4.1 --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index f890690bd..cbb34c9b5 100644 --- a/build.gradle +++ b/build.gradle @@ -53,7 +53,7 @@ ext { // When `android-app` is checkout out, `rootProject.uploaderVersion` in the submodules will point // to `android-app/build.gradle` instead of `submodule/build.gradle`. cyfaceSerializationVersion = "3.4.0" - cyfaceUploaderVersion = "1.4.0" + cyfaceUploaderVersion = "1.4.1" // Android SDK versions minSdkVersion = 21 // device support