如何通过Intent传递拍摄图片到其他Activity并解决空指针异常
嗨,我来帮你搞定这个问题!从你的Logcat报错能明确看到是**NullPointerException**,触发点在bottom_bar.java的186行——也就是你调用data.getData()的地方。这是因为默认调用相机的MediaStore.ACTION_IMAGE_CAPTURE Intent,并不会返回完整的图片Uri(只有缩略图会存在data.getExtras()里),直接拿data.getData()自然会得到null,进而导致崩溃。
下面是完整的修正方案,分步骤来:
第一步:提前指定相机拍照的图片保存路径
我们需要先创建一个文件来存储拍摄的图片,然后把这个文件的Uri传给相机Intent,这样拍照完成后,图片会直接保存到这个路径,我们就能准确拿到Uri了。
首先添加权限(如果是Android 6.0+还要处理动态权限,先加静态权限到AndroidManifest.xml):
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.CAMERA" /> <uses-feature android:name="android.hardware.camera" />
然后修改你的openCamera()方法:
private static final int CAMERA_REQUEST = 1888; private Uri photoUri; // 全局变量保存图片Uri private void openCamera() { // 创建保存图片的文件 File photoFile = null; try { photoFile = createImageFile(); } catch (IOException ex) { // 处理文件创建失败的情况 ex.printStackTrace(); Toast.makeText(this, "无法创建图片文件", Toast.LENGTH_SHORT).show(); return; } if (photoFile != null) { // 获取文件Uri(Android N及以上要使用FileProvider) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { photoUri = FileProvider.getUriForFile(this, getPackageName() + ".fileprovider", photoFile); } else { photoUri = Uri.fromFile(photoFile); } // 启动相机Intent,传入Uri Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri); startActivityForResult(takePictureIntent, CAMERA_REQUEST); dialog.dismiss(); } } // 创建图片文件的工具方法 private File createImageFile() throws IOException { // 生成唯一文件名 String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()); String imageFileName = "JPEG_" + timeStamp + "_"; File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES); return File.createTempFile( imageFileName, /* 前缀 */ ".jpg", /* 后缀 */ storageDir /* 存储目录 */ ); }
注意:如果是Android 7.0及以上,必须使用FileProvider来获取Uri,需要在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="my_images" path="Pictures" /> </paths>
然后在AndroidManifest.xml中注册FileProvider:
<application> ... <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> </application>
第二步:修正onActivityResult方法
现在拍照完成后,我们直接用之前保存的photoUri,不需要从data里拿了(因为data会是null):
private static final int GALLERY_REQUEST = 1889; // 假设你定义的相册请求码 @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); switch (requestCode) { case GALLERY_REQUEST: if (resultCode == RESULT_OK && data != null) { Uri selectedImage = data.getData(); // 处理相册图片逻辑 } break; case CAMERA_REQUEST: if (resultCode == RESULT_OK) { // 直接用全局变量photoUri,转成字符串传递避免Parcelable问题 Intent i = new Intent(bottom_bar.this, fotograf_cekildikten_sonra_kaydet_iptal_yeri.class); i.putExtra("imageUri", photoUri.toString()); startActivity(i); } break; } }
第三步:修正接收图片的Activity代码
你之前用setImageResource()是错误的,这个方法是加载资源id的,应该用setImageURI()或者Glide等图片加载库来显示:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.fotograf_cekildikten_sonra_kaydet_iptal_yeri); ImageView imageView = findViewById(R.id.telefon_arama_ImageView); String uriString = getIntent().getStringExtra("imageUri"); if (uriString != null) { Uri uri = Uri.parse(uriString); imageView.setImageURI(uri); // 或者用Glide加载更稳定(需要添加Glide依赖): // Glide.with(this).load(uri).into(imageView); } }
为什么之前会崩溃?
默认的MediaStore.ACTION_IMAGE_CAPTURE Intent,当你不指定EXTRA_OUTPUT时,系统只会把拍摄的缩略图放在data.getExtras().get("data")里,而data.getData()会返回null,这就是你触发NullPointerException的原因。指定EXTRA_OUTPUT后,图片会保存到你指定的路径,我们直接用这个路径的Uri就不会有问题了。
内容的提问来源于stack exchange,提问作者Berkay Isıkoglu

