I'm trying to read all the contacts using RawContacts.entityIterator but I'm seeing this error:
android.database.CursorIndexOutOfBoundsException: Index -1 requested
Following is my code:
ContentResolver cr = getContentResolver();
Cursor cur = cr.query(Contacts.CONTENT_URI,
null, null, null, null);
String id = cur.getString(cur.getColumnIndex(Contacts._ID));
if (cur.getCount() > 0) {
while (cur.moveToNext()) {
final Uri uri = RawContactsEntity.CONTENT_URI;
final String selection = Data.CONTACT_ID + "=?";
final String[] selectionArgs = new String[] {id};
final Map<String, List<ContentValues>> contentValuesListMap =
new HashMap<String, List<ContentValues>>();
EntityIterator entityIterator = null;
entityIterator = RawContacts.newEntityIterator(cr.query(
uri, null, selection, selectionArgs, null));
while (entityIterator.hasNext()) {
Entity entity = entityIterator.next();
for (NamedContentValues namedContentValues : entity.getSubValues()) {
ContentValues contentValues = namedContentValues.values;
String key = contentValues.getAsString(Data.MIMETYPE);
if (key != null) {
List<ContentValues> contentValuesList =
contentValuesListMap.get(key);
if (contentValuesList == null) {
contentValuesList = new ArrayList<ContentValues>();
contentValuesListMap.put(key, contentValuesList);
}
contentValuesList.add(contentValues);
}
}
}
Log.i(tag, "Contact index=" + id);
}
}
Can somebody please tell me what's wrong with my code.
After you execute query, you must call cur.moveToFirst()...
Try this
ContentResolver cr = getContentResolver();
Cursor cur = cr.query(Contacts.CONTENT_URI,
null, null, null, null);
if(cur != null && cur.moveToFirst())
{
String id = cur.getString(cur.getColumnIndex(Contacts._ID));
if (cur.getCount() > 0) {
...
It is not required to call moveToFirst but to ensure that you moved to any of the returned rows before accessing a value (see moveToLast(), moveToPosition(int position), ... ).
So this one:
Cursor cur = cr.query(Contacts.CONTENT_URI, null, null, null, null);
while (cur.moveToNext()) {
String id = cur.getString(cur.getColumnIndex(Contacts._ID));
final Uri uri = RawContactsEntity.CONTENT_URI;
would work as well - or even better, because there is an issue with the accepted answer, if you continue with ...
while (cur.moveToNext()) {
after
if (cur.getCount() > 0) {
It would skip the first row, what might not be obvious.
Related
I have function to load all contact number in android, and now i want to filter all contact number with prefix "0878","0877","0817" so contact number with that prefix will be loaded, and here my current code :
private void loadContact(){
ContentResolver cr = applicationContext.getContentResolver();
String [] PROJECTION = ContactsQuery.PROJECTION;
Cursor cursor = cr.query(
ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
PROJECTION,
null,
null,
null
);
while (cursor.moveToNext()) {
//String name = cursor.getString(ContactsQuery.DISPLAY_NAME);
String lookUpKey = cursor.getString(ContactsQuery.LOOKUP_KEY);
loadContactDetail(lookUpKey);
}
cursor.close();
}
private void loadContactDetail(String lookUpKey){
ContentResolver cr = applicationContext.getContentResolver();
String [] COLS = {ContactsContract.CommonDataKinds.Phone.NUMBER};
Cursor cursor = cr.query(
ContactsContract.CommonDataKinds.Phone.CONTENT_URI, COLS,
ContactsContract.Data.LOOKUP_KEY + " = ?",
new String[]{lookUpKey},
null
);
while (cursor.moveToNext()) {
String phone = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
String formatted = Util.formatMSISDN(phone);
if(formatted != null)
contactsSet.add(formatted);
}
cursor.close();
}
Try this.
while (cursor.moveToNext()) {
String phone = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
String formatted = Util.formatMSISDN(phone);
if(formatted != null){
if(formatted.startsWith("0878") || formatted.startsWith("0877") || formatted.startsWith("0817"))
contactsSet.add(formatted);
}
}
cursor.close();
Check out the sourceString.contains(CharSequence) method.
I had many query and it was taking lot of time to fetch contact data.
So need to convert all query in into one.
I got all other info like display name, mobile number, label, email in one query
but finding prob only with getting pics
Help me to Convert below photo query into single query and get uri of pics :
ContentResolver KntRslverVar = getContentResolver();
Cursor ContctKsrVar = KntRslverVar.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
new String[] {
ContactsContract.CommonDataKinds.Phone._ID,
ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME,
ContactsContract.CommonDataKinds.Phone.NUMBER},
null, null, null);
while (ContctKsrVar.moveToNext())
{
String ContctUidVar = ContctKsrVar.getString(ContctKsrVar.getColumnIndex(ContactsContract.Contacts._ID));
String ContctNamVar = ContctKsrVar.getString(ContctKsrVar.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
String ContctMobVar = ContctKsrVar.getString(ContctKsrVar.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
Cursor ContctPflPicKsrVar = KntRslverVar.query(
ContactsContract.Data.CONTENT_URI,
null,
ContactsContract.Data.CONTACT_ID + " = ? AND " + ContactsContract.Data.MIMETYPE + " = ?",
new String[]{ContctUidVar, ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE},
null);
if (ContctPflPicKsrVar != null && ContctPflPicKsrVar.getCount() > 0)
{
while(ContctPflPicKsrVar.moveToNext())
{
Uri ContctPflPicUriVar = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, Long.parseLong(ContctUidVar));
PflPicUriVar = Uri.withAppendedPath(ContctPflPicUriVar, ContactsContract.Contacts.Photo.CONTENT_DIRECTORY);
}
ContctPflPicKsrVar.close();
}
}
Try 1 :
Cursor ContctKsrVar = KntRslverVar.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
new String[] {
ContactsContract.CommonDataKinds.Phone._ID,
ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME,
ContactsContract.CommonDataKinds.Phone.NUMBER
ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE},
null, null, null);
Try 2 :
Cursor ContctKsrVar = KntRslverVar.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
new String[] {
ContactsContract.CommonDataKinds.Phone._ID,
ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME,
ContactsContract.CommonDataKinds.Phone.NUMBER
ContactsContract.CommonDataKinds.Phone.PHOTO_THUMBNAIL_URI},
null, null, null);
Also need help on getting uri from fetched query :
Uri KctPflPicUriVar = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, Long.parseLong(KctUidVar));
PflPicUriVar = Uri.withAppendedPath(KctPflPicUriVar, ContactsContract.Contacts.Photo.CONTENT_DIRECTORY);
|*| Optimised : Get Display Name and Number with label and Photo Thumbnail in one query : Gets result query in less than 4 sec.
ContentResolver contntRslverVar = getContentResolver();
Cursor contctKsrVar = contntRslverVar.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
new String[] {
ContactsContract.CommonDataKinds.Phone._ID,
ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME,
ContactsContract.CommonDataKinds.Phone.NUMBER,
ContactsContract.CommonDataKinds.Phone.TYPE,
ContactsContract.CommonDataKinds.Phone.LABEL,
ContactsContract.CommonDataKinds.Phone.PHOTO_THUMBNAIL_URI},
null, null, null);
while (contctKsrVar.moveToNext())
{
String contctUidVar = contctKsrVar.getString(contctKsrVar.getColumnIndex(ContactsContract.Contacts._ID));
String contctNamVar = contctKsrVar.getString(contctKsrVar.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
String contctMobVar = contctKsrVar.getString(contctKsrVar.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
int MobLblTypVar = contctKsrVar.getColumnIndex(ContactsContract.CommonDataKinds.Phone.TYPE);
int MobLblTipVar = contctKsrVar.getColumnIndex(ContactsContract.CommonDataKinds.Phone.LABEL);
MobLblTypVar = contctKsrVar.getInt(MobLblTypVar);
String contctMobLblVar;
if(MobLblTypVar == ContactsContract.CommonDataKinds.Phone.TYPE_CUSTOM)
{
contctMobLblVar = contctKsrVar.getString(MobLblTipVar);
}
else
{
CharSequence MobLblSrgVar = ContactsContract.CommonDataKinds.Phone.getTypeLabel(getResources(), MobLblTypVar, "Mobile");
contctMobLblVar = MobLblSrgVar.toString();
}
String PflPicSrgVar = contctKsrVar.getString(contctKsrVar.getColumnIndex(ContactsContract.CommonDataKinds.Phone.PHOTO_THUMBNAIL_URI));
if(PflPicSrgVar != null) Uri PflPicUriVar = Uri.parse(PflPicSrgVar);
}
My code is returning ID = 1367(correct ID is 233). What is wrong? I have working code searching ID by phone number, but I need to change it to searching by display name.
String selection = ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME+" like'%" + mStructuredName +"%'";
String[] projection = new String[] { ContactsContract.PhoneLookup._ID};
Cursor mcursor = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
projection, selection, null, null);
long idPhone = 0;
try {
if (mcursor != null) {
if (mcursor.moveToFirst()) {
idPhone = Long.valueOf(mcursor.getString(0));
}
}
} finally {
if (mcursor != null) {
mcursor.close();
}
}
if (idPhone > 0) {
Intent intent = new Intent(Intent.ACTION_EDIT);
intent.setData(ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, idPhone));
startActivity(intent);
}
Searching by phone number (working)
Uri lookupUri = Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI, Uri.encode(tempPhoneNum));
Cursor mcursor = getContentResolver().query(lookupUri, new String[]{ContactsContract.PhoneLookup.DISPLAY_NAME, ContactsContract.PhoneLookup._ID}, null, null, null);
long idPhone = 0;
try {
if (mcursor != null) {
if (mcursor.moveToFirst()) {
idPhone = Long.valueOf(mcursor.getString(mcursor.getColumnIndex(ContactsContract.PhoneLookup._ID)));
}
}
} finally {
if (mcursor != null) {
mcursor.close();
}
}
if (idPhone > 0) {
Intent intent = new Intent(Intent.ACTION_EDIT);
intent.setData(ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, idPhone));
startActivity(intent);
}
Your code seems too complicated, here is mine:
Cursor contacts_cur = context.getContentResolver().query(ContactsContract.Contacts.CONTENT_URI, null, null, ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME +" = ?",
new String[]{name}, null);
contacts_cur.moveToNext();
String id = cursor.getString(cursor.getColumnIndex( ContactsContract.Contacts._ID));
Note that is seems dangerous for me to retrieve the id by name since two contacts can have the same name (but not the same id).
folks!
Look I broke my mind with problem -
how get display_name from ContactContract via _ID I got earlier???
Here is the code:
public static long getId(Context context, String number) {
long id = 0;
String displayName;
// define the columns I want the query to return
final String[] projection = new String[] {
ContactsContract.PhoneLookup.DISPLAY_NAME,
ContactsContract.PhoneLookup._ID};
// encode the phone number and build the filter URI
final Uri contactUri = Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI, Uri.encode(number));
// query time
final Cursor cursor = context.getContentResolver().query(contactUri, projection, null, null, null);
if(cursor != null) {
if (cursor.moveToFirst()) {
displayName = cursor.getString(cursor.getColumnIndex(ContactsContract.PhoneLookup.DISPLAY_NAME));
// HERE IS GOOD _ID!
id = cursor.getLong(cursor.getColumnIndex(ContactsContract.PhoneLookup._ID));
Log.d("_TAG_", displayName);
{
//
// v. N-1
//
Cursor cursor2 = context.getContentResolver().query(
contactUri,
projection,
ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?",
new String[]{String.valueOf(id)}, null);
if(cursor2 != null) {
// Cursor valid but string below got error "android.database.CursorIndexOutOfBoundsException: Index -1 requested, with a size of 1 : )"
displayName = cursor2.getString(cursor.getColumnIndex(ContactsContract.PhoneLookup.DISPLAY_NAME));
Log.d("_TAG_", displayName);
}
}
{
//
// v. N
//
Uri myPhoneUri = Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI,
Uri.encode(String.valueOf(id)));
Cursor phoneCursor = context.getContentResolver().query(
myPhoneUri, null, null, null, null);
for (phoneCursor.moveToFirst(); !phoneCursor.isAfterLast(); phoneCursor.moveToNext()) {
// No steps inside!
String str = phoneCursor.getString(phoneCursor
.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.Nickname.NAME));
Log.d(App.LOG_TAG, "ContactUtils.getId: " + str);
}
if(phoneCursor != null) {
phoneCursor.close();
}
}
} else {
Log.d("_TAG_", "Contact Not Found # " + number);
}
cursor.close();
}
return id;
}
"v.N-1" and "v.N" are just 2 ones from a million attempts before.
See - I got _ID, so why it doesn't work back as valid query???
Here is decision i found.
public static String getDisplayName(Context context, long id) {
String displayName = null;
// define the columns I want the query to return
final String[] projection = new String[] {
ContactsContract.Contacts.DISPLAY_NAME,
};
final Cursor cursor = context.getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, projection,
ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?", new String[] { id + "" }, null);
if(cursor != null) {
if (cursor.moveToFirst()) {
displayName = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
}
cursor.close();
}
return displayName;
}
It works...
I'm implementing an AutoCompleteTextView and I need Name and E-Mail of all my contacts.
I found this snippet that I'm running asynchronously but it's very slow.
ContentResolver cr = getContentResolver();
Cursor cur = cr.query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null);
if (cur.getCount() > 0) {
while (cur.moveToNext()) {
String id = cur.getString(cur.getColumnIndex(ContactsContract.Contacts._ID));
String name = cur.getString(cur.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
Cursor emailCur = cr.query(ContactsContract.CommonDataKinds.Email.CONTENT_URI, null, ContactsContract.CommonDataKinds.Email.CONTACT_ID + " = ?", new String[]{id}, null);
while (emailCur.moveToNext()) {
String email = emailCur.getString(emailCur.getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA));
autoCompleteAdapter.add(name + " - " + email);
}
emailCur.close();
}
}
}
I'm performing a sort of inner query and I think that's the problem. Is there a way to tune it and make it faster?
private static final String[] PROJECTION = new String[] {
ContactsContract.CommonDataKinds.Email.CONTACT_ID,
ContactsContract.Contacts.DISPLAY_NAME,
ContactsContract.CommonDataKinds.Email.DATA
};
...
ContentResolver cr = getContentResolver();
Cursor cursor = cr.query(ContactsContract.CommonDataKinds.Email.CONTENT_URI, PROJECTION, null, null, null);
if (cursor != null) {
try {
final int contactIdIndex = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Email.CONTACT_ID);
final int displayNameIndex = cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME);
final int emailIndex = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA);
long contactId;
String displayName, address;
while (cursor.moveToNext()) {
contactId = cursor.getLong(contactIdIndex);
displayName = cursor.getString(displayNameIndex);
address = cursor.getString(emailIndex);
...
}
} finally {
cursor.close();
}
}
few notes:
use just ContactsContract.CommonDataKinds.Email.CONTENT_URI to get information you need, see ContactsContract.CommonDataKinds.Email for information what columns you can query
use projection to get only those columns you really need, you save some memory and increase query performance
get column indexes only once, just before the while cycle
You should not query directly the ContactsContract.Contacts
Make just one query on the ContactsContract.CommonDataKinds with the email data kind.
The ContactsContract.CommonDataKinds.Email inherits a lot of other interfaces that you can use to build your projection. (see inherited constants from the documentation)
For example :
import android.provider.ContactsContract.CommonDataKinds.Email;
[...]
public static final String[] EMAILS_PROJECTION = new String[] {
Email._ID,
Email.DISPLAY_NAME_PRIMARY,
Email.ADDRESS
};
to be used with the
Email.CONTENT_URI
You can retrieve a lot of information (such as user id, user display name ...) directly from the email data kind.
EDIT:
I just realized you're trying to build an AutoCompleteTextView.
You should override the runQueryOnBackgroundThread method and the convertToString of your CursorAdapter and use the Email.CONTENT_FILTER_URI
I really strongly suggest you to take a look at the ApiDemo samples.
Especially the AutoComplete4.java sample that you can find HERE.
ContentResolver cr = mContext.getContentResolver();
Cursor cursor = mContext.getContentResolver().query(ContactsContract.Contacts.CONTENT_URI, PROJECTION, "HAS_PHONE_NUMBER <> 0", null, null);
if (cursor!= null)
{
final int displayNameIndex = cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME);
final int numberIndex = cursor.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER);
final int idIndex= cursor.getColumnIndex(ContactsContract.Contacts._ID);
String displayName, number = null, idValue;
while (cursor.moveToNext())
{
displayName = cursor.getString(displayNameIndex);
idValue= cursor.getString(idIndex);
Cursor phones = mContext.getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, "contact_id = '" + idValue + "'", null, null);
phones.moveToFirst();
try
{
number = phones.getString(phones.getColumnIndex("data1"));
}
catch (CursorIndexOutOfBoundsException e)
{
}
phones.close();
userList.add(new ContactModel(displayName, number, null));
}
}