Android filter contacts in application - android

I made an app that extracts contacts and shows them. My problem is that is pick all contacts from all accounts (skype,viber etc.) This thing can be filtered ??

The Android contacts store aggregates all contacts from all accounts (Which does vary by vendor implementation e.g. HTC stores XML data in the notes field of the contact row).
The aggregated information is available via ContactsContract.Contacts API and gives the most complete version of all contact data in the contacts store with aggregation conflicts and resolutions already dealt with. If you simply want to access information about contacts that meet a certain requirement e.g. they must have a phone number, then I would suggest this API as it allows for SQLite-esque WHERE clauses.
If you want to access raw contact information separated by account that they came from with no aggregation applied, then use the ContactsContract.RawContacts API (Documentation). This would typically be more appropriate when you're editing contact information as an insert or update query will trigger re-aggregation of the device's contact stores.

Related

How to control android contact aggregation

I have an app that exports contacts. Similar contacts get aggregated by an internal scoring mechanism, see Android contacts aggregation process
My issue is that the same contacts exported with Outlook for Android get a different aggregation.
To test this i have created one contact (Identicus) with name, given name, work phone and email 5 times. It gets aggregated for both apps.
I have created another two contacts (Hans Test and Hans Othertest) with the same given name and work phone, but different names.
When i export it the two contacts get aggregated, when Outlook exports it they are not aggregated.
With ContactsContract.RawContacts.AGGREGATION_MODE_DISABLED i can disable aggregation for all my contacts - but i want the identical contacts to be aggregated.
I checked https://developer.android.com/reference/android/provider/ContactsContract.Contacts.AggregationSuggestions to see if i could identify the contacts that were about to be aggregated and un-aggregate them by using an AggregationException, but the data seems to be not useful.
Does anybody have an idea why the aggregation works differently for Outlook and my app?
Or a hint how i could control this behavior?
AggregationExceptions is indeed the key here.
If you know the RawContact IDs of the contacts in question you can tell Android to aggregate them, or un-aggregate them by adding an AggregationException.
So if the RawContacts have ids 111 & 222 -
ContentProviderOperation.newUpdate(AggregationExceptions.CONTENT_URI)
.withValue(AggregationExceptions.TYPE, AggregationExceptions.TYPE_KEEP_SEPARATE)
.withValue(AggregationExceptions.RAW_CONTACT_ID1, 111)
.withValue(AggregationExceptions.RAW_CONTACT_ID2, 222)
.build()
will keep those raws separated, and -
ContentProviderOperation.newUpdate(AggregationExceptions.CONTENT_URI)
.withValue(AggregationExceptions.TYPE, AggregationExceptions.TYPE_KEEP_TOGETHER)
.withValue(AggregationExceptions.RAW_CONTACT_ID1, 111)
.withValue(AggregationExceptions.RAW_CONTACT_ID2, 222)
.build()
will keep those raws aggregated.
you'll of course need to apply the operations, via something like:
context.getContentResolver().applyBatch(ContactsContract.AUTHORITY, operations);

how to display device address book ordered by custom external data

