Android 13/11下如何读取PC创建并复制到平板的文件?
解决方案:Android 11+下读取PC复制的外部文件(无需MANAGE_EXTERNAL_STORAGE)
方法1:通过SAF获取持久化文件权限并处理文件
使用ACTION_OPEN_DOCUMENT让用户选择文件后,可申请持久化访问权限,后续无需重复选择就能直接操作该文件。通过ContentResolver可实现读取、修改文件内容,而非仅“查看”。
实现代码:
private val openFileLauncher = registerForActivityResult(ActivityResultContracts.OpenDocument()) { uri: Uri? -> uri ?: return@registerForActivityResult // 申请持久化权限,后续无需再次让用户选择 contentResolver.takePersistableUriPermission( uri, Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION ) // 读取文件内容并处理赛事数据 readAndProcessRaceData(uri) // 如需修改文件,可调用writeFileContent(uri, "更新后的赛事内容") } private fun readAndProcessRaceData(uri: Uri) { contentResolver.openInputStream(uri)?.use { inputStream -> val fileContent = inputStream.bufferedReader().readText() // 在这里解析游艇详情、更新赛事管理数据 Log.d(TAG, "读取到赛事数据:$fileContent") } } private fun writeFileContent(uri: Uri, content: String) { contentResolver.openOutputStream(uri)?.use { outputStream -> outputStream.write(content.toByteArray()) } }
调用原有的letUserChooseFile()触发文件选择,用户完成选择后即可自动处理文件。
方法2:通过MediaStore查询公共目录下的PC复制文件
若文本文件存放在Downloads、Documents等公共目录,PC复制的文件会被MediaStore自动索引,无需用户手动选择,可直接查询获取文件。
实现代码:
private fun queryPublicTextFiles() { val projection = arrayOf( MediaStore.Files.FileColumns._ID, MediaStore.Files.FileColumns.DISPLAY_NAME ) // 筛选文本类型文件 val selection = "${MediaStore.Files.FileColumns.MIME_TYPE} = ?" val selectionArgs = arrayOf("text/plain") contentResolver.query( MediaStore.Files.getContentUri("external"), projection, selection, selectionArgs, null )?.use { cursor -> while (cursor.moveToNext()) { val fileName = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Files.FileColumns.DISPLAY_NAME)) val fileUri = ContentUris.withAppendedId( MediaStore.Files.getContentUri("external"), cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Files.FileColumns._ID)) ) Log.d(TAG, "找到赛事文件:$fileName") // 调用readAndProcessRaceData(fileUri)处理文件 } } }
注意:Android 10+ 建议通过Uri+ContentResolver访问文件,不要依赖
DATA字段的本地路径。
方法3:引导用户存入应用私有目录(可选)
可提示用户将PC复制的文件放到应用私有外部目录,此目录无需特殊权限,你的应用能直接用原有的File API读取:
// 获取应用私有外部目录路径 val appPrivateDir = getExternalFilesDir(null) Log.d(TAG, "请将赛事文件放到此目录:${appPrivateDir?.absolutePath}")
文件存入后,原有的listFiles()代码即可正常读取。
内容的提问来源于stack exchange,提问作者RatherBeSailing
相关产品推荐
相关产品推荐

