Android Studio中无法附加Drawable矢量图至邮件:空文件错误
解决Android Studio中无法附加Drawable矢量图到邮件的问题
嘿,我来帮你搞定这个问题!你遇到的「无法附加空文件」错误,核心原因是直接把Drawable资源当成设备文件系统里的独立文件来处理是行不通的——Drawable资源是打包在APK内部的,并不是存储在设备的文件系统中,所以你通过Uri.parse("android.resource://...")创建的File对象其实指向了一个不存在的路径,自然会被判定为空文件。
下面是具体的解决步骤和修正后的代码:
核心思路
我们需要先把APK里的Drawable资源读取出来,写入到设备的临时文件中,再把这个临时文件的Uri附加到邮件Intent里。同时要适配Android 7.0及以上的版本,避免FileUriExposedException异常,推荐使用FileProvider来生成安全的文件Uri。
修正后的实现代码
首先,确保你在AndroidManifest.xml中注册了FileProvider:
<application ...> <provider android:name="androidx.core.content.FileProvider" android:authorities="${applicationId}.fileprovider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths" /> </provider> </application>
然后在res/xml目录下创建file_paths.xml文件(如果没有xml目录就新建一个):
<?xml version="1.0" encoding="utf-8"?> <paths xmlns:android="http://schemas.android.com/apk/res/android"> <cache-path name="cache_images" path="images/" /> </paths>
最后修改你的enviarCorreu方法:
public void enviarCorreu(View view) { EditText t = findViewById(R.id.editText); String email = t.getText().toString(); Context context = this; // 1. 获取Drawable资源的输入流 InputStream inputStream = getResources().openRawResource(R.drawable.face); File tempFile = null; try { // 2. 在缓存目录创建临时文件 tempFile = new File(getCacheDir() + "/images/", "face.png"); // 确保父目录存在 if (!tempFile.getParentFile().exists()) { tempFile.getParentFile().mkdirs(); } // 3. 将资源流写入临时文件 FileOutputStream outputStream = new FileOutputStream(tempFile); byte[] buffer = new byte[1024]; int length; while ((length = inputStream.read(buffer)) > 0) { outputStream.write(buffer, 0, length); } outputStream.close(); inputStream.close(); // 4. 生成安全的文件Uri(适配Android 7.0+) Uri fileUri = FileProvider.getUriForFile(context, context.getPackageName() + ".fileprovider", tempFile); // 5. 构建邮件Intent Intent intent = new Intent(Intent.ACTION_SEND); intent.putExtra(Intent.EXTRA_EMAIL, new String[]{email}); intent.setType("image/png"); // 指定图片类型,更精准 intent.putExtra(Intent.EXTRA_SUBJECT, "邮件主题"); // 可自定义主题,原代码用email当主题可按需调整 intent.putExtra(Intent.EXTRA_TEXT, "Missatge enviat de la imatge"); // 授予Uri读取权限 intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); intent.putExtra(Intent.EXTRA_STREAM, fileUri); startActivity(Intent.createChooser(intent, "Enviant Correu ... ")); } catch (IOException e) { e.printStackTrace(); // 处理异常,给用户友好提示 Toast.makeText(context, "无法准备图片,请重试", Toast.LENGTH_SHORT).show(); } finally { // 可选:临时文件可在发送后删除,或依赖系统自动清理缓存 // if (tempFile != null && tempFile.exists()) { // tempFile.delete(); // } } }
关键要点说明
- 资源转临时文件:通过
openRawResource读取Drawable资源的输入流,写入到应用缓存目录的临时文件中,无需申请外部存储权限。 - FileProvider适配:Android 7.0及以上禁止直接暴露文件Uri,使用FileProvider生成符合规范的Uri,同时添加
FLAG_GRANT_READ_URI_PERMISSION授予邮件应用读取权限。 - 异常处理:添加了IO异常捕获,避免应用崩溃,同时给用户清晰的操作反馈。
内容的提问来源于stack exchange,提问作者Gerard Zafra
相关产品推荐
相关产品推荐

