Struggling with a 'run-time' Android WRITE_EXTERNAL_STORAGE permission
I have a fragment. In this fragment I use onActivityResult() to catch an intent when the user chooses to select a photo and import that photo into my app:
Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_CAMERA) {
if (resultCode == Activity.RESULT_OK) {
Uri takenPhotoUri = ImageUtils.getInstance().getPhotoFileUri(getContext(), imageFileName);
actionsListener.onSignalPhotoSelected(takenPhotoUri.getPath());
}
}
if (requestCode == REQUEST_GALLERY && resultCode == Activity.RESULT_OK && data != null && data.getData() != null) {
Uri fileUri = data.getData();
String path = null;
File photoFile = new File(fileUri.toString());
// Differentiate between SDK versions
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
// Code for Android 6 and > goes here
if(getActivity().checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
//showPermissionDialog(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE, WRITE_EXTERNAL_STORAGE_FOR_CLOUDE);
ActivityCompat.requestPermissions(getActivity(), new String {Manifest.permission.WRITE_EXTERNAL_STORAGE}, WRITE_EXTERNAL_STORAGE_FOR_CLOUDE);
}
try {
ParcelFileDescriptor parcelFileDesc = getActivity().getContentResolver().openFileDescriptor(fileUri, "r");
FileDescriptor fileDesc = parcelFileDesc.getFileDescriptor();
Bitmap photo = BitmapFactory.decodeFileDescriptor(fileDesc);
path = MediaStore.Images.Media.insertImage(getContext().getContentResolver(), photo, "temp", null);
parcelFileDesc.close();
// DRY!!
photoFile = ImageUtils.getInstance().getFromMediaUri(getContext(), getContext().getContentResolver(), Uri.parse(path));
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
else {
// DRY!!
photoFile = ImageUtils.getInstance().getFromMediaUri(getContext(), getContext().getContentResolver(), data.getData());
}
if(photoFile != null) {
actionsListener.onSignalPhotoSelected(Uri.fromFile(photoFile).getPath());
}
}
if (requestCode == REQUEST_SIGNAL_DETAILS) {
if (resultCode == Activity.RESULT_OK) {
Signal signal = data.getParcelableExtra("signal");
if (signal != null) {
actionsListener.onSignalStatusUpdated(signal);
}
}
}
}
My problem is this: when the user selects a photo from Google Photos (a photo that only exists on the cloud and it has not been downloaded locally) my app crashes with the following error:
E/MediaStore: Failed to insert image
java.lang.SecurityException: Permission Denial: writing com.android.providers.media.MediaProvider uri content://media/external/images/media from pid=9851, uid=10091 requires android.permission.WRITE_EXTERNAL_STORAGE, or grantUriPermission()
at android.os.Parcel.readException(Parcel.java:1943)
at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:183)
at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:135)
at android.content.ContentProviderProxy.insert(ContentProviderNative.java:476)
at android.content.ContentResolver.insert(ContentResolver.java:1539)
at android.provider.MediaStore$Images$Media.insertImage(MediaStore.java:984)
at org.helpapaw.helpapaw.signalsmap.SignalsMapFragment.onActivityResult(SignalsMapFragment.java:738)
at android.support.v4.app.FragmentActivity.onActivityResult(FragmentActivity.java:151)
at android.app.Activity.dispatchActivityResult(Activity.java:7235)
at android.app.ActivityThread.deliverResults(ActivityThread.java:4320)
at android.app.ActivityThread.handleSendResult(ActivityThread.java:4367)
at android.app.ActivityThread.-wrap19(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1649)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6541)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
D/AndroidRuntime: Shutting down VM
E/AndroidRuntime: FATAL EXCEPTION: main
Process: org.helpapaw.helpapaw, PID: 9851
java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=196611, result=-1, data=Intent { dat=content://com.google.android.apps.photos.contentprovider/0/1/mediakey:/local%3Aabc88a06-d518-4fae-b85d-73f727595a90/ORIGINAL/NONE/1144559444 flg=0x1 clip={text/uri-list U:content://com.google.android.apps.photos.contentprovider/0/1/mediakey%3A%2Flocal%253Aabc88a06-d518-4fae-b85d-73f727595a90/ORIGINAL/NONE/1144559444} }} to activity {org.helpapaw.helpapaw/org.helpapaw.helpapaw.signalsmap.SignalsMapActivity}: java.lang.NullPointerException: uriString
at android.app.ActivityThread.deliverResults(ActivityThread.java:4324)
at android.app.ActivityThread.handleSendResult(ActivityThread.java:4367)
at android.app.ActivityThread.-wrap19(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1649)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6541)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
Caused by: java.lang.NullPointerException: uriString
at android.net.Uri$StringUri.(Uri.java:476)
at android.net.Uri$StringUri.(Unknown Source:0)
at android.net.Uri.parse(Uri.java:438)
at org.helpapaw.helpapaw.signalsmap.SignalsMapFragment.onActivityResult(SignalsMapFragment.java:742)
at android.support.v4.app.FragmentActivity.onActivityResult(FragmentActivity.java:151)
at android.app.Activity.dispatchActivityResult(Activity.java:7235)
at android.app.ActivityThread.deliverResults(ActivityThread.java:4320)
at android.app.ActivityThread.handleSendResult(ActivityThread.java:4367)
at android.app.ActivityThread.-wrap19(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1649)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6541)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
The first line of that error makes me think of a WRITE_TO_EXTERNAL permission error:
E/MediaStore: Failed to insert image
java.lang.SecurityException: Permission Denial: writing com.android.providers.media.MediaProvider uri content://media/external/images/media from pid=9851, uid=10091 requires android.permission.WRITE_EXTERNAL_STORAGE, or grantUriPermission()
So I check to make sure that this API version needs "run-time" permission (as you can see in the code above), and the line:
ActivityCompat.requestPermissions(getActivity(), new String {Manifest.permission.WRITE_EXTERNAL_STORAGE}, WRITE_EXTERNAL_STORAGE_FOR_CLOUDE);
gets hit, but no confirmation dialog appears on the screen.
Another interesting fact, the error only happens the very first time I run the app, (on API 8.0) and works fine on 5.1, 6.0, 7.1 and 8.1 but crashes on 8.0 (emulator). What am I missing?
android android-fragments
add a comment |
I have a fragment. In this fragment I use onActivityResult() to catch an intent when the user chooses to select a photo and import that photo into my app:
Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_CAMERA) {
if (resultCode == Activity.RESULT_OK) {
Uri takenPhotoUri = ImageUtils.getInstance().getPhotoFileUri(getContext(), imageFileName);
actionsListener.onSignalPhotoSelected(takenPhotoUri.getPath());
}
}
if (requestCode == REQUEST_GALLERY && resultCode == Activity.RESULT_OK && data != null && data.getData() != null) {
Uri fileUri = data.getData();
String path = null;
File photoFile = new File(fileUri.toString());
// Differentiate between SDK versions
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
// Code for Android 6 and > goes here
if(getActivity().checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
//showPermissionDialog(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE, WRITE_EXTERNAL_STORAGE_FOR_CLOUDE);
ActivityCompat.requestPermissions(getActivity(), new String {Manifest.permission.WRITE_EXTERNAL_STORAGE}, WRITE_EXTERNAL_STORAGE_FOR_CLOUDE);
}
try {
ParcelFileDescriptor parcelFileDesc = getActivity().getContentResolver().openFileDescriptor(fileUri, "r");
FileDescriptor fileDesc = parcelFileDesc.getFileDescriptor();
Bitmap photo = BitmapFactory.decodeFileDescriptor(fileDesc);
path = MediaStore.Images.Media.insertImage(getContext().getContentResolver(), photo, "temp", null);
parcelFileDesc.close();
// DRY!!
photoFile = ImageUtils.getInstance().getFromMediaUri(getContext(), getContext().getContentResolver(), Uri.parse(path));
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
else {
// DRY!!
photoFile = ImageUtils.getInstance().getFromMediaUri(getContext(), getContext().getContentResolver(), data.getData());
}
if(photoFile != null) {
actionsListener.onSignalPhotoSelected(Uri.fromFile(photoFile).getPath());
}
}
if (requestCode == REQUEST_SIGNAL_DETAILS) {
if (resultCode == Activity.RESULT_OK) {
Signal signal = data.getParcelableExtra("signal");
if (signal != null) {
actionsListener.onSignalStatusUpdated(signal);
}
}
}
}
My problem is this: when the user selects a photo from Google Photos (a photo that only exists on the cloud and it has not been downloaded locally) my app crashes with the following error:
E/MediaStore: Failed to insert image
java.lang.SecurityException: Permission Denial: writing com.android.providers.media.MediaProvider uri content://media/external/images/media from pid=9851, uid=10091 requires android.permission.WRITE_EXTERNAL_STORAGE, or grantUriPermission()
at android.os.Parcel.readException(Parcel.java:1943)
at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:183)
at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:135)
at android.content.ContentProviderProxy.insert(ContentProviderNative.java:476)
at android.content.ContentResolver.insert(ContentResolver.java:1539)
at android.provider.MediaStore$Images$Media.insertImage(MediaStore.java:984)
at org.helpapaw.helpapaw.signalsmap.SignalsMapFragment.onActivityResult(SignalsMapFragment.java:738)
at android.support.v4.app.FragmentActivity.onActivityResult(FragmentActivity.java:151)
at android.app.Activity.dispatchActivityResult(Activity.java:7235)
at android.app.ActivityThread.deliverResults(ActivityThread.java:4320)
at android.app.ActivityThread.handleSendResult(ActivityThread.java:4367)
at android.app.ActivityThread.-wrap19(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1649)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6541)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
D/AndroidRuntime: Shutting down VM
E/AndroidRuntime: FATAL EXCEPTION: main
Process: org.helpapaw.helpapaw, PID: 9851
java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=196611, result=-1, data=Intent { dat=content://com.google.android.apps.photos.contentprovider/0/1/mediakey:/local%3Aabc88a06-d518-4fae-b85d-73f727595a90/ORIGINAL/NONE/1144559444 flg=0x1 clip={text/uri-list U:content://com.google.android.apps.photos.contentprovider/0/1/mediakey%3A%2Flocal%253Aabc88a06-d518-4fae-b85d-73f727595a90/ORIGINAL/NONE/1144559444} }} to activity {org.helpapaw.helpapaw/org.helpapaw.helpapaw.signalsmap.SignalsMapActivity}: java.lang.NullPointerException: uriString
at android.app.ActivityThread.deliverResults(ActivityThread.java:4324)
at android.app.ActivityThread.handleSendResult(ActivityThread.java:4367)
at android.app.ActivityThread.-wrap19(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1649)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6541)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
Caused by: java.lang.NullPointerException: uriString
at android.net.Uri$StringUri.(Uri.java:476)
at android.net.Uri$StringUri.(Unknown Source:0)
at android.net.Uri.parse(Uri.java:438)
at org.helpapaw.helpapaw.signalsmap.SignalsMapFragment.onActivityResult(SignalsMapFragment.java:742)
at android.support.v4.app.FragmentActivity.onActivityResult(FragmentActivity.java:151)
at android.app.Activity.dispatchActivityResult(Activity.java:7235)
at android.app.ActivityThread.deliverResults(ActivityThread.java:4320)
at android.app.ActivityThread.handleSendResult(ActivityThread.java:4367)
at android.app.ActivityThread.-wrap19(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1649)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6541)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
The first line of that error makes me think of a WRITE_TO_EXTERNAL permission error:
E/MediaStore: Failed to insert image
java.lang.SecurityException: Permission Denial: writing com.android.providers.media.MediaProvider uri content://media/external/images/media from pid=9851, uid=10091 requires android.permission.WRITE_EXTERNAL_STORAGE, or grantUriPermission()
So I check to make sure that this API version needs "run-time" permission (as you can see in the code above), and the line:
ActivityCompat.requestPermissions(getActivity(), new String {Manifest.permission.WRITE_EXTERNAL_STORAGE}, WRITE_EXTERNAL_STORAGE_FOR_CLOUDE);
gets hit, but no confirmation dialog appears on the screen.
Another interesting fact, the error only happens the very first time I run the app, (on API 8.0) and works fine on 5.1, 6.0, 7.1 and 8.1 but crashes on 8.0 (emulator). What am I missing?
android android-fragments
nobody has any suggestions, huh? :S
– Nactus
Nov 27 '18 at 23:47
add a comment |
I have a fragment. In this fragment I use onActivityResult() to catch an intent when the user chooses to select a photo and import that photo into my app:
Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_CAMERA) {
if (resultCode == Activity.RESULT_OK) {
Uri takenPhotoUri = ImageUtils.getInstance().getPhotoFileUri(getContext(), imageFileName);
actionsListener.onSignalPhotoSelected(takenPhotoUri.getPath());
}
}
if (requestCode == REQUEST_GALLERY && resultCode == Activity.RESULT_OK && data != null && data.getData() != null) {
Uri fileUri = data.getData();
String path = null;
File photoFile = new File(fileUri.toString());
// Differentiate between SDK versions
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
// Code for Android 6 and > goes here
if(getActivity().checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
//showPermissionDialog(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE, WRITE_EXTERNAL_STORAGE_FOR_CLOUDE);
ActivityCompat.requestPermissions(getActivity(), new String {Manifest.permission.WRITE_EXTERNAL_STORAGE}, WRITE_EXTERNAL_STORAGE_FOR_CLOUDE);
}
try {
ParcelFileDescriptor parcelFileDesc = getActivity().getContentResolver().openFileDescriptor(fileUri, "r");
FileDescriptor fileDesc = parcelFileDesc.getFileDescriptor();
Bitmap photo = BitmapFactory.decodeFileDescriptor(fileDesc);
path = MediaStore.Images.Media.insertImage(getContext().getContentResolver(), photo, "temp", null);
parcelFileDesc.close();
// DRY!!
photoFile = ImageUtils.getInstance().getFromMediaUri(getContext(), getContext().getContentResolver(), Uri.parse(path));
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
else {
// DRY!!
photoFile = ImageUtils.getInstance().getFromMediaUri(getContext(), getContext().getContentResolver(), data.getData());
}
if(photoFile != null) {
actionsListener.onSignalPhotoSelected(Uri.fromFile(photoFile).getPath());
}
}
if (requestCode == REQUEST_SIGNAL_DETAILS) {
if (resultCode == Activity.RESULT_OK) {
Signal signal = data.getParcelableExtra("signal");
if (signal != null) {
actionsListener.onSignalStatusUpdated(signal);
}
}
}
}
My problem is this: when the user selects a photo from Google Photos (a photo that only exists on the cloud and it has not been downloaded locally) my app crashes with the following error:
E/MediaStore: Failed to insert image
java.lang.SecurityException: Permission Denial: writing com.android.providers.media.MediaProvider uri content://media/external/images/media from pid=9851, uid=10091 requires android.permission.WRITE_EXTERNAL_STORAGE, or grantUriPermission()
at android.os.Parcel.readException(Parcel.java:1943)
at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:183)
at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:135)
at android.content.ContentProviderProxy.insert(ContentProviderNative.java:476)
at android.content.ContentResolver.insert(ContentResolver.java:1539)
at android.provider.MediaStore$Images$Media.insertImage(MediaStore.java:984)
at org.helpapaw.helpapaw.signalsmap.SignalsMapFragment.onActivityResult(SignalsMapFragment.java:738)
at android.support.v4.app.FragmentActivity.onActivityResult(FragmentActivity.java:151)
at android.app.Activity.dispatchActivityResult(Activity.java:7235)
at android.app.ActivityThread.deliverResults(ActivityThread.java:4320)
at android.app.ActivityThread.handleSendResult(ActivityThread.java:4367)
at android.app.ActivityThread.-wrap19(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1649)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6541)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
D/AndroidRuntime: Shutting down VM
E/AndroidRuntime: FATAL EXCEPTION: main
Process: org.helpapaw.helpapaw, PID: 9851
java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=196611, result=-1, data=Intent { dat=content://com.google.android.apps.photos.contentprovider/0/1/mediakey:/local%3Aabc88a06-d518-4fae-b85d-73f727595a90/ORIGINAL/NONE/1144559444 flg=0x1 clip={text/uri-list U:content://com.google.android.apps.photos.contentprovider/0/1/mediakey%3A%2Flocal%253Aabc88a06-d518-4fae-b85d-73f727595a90/ORIGINAL/NONE/1144559444} }} to activity {org.helpapaw.helpapaw/org.helpapaw.helpapaw.signalsmap.SignalsMapActivity}: java.lang.NullPointerException: uriString
at android.app.ActivityThread.deliverResults(ActivityThread.java:4324)
at android.app.ActivityThread.handleSendResult(ActivityThread.java:4367)
at android.app.ActivityThread.-wrap19(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1649)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6541)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
Caused by: java.lang.NullPointerException: uriString
at android.net.Uri$StringUri.(Uri.java:476)
at android.net.Uri$StringUri.(Unknown Source:0)
at android.net.Uri.parse(Uri.java:438)
at org.helpapaw.helpapaw.signalsmap.SignalsMapFragment.onActivityResult(SignalsMapFragment.java:742)
at android.support.v4.app.FragmentActivity.onActivityResult(FragmentActivity.java:151)
at android.app.Activity.dispatchActivityResult(Activity.java:7235)
at android.app.ActivityThread.deliverResults(ActivityThread.java:4320)
at android.app.ActivityThread.handleSendResult(ActivityThread.java:4367)
at android.app.ActivityThread.-wrap19(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1649)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6541)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
The first line of that error makes me think of a WRITE_TO_EXTERNAL permission error:
E/MediaStore: Failed to insert image
java.lang.SecurityException: Permission Denial: writing com.android.providers.media.MediaProvider uri content://media/external/images/media from pid=9851, uid=10091 requires android.permission.WRITE_EXTERNAL_STORAGE, or grantUriPermission()
So I check to make sure that this API version needs "run-time" permission (as you can see in the code above), and the line:
ActivityCompat.requestPermissions(getActivity(), new String {Manifest.permission.WRITE_EXTERNAL_STORAGE}, WRITE_EXTERNAL_STORAGE_FOR_CLOUDE);
gets hit, but no confirmation dialog appears on the screen.
Another interesting fact, the error only happens the very first time I run the app, (on API 8.0) and works fine on 5.1, 6.0, 7.1 and 8.1 but crashes on 8.0 (emulator). What am I missing?
android android-fragments
I have a fragment. In this fragment I use onActivityResult() to catch an intent when the user chooses to select a photo and import that photo into my app:
Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_CAMERA) {
if (resultCode == Activity.RESULT_OK) {
Uri takenPhotoUri = ImageUtils.getInstance().getPhotoFileUri(getContext(), imageFileName);
actionsListener.onSignalPhotoSelected(takenPhotoUri.getPath());
}
}
if (requestCode == REQUEST_GALLERY && resultCode == Activity.RESULT_OK && data != null && data.getData() != null) {
Uri fileUri = data.getData();
String path = null;
File photoFile = new File(fileUri.toString());
// Differentiate between SDK versions
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
// Code for Android 6 and > goes here
if(getActivity().checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
//showPermissionDialog(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE, WRITE_EXTERNAL_STORAGE_FOR_CLOUDE);
ActivityCompat.requestPermissions(getActivity(), new String {Manifest.permission.WRITE_EXTERNAL_STORAGE}, WRITE_EXTERNAL_STORAGE_FOR_CLOUDE);
}
try {
ParcelFileDescriptor parcelFileDesc = getActivity().getContentResolver().openFileDescriptor(fileUri, "r");
FileDescriptor fileDesc = parcelFileDesc.getFileDescriptor();
Bitmap photo = BitmapFactory.decodeFileDescriptor(fileDesc);
path = MediaStore.Images.Media.insertImage(getContext().getContentResolver(), photo, "temp", null);
parcelFileDesc.close();
// DRY!!
photoFile = ImageUtils.getInstance().getFromMediaUri(getContext(), getContext().getContentResolver(), Uri.parse(path));
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
else {
// DRY!!
photoFile = ImageUtils.getInstance().getFromMediaUri(getContext(), getContext().getContentResolver(), data.getData());
}
if(photoFile != null) {
actionsListener.onSignalPhotoSelected(Uri.fromFile(photoFile).getPath());
}
}
if (requestCode == REQUEST_SIGNAL_DETAILS) {
if (resultCode == Activity.RESULT_OK) {
Signal signal = data.getParcelableExtra("signal");
if (signal != null) {
actionsListener.onSignalStatusUpdated(signal);
}
}
}
}
My problem is this: when the user selects a photo from Google Photos (a photo that only exists on the cloud and it has not been downloaded locally) my app crashes with the following error:
E/MediaStore: Failed to insert image
java.lang.SecurityException: Permission Denial: writing com.android.providers.media.MediaProvider uri content://media/external/images/media from pid=9851, uid=10091 requires android.permission.WRITE_EXTERNAL_STORAGE, or grantUriPermission()
at android.os.Parcel.readException(Parcel.java:1943)
at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:183)
at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:135)
at android.content.ContentProviderProxy.insert(ContentProviderNative.java:476)
at android.content.ContentResolver.insert(ContentResolver.java:1539)
at android.provider.MediaStore$Images$Media.insertImage(MediaStore.java:984)
at org.helpapaw.helpapaw.signalsmap.SignalsMapFragment.onActivityResult(SignalsMapFragment.java:738)
at android.support.v4.app.FragmentActivity.onActivityResult(FragmentActivity.java:151)
at android.app.Activity.dispatchActivityResult(Activity.java:7235)
at android.app.ActivityThread.deliverResults(ActivityThread.java:4320)
at android.app.ActivityThread.handleSendResult(ActivityThread.java:4367)
at android.app.ActivityThread.-wrap19(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1649)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6541)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
D/AndroidRuntime: Shutting down VM
E/AndroidRuntime: FATAL EXCEPTION: main
Process: org.helpapaw.helpapaw, PID: 9851
java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=196611, result=-1, data=Intent { dat=content://com.google.android.apps.photos.contentprovider/0/1/mediakey:/local%3Aabc88a06-d518-4fae-b85d-73f727595a90/ORIGINAL/NONE/1144559444 flg=0x1 clip={text/uri-list U:content://com.google.android.apps.photos.contentprovider/0/1/mediakey%3A%2Flocal%253Aabc88a06-d518-4fae-b85d-73f727595a90/ORIGINAL/NONE/1144559444} }} to activity {org.helpapaw.helpapaw/org.helpapaw.helpapaw.signalsmap.SignalsMapActivity}: java.lang.NullPointerException: uriString
at android.app.ActivityThread.deliverResults(ActivityThread.java:4324)
at android.app.ActivityThread.handleSendResult(ActivityThread.java:4367)
at android.app.ActivityThread.-wrap19(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1649)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6541)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
Caused by: java.lang.NullPointerException: uriString
at android.net.Uri$StringUri.(Uri.java:476)
at android.net.Uri$StringUri.(Unknown Source:0)
at android.net.Uri.parse(Uri.java:438)
at org.helpapaw.helpapaw.signalsmap.SignalsMapFragment.onActivityResult(SignalsMapFragment.java:742)
at android.support.v4.app.FragmentActivity.onActivityResult(FragmentActivity.java:151)
at android.app.Activity.dispatchActivityResult(Activity.java:7235)
at android.app.ActivityThread.deliverResults(ActivityThread.java:4320)
at android.app.ActivityThread.handleSendResult(ActivityThread.java:4367)
at android.app.ActivityThread.-wrap19(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1649)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6541)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
The first line of that error makes me think of a WRITE_TO_EXTERNAL permission error:
E/MediaStore: Failed to insert image
java.lang.SecurityException: Permission Denial: writing com.android.providers.media.MediaProvider uri content://media/external/images/media from pid=9851, uid=10091 requires android.permission.WRITE_EXTERNAL_STORAGE, or grantUriPermission()
So I check to make sure that this API version needs "run-time" permission (as you can see in the code above), and the line:
ActivityCompat.requestPermissions(getActivity(), new String {Manifest.permission.WRITE_EXTERNAL_STORAGE}, WRITE_EXTERNAL_STORAGE_FOR_CLOUDE);
gets hit, but no confirmation dialog appears on the screen.
Another interesting fact, the error only happens the very first time I run the app, (on API 8.0) and works fine on 5.1, 6.0, 7.1 and 8.1 but crashes on 8.0 (emulator). What am I missing?
android android-fragments
android android-fragments
edited Dec 11 '18 at 5:11
Saikrishna Rajaraman
1,382419
1,382419
asked Nov 22 '18 at 19:51
NactusNactus
428928
428928
nobody has any suggestions, huh? :S
– Nactus
Nov 27 '18 at 23:47
add a comment |
nobody has any suggestions, huh? :S
– Nactus
Nov 27 '18 at 23:47
nobody has any suggestions, huh? :S
– Nactus
Nov 27 '18 at 23:47
nobody has any suggestions, huh? :S
– Nactus
Nov 27 '18 at 23:47
add a comment |
1 Answer
1
active
oldest
votes
For anyone who struggles with something similar; the key is to request the necessary permission(s) all at once, using (in my case) the Fragment.requestPermissions(String permissions, int requestCode);
method. This method allows passing an array of permissions into its first parameter:
String permissions = {Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE};
if (ContextCompat.checkSelfPermission(getContext(), Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED &&
ContextCompat.checkSelfPermission(getContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
requestPermissions(permissions, READ_WRITE_EXTERNAL_STORAGE_FOR_GALLERY);
}
What I wish I knew:
once a new activity gets called by an intent, be it the camera or the photo-gallery; trying to ask the user for permissions doesn't work anymore; meaning - once the camera or the photo-gallery is open, we lose our own app's context and therefore we can not prompt the user for permissions any-longer. It is paramount that all permissions are requested before the user leaves our app (in my case the use of an array was necessary to request permissions to both read and write to the external storage. Ask for all necessary permissions at the same-time before the user leaves the current context, then redirect to a new Activity via an intent.
I hope this helps someone.
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53437311%2fstruggling-with-a-run-time-android-write-external-storage-permission%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
For anyone who struggles with something similar; the key is to request the necessary permission(s) all at once, using (in my case) the Fragment.requestPermissions(String permissions, int requestCode);
method. This method allows passing an array of permissions into its first parameter:
String permissions = {Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE};
if (ContextCompat.checkSelfPermission(getContext(), Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED &&
ContextCompat.checkSelfPermission(getContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
requestPermissions(permissions, READ_WRITE_EXTERNAL_STORAGE_FOR_GALLERY);
}
What I wish I knew:
once a new activity gets called by an intent, be it the camera or the photo-gallery; trying to ask the user for permissions doesn't work anymore; meaning - once the camera or the photo-gallery is open, we lose our own app's context and therefore we can not prompt the user for permissions any-longer. It is paramount that all permissions are requested before the user leaves our app (in my case the use of an array was necessary to request permissions to both read and write to the external storage. Ask for all necessary permissions at the same-time before the user leaves the current context, then redirect to a new Activity via an intent.
I hope this helps someone.
add a comment |
For anyone who struggles with something similar; the key is to request the necessary permission(s) all at once, using (in my case) the Fragment.requestPermissions(String permissions, int requestCode);
method. This method allows passing an array of permissions into its first parameter:
String permissions = {Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE};
if (ContextCompat.checkSelfPermission(getContext(), Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED &&
ContextCompat.checkSelfPermission(getContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
requestPermissions(permissions, READ_WRITE_EXTERNAL_STORAGE_FOR_GALLERY);
}
What I wish I knew:
once a new activity gets called by an intent, be it the camera or the photo-gallery; trying to ask the user for permissions doesn't work anymore; meaning - once the camera or the photo-gallery is open, we lose our own app's context and therefore we can not prompt the user for permissions any-longer. It is paramount that all permissions are requested before the user leaves our app (in my case the use of an array was necessary to request permissions to both read and write to the external storage. Ask for all necessary permissions at the same-time before the user leaves the current context, then redirect to a new Activity via an intent.
I hope this helps someone.
add a comment |
For anyone who struggles with something similar; the key is to request the necessary permission(s) all at once, using (in my case) the Fragment.requestPermissions(String permissions, int requestCode);
method. This method allows passing an array of permissions into its first parameter:
String permissions = {Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE};
if (ContextCompat.checkSelfPermission(getContext(), Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED &&
ContextCompat.checkSelfPermission(getContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
requestPermissions(permissions, READ_WRITE_EXTERNAL_STORAGE_FOR_GALLERY);
}
What I wish I knew:
once a new activity gets called by an intent, be it the camera or the photo-gallery; trying to ask the user for permissions doesn't work anymore; meaning - once the camera or the photo-gallery is open, we lose our own app's context and therefore we can not prompt the user for permissions any-longer. It is paramount that all permissions are requested before the user leaves our app (in my case the use of an array was necessary to request permissions to both read and write to the external storage. Ask for all necessary permissions at the same-time before the user leaves the current context, then redirect to a new Activity via an intent.
I hope this helps someone.
For anyone who struggles with something similar; the key is to request the necessary permission(s) all at once, using (in my case) the Fragment.requestPermissions(String permissions, int requestCode);
method. This method allows passing an array of permissions into its first parameter:
String permissions = {Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE};
if (ContextCompat.checkSelfPermission(getContext(), Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED &&
ContextCompat.checkSelfPermission(getContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
requestPermissions(permissions, READ_WRITE_EXTERNAL_STORAGE_FOR_GALLERY);
}
What I wish I knew:
once a new activity gets called by an intent, be it the camera or the photo-gallery; trying to ask the user for permissions doesn't work anymore; meaning - once the camera or the photo-gallery is open, we lose our own app's context and therefore we can not prompt the user for permissions any-longer. It is paramount that all permissions are requested before the user leaves our app (in my case the use of an array was necessary to request permissions to both read and write to the external storage. Ask for all necessary permissions at the same-time before the user leaves the current context, then redirect to a new Activity via an intent.
I hope this helps someone.
edited Dec 11 '18 at 5:18
answered Dec 11 '18 at 5:00
NactusNactus
428928
428928
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53437311%2fstruggling-with-a-run-time-android-write-external-storage-permission%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
nobody has any suggestions, huh? :S
– Nactus
Nov 27 '18 at 23:47