In my android application I would like to display the mobile user's contacts (names, profile picture ) displaying first the contacts that have already installed and registrered that application (the matching is made by contact's email).
Trying to loop over each contact and match if their email is already registered (in an external SQLITE table) don't seems to be an efficient way.
I would like to directly add (somewhere in the address book ?) the extra data "isRegistered = true/false) and order my addreess book query by this value to scroll the address book.
Is it possible? How to implement this in detail ?
OPTION 1
I think the most efficient way would be what you thought about initially, with a slight improvement:
store the list of registered emails (for the user's contacts) in a local SQLite DB.
read the entire list of emails on application launch, and store them in a HashSet
When sorting the contacts, create a custom Comparator to first check if the contact is an app user or not, and only then fallback to name compare.
OPTION 2
If you still want to check the option of storing the custom value in the Contacts DB, and integrate it into your query, you need to create a SyncAdapter.
This is basically a service that is able to sync contacts to/from a server into your own RawContact, which is then aggregated into one-or-more existing RawContacts, like Google does for Google Contacts.
You can set it to be notified when a new contact is added, and have your SyncAdapter add the needed info to the contact so it'll show links to your app.
If you go to your phone settings > accounts, you can see Whatsapp and Google's SyncAdapters there, where you can turn them off/on.
To create a sync adapter, you can follow the official docs, or this great tutorial.

Should I rely on SOURCE_ID when reading Android Contacts?

I am creating an android contacts app, so I regularly read user's contacts and store them in my app. To do this, I need to rely on some kind of ID so that I know which contact I should update (or add/delete) in my app and Contacts Provider supplies several of them:
CONTACT_ID is the aggregate contact id,
each aggregate contact consists of one or more Raw Contacts, each with its own RAW_CONTACT_ID,
and most important, each Raw Contact has a SOURCE_ID, which is supposed to be the server id, i.e. the id this contact has in this account's server.
I 've chosen to rely on SOURCE_ID, since this sounds like the most stable one. E.g. when user removes and re-adds the same account in their device, I wouldn't want this account's contacts to get different IDs, because I wouldn't be able to match them in my app.
However, only Gmail sync adapter seems to keep the promise documented below. Exchange sync adapters unfortunately do not, SOURCE_ID changes, and it's definitely not any server id, since it has a small number like 23:4.
Question: Any ideas how to overcome this problem? Am I using the right ID for the intended use? Does exchange adapter stores the "permanent server id" in some other field?
Documentation: The SOURCE_ID must be unique for each account type and should be stable across syncs:
Unique: Each raw contact for an account must have its own source id. If you don't enforce this, you'll cause problems in the contacts
application. Notice that two raw contacts for the same account type
may have the same source id. For example, the raw contact "Thomas
Higginson" for the account emily.dickinson#gmail.com is allowed to
have the same source id as the raw contact "Thomas Higginson" for the
account emilyd#gmail.com.
Stable: Source ids are a permanent part of the online service's data for the raw contact. For example, if the user clears Contacts Storage
from the Apps settings and re-syncs, the restored raw contacts should
have the same source ids as before. If you don't enforce this,
shortcuts will stop working.
LOOKUP_KEY is what you're looking for.
LOOKUP_KEY
An opaque value that contains hints on how to find the
contact if its row id changed as a result of a sync or aggregation.
You should use a pair of <CONTACT_ID, LOOKUP_KEY> to keep track of contacts.
In normal use, use the CONTACT_ID value, but if your code gets a hint that the CONTACT_ID has changed (either missing, or unexpected contact name), you can use the LOOKUP_KEY to find the new contact-id.
Or you can use Contacts.getLookupUri() to get a URI you can always use to quickly find a contact no matter what its CONTACT_ID or LOOKUP_KEY actual values are.
First thing, it's not a good idea to store the Id in your application and hoping that the Id won't change over time and be consistent. You are right about 'SOURCE_ID' column that it's more consistent compared to the other two (CONTACT_ID is the most brittle while 'RAW_CONTACT_ID' persists at least until user logs out of an account and logs in again).
We had a syncable account with contacts and we used to keep the unique id in one of the general purpose columns in the 'raw_contacts' table (SYNC1 - SYNC10). So although Google suggests that account providers use the database columns in a certain manner but it's upto the provider totally.
General rule to follow is, never use those id's for long term persistence and if you do so, expect them to change. Also since you are making a contact App, you obviously need some kind of reference key. In such case, don't go by the rule that all account providers will put their key in the same column. It's brittle but that's the way it is.
Edit - You should use ContactsColumns.LOOKUP_KEY (previous answer also cited the same). As per the Google Documentation -
LOOKUP_KEY
Added in API level 5 String LOOKUP_KEY An opaque value that contains
hints on how to find the contact if its row id changed as a result of
a sync or aggregation.
Constant Value: "lookup"
https://developer.android.com/reference/android/provider/ContactsContract.ContactsColumns.html#LOOKUP_KEY
You can fetch the lookup key if you have the contact Id using API's provided. Look here - https://developer.android.com/reference/android/provider/ContactsContract.Contacts.html

How to get contacts from contact list in Android? using Contact Provider

I had to fetch contact list from android using contact provider, but it was showing me duplicate entries. So, How can I filter those duplicate entries.
For example, ABCD - 123467890, 1234567890, 1234567890
how to filter duplicate phone number using contact Provider?
And Can I fetch only phone memory contact list?
It is obvious to get duplicate contacts when you fetch them. Since, same contact (same number, different name or different number, same name) might be stored in either in google contacts, phone contacts or in sim contacts.
In order to eliminate duplicates in your application, use local database (SQLite provided by android) and make phone number as unique, no duplicates will be stored.
For more information refer this post How to get all android contacts but without those which are on SIM
Following Dalma Racz comment, will also lead you to the solution.

How contacts content provider in android structures its data?

My task is to retreive name, phone, email, company and note from all contacts on android device. I have never worked with content providers before. I read content provider documentation, tutorials, saw code samples, but I'm still not quite sure: does android stores information about name, phone, email, company and note in different tables?
So do I have to query name, phone, email, company and note separately for each contact? 5 queries per contact * number of contact = most efficient way? Or do I have alternative with fewer number of queries? Why not to store all contacts and all contact fields in the same table so that it would be possible to get all data with single SELECT query (its analog in android content providers framework)?
So my main question again: do I have to make 5 queries per contact or there is more effient way?
does android stores information about name, phone, email, company and
note in different tables?
Almost. Name is stored in Contacts.DISPLAY_NAME.
phone and emails are in Data table but to interpret column names you need to use
ContactsContract.CommonDataKinds.Phone class.
Update: The original article I referred to was removed.
Here are the relevant links:
Android documentation overall
The columns reference
If you are interested in what goes on behind the curtain, google implemented their contact database (as of 4.2) so that phone, email are stored all in the same table called data. This table has columns like data1, data2 .... data15, which allows storing diverse data in that table as long as attribute of that data item do not exceed 15.
My guess it is for performance reasons - much faster to select all the data about one contact in one query() call.
Name is another story. It is stored in two tables, "raw_contacts"(column display_name) and also "data" (column "data1")

Categories

Resources