I have a Cursor points to a Contact. How can I get an url built from that Cursor?
I need to know that because from here
http://developer.android.com/guide/topics/providers/content-providers.html
I need to have an url so that I can build a phone uri, like this:
phoneUri = Uri.withAppendedPath(uri, People.Phones.CONTENT_DIRECTORY);
and I can query all the phone numbers for that contact.
You can use the following query to retrieve all numbers for a certain contact:
/* the following line assumes that the contactCursor you described
* has the People._ID column at index 0 in its projection. */
int contactId = contactCursor.getInt(0);
Cursor numberCursor = getContentResolver().query(Phones.CONTENT_URI,
new String[] {Phones.NUMBER}, Phones.PERSON_ID + "=" + contactId, null, null);
while(cursor.moveToNext()) {
String number = cursor.getString(0);
}
cursor.close();
Related
I am trying to get first name and last name in contact book by phone number.
Here is my code:
Uri contactUri = Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI, Uri.encode(phoneNumber));
Cursor cursor = cResolver.query(uri, null, null, null, null);
if(cursor != null && cursor.moveToFirst()) {
int idColumnIndex = cursor.getColumnIndex(ContactsContract.Contacts._ID);
int firstNameIndex = cursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME);
int lastNameIndex = cursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME);
while (!cursor.isAfterLast()) {
long id = cursor.getLong(idColumnIndex);
contact = new MyContact();
contact.setId(id);
contact.setFirstName(cursor.getString(firstNameIndex));
contact.setLastName(cursor.getString(lastNameIndex));
}
cursor.close();
}
But firstNameIndex and lastNameIndex is always -1. What I am doing wrong ? Please help me.
PhoneLookup is a nice and quick way to get contact data by a phone number, but it returns a cursor limited to the columns mentioned in the docs.
You can see there's DISPLAY_NAME you can access, but not GIVEN_NAME, FAMILY_NAME.
GIVEN_NAME & FAMILY_NAME are fields stored in the Data table, which means you need to query that table separately to get to those fields.
So, you can just add another query using the contact ID you got from PhoneLookup (note that for each looked up phone there might be multiple contacts returned).
Here's a sample method to get first/last names from contact ID:
private void addNames(MyContact contact, long contactId) {
String[] projection = new String[] {StructuredName.GIVEN_NAME, StructuredName.FAMILY_NAME};
// filter to just StructuredName rows from the data table for the given contact
String selection = Data.CONTACT_ID + "=" + contactID + " AND " + Data.MIMETYPE + "=" + StructuredName.CONTENT_ITEM_TYPE;
Cursor cursor = getContentResolver().query(Data.CONTENT_URI, projection, selection, null, null);
if (cursor.next()) {
contact.setFirstName(cursor.getString(0));
contact.setLastName(cursor.getString(1));
}
cursor.close();
}
I want to filter what numbers I am getting from Android based on which contacts the user chose to display in his contact book. (For example only contacts saved on the device when all other contacts are excluded)
I read here that you can do this by using
Uri queryUri = ContactsContract.Contacts.CONTENT_URI;
I use following code to read the contacts and I allways get every contact, phone, SIM, etc..
//https://stackoverflow.com/questions/16651609/how-to-display-phone-contacts-only-exclude-sim-contacts
// http://www.higherpass.com/Android/Tutorials/Working-With-Android-Contacts/1/
ContentResolver cr = currentActivity.getContentResolver();
Uri queryUri = ContactsContract.Contacts.CONTENT_URI;
Cursor cur = cr.query(queryUri,
null, null, null, null);
if (cur.getCount() > 0) {
while (cur.moveToNext()) { //Are there still contacts?
//See if the contact has at least one number
if (Integer.parseInt(cur.getString(cur.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER))) > 0) {
String id = cur.getString( cur.getColumnIndex(ContactsContract.Contacts._ID) );
String name = cur.getString( cur.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME) );
ArrayList<String> numbers = new ArrayList<String>();
//Read numbers:
Cursor pCur = cr.query(
ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
null,
ContactsContract.CommonDataKinds.Phone.CONTACT_ID +" = ?",
new String[]{id}, null);
while (pCur.moveToNext()) {
numbers.add( pCur.getString(
pCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)) );
Log.e("Contactbook", "The latest added number is: " + numbers.get(numbers.size()-1) );
}
pCur.close();
}
}
}
What am I missing? This code still gives me both SIM and phone contacts to the log.
Edit: To clarifify, in the contactbook you got the "Display options". In there ist the "select contacts to display"-option, and I want to read the contacts that are shown based on the users choice there. So if a user choses to show only SIM-contacts, read only SIM-contacts, if he choses to only show Phone-Contacts, show onyl phone contacts etc...
Try with following "selection".
String selection = ContactsContract.Contacts.IN_VISIBLE_GROUP + " = ?";
From Android docs:
public static final String IN_VISIBLE_GROUP: An indicator of whether this contact is supposed to be visible in the UI. "1" if the contact has at least one raw contact that belongs to a visible group; "0" otherwise.
This should be your "selection" argument in query API.
Update: I tried below code on Android-2.3(I know it is old device, but right now Don't have newer device with me).
final ContentResolver cr = getContentResolver();
String[] projection = new String[] { ContactsContract.Contacts._ID, ContactsContract.Contacts.DISPLAY_NAME };
String selection = ContactsContract.Contacts.IN_VISIBLE_GROUP + " = ?" ;
String[] Args = { "1" };
final Cursor contacts = cr.query(
ContactsContract.Contacts.CONTENT_URI, projection,
selection,Args ,
null);
This could be a long operation (depending on no. of contacts), hence you should use CursorLoader class (A loader that queries the ContentResolver and returns a Cursor) for this.
cursorLoader.loadInBackground();
This will be called on a worker thread to perform the actual load and to return the result of the load operation.
You can easily create two Arrays for each kind of contacts
ArrayList<String> simContacts = new ArrayList<>();
//get all sim contacts
Uri simUri = Uri.parse("content://icc/adn");
Cursor cursorSim = getContext().getContentResolver().query(simUri, null, null, null, null);
while (cursorSim.moveToNext()) {
simContacts.add(cursorSim.getString(cursorSim.getColumnIndex("name")));
}
}
ArrayList<String> allContacts = new ArrayList<>();
//get all contacts
Cursor cur = cr.query(ContactsContract.Contacts.CONTENT_URI,
null, null, null, null);
if (cursor != null && cursor.getCount() > 0) {
while (!cursor.isAfterLast()) {
String phoneNumber = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.Phone.NUMBER));
String displayNameColumn = Utils.hasHoneycomb() ? ContactsContract.Contacts.DISPLAY_NAME_PRIMARY : ContactsContract.Contacts.DISPLAY_NAME;
String displayName = cursor.getString(cursor.getColumnIndexOrThrow(displayNameColumn));
//check if simContacts Array contains this particular name
if (!simContacts.contains(displayNameColumn){
allContacts.add(displayNameColumn);
}
}
}
This is just a working example,of course you can modify to your needs.You can parse more contact fields and make more complication queries.
I am trying to find the contact details corresponding to an sms from the phone's sms inbox. From my understanding the person column is a foreign key to the _id column of ContactsContract.Contacts.
My problem is that I am getting wrong values for the person value from the sms query. Some person ids don't exist in the contact table and some are pointing to totally different contact.
Below is the code that I use for fetching the list of person values, Can anyone tell me if I missed something or faced a similar problem.
Tested with Nexus S running Android 4.1.2
Uri parsedUri = Uri.parse("content://sms/inbox");
String[] projection = new String[] { "_id", "address", "person" };
Cursor cursor = contentResolver.query(parsedUri, projection, null, null, null);
Log.d(TAG, "Total Count " + cursor.getCount());
if (cursor.getCount() > 0) {
// String address;
int person;
int personIndex = cursor.getColumnIndex("person");
if (cursor.moveToFirst())
do {
person = cursor.getInt(personIndex);
if (person > 0) {
// Add this id to a list
}
} while (cursor.moveToNext());
}
cursor.close();
Update: I was looking at some documentation from the Android Developer Portal (http://developer.android.com/guide/topics/providers/contacts-provider.html), Is it possible that the person id that is retrieved from the sms inbox is referring to the ContactsContract.RawContacts instead of ContactsContract.Contacts as I have done.
Indeed the person column in the sms inbox refers to a RawContacts entry's id. By querying the RawContacts table you can find the contact_id for the Contacts table for the specific user.
You can try this code to get the contact id from the RawContacts table..
long contactId = 0;
Uri uri = ContactsContract.RawContacts.CONTENT_URI;
String[] projection = new String[] { ContactsContract.RawContacts._ID, ContactsContract.RawContacts.CONTACT_ID };
Cursor cursor = contentResolver.query(uri, projection,
ContactsContract.RawContacts._ID + " = ?",
new String[] { rawContactId }, null);
if (cursor.moveToFirst()) {
int contactIdIndex = cursor.getColumnIndex(ContactsContract.RawContacts.CONTACT_ID);
contactId = cursor.getLong(contactIdIndex);
}
cursor.close();
This should solve your problem for fetching the correct contact details by reading an sms row in Android. However as the sms data provider is not documented and phone manufacturers may use them differently, there is chance that this approach may not work on phones other than pure android.
You first check that person number is exits in contact list or not.if yes then match both id.
Cursor cursor=managedQuery(uri, null, null, null, null);
while (cursor.moveToNext()) {
String contactId = cursor.getString(cursor.getColumnIndex(
ContactsContract.Contacts._ID));
String hasPhone = cursor.getString(cursor.getColumnIndex(
ContactsContract.Contacts.HAS_PHONE_NUMBER));
if (Boolean.parseBoolean(hasPhone)) {
// You know have the number so now query it like this
Cursor phones = getContentResolver().query(
ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
null,
ContactsContract.CommonDataKinds.Phone.CONTACT_ID +" = "+ contactId,
null, null);
while (phones.moveToNext()) {
String phoneNumber = phones.getString(
phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
}
phones.close();
}
}
I am looking to get the RAW_CONTACT_ID of a specific Contact using PhoneLookup or even just the Contacts LookupKey.
I know the contacts table has a column name_raw_contact_id that references the raw_contacts._id column but it doesn't seem to be returned when querying ContactsContract.Contacts.CONTENT_LOOKUP_URI with the contacts lookup key.
My phone lookup query is:
String[] projection = new String[] {
PhoneLookup.DISPLAY_NAME, PhoneLookup.LOOKUP_KEY };
Uri uri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(number));
Cursor c = resolver.query(uri, projection, null, null, null);
Then I am looking up the Contact based on the lookup key:
String[] contactProjection = new String[] {
ContactsContract.Contacts.NAME_RAW_CONTACT_ID
};
Uri contactUri = Uri.withAppendedPath(
ContactsContract.Contacts.CONTENT_LOOKUP_URI, lookupKey);
Cursor contactCursor = resolver.query(contactUri,
contactProjection, null, null, null);
However, this doesn't compile and I get
cannot find symbol: variable NAME_RAW_CONTACT_ID
location: class android.provider.ContactsContract.Contacts
But the android documentation shows NAME_RAW_CONTACT_ID as a column.
Is there any way I can get the RAW_CONTACT_ID based off either phone number or lookup key?
I found that the answer is to make a third query:
long rawContactId = -1;
Cursor c = getContentResolver().query(RawContacts.CONTENT_URI,
new String[]{RawContacts._ID},
RawContacts.CONTACT_ID + "=?",
new String[]{String.valueOf(contactId)}, null);
try {
if (c.moveToFirst()) {
rawContactId = c.getLong(0);
}
} finally {
c.close();
}
But it should be noted that there can be multiple RawContact's per one Contact and the above query will get ALL RawContact's associated with the contactId
ContactsContract.Contacts.NAME_RAW_CONTACT_ID column needs API level 21 or greater so make sure your are compiling with this version.
Also you can use ContactsContract.PhoneLookup._ID column in your first query to get the Contact_Id and then use this Contact_Id in your 3rd query so your problem will be solved in 2 queries instead of 3.
private HashSet<Long> getRawContactIdsForContact(long contactId)
{
HashSet<Long> ids = new HashSet<Long>();
Cursor cursor = context.getContentResolver().query(RawContacts.CONTENT_URI,
new String[]{RawContacts._ID},
RawContacts.CONTACT_ID + "=?",
new String[]{String.valueOf(contactId)}, null);
if (cursor != null && cursor.moveToFirst())
{
do
{
ids.add(cursor.getLong(0));
} while (cursor.moveToNext());
cursor.close();
}
return ids;
}
I know how to retrieve contact data for specific contacts. However, i can't find a way to get all contacts plus some of their details in a single query. The following code gets all contacts having a postal address:
Uri uri = ContactsContract.CommonDataKinds.StructuredPostal.CONTENT_URI;
String[] projection = new String[] {
StructuredPostal._ID,
StructuredPostal.LOOKUP_KEY,
StructuredPostal.DISPLAY_NAME,
StructuredPostal.STREET,
StructuredPostal.CITY
};
String sortOrder = StructuredPostal.DISPLAY_NAME + " COLLATE LOCALIZED ASC";
Cursor c = getContentResolver().query(uri, projection, null, null, sortOrder);
But what i need are all contacts, whether they have postal address or not. Is this doable using the ContatsContract API, or do i need to create custom outer join query? Any hints on how?
if You have a contact ID and you want to fetch the Postal Address then use this :
Uri postal_uri = ContactsContract.CommonDataKinds.StructuredPostal.CONTENT_URI;
Cursor postal_cursor = getContentResolver().query(postal_uri,null, ContactsContract.Data.CONTACT_ID + "="+contactId.toString(), null,null);
while(postal_cursor.moveToNext())
{
String Strt = postal_cursor.getString(postal_cursor.getColumnIndex(StructuredPostal.STREET));
String Cty = postal_cursor.getString(postal_cursor.getColumnIndex(StructuredPostal.CITY));
String cntry = postal_cursor.getString(postal_cursor.getColumnIndex(StructuredPostal.COUNTRY));
}
postal_cursor.close();
All contact information in Android 2.0 is stored in a single database table. So you can get all the information you need in a single query:
Cursor c = getContentResolver().query(ContactsContract.Data.CONTENT_URI,
null, null, null, sortOrder);
The just iterate through the data and check Data.MIMETYPE column. For example, if this column has StructuredPostal.CONTENT_ITEM_TYPE value, then you can get StructuredPostal fields from this column.