Sync phone Contacts with Database Android application - android

and Iam currently working on an android application which syncs the users contact
and shows those people as user's friends who are in there contact by searching in the database.
This uses a very similar technique as whatsapp.
Iam new to this .And if anyone could help me it would be very kind.Please tell me where should I start from.Also please give me some refference for this.
any help woold be appriciable.Please do help.
Thaks in advance :-))))

Start from Contacts Provider
Ultimately you have to use
new CursorLoader(getActivity(),
contentUri,
ContactMobileNumbQuery.PROJECTION,
ContactMobileNumbQuery.SELECTION,
null,
ContactMobileNumbQuery.SORT_ORDER);
The above code retrives all phone numbers with name using the below interface in your cursor
/**
* This interface defines constants used by mobile number retrieval queries.
*/
public interface ContactMobileNumbQuery{
final static int QUERY_ID = 1;
//A Content Uri for Phone table
final static Uri CONTENT_URI = Phone.CONTENT_URI;
//The search or filter query Uri
final static Uri FILTER_URI = Phone.CONTENT_FILTER_URI;
// The selection clause for the CursorLoader query. The search criteria defined here
// restrict results to contacts that have a phone number and display name.
// Notice that the search on the string provided by the user is implemented by appending
// the search string to CONTENT_FILTER_URI.
final static String SELECTION = Phone.HAS_PHONE_NUMBER + "=1" + " AND " + Phone.DISPLAY_NAME_PRIMARY + "<>''";
// The desired sort order for the returned Cursor - Order by DISPLAY_NAME_PRIMARY
//in Ascending with case insensitively
final static String SORT_ORDER = Phone.DISPLAY_NAME_PRIMARY + " COLLATE NOCASE ASC";
// The projection for the CursorLoader query. This is a list of columns that the Contacts
// Provider should return in the Cursor.
final static String[] PROJECTION = {
// The contact's row id
Phone._ID,
// the Contacts table contains DISPLAY_NAME_PRIMARY, which either contains
// the contact's displayable name or some other useful identifier such as an
// email address.
Phone.DISPLAY_NAME_PRIMARY,
// A pointer to the contact that is guaranteed to be more permanent than _ID. Given
// a contact's current _ID value and LOOKUP_KEY, the Contacts Provider can generate
// a "permanent" contact URI.
Phone.LOOKUP_KEY,
//Phone number of the contact
Phone.NUMBER,
};
// The query column numbers which map to each value in the projection
final static int ID = 0;
final static int DISPLAY_NAME = 1;
final static int LOOKUP_KEY = 2;
final static int NUMBER = 3;
}
The sync logic has to written seperately. Try it and post your comments :)

Related

Filter Android ContactsContract.Data by Company AND Display Name

I have something like this so far, but it seems like ContactsContract.Data URI returns multiple records with the same CONTACT_ID and LOOKUP_KEY. Is there any way to make this cursor return distinct records?
private static final Uri URI = ContactsContract.Data.CONTENT_URI;
#SuppressLint("InlinedApi")
private static final String[] PROJECTION = {
ContactsContract.Data._ID,
ContactsContract.Data.CONTACT_ID,
ContactsContract.Data.LOOKUP_KEY,
ContactsContract.Data.DISPLAY_NAME_PRIMARY
};
private static final String SELECTION =
ContactsContract.Data.DISPLAY_NAME_PRIMARY + " LIKE ?" +
" AND " + ContactsContract.Data.MIMETYPE + " = " + ContactsContract.CommonDataKinds.Organization.MIMETYPE +
" AND " + ContactsContract.CommonDataKinds.Organization.COMPANY + " LIKE ?";
private static final String SORT_ORDER =
ContactsContract.Data.DISPLAY_NAME_PRIMARY + " ASC";
#Override
public Loader<Cursor> onCreateLoader(int loaderId, Bundle args) {
String contactsFilter = getFilter(contactsSearch);
String companyFilter = getFilter(companySearch);
// Starts the query
return new CursorLoader(
getActivity(),
URI,
PROJECTION,
SELECTION,
new String[] { contactsFilter, companyFilter},
SORT_ORDER
);
}
Here's an example of the dump of this cursor:
42 {
_id=74752
contact_id=12603
lookup=2645ie9ffe868ace3d43
display_name=Person 1
}
43 {
_id=74753
contact_id=12603
lookup=2645ie9ffe868ace3d43
display_name=Person 1
}
44 {
_id=74756
contact_id=12603
lookup=2645ie9ffe868ace3d43
display_name=Person 1
}
_ID is different, but I want the cursor to return 1 record per person and all 3 of these are the same person.
Thoughts?
The Contacts DB is organized in three main tables:
Contacts - each entry represents one contact, and groups together one or more RawContacts
RawContacts - each entry represents data about a contact that was synced in by some SyncAdapter (e.g. Whatsapp, Google, Facebook, Viber), this groups multiple Data entries
Data - The actual data about a contact, emails, phones, etc. each line is a single piece of data that belongs to a single RawContact
Usually what happens is that an app (e.g. Google, Whatsapp, Linkedin) that wishes to create a new contact will create a new row in the RawContacts table that will usually contain just a name, and then use that row's _ID to add rows into the Data table for phones, emails, addresses, photos, etc.
You are querying over the Data table which means that if a certain contact has raw-contacts from 2 sources (e.g. 2 Google accounts) and both raw contacts contain a Data row with a certain company name, your cursor will return 2 results for that contact.
I would recommend not using CursorLoader here, instead create a regular Cursor from your projection/selection/selection-args, traverse it to get the data and then use a HashMap by contact-id (or some other method) to make the entries distinct by their Contact ID.

