Android Java:调用相机Intent获取结果时openInputStream触发空指针异常
Hey there! Let's break down why you're hitting that NullPointerException at getContentResolver().openInputStream(data.getData()) and how to fix it.
The Root Cause
When you use the default camera Intent (MediaStore.ACTION_IMAGE_CAPTURE), the system only returns a thumbnail in the data.getExtras().get("data") bundle. The data.getData() call returns null because the camera app doesn't pass a URI for the full-size image by default—unless you explicitly tell it where to save the photo upfront.
The Solution: Specify a Save Path for the Camera Image
Instead of relying on the intent to return the full image URI, you'll need to:
- Create a file to store the full-size photo before launching the camera.
- Pass this file's URI to the camera intent so it saves the photo there.
- Load the image directly from that file path in
onActivityResult.
Step 1: Create a Method to Generate the Image File
This creates a temporary file in your app's private external storage (no extra permissions needed for Android 10+):
private String mCurrentPhotoPath; // Store the path globally private File createImageFile() throws IOException { // Generate a unique filename using timestamp 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, // Prefix ".jpg", // Suffix storageDir // Save directory ); }
Step 2: Launch the Camera Intent with the Save URI
Use FileProvider (required for Android 7.0+) to get a safe URI for the file:
private void takePhotoWithCamera() { Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); // Check if a camera app exists to handle the intent if (takePictureIntent.resolveActivity(getPackageManager()) != null) { File photoFile = null; try { photoFile = createImageFile(); mCurrentPhotoPath = photoFile.getAbsolutePath(); // Save the path } catch (IOException ex) { // Handle file creation errors ex.printStackTrace(); } if (photoFile != null) { Uri photoURI = FileProvider.getUriForFile( this, "com.yourapp.package.fileprovider", // Replace with your app's authority photoFile ); takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI); startActivityForResult(takePictureIntent, CAMERA_PIC_REQUEST); } } }
Step 3: Configure FileProvider in Your Manifest
Add this to your AndroidManifest.xml inside the <application> tag:
<provider android:name="androidx.core.content.FileProvider" android:authorities="com.yourapp.package.fileprovider" // Match the authority above android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths" /> </provider>
Step 4: Create the File Paths XML
Make a new directory res/xml and add file_paths.xml:
<?xml version="1.0" encoding="utf-8"?> <paths xmlns:android="http://schemas.android.com/apk/res/android"> <!-- Grants access to the Pictures directory in your app's external storage --> <external-files-path name="my_images" path="Pictures" /> </paths>
Step 5: Load the Full Image in onActivityResult
Now you can skip data.getData() and load directly from the saved file path:
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == CAMERA_PIC_REQUEST && resultCode == RESULT_OK) { // Show the thumbnail as before Bitmap thumbnail = (Bitmap) data.getExtras().get("data"); pic.setImageBitmap(thumbnail); // Load the full-size image from the saved path BitmapFactory.Options options = new BitmapFactory.Options(); // Optional: Reduce image size to avoid out-of-memory errors options.inSampleSize = 2; bitmapPic = BitmapFactory.decodeFile(mCurrentPhotoPath, options); // Use bitmapPic for your needs now! } }
Why This Works
By specifying MediaStore.EXTRA_OUTPUT, you tell the camera app exactly where to save the full-size photo. Since you control the file path, you don't need to rely on the intent returning a URI (which it doesn't do by default).
内容的提问来源于stack exchange,提问作者BryceSoker

