fixed failing scan of items copied to SD card on older devices
This commit is contained in:
parent
1ae2ceb62a
commit
2db168051e
3 changed files with 82 additions and 59 deletions
|
@ -16,6 +16,7 @@ All notable changes to this project will be documented in this file.
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- rendering of panoramas with inconsistent metadata
|
- rendering of panoramas with inconsistent metadata
|
||||||
|
- failing scan of items copied to SD card on older devices
|
||||||
|
|
||||||
## <a id="v1.7.1"></a>[v1.7.1] - 2022-10-09
|
## <a id="v1.7.1"></a>[v1.7.1] - 2022-10-09
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,7 @@ import java.io.File
|
||||||
import java.io.OutputStream
|
import java.io.OutputStream
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import java.util.concurrent.CompletableFuture
|
import java.util.concurrent.CompletableFuture
|
||||||
|
import kotlin.coroutines.Continuation
|
||||||
import kotlin.coroutines.resume
|
import kotlin.coroutines.resume
|
||||||
import kotlin.coroutines.resumeWithException
|
import kotlin.coroutines.resumeWithException
|
||||||
import kotlin.coroutines.suspendCoroutine
|
import kotlin.coroutines.suspendCoroutine
|
||||||
|
@ -784,7 +785,29 @@ class MediaStoreImageProvider : ImageProvider() {
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun scanNewPath(context: Context, path: String, mimeType: String): FieldMap =
|
suspend fun scanNewPath(context: Context, path: String, mimeType: String): FieldMap =
|
||||||
suspendCoroutine { cont ->
|
suspendCoroutine { cont -> tryScanNewPath(context, path = path, mimeType = mimeType, cont) }
|
||||||
|
|
||||||
|
private fun tryScanNewPath(context: Context, path: String, mimeType: String, cont: Continuation<FieldMap>, iteration: Int = 0) {
|
||||||
|
// `scanFile` may (e.g. when copying to SD card on Android 10 (API 29)):
|
||||||
|
// 1) yield no URI,
|
||||||
|
// 2) yield a temporary URI that fails when queried,
|
||||||
|
// 3) yield a temporary URI that succeeds when queried right away, but the Media Store actually won't have an entry for it until device reboot.
|
||||||
|
if (iteration > 5) {
|
||||||
|
// give up
|
||||||
|
cont.resumeWithException(Exception("failed to scan new path=$path after $iteration iterations"))
|
||||||
|
return
|
||||||
|
} else if (iteration > 0) {
|
||||||
|
// waiting and retrying just once usually works out for cases 1) and 2)
|
||||||
|
Thread.sleep(iteration * 100L)
|
||||||
|
} else if (iteration == 0 && Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
|
||||||
|
// waiting before the first scan usually works out for case 3)
|
||||||
|
StorageUtils.getVolumePath(context, path)?.let { volumePath ->
|
||||||
|
if (volumePath != StorageUtils.getPrimaryVolumePath(context)) {
|
||||||
|
Thread.sleep(100L)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
MediaScannerConnection.scanFile(context, arrayOf(path), arrayOf(mimeType)) { _, newUri: Uri? ->
|
MediaScannerConnection.scanFile(context, arrayOf(path), arrayOf(mimeType)) { _, newUri: Uri? ->
|
||||||
fun scanUri(uri: Uri?): FieldMap? {
|
fun scanUri(uri: Uri?): FieldMap? {
|
||||||
uri ?: return null
|
uri ?: return null
|
||||||
|
@ -830,12 +853,11 @@ class MediaStoreImageProvider : ImageProvider() {
|
||||||
|
|
||||||
if (newFields != null) {
|
if (newFields != null) {
|
||||||
cont.resume(newFields)
|
cont.resume(newFields)
|
||||||
} else {
|
return@scanFile
|
||||||
cont.resumeWithException(Exception("failed to get item details from provider at contentUri=$contentUri (from newUri=$newUri)"))
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
cont.resumeWithException(Exception("failed to get URI of item at path=$path"))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tryScanNewPath(context, path = path, mimeType = mimeType, cont, iteration + 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
18
pubspec.lock
18
pubspec.lock
|
@ -14,7 +14,7 @@ packages:
|
||||||
name: _flutterfire_internals
|
name: _flutterfire_internals
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.4"
|
version: "1.0.5"
|
||||||
analyzer:
|
analyzer:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -126,14 +126,14 @@ packages:
|
||||||
name: cloud_firestore_platform_interface
|
name: cloud_firestore_platform_interface
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "5.8.1"
|
version: "5.8.2"
|
||||||
cloud_firestore_web:
|
cloud_firestore_web:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: cloud_firestore_web
|
name: cloud_firestore_web
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.0.1"
|
version: "3.0.2"
|
||||||
collection:
|
collection:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
@ -147,7 +147,7 @@ packages:
|
||||||
name: connectivity_plus
|
name: connectivity_plus
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.0.1"
|
version: "3.0.2"
|
||||||
connectivity_plus_platform_interface:
|
connectivity_plus_platform_interface:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -284,7 +284,7 @@ packages:
|
||||||
name: firebase_core
|
name: firebase_core
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.0"
|
version: "2.1.0"
|
||||||
firebase_core_platform_interface:
|
firebase_core_platform_interface:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -305,14 +305,14 @@ packages:
|
||||||
name: firebase_crashlytics
|
name: firebase_crashlytics
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.0.1"
|
version: "3.0.2"
|
||||||
firebase_crashlytics_platform_interface:
|
firebase_crashlytics_platform_interface:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: firebase_crashlytics_platform_interface
|
name: firebase_crashlytics_platform_interface
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.3.2"
|
version: "3.3.3"
|
||||||
flex_color_picker:
|
flex_color_picker:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
@ -545,7 +545,7 @@ packages:
|
||||||
name: lints
|
name: lints
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.0"
|
version: "2.0.1"
|
||||||
lists:
|
lists:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -724,7 +724,7 @@ packages:
|
||||||
name: pdf
|
name: pdf
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.8.3"
|
version: "3.8.4"
|
||||||
percent_indicator:
|
percent_indicator:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
|
Loading…
Reference in a new issue