How to search for contacts in android with partial phone number - android

I am trying to do fuzzy search of contacts in my android application with partial phone number, with below code. But my search function always ends in no result.
For example,
I have contact with phone number 1234567890 with name as "example".
fuzzySearch("4567"); should have return with contact named "example".
Can some please point me where am I wrong? I have checked here. But ended in run-time sql query error.
public ArrayList<Contact> fuzzySearch(String match) {
private static final String SELECTION = Phone.NUMBER + " LIKE ? COLLATE NOCASE";
Uri uri = Uri.withAppendedPath(ContactsContract.CommonDataKinds.Phone.CONTENT_FILTER_URI, Uri.encode(match));
String[] projectionFields = new String[]{ContactsContract.Contacts._ID, Phone.NUMBER};
CursorLoader cursorLoader = null;
ArrayList<Contact> listContacts = new ArrayList<>();
if(match.trim().length() == 0){
return listContacts;
}else {
cursorLoader = new CursorLoader(context, uri, projectionFields, SELECTION, new String[]{"%"+match+"%"}, Phone.NUMBER);
}
Cursor c = cursorLoader.loadInBackground();
final Map<String, Contact> contactsMap = new HashMap<>(c.getCount());
if (c.moveToFirst()) {
int idIndex = c.getColumnIndex(ContactsContract.Contacts._ID);
int nameIndex = c.getColumnIndex(Phone.NUMBER);
do {
String contactId = c.getString(idIndex);
String contactDisplayName = c.getString(nameIndex);
Contact contact = new Contact(contactId, contactDisplayName);
contactsMap.put(contactId, contact);
listContacts.add(contact);
} while (c.moveToNext());
}
c.close();
return listContacts;
}

use PhoneLookup instead of phone.
because you already encode the search key into the URL, you don't need SELECTION, remove it.
Uri uri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(match));
Cursor cur = resolver.query(uri, new String[]{PhoneLookup.DISPLAY_NAME,PhoneLookup.NUMBER, PhoneLookup.CONTACT_ID}, null, null, null);

Related

how to implement search contacts using number in ContactsContract query. Like "display_name LIKE ?" for name

