如何解决直接将图像从 Android 图库共享到我的 flutter 应用程序时收到的奇怪且不完整的 Uri 和路径

问题描述 投票:0回答:2

我在 Kotlin 中为 flutter 应用程序编写了一个功能,可以将媒体文件直接从 Android 手机图库共享到应用程序。

在我测试过的许多设备上运行良好,例如 Realme 3 Pro、Oneplus 6t、Samsung m40。

但是,对于

Asus Zenfone Max Pro M2
来说,共享任何媒体文件都会收到奇怪且不完整的
URI
path

来自 Kotlin 代码的日志

D/URI =====(26032) : content://com.android.providers.downloads.documents/document/624

D/路径 =====(26032): /document/624

Kotlin 代码

override fun onAttachedToActivity(binding: ActivityPluginBinding) {
    this.binding = binding
    binding.addOnNewIntentListener(this)
    handleIntent(binding.activity.intent, true)
}
----------------------------------------------------------------------
private fun handleIntent(intent: Intent, initial: Boolean) {
    when {
        (intent.type?.startsWith("text") != true)
                && (intent.action == Intent.ACTION_SEND
                || intent.action == Intent.ACTION_SEND_MULTIPLE) -> { // Sharing images or videos

            val value = getMediaUris(intent)
            if (initial) initialMedia = value
            latestMedia = value
            eventSinkMedia?.success(latestMedia?.toString())
        }
...
----------------------------------------------------------------------
private fun getMediaUris(intent: Intent?): JSONArray? {
    if (intent == null) return null

    return when (intent.action) {
        Intent.ACTION_SEND -> {
            val uri = intent.getParcelableExtra<Uri>(Intent.EXTRA_STREAM)
            Log.d("URI =====",uri)
            val path = uri?.let{ FileDirectory.getPathFromUri(applicationContext, it) } ?: uri?.path
            Log.d("Path =====",path)
            if (path != null) {
...

设备信息

Device Name: Asus Zenfone Max Pro M2
Android Version: 9
External SD card: present

如何解析此 URI 并获取包含文件名和扩展名的正确路径?

android flutter kotlin flutter-android asus
2个回答
0
投票

您可以使用 uri_to_file 插件从

content://uri
获取路径。使用时,只需解析 uri 并使用
toFile(uri)

import 'package:uri_to_file/uri_to_file.dart';

try {
  String uriPath = 'content://com.android.providers.downloads.documents/document/624';
  Uri uri = Uri.parse(uriPath);
  File file = await toFile(uri);
} catch (e) {
  debugPrint(e);
}

0
投票

更新 getMediaUris

private fun getMediaUris(intent: Intent?): JSONArray? {
    if (intent == null) return null

    return when (intent.action) {
        Intent.ACTION_SEND -> {
            val uri = intent.getParcelableExtra<Uri>(Intent.EXTRA_STREAM)
            uri?.let {
                val path = FileDirectory.getPathFromUri(applicationContext, it)
                    ?: getFilePathFromURI(it) // Fallback if path is null
                Log.d("Path =====", path)
            }
            // Continue with the rest of your logic
        }
        else -> null
    }
}

创建辅助函数

private fun getFilePathFromURI(uri: Uri): String? {
    return if (DocumentsContract.isDocumentUri(applicationContext, uri)) {
        when (uri.authority) {
            "com.android.providers.media.documents" -> {
                val documentId = DocumentsContract.getDocumentId(uri)
                val split = documentId.split(":")
                val type = split[0]

                val contentUri = when (type) {
                    "image" -> MediaStore.Images.Media.EXTERNAL_CONTENT_URI
                    "video" -> MediaStore.Video.Media.EXTERNAL_CONTENT_URI
                    "audio" -> MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
                    else -> null
                }

                contentUri?.let {
                    val selection = "_id=?"
                    val selectionArgs = arrayOf(split[1])
                    getColumnData(it, selection, selectionArgs)
                }
            }
            "com.android.providers.downloads.documents" -> {
                val documentId = DocumentsContract.getDocumentId(uri)
                val contentUri = ContentUris.withAppendedId(
                    Uri.parse("content://downloads/public_downloads"), documentId.toLong()
                )
                getColumnData(contentUri, null, null)
            }
            else -> null
        }
    } else {
        null
    }
}

private fun getColumnData(uri: Uri, selection: String?, selectionArgs: Array<String>?): String? {
    val projection = arrayOf(MediaStore.MediaColumns.DATA)
    contentResolver.query(uri, projection, selection, selectionArgs, null)?.use { cursor ->
        if (cursor.moveToFirst()) {
            val columnIndex = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DATA)
            return cursor.getString(columnIndex)
        }
    }
    return null
}

并检查这一点

<application
    android:requestLegacyExternalStorage="true"
    ... >
</application>
© www.soinside.com 2019 - 2024. All rights reserved.