I have implemented Skype video/audio calling functionality using Intent in my application it is working fine. But now I want to get all contacts list from Skype account is it possible?.
Is there any alternate way to show list of contacts of Skype account please give any idea?
All contacts (provided they are synced) can be queried with the ContactsContract provider. The RawContacts.ACCOUNT_TYPE column of the RawContacts table indicates the account type for each entry ("raw" means that it contains all entries, e.g. multiple rows for a single person with multiple aggregated contacts).
To read the Skype contacts, you can do something like this:
Cursor c = getContentResolver().query(
RawContacts.CONTENT_URI,
new String[] { RawContacts.CONTACT_ID, RawContacts.DISPLAY_NAME_PRIMARY },
RawContacts.ACCOUNT_TYPE + "= ?",
new String[] { "com.skype.contacts.sync" },
null);
int contactNameColumn = c.getColumnIndex(RawContacts.DISPLAY_NAME_PRIMARY);
ArrayList<String> mySkypeContacts = new ArrayList<String>();
while (c.moveToNext())
{
/// You can also read RawContacts.CONTACT_ID to query the
// ContactsContract.Contacts table or any of the other related ones.
mySkypeContacts.add(c.getString(contactNameColumn));
}
Be sure to also request the android.permission.READ_CONTACTS permission in the AndroidManifest.xml file.
Related
I am creating an android app that keeps track of all contacts saved on the device (the ones that appear in the default android contacts app) and saves them in a MySQL table on the server.
I managed to read all contact data using ContectResolver:
//to read only android address book
String where = ContactsContract.Contacts.IN_VISIBLE_GROUP + " = '1'";
String[] projection = new String[] { ContactsContract.Contacts._ID, ContactsContract.Contacts.LOOKUP_KEY, ContactsContract.Contacts.HAS_PHONE_NUMBER};
ContentResolver cr = context.getContentResolver();
Cursor cursor = cr.query(ContactsContract.Contacts.CONTENT_URI, projection, where, null, null);
Then, using the ContactsContract.Contacts._ID I query additional contact data:
// Perform a query to retrieve the contact's name parts
String[] nameProjection = new String[] {
ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME,
ContactsContract.CommonDataKinds.StructuredName.MIDDLE_NAME,
ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME,
ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME
};
Cursor nameCursor = cr.query(
ContactsContract.Data.CONTENT_URI,
nameProjection,
ContactsContract.Data.MIMETYPE + " = '" +
ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE + "' AND " +
ContactsContract.CommonDataKinds.StructuredName.CONTACT_ID
+ " = ?", new String[] { id }, null);
// Retrieve the name parts
String firstName = "", middleName = "", lastName = "", displayName = "";
if(nameCursor.moveToNext()) {
firstName = nameCursor.getString(nameCursor.getColumnIndex(
ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME));
middleName = nameCursor.getString(nameCursor.getColumnIndex(
ContactsContract.CommonDataKinds.StructuredName.MIDDLE_NAME));
lastName = nameCursor.getString(nameCursor.getColumnIndex(
ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME));
displayName = nameCursor.getString(nameCursor.getColumnIndex(
ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME));
}
I then send all this data (including the contact's email addresses and phone numbers) to the server.
I want to be able to periodically backup the device's contacts like this, but to be able to detect changes in contact data, by comparing the old data to the new data. But to do this, i need to have some sort of link between the contacts in the android device, and my DB in which i save the contact data.
After some searching i found 3 options:
ContactsContract.Contacts._ID
ContactsContract.Contacts.LOOKUP_KEY
ContactsContract.RawContacts._ID
But from what I found, all of them are not reliable, and can change in certain situations - invalidating the link between my DB to the device's contact list.
I have considered the option to use ContentObserver to detect contact changes. But, I want to be able to detect contact changes even if my app has been uninstalled, then some contacts have changed and then my app has been reinstalled.
Is there a reliable identification key per contact that I can use, to know when a certain contact has been changed or deleted?
EDIT:
I now found this variable exists: ContactsContract.ContactsColumns.CONTACT_LAST_UPDATED_TIMESTAMP
The problem is that it was introduces only in API level 18. I am working on min API 15. Is there something that could replace it for the missing API levels?
I am afraid it is not possible to know if particular contact changed. Therefore you can register observer on whole address book URI. This way you will be able to listen when anything in address book changes.
Now having observer you can scan all contacts and perform "sync" data to your server.
In your particular case pair of ContactsContract.Contacts._ID and ContactsContract.Contacts.LOOKUP_KEY should be reliable enough. But in order to know if anything changed you need either:
send all contacts to server and perform sync logic on server (id and lookup key should be stored on MySQL)
keep local copy of contacts on your device (sqllite db, realm, any other storage) in order to avoid unchanged contacts to be sent to server every time you sync
I've pulled out most of my hair now and really needs some help
before I go completely bold
I'm trying to launch an action picker to select a Contact that has a phone number.
When that contact is selected, I want to extract the name and phone number.
But this only happens for some contacts, not all.
The code is rougly as follows:
Select contact:
Intent contactPicker = new Intent(Intent.ACTION_PICK, contactsContract.CommonDataKinds.Phone.CONTENT_URI);
startActivityForResult(contactPicker, REQ_PICK_CONTACT);
Extract id (notice getData().getLastPathSegment():
onContactForImportPicked(intent.getData().getLastPathSegment());
and then I try to fetch this contact:
String[] fields = new String[] {
ContactsContract.CommonDataKinds.Phone.NUMBER,
ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME_PRIMARY
};
Cursor cursor = content.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
fields,
ContactsContract.CommonDataKinds.Phone.CONTACT_ID + "=?", new String[] { id }, // SEE BELOW
null);
It this point, many contacts are fetched correctly, but a lot is
also non-existing. cursor.getCount() == 0. In the 'SEE BELOW'
section above, I've tried various other fields, linke
Contact._ID, Phone._ID etc etc.
Any idea why some contacts are not fetched with this method?
When I use your code, I don't even get the contact I selected correctly. The intent data contains the URI to the data you want, so you can use that directly.
Try --
Cursor cursor = content.query(data.getData(),
fields,
null,
null,
null);
My issue is, when I'm fetching contacts from phone, it will get all the contacts (from phone, SIM, social accounts etc)
i want to know, if I can get contacts from social accounts separately?
As long as the contacts for the applications are synced, you can query the RawContacts (with the READ_CONTACTS permission in your manifest) and get them filtered by account type. For example:
Cursor c = getContentResolver().query(
RawContacts.CONTENT_URI,
new String[] { RawContacts.CONTACT_ID, RawContacts.DISPLAY_NAME_PRIMARY },
RawContacts.ACCOUNT_TYPE + "= ?",
new String[] { <account type here> },
null);
ArrayList<String> myContacts = new ArrayList<String>();
int contactNameColumn = c.getColumnIndex(RawContacts.DISPLAY_NAME_PRIMARY);
while (c.moveToNext())
{
// You can also read RawContacts.CONTACT_ID to read the
// ContactsContract.Contacts table or any of the other related ones.
myContacts.add(c.getString(contactNameColumn));
}
It's just a matter of supplying the appropriate account type. For example:
"com.google" for Gmail,
"com.whatsapp" for WhatsApp,
"com.skype.contacts.sync" for Skype,
&c.
Currently in my application I fetch all the contacts with the followign Cursor query.
String[] columnsToReturn = new String[] {
ContactsContract.Contacts._ID,
ContactsContract.Contacts.DISPLAY_NAME_PRIMARY
};
Cursor contactsCursor = getActivity().getContentResolver().query(ContactsContract.Contacts.CONTENT_URI, columnsToReturn, null, null, null);
This returns all contacts, including Skype, WhatsApp etc. I don't want these. I only want the "normal" ones. Those that aren't for any apps, just those stored on your Google accounts. How do I do this?
Also, can I exclude the user's own entries? For example, my name appears multiple times on the list for all of my different email addresses.
The ContactsContract.Contacts table contains "consolidated" contacts.
... a record per aggregate of raw contacts representing the same
person.
If you want to query contacts of a particular account or account type, you need to use RawContacts. For example, for Google contacts this would be:
Cursor c = getContentResolver().query(
RawContacts.CONTENT_URI,
new String[] { RawContacts.CONTACT_ID, RawContacts.DISPLAY_NAME_PRIMARY },
RawContacts.ACCOUNT_TYPE + "= ?",
new String[] { "com.google" },
null);
ArrayList<String> myContacts = new ArrayList<String>();
int contactNameColumn = c.getColumnIndex(RawContacts.DISPLAY_NAME_PRIMARY);
while (c.moveToNext())
{
// You can also read RawContacts.CONTACT_ID to read the
// ContactsContract.Contacts table or any of the other related ones.
myContacts.add(c.getString(contactNameColumn));
}
When looking at the Contact Groups on Google Contacts or in the People application of my HTC Legend phone, I get the groups names ok eg: Friends, Family, VIP, Favorite etc...
But in my application I get really wrong names such as
"Family" became "System Group: Family"
"Friends" became "System Group: Friends"
"Favorite" became "Favorite_5656100000000_3245664334564"
I use the below code to read these values:
public Cursor getFromSystem() {
// Get the base URI for the People table in the Contacts content
// provider.
Uri contacts = ContactsContract.Groups.CONTENT_URI;
// Make the query.
ContentResolver cr = ctx.getContentResolver();
// Form an array specifying which columns to return.
String[] projection = new String[] {
ContactsContract.Groups._ID, ContactsContract.Groups.TITLE,
ContactsContract.Groups.NOTES
};
Cursor managedCursor = cr.query(contacts, projection, ContactsContract.Groups.DELETED
+ "=0", null, ContactsContract.Groups.TITLE + " COLLATE LOCALIZED ASC");
return managedCursor;
}
What I am missing?
That sounds like a bug. One of my test phones has correct/sanitized titles, while the other has that type of incorrect title. I'd file this here.
I also inspected the contacts2.db database directly, and found that the SYSTEM_ID column seems to be sanitized – but that's probably not safe to use for display purposes.