Unable to retrieve SMS display name

I've been trying to retrieve SMS information but have only been to retrieve everything BUT the display name of contacts. strDisplayNameonly shows the numerical value of a particular contact and not the name itself. All other string version of data shows their corresponding information correctly (aside from "date"). I've tried other implementations of getting the display name from other answers, but doing so causes the app to crash when trying to test.
Uri smsData = Uri.parse("content://sms/" + folderName);
String[] id = new String[]
{
"_id", "person", "address",
"body", "date"
};
ContentResolver contentResolver = getContentResolver();
Cursor smsCursor = contentResolver.query(smsData, null, null, null, null);
// Retrieve index of data
int indexContactID = smsCursor.getColumnIndex(id[0]);
int indexDisplayName = smsCursor.getColumnIndex(id[1]);
int indexPhoneNumber = smsCursor.getColumnIndex(id[2]);
int indexMsg = smsCursor.getColumnIndex(id[3]);
int indexDate = smsCursor.getColumnIndex(id[4]);
if (indexMsg < 0 || !smsCursor.moveToFirst())
return;
mCustomAdapter.clear();
while (smsCursor.moveToNext())
{
// Retrieve string version of data
String strContactID = smsCursor.getString(indexContactID);
String strDisplayName = smsCursor.getString(indexDisplayName);
String strContactNumber = smsCursor.getString(indexPhoneNumber);
String strMsg = smsCursor.getString(indexMsg);
String strDate = smsCursor.getString(indexDate);
String[] textMessage = new String[]
{
strContactID, strDisplayName, strContactNumber,
strMsg, strDate
};
// Place collected data into custom adapter
mCustomAdapter.add(textMessage);
}
smsCursor.close();
Who told you "person" is the contact's display-name?
According to the docs:
PERSON
The ID of the sender of the conversation, if present.
This is actually a "sender-id" this is never a contact-id, as an sms can be sent from a contact, a non-contact phone number, a non-phone-number (like GOOGLE or FACEBOOK) and from a group containing two or more of the above types.
If you'd like to get check if this is a contact, and if it is, get the contact's name, you need to pass two steps:
Use the canonical-address table to translate between id and phone-number (address). You can copy and use Android's helper class for this RecipientIdCache
In case the address is a single phone number, use the PHONE_LOOKUP table to look for a contact with that number, this will help: https://stackoverflow.com/a/7967182/819355

Find only device contact using CursorLoader

