Android相机Intent点击叉号时如何删除已保存照片?
解决相机拍照取消时删除照片的问题
看起来你遇到的问题是:调用系统相机拍照时,不管用户点击确认(勾选)还是取消(叉号),照片都会被保存到你创建的文件里。这是因为当你通过EXTRA_OUTPUT指定了照片保存路径时,系统相机应用会直接把照片写入这个文件,不管用户最终是否确认操作。要实现取消时删除照片,我们需要在相机返回的回调里判断用户的操作结果,再决定是否删除文件。
下面分两种情况给你具体的解决方案:
一、使用新版 Activity Result API(推荐,适配Android 10+)
首先,你需要在Activity/Fragment里注册相机的Activity Result Launcher,同时保存好你创建的照片文件路径,这样在回调里可以访问到它:
// 全局变量保存照片文件路径 private String mPhotoFilePath; // 注册相机启动器 private ActivityResultLauncher<Intent> cameraLauncher = registerForActivityResult( new ActivityResultContracts.StartActivityForResult(), result -> { if (result.getResultCode() == Activity.RESULT_OK) { // 用户确认拍照,文件保留,这里可以做后续处理(比如显示照片) Log.d("Photo", "照片已保存:" + mPhotoFilePath); } else if (result.getResultCode() == Activity.RESULT_CANCELED) { // 用户取消拍照,删除之前创建的文件 File photoFile = new File(mPhotoFilePath); if (photoFile.exists()) { boolean isDeleted = photoFile.delete(); if (isDeleted) { Log.d("Photo", "已取消拍照,删除临时照片"); } else { Log.e("Photo", "删除临时照片失败"); } } } } ); // 你的Photo点击事件方法 public void Photo(View view) { Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); File photoFile = null; try { photoFile = createImageFile(); // 保存文件路径到全局变量 mPhotoFilePath = photoFile.getAbsolutePath(); } catch (IOException e) { e.printStackTrace(); Toast.makeText(this, "创建照片文件失败", Toast.LENGTH_SHORT).show(); return; } // 注意:Android 7.0+需要用FileProvider获取Uri,避免FileUriExposedException Uri photoUri = FileProvider.getUriForFile( this, getPackageName() + ".fileprovider", // 这里替换成你在Manifest里注册的FileProvider authority photoFile ); intent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri); cameraLauncher.launch(intent); } // 你原来的创建图片文件的方法 private File createImageFile() throws IOException { // 自定义文件名和存储路径,比如: String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(new Date()); String imageFileName = "JPEG_" + timeStamp + "_"; File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES); return File.createTempFile( imageFileName, /* 前缀 */ ".jpg", /* 后缀 */ storageDir /* 存储目录 */ ); }
二、使用旧版 onActivityResult(兼容旧版本)
如果你的项目还在使用旧的onActivityResult方法,修改如下:
// 全局变量保存照片文件路径 private String mPhotoFilePath; public void Photo(View view) { Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); File photoFile = null; try { photoFile = createImageFile(); mPhotoFilePath = photoFile.getAbsolutePath(); } catch (IOException e) { e.printStackTrace(); Toast.makeText(this, "创建照片文件失败", Toast.LENGTH_SHORT).show(); return; } Uri photoUri; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { // Android 7.0+用FileProvider photoUri = FileProvider.getUriForFile(this, getPackageName() + ".fileprovider", photoFile); } else { // 旧版本直接用File Uri photoUri = Uri.fromFile(photoFile); } intent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri); startActivityForResult(intent, 100); // 100是请求码,自定义即可 } @Override protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == 100) { if (resultCode == RESULT_OK) { // 用户确认拍照,保留文件 Log.d("Photo", "照片已保存"); } else if (resultCode == RESULT_CANCELED) { // 用户取消,删除文件 File photoFile = new File(mPhotoFilePath); if (photoFile.exists()) { photoFile.delete(); Log.d("Photo", "已删除取消拍照的临时文件"); } } } } // 你的createImageFile方法不变 private File createImageFile() throws IOException { String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(new Date()); String imageFileName = "JPEG_" + timeStamp + "_"; File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES); return File.createTempFile( imageFileName, ".jpg", storageDir ); }
关键注意点:
- 必须保存
photoFile的路径:因为相机启动后,当前Activity可能会被销毁重建(比如屏幕旋转),所以最好把路径保存到onSaveInstanceState的Bundle里,在onRestoreInstanceState里恢复,避免路径丢失。示例如下:@Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putString("photo_path", mPhotoFilePath); } @Override protected void onRestoreInstanceState(Bundle savedInstanceState) { super.onRestoreInstanceState(savedInstanceState); mPhotoFilePath = savedInstanceState.getString("photo_path"); } - Android 7.0+必须使用
FileProvider:直接用Uri.fromFile()会抛出FileUriExposedException,需要在AndroidManifest.xml里注册FileProvider,并创建xml/file_paths.xml配置文件,这个是基础配置,相信你已经处理了,如果没有的话可以补充这部分配置。
这样修改后,用户点击叉号取消拍照时,之前创建的照片文件就会被自动删除了。
内容的提问来源于stack exchange,提问作者Manu
相关产品推荐
相关产品推荐

