Android 11(SDK 30)下无法创建临时图片文件该如何解决?
Android 11 临时图片文件创建问题排查方案
核心前提说明
你当前使用的getExternalFilesDir(Environment.DIRECTORY_PICTURES)属于应用专属外部存储目录,Android 10及以上系统访问该目录不需要申请任何存储权限,你之前申请的MANAGE_EXTERNAL_STORAGE、WRITE_EXTERNAL_STORAGE等权限均属于冗余配置,和当前问题无关,可直接移除。
排查步骤
- 第一步:排查目录有效性
先确认存储目录是否正常可写,修改代码增加判断逻辑:
运行后查看抛出的异常信息,可直接定位目录层面的问题。private File createImageFile() throws IOException { String timestamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()); String imageFileName = "JPEG_" + timestamp + "_"; File storageDir = activity.getExternalFilesDir(Environment.DIRECTORY_PICTURES); // 新增目录校验逻辑 if (storageDir == null) { throw new IOException("Activity实例无效或外部存储不可用"); } if (!storageDir.exists()) { boolean mkdirSuccess = storageDir.mkdirs(); if (!mkdirSuccess) { throw new IOException("存储目录创建失败"); } } if (!storageDir.canWrite()) { throw new IOException("存储目录无写入权限"); } return File.createTempFile(imageFileName, ".jpg", storageDir); } - 第二步:排查WebView配置限制
Android 11对WebView的文件访问做了额外限制,必须开启以下配置才能让WebView内的逻辑访问本地文件:WebSettings webSettings = webView.getSettings(); // 允许访问本地文件 webSettings.setAllowFileAccess(true); // 允许访问ContentProvider提供的内容 webSettings.setAllowContentAccess(true); // 若你用file://协议加载本地网页,还需开启以下配置 webSettings.setAllowFileAccessFromFileURLs(true); webSettings.setAllowUniversalAccessFromFileURLs(true); - 第三步:排查相机写入权限问题
你创建的临时文件属于应用专属目录,第三方相机应用默认没有该目录的写入权限,会出现「文件创建成功但相机写入后为空」的问题,需要通过FileProvider给相机授予临时访问权限:- 在
AndroidManifest.xml中注册FileProvider
<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"> <external-files-path name="app_images" path="Pictures" /> </paths>- 调用相机时,通过FileProvider生成Content URI并授予临时写入权限:
File photoFile = createImageFile(); Uri photoUri = FileProvider.getUriForFile(context, context.getPackageName() + ".fileprovider", photoFile); Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri); // 给相机授予临时写入权限 takePictureIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION); - 在
内容的提问来源于stack exchange,提问作者Richard
相关产品推荐
相关产品推荐

