I've been trying to make multi contact picker list with checkbox. I already created Multi Contact Picker with contact having atleast one phone number in its contact.
Que
Now I've added contact with in ListView. But contact appear with single contact number in it, it's taking first phone number which is saved in Contact Application. I've added LinkedHashMap & Set to add indexer on the Contact List.
Did LinkedHashMap or Set is removing duplicate values from Collections?
How can i fetch all the phone number associated with that contact name?
Code Snippet:-
ContentResolver cr = getContentResolver();
String selection = Data.HAS_PHONE_NUMBER + " > '" + ("0") + "'";
Cursor cur = cr.query(Data.CONTENT_URI, new String[] { Data.CONTACT_ID, Data.MIMETYPE, Email.ADDRESS,
Contacts.DISPLAY_NAME, Phone.NUMBER }, selection, null, Contacts.DISPLAY_NAME);
Contact contact;
if (cur.getCount() > 0) {
while (cur.moveToNext()) {
String id = cur.getString(cur.getColumnIndex(Data.CONTACT_ID));
String mimeType = cur.getString(cur.getColumnIndex(Data.MIMETYPE));
if (allContacts.containsKey(id)) {
// update contact
contact = allContacts.get(id);
} else {
contact = new Contact();
allContacts.put(id, contact);
// set photoUri
contact.setContactPhotoUri(getContactPhotoUri(Long.parseLong(id)));
}
if (mimeType.equals(StructuredName.CONTENT_ITEM_TYPE))
// set name
contact.setContactName(cur.getString(cur.getColumnIndex(Contacts.DISPLAY_NAME)));
if (mimeType.equals(Phone.CONTENT_ITEM_TYPE))
// set phone munber
contact.setContactNumber(cur.getString(cur.getColumnIndex(Phone.NUMBER)));
}
}
cur.close();
// get contacts from hashmap
contacts.clear();
contacts.addAll(allContacts.values());
These is just a temporary fix as of now, I've been trying to add all contact number associated with same contact person inside android.provider.ContactsContract.
I've added all contact number associated with same contact person inside beans by appending with delimiter(",") which i can fetch back using Tokenizer. But no idea to know which kinda contact type it is whether HOME, WORK, OFFICE , it's less important to me as of now.
Fix:
if (mimeType.equals(Phone.CONTENT_ITEM_TYPE)){
// set phone number
if (contact.getContactNumber().toString().length() == 0) {
contact.setContactNumber(cur.getString(cur.getColumnIndex(Phone.NUMBER)).replaceAll("\\D", ""));
} else {
contact.setContactNumber(contact.getContactNumber().toString().concat(", ").concat(cur.getString(cur.getColumnIndex(Phone.NUMBER)).replaceAll("\\D", "")));//One can add possible contacts "(-/,"
}
}
Related
Im getting showing contacts on a RecyclerView and below code retrieve contacts
Uri Contact_URI=ContactsContract.CommonDataKinds.Phone.CONTENT_URI;
return new CursorLoader(getActivity(),Contact_URI,null,null,null,Build.VERSION.SDK_INT
>= Build.VERSION_CODES.HONEYCOMB ?
ContactsContract.Contacts.DISPLAY_NAME_PRIMARY :
ContactsContract.Contacts.DISPLAY_NAME+ "ASC");
but some contacts are being shown multiple times so I decided to filter Contacts on account_type column. Below code filter based on account_type
if(list.getString(list.getColumnIndex("account_type")).equals("Local Phone Account") || list.getString(list.getColumnIndex("account_type")).equals("SIM Account") ) {
textView.setText(list.getString(list.getColumnIndex(Build.VERSION.SDK_INT
>= Build.VERSION_CODES.HONEYCOMB ?
ContactsContract.Contacts.DISPLAY_NAME_PRIMARY :
ContactsContract.Contacts.DISPLAY_NAME)));
number.setText(list.getString(list.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)));
number.setText(list.getString(list.getColumnIndex("account_type")));
}
Problem is values of account_type for sim and phone contacts varies from device to device. In Samsung GT-l9082 gives values for sim "Sim Account" and for Phone "Local Phone Account" but When I tested it on Galaxy J5 it shows different values against account_type for sim and phone contacts.I want to show only Sim and Phone Contacts
This is not the way to go.
CommonDataKinds.Phone.CONTENT_URI is a table of all the phones in the Contacts DB, not contacts.
So even if you filter to just one account, if a contact contains more then one phone, it'll appear twice in your list.
If you want to display only one row per contact, but you still need to display a phone in your main list, you can't use the CursorLoader paradigm (which actually sucks and I wouldn't use it anyway).
Instead run a simple query for all the items in the Phones.CONTENT_URI table, and create a HashMap from CONTACT_ID to a list of NUMBERs, and then display one row per item in the map, and you'll get access to that contact's list of phones as well for display.
Map<String, List<String>> contacts = new HashMap<String, List<String>>();
String[] projection = { Phone.CONTACT_ID, Phone.DISPLAY_NAME, Phone.NUMBER };
Cursor cur = cr.query(Phone.CONTENT_URI, projection, null, null, null);
while (cur != null && cur.moveToNext()) {
long id = cur.getLong(0);
String name = cur.getString(1);
String data = cur.getString(2); // the actual info, e.g. +1-212-555-1234
Log.d(TAG, "got " + id + ", " + name + ", " + data);
// add info to existing list if this contact-id was already found, or create a new list in case it's new
String key = id + " - " + name;
List<String> infos;
if (contacts.containsKey(key)) {
infos = contacts.get(key);
} else {
infos = new ArrayList<String>();
contacts.put(key, infos);
}
infos.add(data);
}
// now you can iterate over the 'contacts' map to display all contacts
I am creating an app in which I want to show my app icon in front of every contact if contact is associated with my app like in WhatsApp. I have searched a lot but didn't find any appropriate solution.
Fetch all the contacts from your phone like this.
public void getNumber(ContentResolver cr)
{
mItems = new ArrayList<String>();
Cursor phones = cr.query(Phone.CONTENT_URI, null, null, null, Phone.DISPLAY_NAME + " ASC");
while (phones.moveToNext())
{
String name=phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
String phoneNumberString = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
phoneNumberString.replace(" ", "");
contactName.add(name);
contactNumber.add(phoneNumberString);
mItems.add(name);
}
phones.close();
}
now send all these contacts to your server, compare each mobile number in your server database, and list only the contacts that are found in your server.
You need to maintain your own database, when registering user, save his number and while comparing, compare the fetched number to the register member's number in your own database
I'm new to android and i'm working with native contact.
So my app is let user put contact display name and their number for edit/delete.
In case the contact have more that one number.
I tried a lot but still have no luck, the app still doesn't update the number or it crashes.
What I'm going to do as my understanding is:
Find name in contact that matched name user inserted and use that to get contact_id that represent this contact datagroup.
Use contact_id in 1. and the number user input to find ._ID that represent the specific row id.
Do task with ._ID we get from 2.
This is 1. code to get contact_id:
public String getPeopleUniqueID(String name, Context context) {
String s = null;
String selection = ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME+" like'%" + name +"%'";
String[] projection = new String[] {ContactsContract.Data.CONTACT_ID};
Cursor c = context.getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
projection, selection, null, null);
if(c.moveToFirst()) {
s = c.getString(c.getColumnIndex(ContactsContract.Data.CONTACT_ID));
}
c.close();
return s;
}
This is 2. code to get ._ID (num is number user inserted and name is from 1. > the contact_id)
public String checkPhoneNumber(String num, String name, Context context) {
String s = null;
String selection = ContactsContract.CommonDataKinds.Phone.NUMBER + "=?" + " AND "+ContactsContract.Data.CONTACT_ID+ "=?";
String[] projection = new String[] {ContactsContract.Data._ID};
Cursor c = context.getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
projection, selection, new String[]{u,name}, null);
if(c.moveToFirst()) {
s=c.getString(c.getColumnIndex(ContactsContract.Data._ID));
}
c.close();
if (s==null){
s = "null";
}
return s;
}
To do something like editing (num is _.ID we get from 2. and newnum is new number user want to change into).
public void editNumber(String num , String newnum) {
ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
ops.add(ContentProviderOperation.newUpdate(Data.CONTENT_URI)
.withSelection(Data._ID + "=? AND " +
Data.MIMETYPE + "='" +
CommonDataKinds.Phone.CONTENT_ITEM_TYPE + "'",
new String[]{num})
.withValue(Data.DATA1, newnum)
.build());
try{
getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);}
catch (RemoteException e){e.printStackTrace();}catch (OperationApplicationException e) {e.printStackTrace();}
}
And well it crashes when I call editNumber().
Can you help me fix my code and my understanding?
And another question, can I edit/insert group for the contact programatically, like I want to add this contact to family friend or co-worker group (the default group that we can set at contact edit page)?
Use ContactsContract.Contacts.CONTENT_FILTER_URI for searching a contact based on name - to get Id or anything else. The like operator cannot handle all cases which the CONTENT_FILTER_URI does handle - For various languages, special characters etc.
http://developer.android.com/reference/android/provider/ContactsContract.Contacts.html#CONTENT_FILTER_URI
Use following uri to lookup a contact from phone number - you can get person id or anything else :
Uri lookupUri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI,
Uri.encode(phoneNumber));
In the set query you can also use contactId in the condition
For groups you can use custom mimetypes if the default one does not suit you (which is still very primitive for groups across different account types)
I am creating an activity which lists out recent calls from a user. The requirement is that when a user receives the call,the phone number and contact name is stored in DB to be later displayed in the activity. To retrieve the contact Name the phone number is matched with the contacts in the users contact list. I am using below code to get the contact name.
(Below code queries the Contact database and finds a match to the inputted phone number)
String getContactDisplayNameByNumber(String number) {
Uri uri = Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI, Uri.encode(number));
String name = "";
Cursor contactLookup = context.getContentResolver().query(uri, new String[]{
ContactsContract.PhoneLookup.DISPLAY_NAME}, null, null, null);
try {
if (contactLookup != null && contactLookup.moveToNext()) {
name = contactLookup.getString(contactLookup.getColumnIndex(ContactsContract.Data.DISPLAY_NAME));
Log.v("ranjapp", "Name is " + name + " Number is " + number);
}
} finally {
if (contactLookup != null) {
contactLookup.close();
}
}
return name;
}
Now the problem is the phonenumber is saved in the contact list as "1234567891" and the phone number retrieved from an incoming call is "01234567891"(0 prefixed).
As 0 is prefixed in the incoming number the number is not matching with the number in contact list.
There can be also other possibilities the incoming number may have the country code prefixed and saved contact does not have it.
How can i match in these scenarios.
(I am aware of PhoneNumberUtils.compare() but not able to apply it in the code mentioned).
The problem was the method was not getting called with the phone number as input. It works irrespective how the number is i.e with prefix +91 or 0. Corrected the code as below:
Bundle bundle = intent.getExtras();
String number = bundle.getString(TelephonyManager.EXTRA_INCOMING_NUMBER);
String name=getContactDisplayNameByNumber(number);
i want to fetch the contacts from android periodically. for that i
want to something like this. i am taking all the conatcts from the
android and store it in my local db. so i will store last contact id.
so next time on wards if any contacts added , i need to get those
contacts only so for that purpose i want to fetch the contact id
greater than last time fetched contact id. how can write the query for
content resolver to fetch the contacts some thing like.
Select * from tablename where id > 100;
Cursor cursor = getContentResolver().query(ContactsContract.Contacts.CONTENT_URI,
null, // this will be the columns selection
ContactsContract.Contacts._ID + ">100", // this is where you add the "where" part of the query, id is 1 in this case
null, // where args, you are skipping these
null); // sort order
if (cursor.getCount() > 0) {
while (cursor.moveToNext()) {
long id = Long.parseLong(cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID)));
String displayName = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME)).trim();
}
}
Hope this solves your issue