I want to display the native android contacts list and then once the user picks a contact, i would like to move to the next native screen where it shows the details of the contact (like phone numbers, email, etc).
Now once the user selects either an email address or a phone number, I would then like to get that data back to my original activity and do further processing.
I know that I could use
startActivityForResult(new Intent(Intent.ACTION_PICK, Contacts.CONTENT_URI), REQUEST_CODE_PICK_CONTACT);
and then myself parse the contact using getContentResolver().query() and then store each of the required fields. Then finally display on a separate activity as contact details and then once the user chooses any one of the phone numbers or emails, then i use that to do further processing.
I tried to do the following inside onActivityResult():
Uri contactData = data.getData();
Intent intent = new Intent(Intent.ACTION_PICK, contactData);
startActivityForResult(intent, REQUEST_CODE_PICK_CONTACT_DETAIL);
This displays the details of the contact but when the user selects a particular number, android calls it instead of passing it back to me in the previous activity.
But I would like to use the native screens if possible and it would require a lot less parsing and no extra activities/fragments.
Could someone suggest how to go about doing this?
Thanks
You can get contact details from phone contact doing this way
Uri uri = data.getData();
String[] projection = new String[] {ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME,
ContactsContract.CommonDataKinds.Phone.NUMBER};
Cursor people = getActivity().getContentResolver().query(uri, projection, null, null, null);
int indexName = people.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME);
int indexNumber = people.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER);
int type = people.getColumnIndex(ContactsContract.CommonDataKinds.Phone.CONTENT_TYPE);
people.moveToFirst();
do {
String name = people.getString(indexName);
String number = people.getString(indexNumber);
System.out.println(name+number);
} while (people.moveToNext());
This might help:
Uri contactData = data.getData();
ContentResolver cr = getContentResolver();
Cursor c = cr.query(contactData, null, null, null, null);
if (c.moveToFirst()) {
String id = c
.getString(c
.getColumnIndexOrThrow(ContactsContract.Contacts._ID));
String hasPhone = c
.getString(c
.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER));
if (hasPhone.equalsIgnoreCase("1")) {
Cursor phones = getContentResolver()
.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
null,
ContactsContract.CommonDataKinds.Phone.CONTACT_ID
+ " = " + id, null, null);
phones.moveToFirst();
String cNumber = phones
.getString(phones
.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
Toast.makeText(getApplicationContext(), cNumber,
Toast.LENGTH_SHORT).show();
String nameContact = c
.getString(c
.getColumnIndexOrThrow(ContactsContract.Contacts.DISPLAY_NAME));
// contact number = cNumber
//contact name = nameContact
}
}
Related
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 working on my app in which user will select and saves the contacts (3 contacts) from phonebook and sends them SMS with a click of a button . I am done with searching on that sms and button part, all i want to know what things will it require for taking the contacts input and saving them. I'm not expecting any full fledged programming from someone just the breif details on which i can search upon. I am only some months old for android. Thanks in advance
try this, use-
Intent intent = new Intent(Intent.ACTION_PICK,ContactsContract.Contacts.CONTENT_URI);
then, in your onAcitivityResult:
Uri contact = data.getData();
ContentResolver cr = getContentResolver();
Cursor c = managedQuery(contact, null, null, null, null);
// c.moveToFirst();
while(c.moveToNext()){
String id = c.getString(c.getColumnIndex(ContactsContract.Contacts._ID));
String name = c.getString(c.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
if (Integer.parseInt(c.getString(c.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER))) > 0) {
Cursor pCur = cr.query(Phone.CONTENT_URI,null,Phone.CONTACT_ID +" = ?", new String[]{id}, null);
while(pCur.moveToNext()){
String phone = pCur.getString(pCur.getColumnIndex(Phone.NUMBER));
textview.setText(name+" Added " + phone);
}
}
}
You can also check this link for more help- How to call Android contacts list?
I query the phone's calllog into a ListView. So when the user long clicks an item, a dialog comes up with options, including "View contact". To be able to view the contact the intent needs the contact id.
My problem is that I not always get to see the right contact. I click on Peter, and Peter's contact sheet comes up. I click on Sarah, and Jason's contact sheet comes up.
I must have been using this code the wrong way. Please help.
ContentResolver contentResolver = getContentResolver();
Uri uri = Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI, Uri.encode(phone));
Cursor cursor = contentResolver.query(uri, new String[] {PhoneLookup.DISPLAY_NAME, PhoneLookup._ID}, null, null, null);
if(cursor!=null) {
while(cursor.moveToNext())
{
String contactName = cursor.getString(cursor.getColumnIndexOrThrow(PhoneLookup.DISPLAY_NAME));
contactid2 = cursor.getString(cursor.getColumnIndexOrThrow(PhoneLookup._ID));
}
cursor.close();
}
Intent intent_contacts = new Intent(Intent.ACTION_VIEW, Uri.parse("content://contacts/people/" + contactid2));
startActivity(intent_contacts);
Maybe what I need is not the PhoneLookup._ID, but some other ID.
I also tried Felipe's answer here, same happens.
Edit:
on a HTC Desire HD (2.3.5) I get the proper contacts in 99% of the
cases.
on a ZTE Blade (2.2) I get the proper contacts in 60% of the cases.
on a Samsung Galaxy Ace (2.3.3) I get the proper contacts in 5% of the cases.
What the hell is going on???
After digging myself into theme, I found sven's help on googlegroups. The problem was that I was using a depracated intent. I read through many pages on the developer site, I must have missed it somehow.
I also post the full code.
contactid26 = null;
ContentResolver contentResolver = getContentResolver();
Uri uri = Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI, Uri.encode(phonenumintolist));
Cursor cursor =
contentResolver.query(
uri,
new String[] {PhoneLookup.DISPLAY_NAME, PhoneLookup._ID},
null,
null,
null);
if(cursor!=null) {
while(cursor.moveToNext()){
String contactName = cursor.getString(cursor.getColumnIndexOrThrow(PhoneLookup.DISPLAY_NAME));
contactid26 = cursor.getString(cursor.getColumnIndexOrThrow(PhoneLookup._ID));
}
cursor.close();
}
if (contactid26 == null) {
Toast.makeText(DetailedCallHistory.this, "No contact found associated with this number", Toast.LENGTH_SHORT).show();
}
else {
Intent intent_contacts = new Intent(Intent.ACTION_VIEW, Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_URI, String.valueOf(contactid26)));
//Intent intent_contacts = new Intent(Intent.ACTION_VIEW, Uri.parse("content://contacts/people/" + contactid26));
startActivity(intent_contacts);
}
Here in this case i am going to show you that how to get the ID, and
Name of any contact no, which you have enter and want to search, For
Example if you enter a no and want to search its Name and id then use
this code, it is working 100%, if you want further modification in
this, then you can tell me
Uri lookupUri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI,Uri.encode(phnno.getText().toString()));//phone no
String[] proj = new String[]
{///as we need only this colum from a table...
Contacts.DISPLAY_NAME,
Contacts._ID,
};
String id=null;
String sortOrder1 = StructuredPostal.DISPLAY_NAME + " COLLATE LOCALIZED ASC";
Cursor crsr = getContentResolver().query(lookupUri,proj, null, null, sortOrder1);
while(crsr.moveToNext())
{
String name=crsr.getString(crsr.getColumnIndex(Contacts.DISPLAY_NAME));
id = crsr.getString(crsr.getColumnIndex(Contacts._ID));
Toast.makeText(this,"Name of this cntct is : " +name +"\n id is : "+id ,Toast.LENGTH_SHORT).show();
}
crsr.close();
I created an app. It is working on htc desire hd, but when i tested it on ZTE Blade, a strange problem appeared. In my app when user selects a contact name from a spinner a menu appears. In the menu the user can send sms to the user, call him/her or just look at his/her contact info. On HTC Desire HD, everything is working fine. On ZTE there seems to be an exasperating problem with the contact info button: In certain cases when user selects a contact and wants to see his contact info, some other contact's info is shown. So I select Pete from my spinner but I get Dave's contact info. In other cases I select Tom from the spinner and I get Tom's contact info. The problem is not existing on my HTC. I couldn't figure out what causes the problem. By the way, my contact list on HTC is populated also from gmail and facebook and the app still working fine, while the contact list of the ZTE has never seen any gmail or facebook accounts (i am not entirely sure about this).
This is the code i am using to get to the contact info:
infobtn.setOnClickListener(new View.OnClickListener()
{
public void onClick(View v)
{
ContentResolver cr = getContentResolver();
Cursor cur = cr.query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null);
if (cur.getCount() > 0)
{
while (cur.moveToNext()) {
id_contact = cur.getString(cur.getColumnIndex(ContactsContract.Contacts._ID));
name_contact = cur.getString(cur.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
if (name_contact.equals(name1))
{
Cursor pCur = cr.query(
ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null,
ContactsContract.CommonDataKinds.Phone.CONTACT_ID +" = ?", new String[]{id_contact}, null);
id_contact2 = id_contact;
while (pCur.moveToNext()){
}
pCur.close();
}
}
Intent intent_contacts = new Intent(Intent.ACTION_VIEW, Uri.parse("content://contacts/people/" + id_contact2));
startActivity(intent_contacts);
}
}
});
I have similar problems in my application. The app is a widget that give possibility to use favorites contacts in fast way. User creates new widget and assigns contact to it. When he clicks on widget he is able to make common contact actions - call, sms, edit, etc.
Some users send report like this one:
"I select about 4 contacts and the app shows 4 but only one of them right 3 others is same contact which I didnt even picked".
"Why does the wrong contact show when picked? On my droid incredible"
I can't reproduce the problem on my side. I have tried several different devices, tried to make import/export contacts - no results.
Anyway, i have some ideas about source of the problem.
My application uses lookup keys to store contacts, according to sdk. So, when user picks up a contact, application stores contact lookup key. Then it uses this lookup key to get Contact ID for this contact. After that, it uses ONLY received Contact ID in all other functions. So does your function - it uses only Contact ID in sub-query.
The question is: is it possible that different contacts (with different lookup keys) have same Contact ID? It looks like it's possible on some devices in rare cases... If so, we need to use Contact ID + lookup key always together to identify contact. (update: the suggestion was incorrect. Lookup key can be changed after contact info modification, you won't find contact).
As I understand, you are able to reproduce the problem on your side. I would suggest to change your code in such way:
infobtn.setOnClickListener(new View.OnClickListener()
{
public void onClick(View v)
{
ContentResolver cr = getContentResolver();
Cursor cur = cr.query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null);
if (cur.getCount() > 0)
{
while (cur.moveToNext()) {
id_contact = cur.getString(cur.getColumnIndex(ContactsContract.Contacts._ID));
name_contact = cur.getString(cur.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
String lookup_key = cur.getString(cur.getColumnIndex(ContactsContract.Contacts.LOOKUP_KEY));
if (name_contact.equals(name1))
{
Cursor pCur = cr.query(
ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null,
ContactsContract.CommonDataKinds.Phone.CONTACT_ID +" = ? AND " + ContactsContract.CommonDataKinds.Phone.LOOKUP_KEY + " = ?", new String[]{id_contact, lookup_key}, null);
id_contact2 = id_contact;
while (pCur.moveToNext()){
}
pCur.close();
}
}
Intent intent_contacts = new Intent(Intent.ACTION_VIEW, Uri.parse("content://contacts/people/" + id_contact2));
startActivity(intent_contacts);
}
}
});
and try to reproduce the problem again.
You can see this link, It's very good: http://www.vtutorials.info/2014/08/working-with-android-contacts-how-to.html
private Map<Long, ArrayList<LocalContactInfo>> queryAllPhones(ContentResolver contentresolver)
{
HashMap<Long, ArrayList<LocalContactInfo>> hashmap = new HashMap<Long, ArrayList<LocalContactInfo>>();
Uri PhoneCONTENT_URI = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;
String Phone_CONTACT_ID = ContactsContract.CommonDataKinds.Phone.CONTACT_ID;
String NUMBER = ContactsContract.CommonDataKinds.Phone.NUMBER;
Cursor cursor = contentresolver.query(PhoneCONTENT_URI, null, null, null, null);
do
{
if (!cursor.moveToNext())
{
cursor.close();
return hashmap;
}
long l = cursor.getLong(cursor.getColumnIndex(Phone_CONTACT_ID));
String s = cursor.getString(cursor.getColumnIndex(NUMBER));
LocalContactInfo temp = new LocalContactInfo(String.valueOf(l), "", s, "", 1);
if (hashmap.containsKey(Long.valueOf(l))){
((List<LocalContactInfo>)hashmap.get(Long.valueOf(l))).add(temp);
} else{
ArrayList<LocalContactInfo> arraylist = new ArrayList<LocalContactInfo>();
arraylist.add(temp);
hashmap.put(Long.valueOf(l), arraylist);
}
} while (true);
}
And:
public List<LocalContactInfo> doloadContacts() {
List<LocalContactInfo> _return = new ArrayList<LocalContactInfo>();
Uri CONTENT_URI = ContactsContract.Contacts.CONTENT_URI;
String _ID = ContactsContract.Contacts._ID;
String DISPLAY_NAME = ContactsContract.Contacts.DISPLAY_NAME;
String HAS_PHONE_NUMBER = ContactsContract.Contacts.HAS_PHONE_NUMBER;
ContentResolver contentResolver = mContext.getContentResolver();
Map<Long, ArrayList<LocalContactInfo>> map = queryAllPhones(contentResolver);
Cursor cursor = contentResolver.query(CONTENT_URI, null,null, null, null);
if(cursor == null || cursor.getCount()==0){
return _return;
}
if (cursor.getCount() > 0) {
while (cursor.moveToNext()) {
Long contact_id = cursor.getLong(cursor.getColumnIndex( _ID ));
String fullname = cursor.getString(cursor.getColumnIndex( DISPLAY_NAME )).trim();
int hasPhoneNumber = Integer.parseInt(cursor.getString(cursor.getColumnIndex( HAS_PHONE_NUMBER )));
if (hasPhoneNumber > 0 && map.get(contact_id) != null){
Object obj = ((List<LocalContactInfo>)map.get(contact_id)).get(0);
if(obj instanceof LocalContactInfo){
LocalContactInfo _temp = (LocalContactInfo)obj;
_return.add(new LocalContactInfo(String.valueOf(contact_id), fullname, _temp.getNumberPhone(), "",hasPhoneNumber));
}
}
}
}
return _return;
}
instead of using "contacts/people/xxx", try using contactsContract.Contacts.CONTENT_URI.
basically, you want to replace.
Uri contactUri = Uri.parse("content://contacts/people/" + id_contact2));
with
Uri contactUri = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_URI,
id_contact2);
Another thing to note is that "id_contact2" may be changed if a sync occurs before you use it (like when google sync merges a contact). To prevent this, it might be better to use a LookupKey instead.
ContactsContract.Contacts.LOOKUP_KEY
and retrieve using
Uri contactUri = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_LOOKUP_URI,
yourContactLookupKey);
In my app, user writes a phone number, and I want to find the contact name with that phone number?
I usually search the contacts like this:
Cursor cur = getContentResolver().query(ContactsContract.Contacts.CONTENT_URI,
null, null, null, null);
But I do this to access all contacts... In this app I only want to get the contact name of the given phone number... How can I restrict the query?
Or do I have to go trough all contacts and see if any has the given phone number? But I believe that this can be very slow this way...
If you want the complete code:
public String getContactDisplayNameByNumber(String number) {
Uri uri = Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI, Uri.encode(number));
String name = "?";
ContentResolver contentResolver = getContentResolver();
Cursor contactLookup = contentResolver.query(uri, new String[] {BaseColumns._ID,
ContactsContract.PhoneLookup.DISPLAY_NAME }, null, null, null);
try {
if (contactLookup != null && contactLookup.getCount() > 0) {
contactLookup.moveToNext();
name = contactLookup.getString(contactLookup.getColumnIndex(ContactsContract.Data.DISPLAY_NAME));
//String contactId = contactLookup.getString(contactLookup.getColumnIndex(BaseColumns._ID));
}
} finally {
if (contactLookup != null) {
contactLookup.close();
}
}
return name;
}
You should have a look at the recommended ContactsContract.PhoneLookup provider
A table that represents the result of looking up a phone number, for example for caller ID. To perform a lookup you must append the number you want to find to CONTENT_FILTER_URI. This query is highly optimized.
Uri uri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(phoneNumber));
resolver.query(uri, new String[]{PhoneLookup.DISPLAY_NAME,...