Skip to content
Open
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
* Nextcloud - Android Client
*
* SPDX-FileCopyrightText: 2026 Alper Ozturk <alper.ozturk@nextcloud.com>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

package com.owncloud.android.ui.asynctasks

import android.content.ContentResolver
import android.net.Uri
import android.provider.DocumentsContract
import android.provider.MediaStore
import android.system.Os
import android.system.OsConstants
import android.system.StructStat
import java.util.concurrent.TimeUnit

class ContentUriLastModifiedResolver(private val contentResolver: ContentResolver) {
companion object {
private val TIMESTAMP_COLUMNS = listOf(
DocumentsContract.Document.COLUMN_LAST_MODIFIED to TimeUnit.MILLISECONDS,
MediaStore.MediaColumns.DATE_MODIFIED to TimeUnit.SECONDS
)
}

fun resolve(uri: Uri): Long = fromMetadata(uri).takeIf { it > 0L } ?: fromFileDescriptor(uri)

private fun fromMetadata(uri: Uri): Long = runCatching {
contentResolver.query(uri, null, null, null, null)?.use { cursor ->
if (!cursor.moveToFirst()) return@use null

TIMESTAMP_COLUMNS.firstNotNullOfOrNull { (column, unit) ->
runCatching {
cursor.getColumnIndex(column)
.takeIf { it >= 0 && !cursor.isNull(it) }
?.let(cursor::getLong)
?.takeIf { it > 0L }
?.let(unit::toMillis)
}.getOrNull()
}
}
}.getOrNull() ?: 0L

private fun fromFileDescriptor(uri: Uri): Long = runCatching {
contentResolver.openFileDescriptor(uri, "r")?.use { pfd ->
Os.fstat(pfd.fileDescriptor)
.takeIf { OsConstants.S_ISREG(it.st_mode) }
?.lastModifiedMillis()
?.takeIf { it > 0L }
}
}.getOrNull() ?: 0L

private fun StructStat.lastModifiedMillis(): Long =
TimeUnit.SECONDS.toMillis(st_mtim.tv_sec) + TimeUnit.NANOSECONDS.toMillis(st_mtim.tv_nsec)
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ package com.owncloud.android.ui.asynctasks
import android.content.ContentResolver
import android.content.Context
import android.net.Uri
import android.provider.DocumentsContract
import android.widget.Toast
import com.nextcloud.client.account.User
import com.nextcloud.client.jobs.upload.FileUploadHelper
Expand Down Expand Up @@ -66,11 +65,12 @@ class CopyAndUploadContentUrisTask(
val localPaths = arrayOfNulls<String>(sourceUris.size)
val resolvedRemotePaths = arrayOfNulls<String>(sourceUris.size)
var currentTempPath: String? = null
val lastModifiedResolver = ContentUriLastModifiedResolver(contentResolver)

return try {
sourceUris.forEachIndexed { index, uri ->
val remotePath = remotePaths[index]
val lastModified = queryLastModified(contentResolver, uri)
val lastModified = lastModifiedResolver.resolve(uri)

currentTempPath = "${FileStorageUtils.getTemporalPath(user.accountName)}$remotePath"
val cacheFile = File(currentTempPath)
Expand Down Expand Up @@ -130,18 +130,11 @@ class CopyAndUploadContentUrisTask(
}
}

private fun queryLastModified(contentResolver: ContentResolver, uri: Uri): Long = runCatching {
contentResolver.query(uri, null, null, null, null)?.use { cursor ->
if (!cursor.moveToFirst()) return@use 0L
val col = cursor.getColumnIndex(DocumentsContract.Document.COLUMN_LAST_MODIFIED)
if (col >= 0) cursor.getLong(col) else 0L
} ?: 0L
}.getOrDefault(0L)

private fun applyLastModified(file: File, lastModified: Long) {
if (lastModified == 0L) return
runCatching { file.setLastModified(lastModified) }
.onFailure { Log_OC.w(TAG, "Could not set lastModified on cache file: ${it.message}") }
if (lastModified <= 0L) return
if (!file.setLastModified(lastModified)) {
Log_OC.w(TAG, "Could not set lastModified on cache file: ${file.path}")
}
}

private fun dispatchResult(result: ResultCode) {
Expand Down
Loading