Reputation: 4219
I have modified the code in this question ,according to the answers there, in order to load contact's picture on a ListView. I am getting the Photo_id, and use it to get the Bitmap of the contact, using loadContactPhoto(ContentResolver cr, long id) . The problem is that no ImageView is getting a new image, although the photo id is always different. I tried using the Contact._ID, but still only two contacts' ImageView got a contact picture, and they were both wrong. I have commented the new lines I have added below.
Here is the code after the edit:
ContactStock:
public class ContactStock {
private String name;
private String number;
private Bitmap picture;
public ContactStock(String name, String number) {
this.name = name;
this.number = number;
}
public ContactStock(String name, String number, Bitmap photo) {
this.name = name;
this.number = number;
this.picture = photo;
}
public void setName(String name) {
this.name = name;
}
public void setNumber(String number) {
this.number = number;
}
public String getName() {
return this.name;
}
public String getNumber() {
return this.number;
}
public void setPicture(Bitmap picture) { // NEW METHOD
this.picture = picture;
}
public Bitmap getPicture() { // NEW METHOD
return picture;
}
}
addlistfromcontact:
public class addlistfromcontact extends Activity {
private ListView lst;
private List<ContactStock> contactstock;
private Cursor mCursor;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.tab_contact_list);
lst = (ListView) findViewById(R.id.tab_contact_list);
contactstock = new ArrayList<ContactStock>();
mCursor = managedQuery(ContactsContract.Data.CONTENT_URI, null,
Data.MIMETYPE + "='" + Phone.CONTENT_ITEM_TYPE + "'", null,
ContactsContract.Data.DISPLAY_NAME + " ASC");
int number = mCursor.getColumnIndex(Phone.NUMBER);
int name = mCursor.getColumnIndex(ContactsContract.Data.DISPLAY_NAME);
int id = mCursor.getColumnIndex(Contacts.PHOTO_ID); // NEW LINE
while (mCursor.moveToNext()) {
String phName = mCursor.getString(name);
String phNumber = mCursor.getString(number);
long phId = mCursor.getLong(id); // NEW LINE
Bitmap phPhoto = loadContactPhoto(getContentResolver(), phId); // NEW LINE
Log.d("phId=", phId + "");
contactstock.add(new ContactStock(phName, phNumber, phPhoto)); // NEW LINE EDIT
}
lst.setAdapter(new ContactListAdapter(addlistfromcontact.this,
contactstock));
}
public static Bitmap loadContactPhoto(ContentResolver cr, long id) { // NEW METHOD
Uri uri = ContentUris.withAppendedId(
ContactsContract.Contacts.CONTENT_URI, id);
InputStream input = ContactsContract.Contacts
.openContactPhotoInputStream(cr, uri);
if (input == null) {
return null;
}
return BitmapFactory.decodeStream(input);
}
}
ContactListAdapter:
public class ContactListAdapter extends ArrayAdapter {
private final Activity activity;
private final List stocks;
public ContactListAdapter(Activity activity, List objects) {
super(activity, R.layout.listview_detail_tab_contact_list, objects);
this.activity = activity;
this.stocks = objects;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View rowView = convertView;
ContactStockView sv = null;
if (rowView == null) {
// Get a new instance of the row layout view
LayoutInflater inflater = activity.getLayoutInflater();
rowView = inflater.inflate(
R.layout.listview_detail_tab_contact_list, null);
// Hold the view objects in an object,
// so they don't need to be re-fetched
sv = new ContactStockView();
sv.name = (TextView) rowView.findViewById(R.id.contact_name);
sv.number = (TextView) rowView.findViewById(R.id.contact_number);
sv.photo = (ImageView) rowView.findViewById(R.id.contact_photo);
// Cache the view objects in the tag,
// so they can be re-accessed later
rowView.setTag(sv);
} else {
sv = (ContactStockView) rowView.getTag();
}
// Transfer the stock data from the data object
// to the view objects
ContactStock currentStock = (ContactStock) stocks.get(position);
sv.name.setText(currentStock.getName());
sv.number.setText(currentStock.getNumber());
sv.photo.setImageBitmap(currentStock.getPicture()); // NEW LINE
// TODO Auto-generated method stub
return rowView;
}
protected static class ContactStockView {
protected TextView name;
protected TextView number;
protected ImageView photo; // NEW LINE
}
}
Upvotes: 0
Views: 2110
Reputation: 4219
Since I had lots of trouble figuring out how to load all contacts' photos efficiently without any UI freezing, errors on loading the images when I first started working on Android, I highly recommend anyone looking at my question to take a good look here.
It's a sample app that teaches you how to handle all proccessing data and loading images seamingly, efficiently without any 'hiccups' while scrolling your list. It is also a great project to get you started working on Android!
Specifically, for the contact image part of my questions code, the API provides two simple methods that can be found here that returns the InputStream
of the contact's high res image or thumbnail. All you have to do is decode it using BitmapFactory.decodeByteArray()
. Remember to load the size of the image you need to use in your app (something described in the link above), so that you won't get an OutOfMemoryError!
In order to improve the code further, you can also replace the ArrayAdapter with a custom Cursor adapter, and only load the lines of the listView you need on the spot.
Upvotes: 0
Reputation: 2402
There are two problems in your code. The first one is easy to overcome, the others need more work.
Lets start with the easy one:
The method ContactsContract.Contacts.openContactPhotoInputStream(cr, uri)
takes a contact uri and not a photo uri. That is the id in your call to ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, id)
has to be a contact id.
Also you create a lot of Bitmap
objects when iterating over the result set. Don't do this. Though this might work at first, it probably crashes with OutOfMemory
errors when the list get's to long. Try to create as few Bitmap
objects as necessary. That is: Only for those rows visible. When scrolling the list view you have to recycle existing Bitmaps.
Upvotes: 1