Android中Intent.ACTION_VIEW打开文件报“no file received”错误排查
使用Intent.ACTION_VIEW打开文件时出现“no file received”错误的解决方案
我在使用Intent.ACTION_VIEW打开文件时遇到了“no file received”错误,以下是相关信息及修复方案:
当前代码
重点关注fileOpener变量,SafeFiles为自定义类无需过多关注:
fileOpener = { file: File -> val uri: Uri = Uri.fromFile(file).normalizeScheme() val mime = MimeTypeMap .getSingleton() .getMimeTypeFromExtension(safeFile.extension.substring(1)) Log.d(TAG, "mime = $mime") val intent = Intent(Intent.ACTION_VIEW) intent.data = uri intent.type = mime intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK Log.d( TAG, "data received:" + "uri = $uri\n" + "extension = ${safeFile.extension.substring(1)}\n" + "path = ${file.absolutePath}\n" + "size = ${file.totalSpace} " ) CoroutineScope(Dispatchers.Main).launch { context!!.startActivity(intent) } }
日志信息
2022-07-30 16:41:41.005 19233-19285/com.example.cryptile D/SafeViewerFragment: mime = image/png 2022-07-30 16:41:41.005 19233-19285/com.example.cryptile D/SafeViewerFragment: data received:uri = file:///storage/emulated/0/Cryptile/CRYPTILE_2022_07_30/.CACHE/aa854c7e-9fa4-4313-9750-cf58fde467b8.png extension = png path = /storage/emulated/0/Cryptile/CRYPTILE_2022_07_30/.CACHE/aa854c7e-9fa4-4313-9750-cf58fde467b8.png size = 119640424448
注:日志中totalSpace是存储分区总容量,并非文件实际大小,应使用file.length()验证文件有效性。文件确实存在且可通过系统文件管理器打开,因此问题出在FileProvider的使用上。
Manifest配置
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.cryptile"> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.USE_BIOMETRIC" /> <application android:name=".app_data.AppApplication" android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.CRYPTILE"> <activity android:name=".MainActivity" android:exported="true"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <provider android:name="androidx.core.content.FileProvider" android:authorities="com.example.cryptile.fileProvider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/filepaths" /> </provider> </application> </manifest>
filepaths.xml配置
<?xml version="1.0" encoding="utf-8"?> <paths> <external-path name="/storage/emulated/0" path="." /> </paths>
问题根源
你当前用Uri.fromFile(file)生成的是file://格式Uri,Android 7.0(API 24)及以上版本中,这种Uri无法直接共享给其他应用——其他应用没有权限访问该路径,因此出现“no file received”错误。虽然已配置FileProvider,但并未实际使用它生成合法的content://格式Uri。
修复步骤
1. 修改Uri生成逻辑,使用FileProvider
替换Uri.fromFile(file)为FileProvider生成content://Uri,并给Intent添加权限标记,确保目标应用能读取文件。
2. 修正filepaths.xml的name属性
name是路径别名,无需写完整路径,避免冲突。
3. 合并Intent的data和type设置
分开设置intent.data和intent.type可能导致冲突,建议用setDataAndType统一设置。
修改后的代码
fileOpener = { file: File -> val mime = MimeTypeMap .getSingleton() .getMimeTypeFromExtension(safeFile.extension.substring(1)) Log.d(TAG, "mime = $mime") // 使用FileProvider生成合法的content:// Uri val uri: Uri = FileProvider.getUriForFile( context!!, "com.example.cryptile.fileProvider", // 与Manifest中authorities保持一致 file ) val intent = Intent(Intent.ACTION_VIEW) // 统一设置data和type,避免冲突 intent.setDataAndType(uri, mime) // 添加权限标记,允许目标应用读取文件 intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_GRANT_READ_URI_PERMISSION Log.d( TAG, "data received:" + "uri = $uri\n" + "extension = ${safeFile.extension.substring(1)}\n" + "path = ${file.absolutePath}\n" + "size = ${file.length()} " // 改用file.length()获取实际文件大小 ) CoroutineScope(Dispatchers.Main).launch { context!!.startActivity(intent) } }
修正后的filepaths.xml
<?xml version="1.0" encoding="utf-8"?> <paths> <external-path name="external_files" path="." /> </paths>
内容的提问来源于stack exchange,提问作者Vaishnav Kanhirathingal
相关产品推荐
相关产品推荐

