This question already has an answer here:
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);
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 theACTION_IMAGE_CAPTURE
Intent
, in which case the image is supposed to be saved to that location (see this sample app), orYou do not provide
EXTRA_OUTPUT
on theACTION_IMAGE_CAPTURE
Intent
, in which case you get a thumbnailBitmap
back via the"data"
extra on theIntent
delivered toonActivityResult()
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.
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();
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();
}
targetSdkVersion 21
change your targetsdk version in build.gradle to marshmallow it will be solved.
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().
来源:https://stackoverflow.com/questions/47979273/null-uri-on-api-level-23-camera-intent