Flutter Android:从Intent获取文件及读取内容的问题
问题解决方案
1. 解决Intent路径格式不一致的问题
直接取intent.data?.path会因Uri协议类型不同导致路径混乱:当Uri为file://协议时返回文件系统路径,content://协议时返回内容提供者的内部路径。正确做法是通过ContentResolver解析真实文件路径:
修正后的Kotlin代码:
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) handleOpenFileUrl(intent) } override fun onNewIntent(intent: Intent) { super.onNewIntent(intent) handleOpenFileUrl(intent) } private fun handleOpenFileUrl(intent: Intent?) { intent?.data?.let { uri -> intentPath = getRealPathFromUri(uri) } } private fun getRealPathFromUri(uri: Uri): String? { val scheme = uri.scheme return when (scheme) { "file" -> uri.path "content" -> { val projection = arrayOf(MediaStore.Files.FileColumns.DATA) contentResolver.query(uri, projection, null, null, null)?.use { cursor -> if (cursor.moveToFirst()) { val columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Files.FileColumns.DATA) return cursor.getString(columnIndex) } } null } else -> null } }
注:Android API 29+直接获取DATA列可能受权限限制,此时可通过ContentResolver打开输入流读取文件内容,再传递给Flutter;或使用DocumentFile操作文件。
2. Flutter端获取文件并读取内容
通过MethodChannel将原生处理后的文件路径(或内容)传递到Flutter层:
步骤1:原生端配置MethodChannel
在MainActivity中初始化通道并提供路径获取方法:
private val CHANNEL = "com.example.file_channel" private var intentPath: String? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler { call, result -> when (call.method) { "getOpenedFilePath" -> { result.success(intentPath) } else -> result.notImplemented() } } handleOpenFileUrl(intent) } // 保留之前的onNewIntent、handleOpenFileUrl、getRealPathFromUri方法
步骤2:Flutter端调用通道并读取文件
import 'package:flutter/services.dart'; import 'dart:io'; class FileHandler { static const MethodChannel _channel = MethodChannel('com.example.file_channel'); static Future<String?> getOpenedFilePath() async { try { return await _channel.invokeMethod('getOpenedFilePath'); } on PlatformException catch (e) { print("获取文件路径失败: ${e.message}"); return null; } } static Future<String?> readFileContent() async { String? path = await getOpenedFilePath(); if (path != null && File(path).existsSync()) { return await File(path).readAsString(); } return null; } }
在需要读取文件的地方调用FileHandler.readFileContent()即可获取内容。若高版本Android无法获取真实路径,可在原生端直接读取文件输入流,将内容转为字符串后通过MethodChannel传递给Flutter。
内容的提问来源于stack exchange,提问作者Maximilian Kröll
相关产品推荐
相关产品推荐

