Android应用通过邮件发送图片提示文件不存在或权限错误
Android发送带图片附件邮件无附件/报错问题修复方案
问题根源
- 静态申请的存储权限未适配Android系统版本要求:Android 6.0及以上需要动态申请读写存储权限,Android 10及以上已禁止直接访问公共外部存储根目录,原代码case1使用
Environment.getExternalStorageDirectory()会直接报错 - 存储路径逻辑错误:使用
getCacheDir()时重复创建系统已存在的缓存目录,默认生成的私有目录文件第三方邮件应用无权限访问 - Uri构造错误:case1的Uri拼写错误,缺少
file://中的冒号;Android 7.0及以上禁止直接向外部暴露file://类型的Uri,会抛出FileUriExposedException - Intent配置错误:MIME类型设置错误,变量名、方法名存在笔误(
mailIntent和emailIntent混用、gtartActivity应为startActivity)
修复步骤
1. 配置FileProvider适配跨应用Uri访问
首先在AndroidManifest.xml的<application>标签内添加Provider配置:
<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>
在res/xml目录下新建file_paths.xml文件,配置允许共享的路径:
<?xml version="1.0" encoding="utf-8"?> <paths xmlns:android="http://schemas.android.com/apk/res/android"> <!-- 允许共享应用缓存目录下的文件 --> <cache-path name="cache_attachments" path="." /> </paths>
2. 适配动态权限申请
Android 6.0及以上版本,在调用发送邮件逻辑前,先动态申请READ_EXTERNAL_STORAGE、WRITE_EXTERNAL_STORAGE权限,权限申请通过后再执行后续逻辑。如果仅使用应用专属缓存目录存储附件,可不需要申请外部存储权限。
3. 修正图片存储逻辑
修改storeImage方法,使用应用专属缓存目录存储图片,避免权限问题:
private File storeImage(Bitmap image) { String filename = "pic.png"; File pic = null; try { // 应用专属缓存目录,无需外部存储权限,可通过FileProvider共享给其他应用 File cacheDir = getCacheDir(); pic = new File(cacheDir, filename); FileOutputStream out = new FileOutputStream(pic); boolean compressSuccess = image.compress(Bitmap.CompressFormat.PNG, 100, out); out.flush(); out.close(); if (!compressSuccess) { pic = null; } } catch (Exception e) { Log.e("BROKEN", "图片存储失败: " + e.getMessage(), e); pic = null; } return pic; }
4. 修正邮件发送逻辑
String msgtext = "#22 Please warn/fine/terminate the user \n\n"; Bitmap photo = (Bitmap) data.getExtras().get("data"); File fileThing = storeImage(photo); // 先校验文件是否有效 if (fileThing != null && fileThing.exists() && fileThing.length() > 0) { Intent emailIntent = new Intent(Intent.ACTION_SEND); // 正确设置MIME类型 emailIntent.setType("image/png"); String[] recipient = new String[]{"roySpin@royweil.com", "roysoin2@royweil.com"}; emailIntent.putExtra(Intent.EXTRA_EMAIL, recipient); emailIntent.putExtra(Intent.EXTRA_SUBJECT, "Scooter Illegaly Parked"); emailIntent.putExtra(Intent.EXTRA_TEXT, msgtext); // 通过FileProvider生成可跨应用访问的Uri Uri pngUri = FileProvider.getUriForFile(this, getPackageName() + ".fileprovider", fileThing); emailIntent.putExtra(Intent.EXTRA_STREAM, pngUri); // 授予邮件应用读取附件的权限 emailIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); // 调用系统选择器避免崩溃 startActivity(Intent.createChooser(emailIntent, "选择邮件应用发送")); } else { Log.e("BROKEN", "附件文件无效,无法发送"); }
内容的提问来源于stack exchange,提问作者Roy Weil
相关产品推荐
相关产品推荐

