拍照返回null数据、无SD卡失效及红米手机APP崩溃问题咨询
解答你的Android拍照存储相关问题
一、关于返回null数据、内部存储保存及无SD卡适配问题
咱们逐个拆解你的疑问:
- 为什么会返回null数据?
很多系统相机应用(尤其是当你指定了照片保存路径时),拍照后不会通过返回的Intent传递data数据,这时候Intent.getData()自然就会返回null。这并不是异常情况,而是相机应用的常规行为——因为你已经告诉它要把照片存到指定路径了,它就不会再通过Intent返回Uri。 - 数据是否已保存至内部存储?
如果你在调用相机时指定了内部存储的路径(比如getFilesDir()或者getCacheDir()这类应用私有目录),那照片肯定是存在内部存储里的。你可以通过代码检查对应路径下的文件是否存在,比如用new File(yourFilePath).exists()来验证。内部存储是应用的私有空间,只有你的应用能访问,所以不用担心其他应用干扰。 - 无SD卡的手机上无法正常工作?
这大概率是你的代码只适配了外部存储(SD卡)的场景,没考虑无SD卡的情况。你需要先判断外部存储的可用性:用Environment.getExternalStorageState()检查状态,如果返回的不是Environment.MEDIA_MOUNTED,就切换到内部存储路径来保存照片,这样就能覆盖无SD卡的场景了。
二、红米手机拍照返回后应用崩溃的问题
从你给出的Logcat日志来看,崩溃的核心原因是你尝试调用Intent.getData(),但返回的Intent是null,直接触发了NullPointerException:
java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=1, result=-1, data=null}
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.net.Uri android.content.Intent.getData()' on a null object reference
解决这个问题的关键思路很明确:
- 不要依赖返回的Intent获取照片Uri:如果调用相机时你已经指定了输出路径,那直接用预先定义好的输出Uri即可,完全不用管
data是否为null。 - 如果没指定输出路径,改为指定路径的方式调用相机:这是最稳妥的做法,步骤大概是:
- 先创建一个用于保存照片的文件(优先选外部存储的公共目录,不行就用内部存储)
- Android 7.0及以上版本要使用
FileProvider生成Uri,避免FileUriExposedException - 启动相机Intent时,通过
putExtra(MediaStore.EXTRA_OUTPUT, outputUri)把输出Uri传进去 - 在
onActivityResult里,直接用这个outputUri来处理照片
给你一段简化的代码示例参考:
// 第一步:创建保存照片的文件 private File createImageFile() throws IOException { String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()); String imageFileName = "JPEG_" + timeStamp + "_"; // 优先用外部存储的图片目录,没有的话用内部存储 File storageDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES); if (!storageDir.exists()) { storageDir = getFilesDir(); } return File.createTempFile( imageFileName, /* 前缀 */ ".jpg", /* 后缀 */ storageDir /* 存储目录 */ ); } // 第二步:启动相机 private void dispatchTakePictureIntent() { Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); // 确保有相机应用可以处理这个Intent if (takePictureIntent.resolveActivity(getPackageManager()) != null) { File photoFile = null; try { photoFile = createImageFile(); } catch (IOException ex) { // 处理文件创建失败的情况 ex.printStackTrace(); } // 如果文件创建成功,启动相机 if (photoFile != null) { Uri photoUri = FileProvider.getUriForFile(this, "com.your.app.package.fileprovider", // 这里替换成你的FileProvider授权 photoFile); takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri); startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE); } } } // 第三步:处理拍照结果 @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) { // 直接用之前创建的photoUri处理照片,不用管data // 这里可以写你处理照片的逻辑,比如显示到ImageView imageView.setImageURI(photoUri); } }
另外还要注意权限适配:Android 6.0及以上需要动态申请WRITE_EXTERNAL_STORAGE权限;Android 10及以上如果用传统外部存储方式,需要在Manifest里添加android:requestLegacyExternalStorage="true"来兼容,或者直接使用作用域存储。
内容的提问来源于stack exchange,提问作者irfan sam
相关产品推荐
相关产品推荐

