I'm working an app which pulls info from the SQLite database and displays it in a RecyclerView. I am having trouble setting the image in the RecyclerView using the URI.
Uri mImageUri=data.getData();
imgUri = data.getData();
// Get path (Path will be stored in database)
String imgToString = imgUri.toString();
// Get URI back from path
imgUri = Uri.parse(imgToString);
// Set ImageView
plainImage.setImageURI(imgUri);
// Set Glide image
Glide.with(this)
.asBitmap()
.load(imgUri)
.into(image);
This is a snippet from my OnActivityResult() after choosing pictures from gallery. Setting the images in a basic activity using this code works. I'm taking the toString() from the URI and saving this in my database. (I will be moving selected pictures to an app folder before taking URIs in final version of app)
However when I retrieve the URI strings from the database, parse them back into URIs, and attempt to set the image in the RecyclerView this method no longer works.
Here is the OnBindViewHolder() from the RecyclerAdapter
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, final int position) {
Log.d(TAG, "onBindViewHolder: called.");
// Load only first image for now
if(mImages.get(position).size() > 0) {
tempUri = Uri.parse(mImages.get(position).get(0));
// Make glide work with image
Glide.with(mContext)
.asBitmap()
.load(tempUri)
.into(holder.image);
// With regular ImageView
holder.imageViewTest.setImageURI(tempUri);
}
holder.weight.setText(mWeights.get(position).toString());
holder.location.setText(mLocations.get(position));
holder.confidence.setText(mConfidences.get(position).toString());
// Open item view
holder.parentLayout.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(mContext, ItemView.class);
// Attach additional data to intent
intent.putExtra("image_url", mImages.get(position));
intent.putExtra("location", mLocations.get(position));
intent.putExtra("confidence", mConfidences.get(position));
intent.putExtra("weight", mWeights.get(position));
mContext.startActivity(intent);
}
});
}
The URI seems fine when inspecting the variable. What might be causing this and how can I get the images to set in the RecyclerView?
Thanks
EDIT
Here is the Adapter code
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder> {
private static final String TAG = "RecyclerViewAdapter";
private ArrayList<ArrayList<String>> mImages;
private ArrayList<Float> mWeights;
private ArrayList<Float> mConfidences;
private ArrayList<String> mLocations;
private ArrayList<Integer> mSharkEntryIds;
private Context mContext;
private Uri tempUri;
public RecyclerViewAdapter(Context context, ArrayList<Integer> ids, ArrayList<ArrayList<String>> images, ArrayList<Float> weights
, ArrayList<Float> confidences, ArrayList<String> locations) {
this.mContext = context;
this.mSharkEntryIds = ids;
this.mImages = images;
this.mWeights = weights;
this.mLocations = locations;
this.mConfidences = confidences;
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.recycler_list_item, parent, false);
ViewHolder holder = new ViewHolder(view);
return holder;
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, final int position) {
Log.d(TAG, "onBindViewHolder: called.");
// Load only first image for now
if(mImages.get(position).size() > 0) {
tempUri = Uri.parse(mImages.get(position).get(0));
// Make glide work with image
Glide.with(mContext)
.asBitmap()
.load(tempUri)
.into(holder.image);
}
holder.weight.setText(mWeights.get(position).toString() + " kg");
holder.location.setText(mLocations.get(position));
holder.confidence.setText(mConfidences.get(position).toString() + " %");
// Open item view
holder.parentLayout.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(mContext, ItemView.class);
// Attach additional data to intent
intent.putExtra("id", mSharkEntryIds.get(position));
intent.putExtra("image_url", mImages.get(position));
intent.putExtra("location", mLocations.get(position));
intent.putExtra("confidence", mConfidences.get(position));
intent.putExtra("weight", mWeights.get(position));
mContext.startActivity(intent);
}
});
}
@Override
public int getItemCount() {
return mImages.size();
}
public class ViewHolder extends RecyclerView.ViewHolder{
CircleImageView image;
TextView weight;
TextView confidence;
TextView location;
RelativeLayout parentLayout;
public ViewHolder(@NonNull View itemView) {
super(itemView);
image = itemView.findViewById(R.id.thumbnail);
weight = itemView.findViewById(R.id.biomassText);
confidence = itemView.findViewById(R.id.confidenceText);
location = itemView.findViewById(R.id.locationText);
parentLayout = itemView.findViewById(R.id.parent_layout);
}
}
}
Here is the code in which I initialize the RecyclerView
// Vars
private ArrayList<Integer> mSharkEntryIds = new ArrayList<>();
private ArrayList<String> mLocations = new ArrayList<>();
//private ArrayList<String> mImageUrls = new ArrayList<>();
private ArrayList<ArrayList<String>> mImagePaths = new ArrayList<>();
private ArrayList<Float> mConfidences = new ArrayList<>();
private ArrayList<Float> mWeights = new ArrayList<>();
private DatabaseHelper mDatabaseHelper;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_list_view);
mDatabaseHelper = new DatabaseHelper(this);
Log.d(TAG, "onCreate: started");
//initImageBitmaps();
// Populate list view
Cursor data = mDatabaseHelper.getSharkEntriesFromDatabase();
while(data.moveToNext()){
mSharkEntryIds.add(data.getInt(0));
mWeights.add(data.getFloat(1));
mLocations.add(data.getString(2));
mConfidences.add(data.getFloat(3));
}
Log.d(TAG, "onCreate: test");
// Get associated image paths
ArrayList<String> photosForEntry;
for(Integer id : mSharkEntryIds){
data = mDatabaseHelper.getPhotosWithSharkID(id);
photosForEntry = new ArrayList<>();
while(data.moveToNext()){
photosForEntry.add(data.getString(0));
}
mImagePaths.add(photosForEntry);
}
initRecyclerView();
}
private void initRecyclerView(){
Log.d(TAG, "initRecyclerView: init recyclerview");
RecyclerView recyclerView = findViewById(R.id.recycler_view);
RecyclerViewAdapter adapter = new RecyclerViewAdapter(this, mSharkEntryIds, mImagePaths, mWeights, mConfidences, mLocations);
recyclerView.setAdapter(adapter);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
}
I am thinking that you are doing it wrong, I will assume that you got the paths in string form in your mImages
Do you see this part of your onBindViewHolder
:
...................
// Load only first image for now
if(mImages.get(position).size() > 0) {
tempUri = Uri.parse(mImages.get(position).get(0));
// Make glide work with image
Glide.with(mContext)
.asBitmap()
.load(tempUri)
.into(holder.image);
// With regular ImageView
holder.imageViewTest.setImageURI(tempUri);
}
..................
Change it to this:
........
// Load only first image for now
if(position == 0) {
tempUri = Uri.parse(mImages.get(position));
// Make glide work with image
Glide.with(mContext)
.asBitmap()
.load(tempUri)
.into(holder.image);
// With regular ImageView
holder.imageViewTest.setImageURI(tempUri);
}
..............
UPDATE:
Your code seems fine and you say that the Uri's are present in the list, so my guess here is maybe set the layout manager before setting the adapter:
I mean in your initRecyclerView()
:
..........
//add this first
recyclerView.setLayoutManager(new LinearLayoutManager(this));
//add this next
recyclerView.setAdapter(adapter);
......
I have fixed the issue:
The log included this message:
java.lang.SecurityException(Permission Denial: opening provider com.android.providers.downloads.DownloadStorageProvider from ProcessRecord{985e802 27308:com.oshea.sharkbiomass/u0a82} (pid=27308, uid=10082) requires that you obtain access using ACTION_OPEN_DOCUMENT or related APIs)
The problem was in my on click listener for the select photo button.
// Select photo button listener
btnSelectPhotos.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent();
intent.setType("image/*");
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(intent, 1);
}
});
I changed this to:
// Select photo button listener
btnSelectPhotos.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent();
intent.setType("image/*");
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
intent.setAction(Intent.ACTION_OPEN_DOCUMENT);
startActivityForResult(intent, 1);
}
});
(Changed ACTION_GET_CONTENT to ACTION_OPEN_DOCUMENT) and it worked.
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.