i am create an application which use contact to display. My problem is that i can show all conacts (from my email accounts,skype and other), but i want show only contacts from my device (with images like i am getting now), like when open native contacts app and go to Contacts->Menu->Settings->Contacts->Contact to display->Device contacts. I am not very well understand Contact content provider and need a help. There a lot of posts on stackoverflow, bu t i cant find post for my requirements.
For retreive all contact i am using this CursorLoader
CursorLoader cL = new CursorLoader(getActivity(),
contentUri,
ContactsQuery.PROJECTION,
ContactsQuery.SELECTION,
null,
ContactsQuery.SORT_ORDER
);
This is my criteria and projections:
final static int QUERY_ID = 1;
// A content URI for the Contacts table
final static Uri CONTENT_URI = ContactsContract.Contacts.CONTENT_URI;
// The search/filter query Uri
final static Uri FILTER_URI = ContactsContract.Contacts.CONTENT_FILTER_URI;
// The selection clause for the CursorLoader query. The search criteria defined here
// restrict results to contacts that have a display name and are linked to visible groups.
// Notice that the search on the string provided by the user is implemented by appending
// the search string to CONTENT_FILTER_URI.
#SuppressLint("InlinedApi")
final static String SELECTION =
(Utils.hasHoneycomb() ? ContactsContract.Contacts.DISPLAY_NAME_PRIMARY : ContactsContract.Contacts.DISPLAY_NAME) +
"<>''" + " AND " + ContactsContract.Contacts.IN_VISIBLE_GROUP + "= 1 AND "+ContactsContract.Contacts.HAS_PHONE_NUMBER + "=1";
// The desired sort order for the returned Cursor. In Android 3.0 and later, the primary
// sort key allows for localization. In earlier versions. use the display name as the sort
// key.
#SuppressLint("InlinedApi")
final static String SORT_ORDER =
Utils.hasHoneycomb() ? ContactsContract.Contacts.SORT_KEY_PRIMARY : ContactsContract.Contacts.DISPLAY_NAME;
// The projection for the CursorLoader query. This is a list of columns that the Contacts
// Provider should return in the Cursor.
#SuppressLint("InlinedApi")
final static String[] PROJECTION = {
// The contact's row id
ContactsContract.Contacts._ID,
// A pointer to the contact that is guaranteed to be more permanent than _ID. Given
// a contact's current _ID value and LOOKUP_KEY, the Contacts Provider can generate
// a "permanent" contact URI.
ContactsContract.Contacts.LOOKUP_KEY,
// In platform version 3.0 and later, the Contacts table contains
// DISPLAY_NAME_PRIMARY, which either contains the contact's displayable name or
// some other useful identifier such as an email address. This column isn't
// available in earlier versions of Android, so you must use Contacts.DISPLAY_NAME
// instead.
Utils.hasHoneycomb() ? ContactsContract.Contacts.DISPLAY_NAME_PRIMARY : ContactsContract.Contacts.DISPLAY_NAME,
// In Android 3.0 and later, the thumbnail image is pointed to by
// PHOTO_THUMBNAIL_URI. In earlier versions, there is no direct pointer; instead,
// you generate the pointer from the contact's ID value and constants defined in
// android.provider.ContactsContract.Contacts.
Utils.hasHoneycomb() ? ContactsContract.Contacts.PHOTO_THUMBNAIL_URI : ContactsContract.Contacts._ID,
// The sort order column for the returned Cursor, used by the AlphabetIndexer
SORT_ORDER,
ContactsContract.Contacts.HAS_PHONE_NUMBER
};
After some time , i am return to search answer to thisquestion.
the answer maybe is not correct byt it helps me.
public static boolean getConnections(Context context, String contactId) {
// Read all data for contactId
String selection = ContactsContract.RawContacts.CONTACT_ID + " = ?";
String[] selectionArgs = new String[]{contactId};
Cursor c = context.getContentResolver().query(ContactsContract.Data.CONTENT_URI, null, selection, selectionArgs, null);
String accountType = null;
while (c.moveToNext()) {
accountType = c.getString(c.getColumnIndexOrThrow(ContactsContract.RawContacts.ACCOUNT_TYPE));
}
Log.e("getConnections", accountType + "");
c.close();
if (accountType.equals("SIM Account") || accountType.equals("vnd.sec.contact.phone"))
return true;
else
return false;
}
After my query posted in question i am filter contacts by contactId and check their ACCOUNT_TYPE , in my logs i see on samsung vnd.sec.contact.phone(means that is phone contact) and on my lg with 2 sim i found this SIM Account.
Perhaps there is better solution, but i figure it out this way.

How to retrieve contact's phone number with one cursor or projection