I want to implement search the contacts on basis of number provided.
I have used ContactsContract to read all the contacts. I have implemented search criteria on basis of name by proving a searchView and the matching name will be displayed but I want to do the same by number also
private List<ContactItem> getContacts(String s) {
String whereString = "display_name LIKE ?";
String[] whereParams = new String[]{ "%" + s + "%"};
ContentResolver cr = getContentResolver();
Cursor cur = cr.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, whereString, whereParams, null);
List<ContactItem> contacts = new ArrayList<>();
assert cur != null;
while (cur.moveToNext()) {
String name = cur.getString(cur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
String phoneNumber = cur.getString(cur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
contacts.add(new ContactItem(name,phoneNumber));
}
cur.close();
return contacts;
}
I want to use phone number instead of display_name here. How to do that
Try the following code, should filter based on both name and number:
private List<ContactItem> getContacts(String numberOrName) {
Uri searchUri = Uri.withAppendedPath(Phone.CONTENT_FILTER_URI, Uri.encode(numberOrName));
String[] projection = new String[] { Phone.DISPLAY_NAME, Phone.NUMBER };
Cursor cur = getContentResolver().query(searchUri, projection, null, null, null);
List<ContactItem> contacts = new ArrayList<>();
assert cur != null;
while (cur.moveToNext()) {
String name = cur.getString(0);
String phoneNumber = cur.getString(1);
contacts.add(new ContactItem(name, phoneNumber));
}
cur.close();
return contacts;
}

How to read latest SMS from all contacts efficiently?

I am trying to read latest SMS from All contacts but the procedure Currently I am using seems to be very slow. How can I improve it?
public Map<String, SMS> getLatestMsgs(){
Uri uriSMSURI = Uri.parse("content://sms/");
String[] projection = {_id, address, body,
read, date, subscriptionId, type};
String selection = "";
String[] selectionArgs = {};
String sortOrder = Telephony.Sms.DATE +" desc";
Cursor c = context.getContentResolver()
.query(uriSMSURI, projection, selection, selectionArgs, sortOrder);
LinkedHashMap<String, SMS> smsMap = new LinkedHashMap<>();
log.info(methodName, "Reading Messages..");
if(c==null){
log.info(methodName, "Query returned null cursor");
return smsMap;
}
while (c.moveToNext()) {
String id = c.getString(c.getColumnIndexOrThrow(this._id));
String from = c.getString(c.getColumnIndexOrThrow(this.address));
String body = c.getString(c.getColumnIndexOrThrow(this.body));
int serviceCenter = c.getInt(c.getColumnIndexOrThrow(this.subscriptionId));
boolean readState = c.getInt(c.getColumnIndex(this.read)) == 1;
long time = c.getLong(c.getColumnIndexOrThrow(this.date));
long type = c.getLong(c.getColumnIndexOrThrow(this.type));
if(!smsMap.containsKey(from)) {
SMS sms = new SMS();
sms.setId(id);
sms.setFrom(from);
sms.setBody(body);
sms.setRead(readState);
sms.setDateTime(time);
sms.setType(type);
sms.setSubscription(serviceCenter);
smsMap.put(from, sms);
}
}
c.close();
return smsMap;
}
This method has following steps:
Read all sms in decreasing order of timestamp
Start Iterating over fetched rows
If sms address already in map then ignore
else put SMS into LinkedHashMap

Xamarin android Read Contacts and Numbers

I know to retrieve the names of contacts that's code below. But what should I change in this code to also have the numbers of phone associated with the contact list?
var uri = ContactsContract.Contacts.ContentUri;
string[] projection = { ContactsContract.Contacts.InterfaceConsts.Id,
ContactsContract.Contacts.InterfaceConsts.DisplayName };
var cursor = ManagedQuery(uri, projection, null, null, null);
var contactList = new List<string>();
if (cursor.MoveToFirst())
{
do
{
String phoneNumber = cursor.GetString(cursor.GetColumnIndex(ContactsContract.CommonDataKinds.Phone.Number));
contactList.Add(cursor.GetString(
cursor.GetColumnIndex(projection[1])));
} while (cursor.MoveToNext());
}
I came across your question while I recently wrote a similar code. The only thing you need in order to retrieve phone numbers, is to:
Make another query to Uri
ContactsContract.CommonDataKinds.Phone.ContentUri;
Set projection to include ContactsContract.CommonDataKinds.Phone.Number; and
Select based on id, i.e. selection parameter should include "_id = " +
contactId
Your query should look like this:
string[] projection = { ontactsContract.CommonDataKinds.Phone.Number };
string selection = "_id = " + contactId;
var cursor = ContentResolver.Query(ContactsContract.CommonDataKinds.Phone.ContentUri, projection, selection, null, null);
This query will bring you phone numbers for a contact id but in code below, due to performance issues, I just made one call for all phone numbers and then assign each contract their numbers. Hope it helps.
private List<Contact> GetContactList()
{
List<Contact> contacts = new List<Contact>();
string[] projection = {
ContactsContract.Contacts.InterfaceConsts.Id,
ContactsContract.Contacts.InterfaceConsts.DisplayName,
ContactsContract.Contacts.InterfaceConsts.PhotoUri
};
var uri = ContactsContract.Contacts.ContentUri;
ICursor cursor = ContentResolver.Query(uri, projection, null, null, null);
if (cursor.MoveToFirst())
{
do
{
string id = cursor.GetString(cursor.GetColumnIndex(projection[0]));
string name = cursor.GetString(cursor.GetColumnIndex(projection[1]));
string photoUri = cursor.GetString(cursor.GetColumnIndex(projection[2]));
contacts.Add(new Contact() { Id = long.Parse(id), DisplayName = name, PhotoUri = photoUri });
} while (cursor.MoveToNext());
GetContactPhoneNumber(contacts);
}
return contacts;
}
private async void GetContactPhoneNumber(List<Contact> list)
{
string[] projection =
{
ContactsContract.CommonDataKinds.Phone.Number,
ContactsContract.CommonDataKinds.Phone.InterfaceConsts.ContactId
};
var cursor = ContentResolver.Query(ContactsContract.CommonDataKinds.Phone.ContentUri, projection, null, null, null);
if (cursor.Count > 0)
{
await Task.Factory.StartNew(() =>
{
do
{
try
{
string id = cursor.GetString(cursor.GetColumnIndex(projection[1]));
string phoneNumber = cursor.GetString(cursor.GetColumnIndex(projection[0]));
Contact contact = list.Where(c => c.Id == long.Parse(id)).FirstOrDefault();
contact.PhoneNumber = phoneNumber;
}
catch
{
}
} while (cursor.MoveToNext());
cursor.Close();
});
}
}

Getting name and email from contact list is very slow

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));
}
}

