I am currently trying to load a Uri of an image i have saved into my MySQLite database into a RecyclerView.
The code for the RecyclerViewAdapter :
public void onBindViewHolder(MyCatchesAdapter.MyViewHolder holder, int position) {
MyCatch myCatch = myCatchArrayList.get(position);
holder.txtName.setText(myCatch.get_name());
holder.txtLocation.setText(myCatch.get_location());
holder.txtDate.setText(myCatch.get_date());
holder.catchImage.setImageURI(Uri.parse(myCatch.get_catchImage()));
}
All the data loads into the recycler view except the image. I get the following from the Logcat
Unable to open content: content://com.android.externalstorage.documents/document/primary%3ADownload%2Fsunrise.png
java.lang.SecurityException: Permission Denial: opening provider com.android.externalstorage.ExternalStorageProvider from ProcessRecord
{ee1a504 28074:com.example.pavlos.myproject/u0a74} (pid=28074, uid=10074) requires android.permission.MANAGE_DOCUMENTS or android.permission.MANAGE_DOCUMENTS
And my Manifest permissions are :
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.MANAGE_DOCUMENTS"/>
Is there something that i am missing?
EDIT: How i get the Uri:
catchImage.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent,
"Select Picture"), SELECT_PICTURE);
}
});
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK) {
if (requestCode == SELECT_PICTURE) {
Uri selectedImageUri = data.getData();
selectedImagePath = getPath(selectedImageUri);
catchImage.setImageURI(selectedImageUri);
imagePath = selectedImageUri;
Log.d("imagePath","URI "+selectedImageUri);
}
}
}
public String getPath(Uri uri) {
// just some safety built in
if( uri == null ) {
// TODO perform some logging or show user feedback
return null;
}
// try to retrieve the image from the media store first
// this will only work for images selected from gallery
String[] projection = { MediaStore.Images.Media.DATA };
Cursor cursor = managedQuery(uri, projection, null, null, null);
if( cursor != null ){
int column_index = cursor
.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
String path = cursor.getString(column_index);
cursor.close();
return path;
}
// this is our fallback here
return uri.getPath();
}
First, getPath()
is completely wrong. At best, it will work for some subset of images returned from the MediaStore
. Get rid of it entirely. Use an image-loading library to populate your ImageView
.
In terms of your problem, the Uri
that you get back from ACTION_GET_CONTENT
can be used by your activity, for as long as that activity instance is around. You can pass that Uri
to other components (eg, another activity), if and only if you include FLAG_GRANT_READ_URI_PERMISSION
. Once your process terminates, you lose all rights to access the content. So, stop persisting the Uri
to a database, or switch to ACTION_OPEN_DOCUMENT
and take persistable Uri
permissions.
Looks like you are getting the image URI (usually from gallery) which would come as a content URI (content://). This content URI comes with temporary permission which would get lost when it loses the current context. So when you load the URI next time, you might not have permission to load it in the current context.
I would suggest you to store the content of the image in DB and load it whenever required. Various image optimizations like image compression can be applied. You may also look this Glide library for image management which is recommended by Google.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.