Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Task/leip 287 fix jpg header #306

Merged
merged 6 commits into from
Oct 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -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.2"
cyfaceUploaderVersion = "1.5.0"
cyfaceUploaderVersion = "1.5.1"

// Android SDK versions
minSdkVersion = 21 // device support
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2017-2023 Cyface GmbH
* Copyright 2017-2024 Cyface GmbH
*
* This file is part of the Cyface SDK for Android.
*
Expand Down Expand Up @@ -65,8 +65,6 @@ import kotlin.math.max
*
* @author Klemens Muthmann
* @author Armin Schnabel
* @version 19.1.0
* @since 2.0.0
* @property persistenceBehaviour The [PersistenceBehaviour] defines how the `Persistence` layer works.
* We need this behaviour to differentiate if the [DefaultPersistenceLayer] is used for live capturing
* and or to load existing data.
Expand Down Expand Up @@ -319,15 +317,15 @@ class DefaultPersistenceLayer<B : PersistenceBehaviour?> : PersistenceLayer<B> {
.file
Validate.isTrue(accelerationFile.delete())
} catch (e: NoSuchFileException) {
Log.v(TAG, "markAsSynchronized: No acceleration file found to delete, nothing to do")
Log.v(TAG, "markAsSynchronized: No acceleration file found to delete, nothing to do", e)
}
try {
val rotationFile = Point3DFile.loadFile(
context!!, fileIOHandler, measurementId, Point3DType.ROTATION
).file
Validate.isTrue(rotationFile.delete())
} catch (e: NoSuchFileException) {
Log.v(TAG, "markAsSynchronized: No rotation file found to delete, nothing to do")
Log.v(TAG, "markAsSynchronized: No rotation file found to delete, nothing to do", e)
}
try {
val directionFile = Point3DFile.loadFile(
Expand All @@ -336,7 +334,7 @@ class DefaultPersistenceLayer<B : PersistenceBehaviour?> : PersistenceLayer<B> {
.file
Validate.isTrue(directionFile.delete())
} catch (e: NoSuchFileException) {
Log.v(TAG, "markAsSynchronized: No direction file found to delete, nothing to do")
Log.v(TAG, "markAsSynchronized: No direction file found to delete, nothing to do", e)
}

// Also delete syncable attachments binaries when the measurement is skipped or deprecated
Expand Down Expand Up @@ -421,8 +419,13 @@ class DefaultPersistenceLayer<B : PersistenceBehaviour?> : PersistenceLayer<B> {
private fun markSavedAs(newStatus: AttachmentStatus, attachment: Attachment) {

// The status in the database could be different from the one in the object so load it again
Validate.isTrue(attachment.status === AttachmentStatus.SAVED, "Unexpected status: ${attachment.status}")
Validate.isTrue(newStatus == AttachmentStatus.SYNCED || newStatus == AttachmentStatus.SKIPPED || newStatus == AttachmentStatus.DEPRECATED, "Unexpected status change from ${attachment.status} to $newStatus")
require(attachment.status === AttachmentStatus.SAVED) {
"Unexpected status: ${attachment.status}"
}
require(
newStatus == AttachmentStatus.SYNCED || newStatus == AttachmentStatus.SKIPPED ||
newStatus == AttachmentStatus.DEPRECATED
) { "Unexpected status change from ${attachment.status} to $newStatus" }
runBlocking {
attachmentDao!!.updateStatus(attachment.id, newStatus)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2023 Cyface GmbH
* Copyright 2023-2024 Cyface GmbH
*
* This file is part of the Cyface SDK for Android.
*
Expand Down Expand Up @@ -31,8 +31,6 @@ import de.cyface.protos.model.File.FileType
* Data access object which provides the API to interact with the [Attachment] database table.
*
* @author Armin Schnabel
* @version 1.0.0
* @since 7.10.0
*/
@Dao
interface AttachmentDao {
Expand All @@ -57,16 +55,22 @@ interface AttachmentDao {
/**
* Ordered by timestamp for [de.cyface.persistence.DefaultPersistenceLayer.loadTracks] to work.
*/
@Query("SELECT * FROM ${AttachmentTable.URI_PATH} WHERE ${BaseColumns.MEASUREMENT_ID} = :measurementId ORDER BY ${BaseColumns.TIMESTAMP} ASC")
@Query("SELECT * FROM ${AttachmentTable.URI_PATH} " +
"WHERE ${BaseColumns.MEASUREMENT_ID} = :measurementId ORDER BY ${BaseColumns.TIMESTAMP} ASC")
suspend fun loadAllByMeasurementId(measurementId: Long): List<Attachment>

@Query("SELECT * FROM ${AttachmentTable.URI_PATH} WHERE ${BaseColumns.MEASUREMENT_ID} = :measurementId LIMIT 1")
@Query("SELECT * FROM ${AttachmentTable.URI_PATH} " +
"WHERE ${BaseColumns.MEASUREMENT_ID} = :measurementId LIMIT 1")
suspend fun loadOneByMeasurementId(measurementId: Long): Attachment?

@Query("SELECT * FROM ${AttachmentTable.URI_PATH} WHERE ${BaseColumns.MEASUREMENT_ID} = :measurementId AND ${AttachmentTable.COLUMN_TYPE} = :type ORDER BY ${BaseColumns.TIMESTAMP} ASC")
@Query("SELECT * FROM ${AttachmentTable.URI_PATH} " +
"WHERE ${BaseColumns.MEASUREMENT_ID} = :measurementId " +
"AND ${AttachmentTable.COLUMN_TYPE} = :type ORDER BY ${BaseColumns.TIMESTAMP} ASC")
suspend fun loadOneByMeasurementIdAndType(measurementId: Long, type: FileType): Attachment?

@Query("SELECT * FROM ${AttachmentTable.URI_PATH} WHERE ${BaseColumns.MEASUREMENT_ID} = :measurementId AND ${AttachmentTable.COLUMN_STATUS} = :status ORDER BY ${BaseColumns.TIMESTAMP} ASC")
@Query("SELECT * FROM ${AttachmentTable.URI_PATH} " +
"WHERE ${BaseColumns.MEASUREMENT_ID} = :measurementId " +
"AND ${AttachmentTable.COLUMN_STATUS} = :status ORDER BY ${BaseColumns.TIMESTAMP} ASC")
suspend fun loadAllByMeasurementIdAndStatus(measurementId: Long, status: AttachmentStatus): List<Attachment>

/**
Expand All @@ -78,7 +82,8 @@ interface AttachmentDao {
/**
* Returns the number of files found for a specific [measurementId] and [type].
*/
@Query("SELECT COUNT(*) FROM ${AttachmentTable.URI_PATH} WHERE ${BaseColumns.MEASUREMENT_ID} = :measurementId AND ${AttachmentTable.COLUMN_TYPE} = :type")
@Query("SELECT COUNT(*) FROM ${AttachmentTable.URI_PATH} " +
"WHERE ${BaseColumns.MEASUREMENT_ID} = :measurementId AND ${AttachmentTable.COLUMN_TYPE} = :type")
suspend fun countByMeasurementIdAndType(measurementId: Long, type: FileType): Int

@Query("DELETE FROM ${AttachmentTable.URI_PATH} WHERE ${BaseColumns.MEASUREMENT_ID} = :measurementId")
Expand All @@ -87,9 +92,11 @@ interface AttachmentDao {
@Query("DELETE FROM ${AttachmentTable.URI_PATH}")
suspend fun deleteAll(): Int

@Query("UPDATE ${AttachmentTable.URI_PATH} SET ${AttachmentTable.COLUMN_SIZE} = :size WHERE ${BaseColumns.ID} = :id")
@Query("UPDATE ${AttachmentTable.URI_PATH} SET ${AttachmentTable.COLUMN_SIZE} = :size " +
"WHERE ${BaseColumns.ID} = :id")
suspend fun updateSize(id: Long, size: Long)

@Query("UPDATE ${AttachmentTable.URI_PATH} SET ${AttachmentTable.COLUMN_STATUS} = :status WHERE ${BaseColumns.ID} = :id")
@Query("UPDATE ${AttachmentTable.URI_PATH} SET ${AttachmentTable.COLUMN_STATUS} = :status " +
"WHERE ${BaseColumns.ID} = :id")
suspend fun updateStatus(id: Long, status: AttachmentStatus)
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2018-2023 Cyface GmbH
* Copyright 2018-2024 Cyface GmbH
*
* This file is part of the Cyface SDK for Android.
*
Expand Down Expand Up @@ -48,14 +48,13 @@ import java.util.zip.DeflaterOutputStream
*
* @author Klemens Muthmann
* @author Armin Schnabel
* @version 9.1.0
* @since 2.0.0
*/
class MeasurementSerializer {
/**
* Loads the [de.cyface.persistence.model.Measurement] with the provided identifier from the persistence layer serialized and compressed
* in the [MeasurementSerializer.TRANSFER_FILE_FORMAT_VERSION] format and writes it to a temp file, ready to
* be transferred.
* Loads the [de.cyface.persistence.model.Measurement] with the provided identifier from the
* persistence layer serialized and compressed in the
* [MeasurementSerializer.TRANSFER_FILE_FORMAT_VERSION] format and writes it to a temp file,
* ready to be transferred.
*
* **ATTENTION**: The caller needs to delete the file which is referenced by the returned `FileInputStream`
* when no longer needed or on program crash!
Expand All @@ -80,7 +79,8 @@ class MeasurementSerializer {
}
withContext(Dispatchers.IO) {
FileOutputStream(compressedTempFile).use { fileOutputStream ->
// As we create the DeflaterOutputStream with an FileOutputStream the compressed data is written to file
// As the DeflaterOutputStream is created with an FileOutputStream, the
// compressed data is written to file
loadSerializedCompressed(
fileOutputStream,
measurementId,
Expand Down Expand Up @@ -119,11 +119,8 @@ class MeasurementSerializer {
val cacheDir = persistenceLayer.cacheDir
var tempFile: File? = null
try {
tempFile =
withContext(Dispatchers.IO) {
File.createTempFile(TRANSFER_FILE_PREFIX, ".tmp", cacheDir)
}
withContext(Dispatchers.IO) {
tempFile = File.createTempFile(TRANSFER_FILE_PREFIX, ".tmp", cacheDir)
FileOutputStream(tempFile).use { fileOutputStream ->
loadSerializedAttachment(
fileOutputStream,
Expand All @@ -132,17 +129,18 @@ class MeasurementSerializer {
}
}
} catch (e: IOException) {
if (tempFile != null && tempFile.exists()) {
Validate.isTrue(tempFile.delete())
if (tempFile != null && tempFile!!.exists()) {
require(tempFile!!.delete())
}
throw IllegalStateException(e)
}
return tempFile
}

/**
* Writes the [de.cyface.persistence.model.Measurement] with the provided identifier from the persistence layer serialized and compressed
* in the [MeasurementSerializer.TRANSFER_FILE_FORMAT_VERSION] format, ready to be transferred.
* Writes the [de.cyface.persistence.model.Measurement] with the provided identifier from the
* persistence layer serialized and compressed in the
* [MeasurementSerializer.TRANSFER_FILE_FORMAT_VERSION] format, ready to be transferred.
*
* The Deflater ZLIB (RFC-1950) compression is used.
*
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2019-2023 Cyface GmbH
* Copyright 2019-2024 Cyface GmbH
*
* This file is part of the Cyface SDK for Android.
*
Expand Down Expand Up @@ -107,7 +107,9 @@ object TransferFileSerializer {
Validate.isTrue(measurement!!.fileFormatVersion == DefaultPersistenceLayer.PERSISTENCE_FILE_FORMAT_VERSION)
if (accelerationFile.exists()) {
Log.v(
TAG, String.format(
TAG,
String.format(
Locale.getDefault(),
"Serializing %s accelerations for synchronization.",
DataSerializable.humanReadableSize(accelerationFile.length(), true)
)
Expand All @@ -117,7 +119,9 @@ object TransferFileSerializer {
}
if (rotationFile.exists()) {
Log.v(
TAG, String.format(
TAG,
String.format(
Locale.getDefault(),
"Serializing %s rotations for synchronization.",
DataSerializable.humanReadableSize(rotationFile.length(), true)
)
Expand All @@ -127,7 +131,9 @@ object TransferFileSerializer {
}
if (directionFile.exists()) {
Log.v(
TAG, String.format(
TAG,
String.format(
Locale.getDefault(),
"Serializing %s directions for synchronization.",
DataSerializable.humanReadableSize(directionFile.length(), true)
)
Expand All @@ -152,7 +158,9 @@ object TransferFileSerializer {
throw IllegalStateException(e)
}
Log.d(
TAG, String.format(
TAG,
String.format(
Locale.getDefault(),
"Serialized %s",
DataSerializable.humanReadableSize(
(transferFileHeader.size + measurementBytes.size).toLong(),
Expand Down Expand Up @@ -302,25 +310,26 @@ object TransferFileSerializer {
// Currently loading one image per transfer file into memory (~ 2-5 MB / image).
// - To load add all high-res image data or video data in the future we cannot use the pre-compiled
// builder but have to stream the data without loading it into memory to avoid an OOM exception.
val transferFileHeader = DataSerializable.transferFileHeader()
//val transferFileHeader = DataSerializable.transferFileHeader()
//val uploadBytes = builder.build().toByteArray()
val uploadBytes = attachment.bytes.toByteArray()
try {
// The stream must be closed by the caller in a finally catch
withContext(Dispatchers.IO) {
bufferedOutputStream.write(transferFileHeader)
//bufferedOutputStream.write(transferFileHeader)
hb0 marked this conversation as resolved.
Show resolved Hide resolved
bufferedOutputStream.write(uploadBytes)
bufferedOutputStream.flush()
}
} catch (e: IOException) {
throw IllegalStateException(e)
}
Log.d(
TAG, String.format(
TAG,
String.format(
Locale.getDefault(),
"Serialized attachment: %s",
DataSerializable.humanReadableSize(
(transferFileHeader.size + uploadBytes.size).toLong(),
(/*transferFileHeader.size +*/ uploadBytes.size).toLong(),
true
)
)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2018-2023 Cyface GmbH
* Copyright 2018-2024 Cyface GmbH
*
* This file is part of the Cyface SDK for Android.
*
Expand Down Expand Up @@ -41,8 +41,6 @@
* support time for all involved.
*
* @author Armin Schnabel
* @version 2.2.0
* @since 2.2.0
*/
public class ErrorHandler extends BroadcastReceiver {

Expand Down Expand Up @@ -121,7 +119,6 @@ public void onReceive(final Context context, final Intent intent) {
Validate.notNull(errorCode);
String errorMessage;
switch (errorCode) {

case UNAUTHORIZED:
errorMessage = context
.getString(de.cyface.synchronization.R.string.error_message_credentials_incorrect);
Expand Down Expand Up @@ -234,8 +231,6 @@ public void onReceive(final Context context, final Intent intent) {
* A list of known Errors which are thrown by the Cyface SDK.
*
* @author Armin Schnabel
* @version 1.3.0
* @since 1.0.0
*/
public enum ErrorCode {

Expand Down Expand Up @@ -276,8 +271,6 @@ public static ErrorCode getValueForCode(final int code) {
* Interface for listeners receiving errors.
*
* @author Armin Schnabel
* @version 1.0.0
* @since 1.0.0
*/
public interface ErrorListener {
/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2017-2023 Cyface GmbH
* Copyright 2017-2024 Cyface GmbH
*
* This file is part of the Cyface SDK for Android.
*
Expand All @@ -23,13 +23,10 @@ package de.cyface.synchronization
*
* @author Klemens Muthmann
* @author Armin Schnabel
* @version 1.3.1
* @since 2.0.0
*/
object Constants {
/**
* Tag used to identify Logcat messages issued by instances of this package.
*/
const val TAG = "de.cyface.sync"

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package de.cyface.synchronization

/**
* Exception thrown when no location data is available but needed, e.g. to generate the upload
* path in `de.cyface.app.digural.upload.WebdavUploader`.
*
* @author Armin Schnabel
*/
class NoLocationData(message: String?) : Exception(message)
Loading
Loading