how to retrieve recent call list and favourites list in android?

I need to call recent call list and favourite call list on the click of respective buttons and need the data in my own list layout.I am new to android and having lot of trouble with this.can anyone please help me..thanks in advance..
With some extra, useful code:
getFavoriteContacts:
Map getFavoriteContacts(){
Map contactMap = new HashMap();
Uri queryUri = ContactsContract.Contacts.CONTENT_URI;
String[] projection = new String[] {
ContactsContract.Contacts._ID,
ContactsContract.Contacts.DISPLAY_NAME,
ContactsContract.Contacts.STARRED};
String selection =ContactsContract.Contacts.STARRED + "='1'";
Cursor cursor = getContentResolver().query(queryUri, projection, selection,null,null);
while (cursor.moveToNext()) {
String contactID = cursor.getString(cursor
.getColumnIndex(ContactsContract.Contacts._ID));
Intent intent = new Intent(Intent.ACTION_VIEW);
Uri uri = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_URI, String.valueOf(contactID));
intent.setData(uri);
String intentUriString = intent.toUri(0);
String title = (cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME)));
contactMap.put(title,intentUriString);
}
cursor.close();
return contactMap;
}
getRecentContacts:
Map getRecentContacts(){
Map contactMap = new HashMap();
Uri queryUri = android.provider.CallLog.Calls.CONTENT_URI;
String[] projection = new String[] {
ContactsContract.Contacts._ID,
CallLog.Calls._ID,
CallLog.Calls.NUMBER,
CallLog.Calls.CACHED_NAME,
CallLog.Calls.DATE};
String sortOrder = String.format("%s limit 500 ", CallLog.Calls.DATE + " DESC");
Cursor cursor = getContentResolver().query(queryUri, projection, null,null,sortOrder);
while (cursor.moveToNext()) {
String phoneNumber = cursor.getString(cursor
.getColumnIndex(CallLog.Calls.NUMBER));
String title = (cursor.getString(cursor.getColumnIndex(CallLog.Calls.CACHED_NAME)));
if(phoneNumber==null||title==null)continue;
String uri = "tel:" + phoneNumber ;
Intent intent = new Intent(Intent.ACTION_CALL);
intent.setData(Uri.parse(uri));
String intentUriString = intent.toUri(0);
contactMap.put(title,intentUriString);
}
cursor.close();
return contactMap;
}
For getting recent calls list,you can use CallLog in android. Here is a good tutorial.This is also helpful.
You can use it for all outgoing calls like this :
Cursor cursor = getContentResolver().query(android.provider.CallLog.Calls.CONTENT_URI,null, android.provider.CallLog.Calls.TYPE+"="+android.provider.CallLog.Calls.OUTGOING_TYPE, null,null);
For all types of calls,use it like:
Cursor cursor = getContentResolver().query(android.provider.CallLog.Calls.CONTENT_URI,null, null, null,null);
You can use the following Java code to get the recent calls list:
Cursor phones = getActivity().getContentResolver().query(CallLog.Calls.CONTENT_URI, null, null, null,null);
while (phones.moveToNext()) {
String phoneNumber = phones.getString(phones.getColumnIndex(CallLog.Calls.NUMBER));
if (phoneNumber.length() > 6) {
String name = phones.getString(phones.getColumnIndex(CallLog.Calls.CACHED_NAME));
numbers.add(phoneNumber);
}
}

Categories

Resources