Android相机APP拍照无法保存查看问题求助(附代码及报错日志)
解决Android相机APP无法保存及查看照片的问题
你遇到的核心问题是目标文件的父目录未创建导致的FileNotFoundException,再加上Android 6.0+的动态权限要求没处理,所以照片既存不了也看不了。下面是一步步的修复方案:
1. 先解决文件目录不存在的问题
你代码里直接创建了YOUR_APP_NAME文件夹下的文件,但这个父目录不会自动生成。在生成output文件前,必须先检查并创建目录:
// 修改目录创建逻辑 File dir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM), "YOUR_APP_NAME"); // mkdirs()会自动创建多级不存在的目录 if (!dir.exists()) { dir.mkdirs(); } // 给文件名加时间戳,避免重复覆盖旧照片 String fileName = "IMG_" + System.currentTimeMillis() + ".jpg"; output = new File(dir, fileName);
2. 添加动态权限申请
Android 6.0(API 23)及以上版本,存储类权限需要动态请求,只在Manifest里声明是无效的:
第一步:在Manifest里补充权限
<manifest ...> <!-- Android 12及以下的存储权限 --> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <!-- Android 13+的媒体读写权限 --> <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" /> <uses-permission android:name="android.permission.WRITE_MEDIA_IMAGES" /> <!-- 你的application和provider配置... --> </manifest>
第二步:在MainActivity里处理权限请求
把启动相机的逻辑抽出来,先检查权限再执行相机启动:
import android.Manifest; import android.content.pm.PackageManager; import android.widget.Toast; import androidx.core.app.ActivityCompat; import androidx.core.content.ContextCompat; public class MainActivity extends AppCompatActivity { private File output = null; private static final int CONTENT_REQUEST = 1745; private static final int PERMISSION_REQUEST_CODE = 100; private Uri photoURI; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 先检查权限,再启动相机 checkPermissionsAndStartCamera(); } private void checkPermissionsAndStartCamera() { // 根据Android版本判断需要申请的权限 String[] permissions; if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.TIRAMISU) { permissions = new String[]{Manifest.permission.WRITE_MEDIA_IMAGES}; } else { permissions = new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}; } if (ContextCompat.checkSelfPermission(this, permissions[0]) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, permissions, PERMISSION_REQUEST_CODE); } else { startCamera(); } } // 处理权限申请结果 @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == PERMISSION_REQUEST_CODE) { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { startCamera(); } else { Toast.makeText(this, "需要存储权限才能保存照片", Toast.LENGTH_SHORT).show(); finish(); } } } // 启动相机的核心逻辑 private void startCamera() { Intent i = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); File dir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM), "YOUR_APP_NAME"); if (!dir.exists()) { dir.mkdirs(); } String fileName = "IMG_" + System.currentTimeMillis() + ".jpg"; output = new File(dir, fileName); photoURI = FileProvider.getUriForFile(MainActivity.this, BuildConfig.APPLICATION_ID + ".provider", output); i.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION); i.putExtra(MediaStore.EXTRA_OUTPUT, photoURI); startActivityForResult(i, CONTENT_REQUEST); } // 你的onActivityResult方法... }
3. 确认FileProvider路径配置正确
确保res/xml/provider_paths.xml的配置包含DCIM目录,这样FileProvider才能正确映射你的文件路径:
<?xml version="1.0" encoding="utf-8"?> <paths xmlns:android="http://schemas.android.com/apk/res/android"> <external-path name="external_files" path="DCIM/" /> </paths>
4. 优化拍照后的处理(可选但建议)
拍照成功后,通知系统媒体库扫描新照片,这样照片才能在系统相册里显示:
@Override protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == CONTENT_REQUEST) { if (resultCode == RESULT_OK) { // 通知媒体库扫描新增照片 Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE); mediaScanIntent.setData(Uri.fromFile(output)); sendBroadcast(mediaScanIntent); // 打开查看照片 Intent i = new Intent(Intent.ACTION_VIEW); i.setDataAndType(photoURI, "image/jpeg"); i.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION); startActivity(i); finish(); } else { // 拍照取消时,删除空文件 if (output != null && output.exists()) { output.delete(); } } } }
按照这些步骤修改后,你的相机APP应该就能正常保存并查看照片了。
内容的提问来源于stack exchange,提问作者ghost deathrider
相关产品推荐
相关产品推荐