I'm writing an activity which contains a ListFragment listing my contacts with their image,name and phonenumber. I found a good training lesson at http://developer.android.com/training/contacts-provider/retrieve-names.html
However the demo code seems not presenting each contact's phone number. The main looking up code is:
public interface ContactsQuery {
// An identifier for the loader
final static int QUERY_ID = 1;
// A content URI for the Contacts table
final static Uri CONTENT_URI = Contacts.CONTENT_URI;
// The search/filter query Uri
final static Uri FILTER_URI = Contacts.CONTENT_FILTER_URI;
// The selection clause for the CursorLoader query. The search criteria
// defined here
// restrict results to contacts that have a display name and are linked
// to visible groups.
// Notice that the search on the string provided by the user is
// implemented by appending
// the search string to CONTENT_FILTER_URI.
#SuppressLint("InlinedApi")
final static String SELECTION = (Contacts.DISPLAY_NAME_PRIMARY)
+ "<>''" + " AND " + Contacts.IN_VISIBLE_GROUP + "=1";
// The desired sort order for the returned Cursor. In Android 3.0 and
// later, the primary
// sort key allows for localization. In earlier versions. use the
// display name as the sort
// key.
#SuppressLint("InlinedApi")
final static String SORT_ORDER = Contacts.SORT_KEY_PRIMARY;
#SuppressLint("InlinedApi")
final static String[] PROJECTION = {
// 行ID
Contacts._ID,
// Given a contact's current _ID value and LOOKUP_KEY, the
// Contacts Provider can generate a "permanent" contact URI.
Contacts.LOOKUP_KEY,
// Name
Contacts.DISPLAY_NAME_PRIMARY,
// Photo
Contacts.PHOTO_THUMBNAIL_URI,
// The sort order column for the returned Cursor, used by the
// AlphabetIndexer
SORT_ORDER, };
// The query column numbers which map to each value in the projection
final static int ID = 0;
final static int LOOKUP_KEY = 1;
final static int DISPLAY_NAME = 2;
final static int PHOTO_THUMBNAIL_DATA = 3;
final static int SORT_KEY = 4;
}
Then it binds the value to the ListItem's view like this:
public void bindView(View view, Context context, Cursor cursor) {
// Gets handles to individual view resources
final ViewHolder holder = (ViewHolder) view.getTag();
final String photoUri = cursor
.getString(ContactsQuery.PHOTO_THUMBNAIL_DATA);
final String displayName = cursor
.getString(ContactsQuery.DISPLAY_NAME);
holder.text1.setText(displayName);
int idColumn = cursor.getColumnIndex(ContactsContract.Contacts._ID);
String contactId = cursor.getString(idColumn);
}
I've tried to use the following code to get the contact's phone number but I failed to find the parameter like ContactsQuery.XXX.
final String displayPhoneNumber = cursor.getString(parameter);
I know another way to retrieve the phone number is to write like this but it really reduced the ListView's performance due to the second cursor's usage:
String[] projection1 = { ContactsContract.PhoneLookup.DISPLAY_NAME,
ContactsContract.CommonDataKinds.Phone.NUMBER,
ContactsContract.CommonDataKinds.Phone.CONTACT_ID };
final String order = "sort_key asc";
Cursor phones = ContactsPickerActivity.this.getContentResolver().query(
ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
projection1, null, null, order);
String resultNumber = phones
.getString(phones
.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));;
Is their any other methods I can taken to solve this problem?

Android: Get CallLog History from a certain contact

I query the CallLog.Calls provider in order to retrieve a list of calls from a certain contact, based on the contact's display name. In particular, I use this query:
String selection = CallLog.Calls.CACHED_NAME + "= ?";
String dispName = dataCollector.getDisplayName();
Cursor callCursor =
cr.query(callLogUri, callLogProjection, selection,
new String[] {dispName},CallLog.Calls.DATE + " DESC");
The dataCollector object is used to hold information from queries based on a given contact id.
The problem is that this code only returns one call for the given contact. I can't understand why. Any clues?
int i=0;
while(cursor.moveToNext())
{
Sring id = cursor.getString(cursor.getColumnIndex(CallLog.Calls._ID));
numbersTemp[i]=cursor.getString(cursor.getColumnIndex(CallLog.Calls.NUMBER));
valuesTemp[i]=cursor.getString(cursor.getColumnIndex(CallLog.Calls.CACHED_NAME));
i++;
}

Categories

Resources