I want to get a contact list (name && photo) and show it in RecyclerView .
I used several methods, but they have one common problem: the contact photo and name do not match.
I. photo uri is incorrect and confusing for each contact.

I tried using these methods:
Most important here:
Model class:
public class ContactModel {
private String name;
private String photoUri;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPhotoUri() {
return photoUri;
}
public void setPhotoUri(String photoUri) {
this.photoUri = photoUri;
}
}
XML element:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
>
<data>
<variable
name="contact"
type="xyz.letscoder.testcontacts.model.ContactModel" />
</data>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:id="@+id/item_contact_icon"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_marginBottom="16dp"
app:icon="@{contact.photoUri}"
android:layout_marginTop="16dp" />
<TextView
android:id="@+id/item_contact_name"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="center"
android:layout_marginLeft="16dp"
android:layout_marginStart="16dp"
android:gravity="center"
android:text="@{contact.name}" />
</LinearLayout>
</layout>
Adapter Code:
public class ContactItemAdapter
extends RecyclerView.Adapter<ContactItemAdapter.ContactItemViewHolder> {
private List<ContactModel> contacts;
public ContactItemAdapter(List<ContactModel> contacts) {
this.contacts = contacts;
}
@Override
public ContactItemViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
ItemContactBinding binding = ItemContactBinding.inflate(inflater, parent, false);
return new ContactItemViewHolder(binding.getRoot());
}
@Override
public void onBindViewHolder(ContactItemViewHolder holder, int position) {
ContactModel model = contacts.get(position);
holder.binding.setContact(model);
}
@Override
public int getItemCount() {
return contacts.size();
}
class ContactItemViewHolder extends RecyclerView.ViewHolder {
private ItemContactBinding binding;
ContactItemViewHolder(View itemView) {
super(itemView);
binding = DataBindingUtil.bind(itemView);
}
}
@BindingAdapter("bind:icon")
public static void loadIcon(ImageView imageView, String v) {
if(v != null)
imageView.setImageURI(Uri.parse(v));
}
}
Operation code:
public class MainActivity extends AppCompatActivity {
private RecyclerView recyclerView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setupRecyclerView();
}
private void setupRecyclerView() {
recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(layoutManager);
showContacts();
}
private void showContacts() {
if (PermissionUtils.isReadContactsPermissionGranted(this)) {
setupAdapter();
} else {
PermissionUtils.requestReadContactsPermission(this);
}
}
private void setupAdapter() {
ContactItemAdapter adapter = new ContactItemAdapter(fetchContacts());
recyclerView.setAdapter(adapter);
}
private List<ContactModel> fetchContacts() {
return ContactFetchUtils.getContactsWithContactsLibrary();
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
@NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (PermissionUtils.isReadContactsPermissionGranted(requestCode, grantResults)) {
setupAdapter();
}
}
}
Extract contacts utils code:
public final class ContactFetchUtils {
private ContactFetchUtils() { }
public static List<ContactModel> getContactsWithNativeMethod(Context context) {
List<ContactModel> contacts = new ArrayList<>();
Cursor phones = context.getContentResolver()
.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
null, null, null, null);
while (phones.moveToNext()) {
String name = phones.getString(
phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
String photoUri = phones.getString(
phones.getColumnIndex(ContactsContract.CommonDataKinds.Photo.PHOTO_THUMBNAIL_URI));
ContactModel contact = new ContactModel();
contact.setPhotoUri(photoUri);
contact.setName(name);
contacts.add(contact);
}
phones.close();
return contacts;
}
public static List<ContactModel> getContactsWithEasyProvidersLibrary(Context context) {
ContactsProvider provider = new ContactsProvider(context);
List<ContactModel> models = new ArrayList<>();
List<me.everything.providers.android.contacts.Contact> contacts = provider.getContacts()
.getList();
for (me.everything.providers.android.contacts.Contact contact : contacts) {
ContactModel model = new ContactModel();
model.setName(contact.displayName);
model.setPhotoUri(contact.uriPhoto);
models.add(model);
}
return models;
}
public static List<ContactModel> getContactsWithContactsLibrary() {
List<Contact> contacts = Contacts.getQuery().find();
List<ContactModel> models = new ArrayList<>();
for (Contact contact : contacts) {
ContactModel model = new ContactModel();
model.setName(contact.getDisplayName());
model.setPhotoUri(contact.getPhotoUri());
models.add(model);
}
return models;
}
}
The problem exists on all devices that I tested: