Search for a contact's phone number by name in Android - android

I have successfully implemented a search in Android to find a contact's name by voice recognition. Now I would like to find the number by voice recognition.
I tried already this How to call Android contacts list?, but it doesn't work with my SGS2. I think the source is old version. That's why it doesn't work.
How can I find the number by name which is result from voice recognition in Android Contacts?

private void getContactData() {
Cursor phoneCursor = null;
contactList = new HashMap<String,String>();
try{
// 주소록이 저장된 URI
Uri uContactsUri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;
// 주소록의 이름과 전화번호의 열 이름
String strProjection = ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME;
// 주소록을 얻기 위한 쿼리문을 날리고 커서를 리턴
phoneCursor = getContentResolver().query(uContactsUri, null, null, null, strProjection);
phoneCursor.moveToFirst();
String name = "";
String phoneNumber = "";
// 주소록의 이름
int nameColumn = phoneCursor.getColumnIndex(Phone.DISPLAY_NAME);
// 주소록의 전화번호
int phoneColumn = phoneCursor.getColumnIndex(Phone.NUMBER);
while(!phoneCursor.isAfterLast()){
name = phoneCursor.getString(nameColumn);
phoneNumber = phoneCursor.getString(phoneColumn);
// HashMap에 data 넣음
contactList.put(name, phoneNumber);
phoneCursor.moveToNext();
}
}
catch(Exception e){
Log.e("[SmsMain] getContactData", e.toString());
}
finally{
if(phoneCursor != null){
phoneCursor.close();
phoneCursor = null;
}
}
}
This is the source to get a contact DB.
I solved by searching.

Related

All Contacts are not showing while retrieving contacts

I implemented a code to retrieve all contacts but it is not showing all contacts where few of them are missed.
Here is my code:
String[] projection = new String[]{
ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME,
ContactsContract.CommonDataKinds.Phone.NUMBER,
ContactsContract.CommonDataKinds.Phone.NORMALIZED_NUMBER,
};
Cursor cursor = null;
try {
cursor = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
projection, null, null, null);
} catch (SecurityException e) {
}
if (cursor != null) {
try {
HashSet<String> normalizedNumbersAlreadyFound = new HashSet<>();
int indexOfNormalizedNumber = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NORMALIZED_NUMBER);
int indexOfDisplayName = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME);
int indexOfDisplayNumber = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER);
while (cursor.moveToNext()) {
String normalizedNumber = cursor.getString(indexOfNormalizedNumber);
if (normalizedNumbersAlreadyFound.add(normalizedNumber)) {
String displayName = cursor.getString(indexOfDisplayName);
String displayNumber = cursor.getString(indexOfDisplayNumber);
listOfContacts.add(new PhoneContactsModel(displayName, displayNumber, false));
} else {
}
}
Log.d("tag", "size of listOfContacts =1====" + listOfContacts.size());
} finally {
cursor.close();
}
}
don't know what is happening. Please help me.
There are many issues in the code:
You're querying over the CommonDataKinds.Phone.CONTENT_URI table, so naturally, you won't get contacts that have no phone numbers (e.g. contacts with name and email)
You're skipping contacts that contains phones you've already encountered in normalizedNumbersAlreadyFound, so if you have two contacts with a shared phone (like a home phone number) you might skip one of them.
CommonDataKinds.Phone.NORMALIZED_NUMBER may be null, in which case you'll skip many contacts that do not have their NORMALIZED_NUMBER field set
If you need to also include contacts that have no phones, I would recommend a completely different code. If you only need to get contacts with phones, I would recommend not relying on NORMALIZED_NUMBER, and instead add CommonDataKinds.Phone.CONTACT_ID to your projection, and have that as your unique key per contact.

How to identify a local phone contact and an SYNC phone contact in android?

Can anybody guide me to find the solution for the following problem.
I have to identify whether the phone contact saved in locally or from Email ?(programatically)
i have read fromgoogle doc that ContactsContract.Groups, which contains information about raw contact groups such as Gmail contact groups. The current API does not support the notion of groups spanning multiple accounts.
Based on that i have tried the following code.
StringBuffer output = new StringBuffer();
final String[] GROUP_PROJECTION = new String[] {
ContactsContract.Groups._ID,
ContactsContract.Groups.TITLE,
ContactsContract.Groups.SUMMARY_WITH_PHONES
};
Cursor c = getContentResolver().query(
ContactsContract.Groups.CONTENT_URI, GROUP_PROJECTION, null,
null, ContactsContract.Groups.TITLE);
int IDX_ID = c.getColumnIndex(ContactsContract.Groups._ID);
int IDX_TITLE = c.getColumnIndex(ContactsContract.Groups.TITLE);
output.append("title"+IDX_TITLE+"\n");
Map<String,GroupInfo> m = new HashMap<String, GroupInfo>();
while (c.moveToNext()) {
output.append("test...\n");
GroupInfo g = new GroupInfo();
g.id = c.getString(IDX_ID);
g.title = c.getString(IDX_TITLE);
output.append("title"+c.getString(IDX_TITLE)+"\n");
int users = c.getInt(c.getColumnIndex(ContactsContract.Groups.SUMMARY_WITH_PHONES));
if (users>0) {
// group with duplicate name?
GroupInfo g2 = m.get(g.title);
if (g2==null) {
m.put(g.title, g);
output.append("title"+g.title+"\n");
groups.add(g);
} else {
g2.id+=","+g.id;
}
}
}
outputText.setText(output);
c.close();
but no hope.
I am posting this answer for future use. We can differentiate the local phone contacts and the sync contacts by using the field called RawContacts.SOURCE_ID
It is described here
SOURCE_ID
read/write
String that uniquely identifies this row to its source account. Typically it is set at the time the raw contact is inserted and never changed afterwards. The one notable exception is a new raw contact: it will have an account name and type (and possibly a data set), but no source id. This indicates to the sync adapter that a new contact needs to be created server-side and its ID stored in the corresponding SOURCE_ID field on the phone.
The sample code is follows, it gives the id for sync contacts and null for others.
private void testContact() {
StringBuffer output = new StringBuffer();
ContentResolver resolver = getContentResolver();
Cursor contacts = resolver.query(Contacts.CONTENT_URI, null,
Contacts.HAS_PHONE_NUMBER + " != 0", null, Contacts._ID
+ " ASC");
Cursor data = resolver.query(Data.CONTENT_URI, null, Data.MIMETYPE
+ "=? OR " + Data.MIMETYPE + "=?", new String[]{
Email.CONTENT_ITEM_TYPE, Phone.CONTENT_ITEM_TYPE},
Data.CONTACT_ID + " ASC");
int idIndex = contacts.getColumnIndexOrThrow(Contacts._ID);
int nameIndex = contacts.getColumnIndexOrThrow(Contacts.DISPLAY_NAME);
int cidIndex = data.getColumnIndexOrThrow(Data.CONTACT_ID);
int data1Index = data.getColumnIndexOrThrow(Data.DATA1);
boolean hasData = data.moveToNext();
while (contacts.moveToNext()) {
long id = contacts.getLong(idIndex);
Uri rawContactUri =
ContentUris.withAppendedId(RawContacts.CONTENT_URI, id);
Uri entityUri =
Uri.withAppendedPath(rawContactUri, Entity.CONTENT_DIRECTORY);
Cursor c =
getContentResolver().query(
entityUri,
new String[] {
RawContacts.ACCOUNT_NAME,
RawContacts.SOURCE_ID, Entity.DATA_ID, Entity.MIMETYPE, Entity.DATA1},
null, null, null);
try {
while (c.moveToNext()) {
String sourceId = c.getString(0);
if (!c.isNull(1)) {
String source_id = c.getString(1);
try {
output.append(c.getString(4)+sourceId+" "+source_id+"\n");
//output.append(datas+ "Sync1 "+ c.getString(4)+" Sync2 "+ c.getString(5)+" Sync3"+ c.getString(6)+" Sync4 "+ c.getString(7)+"\n");
} catch (Exception e) {
e.printStackTrace();
}
//decide here based on mimeType, see comment later
}
}
} finally {
c.close();
}
}
outputText.setText(output);
}
Have a read through this and see if ACCOUNT_TYPE might be able to help you

Checking if contact has an email address without a second query

I am very new android developer and i'm trying to fill a autocompletetextview with contact display names, and when a suggestion is clicked i want it to autofill the email field from that contact. I managed to get it working, but my problem is speed. Because I need to get the email address of all contacts, I need to do a query for every single contact, which takes a very long time when I have about 3000 contacts on the device i'm testing on. The thing is, most of the contacts don't even have an email address, but I still need to do a query to discover that. I am getting the contacts via an async task. Here is the
doInBackground of the AsyncTask:
protected Object[] doInBackground(ContentResolver...cr) {
try{
List<String> names = new ArrayList<String>();
Map<Integer, String> emails = new HashMap<Integer, String>();
Map <Integer, List<String>> contacts = new HashMap<Integer, List<String>>();
/*********** Reading Contacts Name **********/
//Query to get contact name
Cursor cur = cr[0]
.query(ContactsContract.Contacts.CONTENT_URI,
null,
null,
null,
null);
// If data data found in contacts
if (cur.getCount() > 0) {
Log.i("AutocompleteContacts", "Reading contacts........");
String name = "";
String id = "";
while (cur.moveToNext())
{
name = cur.getString(cur.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
id = cur.getString(cur.getColumnIndex(ContactsContract.Contacts._ID));
String email = "";
if(name != null)
{
names.add(name.toString());
}
Cursor cur1 = cr[0].query(ContactsContract.CommonDataKinds.Email.CONTENT_URI, null,ContactsContract.CommonDataKinds.Email.CONTACT_ID + " = ?", new String[]{id}, null);
if(cur1.getCount()>0)
{
while(cur1.moveToNext())
{
email = cur1.getString(cur1.getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA));
if(email != null)
{
emails.put(Integer.parseInt(id), email);
}
}
}
cur1.close();
List<String> line = new ArrayList<String>();
line.add(name);
line.add(email);
contacts.put(Integer.parseInt(id), line);
} // End while loop
} // End Cursor value check
else
{
Log.i("contacts", "No contacts found");
}
cur.close();
results[0] = names;
results[1] = contacts;
results[2] = emails;
} catch (NullPointerException e) {
Log.i("AutocompleteContacts","Exception : "+ e);
}
return results;
}
Basically my question is: Is there a way to check if the contact has an email without another query like HAS_EMAIL_ADDRESS column or something.
If you want to view the full source of my app: https://github.com/michael-elgavi/perlib
After thinking for a while a realized I only need the email of the contact that you click on, so I just removed the email code from the asynctask and made another asynctask that loads an email of a specific contact. Then I get the email of the contact that was clicked and fill the email field. Code can be found in the repository I linked to in the question.

Android getting contact phone image

Hey all i have a programmer thats having some trouble with getting my phone image to display in an app. the following code is what he is using to get the contact picture:
private long getContactIdFromNumber(String number) {
Cursor c = null;
try {
String[] projection = new String[] { Contacts.Phones.PERSON_ID };
Uri contactUri = Uri.withAppendedPath(
Contacts.Phones.CONTENT_FILTER_URL, Uri.encode(number));
c = getContentResolver().query(contactUri, projection, null, null,
null);
if (c.moveToFirst()) {
long contactId = c.getLong(c
.getColumnIndex(Contacts.Phones.PERSON_ID));
return contactId;
}
} finally {
c.close();
}
return -1;
}
private boolean initPhoto() {
boolean result = true;
try {
contactPhoto = People.loadContactPhoto(getApplicationContext(),
ContentUris.withAppendedId(People.CONTENT_URI,
getContactIdFromNumber(phoneNumber)),
R.drawable.header, null);
} catch (Exception e) {
result = false;
}
return result;
}
if (initPhoto()) {
contact1.setImageBitmap(contactPhoto);
contact2.setImageBitmap(contactPhoto);
contact3.setImageBitmap(contactPhoto);
}
I made a contact with my phone number and image but it never loads up in the app. What should he be looking for in the code i posted above in order to make sure it is grabbing the correct phone number?
Do you have to use Contacts instead of ContactsContract? Contacts was deprecated in API level 5.
If you're trying to load a photo for a phone number, use ContactsContract.PhoneLookup. There's an example in the reference doc for android.provider.ContactsContract.PhoneLookup. Querying on that table will return LOOKUP_KEY for the Contact. Use that to query
ContactsContract.Contacts.Photo.
Turned out the number was formatted incorrectly. It was looking for xxxxxxxxxx and the number was this way (xxx)xxx-xxxx in the phone so it never matched up.

How can I get an outgoing mms's address in android

I've spent 5 days trying out different things and lots of googling with no luck
I have a broadcast receiver to monitor and backup incoming mms & sms.
The sms - outgoing and incoming is easy no problem. MMS however...
I have a broadcast receiver for incoming MMS, no problem there.
For outgoing MMS however, I use a content observer directed towards content://mms
heres the part registering the content observer from the service class
mo = new MMSObserver(new Handler(),getApplicationContext());
try{
getContentResolver().unregisterContentObserver(mo);
}
finally{
getContentResolver().registerContentObserver(Uri.parse("content://mms"), true, mo);
}
This is the onchange part in the above content observer
public void onChange(boolean bSelfChange)
{
super.onChange(bSelfChange);
Log.i(TAG,"MMSObserver onChange");
ContentResolver contentResolver = context.getContentResolver();
Uri uri = Uri.parse("content://mms");
Cursor cur = contentResolver.quert("content://mms",null,null,null,null)
if(cur.moveToNext()){
String id = cur.getString(cur.getColumnIndex("_id"));
String date = cur.getString (cur.getColumnIndex ("date"));
String address = getAddress(id);
}
}
private static String getAddress(String id){
String selectionAdd = new String("msg_id=" + id);
String uriStr = MessageFormat.format("content://mms/{0}/addr", id);
Uri uriAddress = Uri.parse(uriStr);
Cursor cAdd = context.getContentResolver().query(uriAddress, null,
selectionAdd, null, null);
String name = null;
if (cAdd.moveToFirst()) {
do {
String number = cAdd.getString(cAdd.getColumnIndex("address"));
if (number != null) {
try {
Long.parseLong(number.replace("-", ""));
name = number;
} catch (NumberFormatException nfe) {
if (name == null) {
name = number;
}
}
}
} while (cAdd.moveToNext());
}
if (cAdd != null) {
cAdd.close();
}
return name;
}
The problem is the address column always returns "insert-address-token" for outgoing mms.
Is there any possible way to get the number the mms is going to?
Also I noticed that the content observer is triggered when the message is in draft form not when it is sent or pending. since depending on those uris is generally a bad idea since they're not part of the sdk, i switched to a different method. cataloging all sms & mms messages and storing their _id columns, and just syncing them with the backup. However my problem still remains.
MMS address column is always "insert-address-token"
Any suggestions?
You may want to try something like this:
Uri uri = Uri.parse("content://mms-sms/conversations/" + mThreadId);
String[] projection = new String[] {
"body", "person", "sub", "subject", "retr_st", "type", "date", "ct_cls", "sub_cs", "_id", "read", "ct_l", "st", "msg_box", "reply_path_present", "m_cls", "read_status", "ct_t", "status", "retr_txt_cs", "d_rpt", "error_code", "m_id", "date_sent", "m_type", "v", "exp", "pri", "service_center", "address", "rr", "rpt_a", "resp_txt", "locked", "resp_st", "m_size"
};
String sortOrder = "normalized_date";
Cursor mCursor = getActivity().getContentResolver().query(uri, projection, null, null, sortOrder);
String messageAddress;
int type;
while (mCursor.moveToNext()) {
String messageId = mCursor.getString(mCursor.getColumnIndex("_id"));
Uri.Builder builder = Uri.parse("content://mms").buildUpon();
builder.appendPath(messageId).appendPath("addr");
Cursor c = mContext.getContentResolver().query(builder.build(), new String[] {
"*"
}, null, null, null);
while (c.moveToNext()) {
messageAddress = c.getString(c.getColumnIndex("address"));
if (!messageAddress.equals("insert-address-token")) {
type = c.getInt(c.getColumnIndex("type"));
c.moveToLast();
}
}
c.close();
}
I am not actually calling the mCursor's moveToNext() method in my code but instead I am implementing this logic in the getView() method of a SimpleCursorAdapter.

Categories

Resources