Modification time is not preserved when uploading MediaStore content via Android share
まだ誰も着手していません。
評価
- 難易度
- 2/5
- 見積もり時間
- 1〜3時間
- 初心者へのやさしさ
- 84/100
調査の方向性
app/src/main/java/com/owncloud/android/ui/asynctasks/CopyAndUploadContentUrisTask.kt から始め、特に queryLastModified() を確認し、共有された MediaStore の content:// URI がアップロード前にどのようにコピーされるかを調べます。date_modified を公開するファイルで共有フローを再現し、元の変更時刻が保持されることを確認するとともに、タイムスタンプを利用できない場合は既存のフォールバックが変更されないことを確認します。
索引モデルが issue の本文から書いたものです。
説明
⚠️ Before posting ⚠️
- This is a bug, not a question or an enhancement.
- I've searched for similar issues and didn't find a duplicate.
- I've written a clear and descriptive title for this issue, not just "Bug" or "Crash".
- I agree to follow Nextcloud's Code of Conduct.
Steps to reproduce
- Take an existing media file (photo) whose modification time is older than the current time.
- Upload that file normally from within the Nextcloud Android app.
- Verify that the original modification time is preserved on the server (as expected).
- Delete the uploaded file again or choose another destination.
- Open the same file in an Android app with sharing possibility, which shares it as a MediaStore
content://URI, e.g. the Google Photos app. - Use the Share function and select Nextcloud.
- Upload the file to Nextcloud.
- Compare the modification time of the uploaded file and see that it has the upload time as modification time instead of the original modification time.
Expected behaviour
The original file modification time should be preserved, just as it is when uploading the same file directly from within the Nextcloud app, provided that the source ContentProvider exposes the modification time.
Actual behaviour
When the file is uploaded through Android's Share function, the modification time is not preserved and the uploaded file gets the time of the upload / temporary copy instead.
Android version
17
Device brand and model
Google Pixel 11 Pro
Stock or custom OS?
Stock
Nextcloud android app version
35.0.0
Nextcloud server version
n/a – FileRun server, version 2026.3.0
Using a reverse proxy?
No
Android logs
No response
Server error logs
Additional information
I am using the Nextcloud Android app with a FileRun server, not a Nextcloud Server. However, this issue appears to happen on the Android client side before the actual upload, so the server implementation should not be relevant.
Looking at the current Android app code, CopyAndUploadContentUrisTask.queryLastModified() only checks:
DocumentsContract.Document.COLUMN_LAST_MODIFIED
If that column is not available, the function returns 0L and the modification time is not applied to the temporary file.
This seems problematic for files shared through Android's share sheet using a MediaStore URI such as:
content://media/external/images/media/...
MediaStore commonly exposes the modification timestamp as:
MediaStore.MediaColumns.DATE_MODIFIED
rather than DocumentsContract.Document.COLUMN_LAST_MODIFIED.
This situation can also be seen in the historical issues #7745 and #7752, where a MediaStore cursor exposed date_modified but not last_modified.
A possible solution would be to first try DocumentsContract.Document.COLUMN_LAST_MODIFIED and, if unavailable, fall back to MediaStore.MediaColumns.DATE_MODIFIED.
Please note that the units differ:
DocumentsContract.Document.COLUMN_LAST_MODIFIED: milliseconds since epochMediaStore.MediaColumns.DATE_MODIFIED: seconds since epoch
So the MediaStore value would need to be converted to milliseconds before applying it.
Suggested fix:
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 documentColumn =
cursor.getColumnIndex(
DocumentsContract.Document.COLUMN_LAST_MODIFIED
)
if (
documentColumn >= 0 &&
!cursor.isNull(documentColumn)
) {
return@use cursor.getLong(documentColumn)
}
val mediaColumn =
cursor.getColumnIndex(
MediaStore.MediaColumns.DATE_MODIFIED
)
if (
mediaColumn >= 0 &&
!cursor.isNull(mediaColumn)
) {
return@use TimeUnit.SECONDS.toMillis(
cursor.getLong(mediaColumn)
)
}
0L
} ?: 0L
}.getOrDefault(0L)
If neither value is exposed by the provider, the current fallback behaviour could remain unchanged.
- 主要言語
- Kotlin
- スター
- 5.6k
- フォーク
- 2k
- 平均マージ
- 1日 21時間
- マージ済み PR(30日)
- 101
コントリビューションガイド
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
nextcloud/android のほかの issue
-
0. Needs triage
難易度 2/5 1〜3時間 初心者へのやさしさ 84/100
-
0. Needs triage bug
難易度 2/5 1〜3時間 初心者へのやさしさ 85/100
-
0. Needs triage bug
難易度 2/5 1〜3時間 初心者へのやさしさ 64/100
-
0. Needs triage enhancement
難易度 2/5 1〜3時間 初心者へのやさしさ 65/100
-
0. Needs triage bug feature: dashboard and widgets performance: ISE/IAE :confused:
難易度 2/5 1〜3時間 初心者へのやさしさ 68/100
nextcloud/android の issue をすべて見る
似ている issue
-
bug
難易度 2/5 1〜3時間 初心者へのやさしさ 68/100
-
難易度 2/5 1〜3時間 初心者へのやさしさ 76/100
bitcoindevkit/bdk-ffi#1125 ·
-
Issue: Bug
難易度 1/5 1時間未満 初心者へのやさしさ 91/100
OpenAPITools/openapi-generator#24978 ·
-
helsemelding-json-schema json-schema-core
難易度 2/5 1〜3時間 初心者へのやさしさ 68/100
-
contributor: external needs review
難易度 2/5 1〜3時間 初心者へのやさしさ 82/100