Null URI on API level >=23 camera intent [duplicat

2020-02-07 12:57发布

This might be a possible duplicate but i can't seem to pinpoint the exact solution. Camera works fine and returns the image uri on devices below api 23. However app crushes right after capturing image on devices apove api 23 with log error

java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=2, result=-1, data=Intent { act=inline-data (has extras) }} to activity {ana.foodi/ana.foodi.MainActivity}: java.lang.NullPointerException: uri
                                                         at android.app.ActivityThread.deliverResults(ActivityThread.java:3940)
                                                         at android.app.ActivityThread.handleSendResult(ActivityThread.java:3983)
                                                         at android.app.ActivityThread.-wrap16(ActivityThread.java)
                                                         at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1548)
                                                         at android.os.Handler.dispatchMessage(Handler.java:111)
                                                         at android.os.Looper.loop(Looper.java:207)
                                                         at android.app.ActivityThread.main(ActivityThread.java:5765)
                                                         at java.lang.reflect.Method.invoke(Native Method)
                                                         at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:789)
                                                         at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:679)
                                                      Caused by: java.lang.NullPointerException: uri
                                                         at com.android.internal.util.Preconditions.checkNotNull(Preconditions.java:60)
                                                         at android.content.ContentResolver.query(ContentResolver.java:481)
                                                         at android.content.ContentResolver.query(ContentResolver.java:441)
                                                         at ana.foodi.MainActivity.onActivityResult(MainActivity.java:672)

After checking with breakpoints,realised Uri (selectedImage) is null below:

 @Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    final String filePath;
    if(resultCode == Activity.RESULT_OK && REQUEST_POST_PHOTO==999){


        if(requestCode == 2 ) {
            requestRuntimePermission();
            Uri selectedImage = data.getData();
            String[] filePaths = {MediaStore.Images.Media.DATA};
            Cursor c = this.getContentResolver().query(selectedImage, filePaths, null, null, null);
            c.moveToFirst();
            int columnIndex = c.getColumnIndex(filePaths[0]);
            filePath = c.getString(columnIndex);
            c.close();

I've tried requesting runtime permission with this

public void requestRuntimePermission() {
    if (Build.VERSION.SDK_INT >= 23) {
        if (ContextCompat.checkSelfPermission(context,android.Manifest.permission.WRITE_EXTERNAL_STORAGE)
                != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this,
                    new String[]{android.Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
        }
    }
}

but error persist.

startActivityForResult call

REQUEST_POST_PHOTO=999;
                Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
                startActivityForResult(cameraIntent, REQUEST_CODE_POST);

5条回答
虎瘦雄心在
2楼-- · 2020-02-07 13:08

At least for older versions, if multiple selection is allowed (Intent#EXTRA_ALLOW_MULTIPLE), URIs will be returned as clipboard data:

data.getClipData()

See Intent#getClipData() and ClipData.

Check if data is being returned there:

ClipData clipData = data.getClipData();
Uri selectedImage = null;
if (clipData != null) {
    selectedImage = clipData.getItemAt(0).getUri();
} else {
    selectedImage = data.getData();
}
查看更多
劳资没心,怎么记你
3楼-- · 2020-02-07 13:08
 targetSdkVersion 21
 change your targetsdk version in build.gradle to marshmallow it will be solved. 
查看更多
劫难
4楼-- · 2020-02-07 13:14

Try this

Use both WRITE_EXTERNAL_STORAGE and WRITE_EXTERNAL_STORAGE to read and write file

<uses-feature android:name="android.hardware.camera2" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

Here ask to write permission & read permission add multiple permission

public void requestRuntimePermission() {
    if (Build.VERSION.SDK_INT >= 23) {
        if (ContextCompat.checkSelfPermission(context,android.Manifest.permission.WRITE_EXTERNAL_STORAGE)
                != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this,
                    new String[]{android.Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
        }
    }
}

Check this Android 6.0 multiple permissions

//Check permission granted or not if granted then call this block

        Uri selectedImage = data.getData();
        String[] filePaths = {MediaStore.Images.Media.DATA};
        Cursor c = this.getContentResolver().query(selectedImage, filePaths, null, null, null);
        c.moveToFirst();
        int columnIndex = c.getColumnIndex(filePaths[0]);
        filePath = c.getString(columnIndex);
        c.close();
查看更多
\"骚年 ilove
5楼-- · 2020-02-07 13:15

You are using ACTION_IMAGE_CAPTURE. ACTION_IMAGE_CAPTURE is not supposed to return a Uri via onActivityResult(). Instead, either:

  • You provide EXTRA_OUTPUT on the ACTION_IMAGE_CAPTURE Intent, in which case the image is supposed to be saved to that location (see this sample app), or

  • You do not provide EXTRA_OUTPUT on the ACTION_IMAGE_CAPTURE Intent, in which case you get a thumbnail Bitmap back via the "data" extra on the Intent delivered to onActivityResult()

This is covered in the documentation.

Some buggy camera apps will return a Uri. Do not count on this behavior, as well-written camera apps will not.

查看更多
Deceive 欺骗
6楼-- · 2020-02-07 13:15
private static final int REQUEST_CODE_IMAGE = 1000;
private String importFileName = "";

private void cameraIntent() {
    importFileName = getString(R.string.app_name) + new Random().nextInt();
    startActivityForResult(getCameraIntent(context, importFileName), REQUEST_CODE_IMAGE);
}

public Intent getCameraIntent(Context context, String fileName) {
    Intent chooserIntent = null;
    List<Intent> intentList = new ArrayList<>();
    Intent takePhotoIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    takePhotoIntent.putExtra("return-data", true);
    takePhotoIntent.putExtra(MediaStore.EXTRA_SCREEN_ORIENTATION, context.getResources().getConfiguration().orientation);
    takePhotoIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(context.getExternalCacheDir(), fileName)));
    intentList = addIntentsToList(context, intentList, Collections.singletonList(takePhotoIntent));

    if (intentList.size() > 0) {
        String title = context.getResources().getString(R.string.choose);
        chooserIntent = Intent.createChooser(intentList.remove(intentList.size() - 1), title);
        chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, intentList.toArray(new Parcelable[]{}));
    }
    return chooserIntent;
}

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    switch (requestCode) {
        case REQUEST_CODE_IMAGE:
            if (resultCode == RESULT_OK) {
                onCaptureImageResult(data);
            }
            break;
    }
}

private void onCaptureImageResult(Intent data) {
    Uri imageUri;
    if (data == null) {
        imageUri = Uri.fromFile(new File(getExternalCacheDir(), importFileName));
    } else {
        imageUri = data.getData();
        if (imageUri == null)
            imageUri = Uri.fromFile(new File(getExternalCacheDir(), importFileName));
    }
}

If you get permissions (camera, read/write external storage permissions) from user, this code snippet will work correctly. You can call cameraIntent().

查看更多
登录 后发表回答