Android slow performance for getting contact's details - android

I want to display contacts, which has phone numbers, but with all assigned numbers. I want to improve the performance. Is there any more effective way to do this? Like obtaining all contacts thumbnails at once? This approach somehow fails for me, as the cursor is not empty, but returns empty(?) uri.
I have done some time tracking and it looks like appendContactNumber() takes to execute from 15 ms (one phone number) up to about 20 ms (three phone numbers).
// List specific variables
private static ArrayList<String> Contacts;
private static ArrayList<String> Numbers;
private static ArrayList<Bitmap> Photo;
// ContentResolver query specific variables
private static final Uri CONTACTS_URI = ContactsContract.Contacts.CONTENT_URI;
private static final String[] CONTACTS_PROJECTION = {
ContactsContract.Contacts._ID,
};
private static final String CONTACTS_SELECTION = ContactsContract.Contacts.HAS_PHONE_NUMBER + "=1";
private static final String CONTACTS_SORT_ORDER = ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + " COLLATE LOCALIZED ASC";
private static final Uri PHONES_URI = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;
private static final String[] PHONE_PROJECTION = {
ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME,
ContactsContract.CommonDataKinds.Phone.NUMBER
};
private static final String PHONE_SELECTION = ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ";
private static final String[] PHOTO_PROJECTION = { ContactsContract.Contacts.Photo.PHOTO };
private Context context;
public ContactsLoader(Context context) {
this.context = context;
}
#Override
public void run()
{
loadContacts();
}
private void loadContacts() {
Contacts = new ArrayList<>();
Numbers = new ArrayList<>();
Photo = new ArrayList<>();
// Retrieve all contacts with phone numbers
Cursor contactsCursor = context.getContentResolver().query(
CONTACTS_URI,
CONTACTS_PROJECTION,
CONTACTS_SELECTION,
null,
CONTACTS_SORT_ORDER
);
if (contactsCursor != null) {
while (contactsCursor.moveToNext()) {
appendContactNumber(contactsCursor.getString(contactsCursor.getColumnIndex(ContactsContract.Contacts._ID)));
}
contactsCursor.close();
}
}
private void appendContactNumber(final String contactId) {
// Retrieve phone numbers for contact specified by id
Cursor numbersCursor = context.getContentResolver().query(
PHONES_URI,
PHONE_PROJECTION,
PHONE_SELECTION + contactId,
null,
null
);
// If phone numbers cursor is not empty
if (numbersCursor != null) {
Bitmap thumbnail = getContactThumb(contactId);
while (numbersCursor.moveToNext()) {
Contacts.add(numbersCursor.getString(numbersCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME)));
Numbers.add(numbersCursor.getString(numbersCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)));
Photo.add(thumbnail);
}
numbersCursor.close();
}
}
private Bitmap getContactThumb(final String contactId) {
// Get contact thumbnail for given contactId
Uri contactUri = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, Long.parseLong(contactId));
Uri photoUri = Uri.withAppendedPath(contactUri, ContactsContract.Contacts.Photo.CONTENT_DIRECTORY);
Cursor thumbnailCursor = context.getContentResolver().query(
photoUri,
PHOTO_PROJECTION,
null,
null,
null
);
if (thumbnailCursor != null) {
// If contact thumbnail is not empty
if (thumbnailCursor.moveToFirst()) {
Bitmap contactPhoto = BitmapFactory.decodeStream(new ByteArrayInputStream(thumbnailCursor.getBlob(0)));
thumbnailCursor.close();
return contactPhoto;
}
}
// Default Bitmap
return BitmapFactory.decodeResource(context.getResources(), R.mipmap.ic_contact_picture);
}

I did some workaround: rather than query for Bitmap it is faster to get photo URI. Here is my code:
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.provider.ContactsContract;
import android.util.Log;
import java.util.ArrayList;
public class PhoneContactsLoader extends ContactsLoader {
// Class specific variables
private ArrayList<String> Numbers;
public PhoneContactsLoader(Context context) {
super(context);
// ContentResolver query specific variables
URI = ContactsContract.CommonDataKinds.Phone.CONTENT_URI.toString();
PROJECTION = new String[] {
ContactsContract.Contacts._ID,
ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME,
ContactsContract.CommonDataKinds.Phone.NUMBER,
ContactsContract.Contacts.PHOTO_URI
};
SELECTION = ContactsContract.Contacts.HAS_PHONE_NUMBER + "=1";
SORT_ORDER = ContactsContract.Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC";
}
#Override
protected void fetchContacts() {
Contacts = new ArrayList<>();
Numbers = new ArrayList<>();
Photos = new ArrayList<>();
Long timer = System.currentTimeMillis();
// Retrieve all contacts containing phone numbers
Cursor contactsCursor = context.getContentResolver().query(
Uri.parse(URI),
PROJECTION,
SELECTION,
null,
SORT_ORDER
);
if (contactsCursor != null) {
while (contactsCursor.moveToNext()) {
Contacts.add(contactsCursor.getString(contactsCursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME)));
Numbers.add(contactsCursor.getString(contactsCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)));
String photoUri = contactsCursor.getString(contactsCursor.getColumnIndex(ContactsContract.Contacts.PHOTO_URI));
if (photoUri != null)
Photos.add(photoUri);
else
Photos.add("useDefault");
}
contactsCursor.close();
}
Log.i("PhoneContactsLoader", "Thread execution time: " + (System.currentTimeMillis() - timer) + " ms");
}
#Override
public ArrayList<String> getNumbers() {
return Numbers;
}
}

Related

How do I get the telephone numbers of a Contact retrieved by clicking on a custom field in the native Contacts app in Android?

The situation:
I've added a custom action to a contact in Android following the instructions in this question and the related sample app on GitHub. When pressed I want to dial that contact in my application. I am able to successfully retrieve the Contact in the Activity that is opened when the custom action is pressed.
I execute this:
Cursor cursor = context.getContentResolver().query(data, null, null, null, null);
if (cursor != null) {
newIntent = true;
contact = LocalContactAsync.getContacts(cursor, context.getContentResolver()).get(0);
cursor.close();
}
And the data I retrieve from Android is:
content://com.android.contacts/data/2849
Notice the number 2849 at the end, this is not the native ID of the contact. The native ID of the contact is 459. I am able to successfully retrieve the contact executing this query, the following data returns:
cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID);
-returns '2849'
cur.getString(cur.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME)) ;
-returns 'sample samplee' wich is correct
But although this is true:
cursor.getInt(cur.getColumnIndex(
ContactsContract.Contacts.HAS_PHONE_NUMBER)) > 0)
The following function returns an empty cursor:
Cursor pCur = cr.query(
ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
null,
ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?",
new String[]{id}, null);
-id = 2849 in this case but if I fill in 459 I retrieve the right amount of telephone numbers
The real contact has 3 numbers so it should return 3 numbers.
How am I able to fix this?
Edited:
This is how I retrieve numbers, to be clear: I get the correct name, but the following query returns null while the contact has numbers.
ArrayList<Number> numbers = new ArrayList<>();
if (cur.getInt(cur.getColumnIndex(
ContactsContract.Contacts.HAS_PHONE_NUMBER)) > 0) {
Cursor pCur = cr.query(
ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
null,
ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?",
new String[]{id}, null);
while (pCur.moveToNext()) {
numbers.add(new nl.coffeeit.clearvoxnexxt.objects.dto.Number(pCur.getString(pCur.getColumnIndex(
ContactsContract.CommonDataKinds.Phone.NUMBER))));
}
pCur.close();
}
return numbers;
Please note that I do not request an intent, I receive it through a custom action that is added to a native contact, like Viber and WhatsApp do:
Full code LocalContacts Async:
private static final String TAG = "LocalContactAsync";
private static List<Contact> contacts;
private Context context;
private boolean refreshOtherFragments;
private boolean renew;
private synchronized List<Contact> getContacts(Context context) {
if (!renew && contacts != null) {
return contacts;
}
ContentResolver cr = context.getContentResolver();
Cursor cur = cr.query(ContactsContract.Contacts.CONTENT_URI,
null, null, null, null);
if (cur != null && cur.getCount() > 0) {
contacts = getContacts(cur, cr);
cur.close();
return contacts;
}
if (cur != null) {
cur.close();
}
return new ArrayList<>();
}
public static List<Contact> getContacts(Cursor cur, ContentResolver cr) {
List<Contact> contacts = new ArrayList<>();
while (cur.moveToNext()) {
String id = getId(cur);
String name = getName(cur);
ArrayList<Number> numbers = getNumbers(cur, cr, id);
if (name != null) {
contacts.add(new Contact(id, name, numbers));
}
}
Log.d(TAG, "amount of contacts" + contacts.size());
return contacts;
}
private static ArrayList<Number> getNumbers(Cursor cur, ContentResolver cr, String id) {
ArrayList<Number> numbers = new ArrayList<>();
if (cur.getInt(cur.getColumnIndex(
ContactsContract.Contacts.HAS_PHONE_NUMBER)) > 0) {
Cursor pCur = cr.query(
ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
null,
ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?",
new String[]{id}, null);
while (pCur.moveToNext()) {
numbers.add(getNumber(pCur));
}
pCur.close();
}
return numbers;
}
private static Number getNumber(Cursor pCur) {
return new nl.coffeeit.clearvoxnexxt.objects.dto.Number(pCur.getString(pCur.getColumnIndex(
ContactsContract.CommonDataKinds.Phone.NUMBER)));
}
private static String getId(Cursor cur) {
return cur.getString(
cur.getColumnIndex(ContactsContract.Contacts._ID));
}
private static String getName(Cursor cur) {
return cur.getString(cur.getColumnIndex(
ContactsContract.Contacts.DISPLAY_NAME));
}
Code for Number DTO:
public class Number implements Parcelable, Serializable {
#SerializedName("number")
#Expose
public String number;
#SerializedName("type")
#Expose
public String type = "";
#SerializedName("inherited")
#Expose
public Boolean inherited = false;
public Number(String number) {
this.number = number;
}
protected Number(Parcel in) {
number = in.readString();
type = in.readString();
byte inheritedVal = in.readByte();
inherited = inheritedVal == 0x02 ? null : inheritedVal != 0x00;
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(number);
dest.writeString(type);
if (inherited == null) {
dest.writeByte((byte) (0x02));
} else {
dest.writeByte((byte) (inherited ? 0x01 : 0x00));
}
}
#SuppressWarnings("unused")
public static final Parcelable.Creator<Number> CREATOR = new Parcelable.Creator<Number>() {
#Override
public Number createFromParcel(Parcel in) {
return new Number(in);
}
#Override
public Number[] newArray(int size) {
return new Number[size];
}
};
public Number setNumber(String number) {
this.number = number;
return this;
}
}
The first thing to notice is that a call to the contacts picker like this:
Intent intent = new Intent(Intent.ACTION_PICK, ContactsContract.Contacts.CONTENT_URI);
will return a Uri like this:
content://com.android.contacts/contacts/lookup/3163r328-4D2941473F314D2941473F3131/328
The second to last path (3163r....) is the lookup key, while 328 is the NAME_RAW_ID.
Compare this with the Intent you get from the sample application. This contains an Uri that looks like this:
content://com.android.contacts/data/2849
As you have said, calling the content resolver with this Uri is not sufficient to retrieve phone numbers, although it may be used to retrieve the name of the contact and the id. So we will use the incomplete Intent Uri to construct a new Lookup Uri that we can use to get the phone numbers.
Let's add the following methods to your LocalContactAsync (I won't refactor anything you have done so far, I'll just add in the style you have used):
public static Uri getLookupUri(Cursor cur) {
return getContentUri(getLookupKey(cur), getNameRawId(cur));
}
private static String getLookupKey(Cursor cur) {
return cur.getString(
cur.getColumnIndex(ContactsContract.Contacts.LOOKUP_KEY));
}
private static String getNameRawId(Cursor cur) {
return cur.getString(cur.getColumnIndex(ContactsContract.Contacts.NAME_RAW_CONTACT_ID));
}
private static Uri getContentUri(String lookupKey, String nameRawId) {
return new Uri.Builder()
.scheme("content")
.authority("com.android.contacts")
.appendPath("contacts")
.appendPath("lookup")
.appendPath(lookupKey)
.appendPath(nameRawId)
.build();
}
Let's alter the ViewingActivity inside the sample application so that it actually retrieves the contact details. We can now do that with the following code inside onResume():
#Override
protected void onResume() {
super.onResume();
Uri uri = getIntent().getData();
Cursor intentCursor = this.getContentResolver().query(uri, null, null, null, null);
Contact contact = null;
if (intentCursor != null) {
intentCursor.moveToFirst();
Uri lookupUri = LocalContactAsync.getLookupUri(intentCursor);
Cursor lookupCursor = this.getContentResolver().query(lookupUri, null, null, null, null);
contact = LocalContactAsync.getContacts(lookupCursor, this.getContentResolver()).get(0);
intentCursor.close();
lookupCursor.close();
}
}
The contact will now contain the phone numbers as required.

How to get photo of the contact in Android?

I'm simply getting the all contact list to an object (PhoneBookContact):
private static final Uri PURI = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;
private static final String PID = ContactsContract.CommonDataKinds.Phone._ID;
private static final String PNAME = ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME;
private static final String PNUM = ContactsContract.CommonDataKinds.Phone.NUMBER;
String[] projection = new String[]{PID, PNAME, PNUM};
String sortOrder = PNAME + " COLLATE LOCALIZED ASC";
Cursor people = mContext.getContentResolver().query(PURI, projection, null, null, sortOrder);
int indexid = people.getColumnIndex(PID);
int indexName = people.getColumnIndex(PNAME);
int indexNumber = people.getColumnIndex(PNUM);
people.moveToFirst();
do {
PhoneBookContact phoneBookContact = new PhoneBookContact();
phoneBookContact.setmCursorId(people.getLong(indexid));
phoneBookContact.setmDisplayName(people.getString(indexName));
phoneBookContact.setmPhoneNumber(UriFactory.formatNumberToInternational(people.getString(indexNumber)));
phoneList.put(phoneBookContact.getmPhoneNumber(), phoneBookContact);
} while (people.moveToNext());
people.close();
To fetch the photo of the user from Android Contacts, I'am using this method:
public static Uri loadContactPhotoUri(ContentResolver contentResolver, long id) {
try {
Uri person = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, id);
return person;
}
catch (Exception e) {
e.printStackTrace();
return null;
}
}
Finally, this code gives this URI for a specific user:
content://com.android.contacts/contacts/5907
Since I'm calling this URI with ContactsContract.CommonDataKinds.Phone._ID id, I can't get the photo of the user successfully. In fact, it should be the id of ContactsContract.Contacts._ID. How can I query the photo of the user and fix this problem?
Instead of ContactsContract.CommonDataKinds.Phone._ID, you must use ContactsContract.CommonDataKinds.Phone.CONTACT_ID to save the cursorID of Contacts table. It solved my problem.
This file have funtion get contact photo
https://github.com/heinrisch/Contact-Picture-Sync/blob/master/src/heinrisch/contact/picture/sync/ContactHandler.java
package heinrisch.contact.picture.sync;
import java.io.InputStream;
import java.util.ArrayList;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDiskIOException;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.provider.ContactsContract;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.Contacts.Data;
import android.provider.ContactsContract.RawContacts;
import android.util.Log;
public class ContactHandler {
public static ArrayList<String> getNumbers(String ID, Context context){
ArrayList<String> numbers = new ArrayList<String>();
ContentResolver cr = context.getContentResolver();
Cursor phones = cr.query(Phone.CONTENT_URI, null,Phone.CONTACT_ID + " = " + ID, null, null);
while (phones.moveToNext()) {
numbers.add(phones.getString(phones.getColumnIndex(Phone.NUMBER)));
}
phones.close();
return numbers;
}
public static void matchContactsToFriends(ArrayList<Friend> friends, Context context) {
Cursor people = context.getContentResolver().query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null);
if(people == null){
Log.e("ContactHandler", "Could not find contacts...?");
return;
}
while(people.moveToNext()) {
String ID = null,name = null;
int columnIndex = people.getColumnIndex(ContactsContract.Contacts._ID);
if(columnIndex != -1) ID = people.getString(columnIndex);
columnIndex = people.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME);
if(columnIndex != -1) name = people.getString(columnIndex);
//ArrayList<String> numbers = getNumbers(ID,context); //"can't" get this from facebook
if(name == null) continue;
for(Friend f : friends){
if(f.isMatchedWithContact()) continue;
if(f.getName().equals(name)){
f.setContactID(ID);
Bitmap contactPhoto = getPhoto(context, ID);
if(contactPhoto != null) f.setContactPicture(contactPhoto);
break;
}
}
}
people.close();
}
public static void setContactPicture(Friend f, Context context){
f.setContactPicture(getPhoto(context, f.getContactID()));
}
public static int getNumberOfContacts(Context context) {
Cursor people = context.getContentResolver().query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null);
int numberOfContacts = people.getCount();
people.close();
return numberOfContacts;
}
public static Uri getPicture(Context context, String ID){
ContentResolver cr = context.getContentResolver();
Uri rawContactUri = null;
Cursor rawContactCursor = cr.query(RawContacts.CONTENT_URI, new String[] {RawContacts._ID}, RawContacts.CONTACT_ID + " = " + ID, null, null);
if(!rawContactCursor.isAfterLast()) {
rawContactCursor.moveToFirst();
rawContactUri = RawContacts.CONTENT_URI.buildUpon().appendPath(""+rawContactCursor.getLong(0)).build();
}
rawContactCursor.close();
return rawContactUri;
}
public static void setContactPicture(Context context, String ID, Bitmap picture){
ContentResolver cr = context.getContentResolver();
Uri rawContactUri = getPicture(context, ID);
if(rawContactUri == null){
Log.e("rawContactUri", "is null");
return;
}
ContentValues values = new ContentValues();
int photoRow = -1;
String where = ContactsContract.Data.RAW_CONTACT_ID + " == " +
ContentUris.parseId(rawContactUri) + " AND " + Data.MIMETYPE + "=='" +
ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE + "'";
Cursor cursor = cr.query(ContactsContract.Data.CONTENT_URI, null, where, null, null);
int idIdx = cursor.getColumnIndexOrThrow(ContactsContract.Data._ID);
if(cursor.moveToFirst()){
photoRow = cursor.getInt(idIdx);
}
cursor.close();
values.put(ContactsContract.Data.RAW_CONTACT_ID,
ContentUris.parseId(rawContactUri));
values.put(ContactsContract.Data.IS_SUPER_PRIMARY, 1);
values.put(ContactsContract.CommonDataKinds.Photo.PHOTO, Tools.bitmapToByteArray(picture));
values.put(ContactsContract.Data.MIMETYPE,
ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE);
try{
if(photoRow >= 0){
cr.update(
ContactsContract.Data.CONTENT_URI,
values,
ContactsContract.Data._ID + " = " + photoRow, null);
} else {
cr.insert(
ContactsContract.Data.CONTENT_URI,
values);
}
}catch(SQLiteDiskIOException dIOe){
//TODO: should show this to the user..
dIOe.printStackTrace();
}
}
public static Bitmap getPhoto(Context context, String contactId) {
Uri uri = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, Long.parseLong(contactId));
InputStream input = ContactsContract.Contacts.openContactPhotoInputStream(context.getContentResolver(), uri);
if (input == null) {
return null;
}
return BitmapFactory.decodeStream(input);
}
}

How can I read the favorites contacts inside service?

I am looking for a way to get the contacts in the favorites list inside service from phone number or from name it dose not matter. Can any one help me with this?
It's not important to use any code related to this code
I found in the developer.android.com something like this (IN_VISIBLE_GROUP).
How to use this variable in my case?
case (PICK_CONTACT):
if (resultCode == Activity.RESULT_OK) {
Uri contactData = data.getData();
Cursor c = managedQuery(contactData, null, null, null, null);
ContentResolver cr = getContentResolver();
if (c.moveToFirst()) {
String name = c.getString(c.getColumnIndexOrThrow(People.NAME));
String id =c.getString(c.getColumnIndexOrThrow(People._ID));
Cursor phones = cr.query(Phone.CONTENT_URI, null,
Phone.CONTACT_ID + " = " + id, null, null);
}
Lets assume that you are searching a contact by name..
If you want to get Favourite value of all the possible contacts , drop the selection parameter in the given code.
//First get the contact ID from a display name as:-
String displayName = "Albert Einstein";
Uri contacts = ContactsContract.Contacts.CONTENT_URI;
cur = cr.query(contacts, null, ContactsContract.Contacts.DISPLAY_NAME +"="+displayName,null, null);
int contactIdIndex = cur.getColumnIndex(ContactsContract.PhoneLookup._ID);
int contactId = cur.getInt(contactIdIndex);
//Make a query to get the Starred value:-
Cursor starred = cr.query(ContactsContract.Contacts.CONTENT_URI,
new String[] { ContactsContract.Contacts.STARRED },
ContactsContract.Contacts._ID + " = " + contactId,
null, null);
if (starred != null && starred.moveToFirst())
{
int fav = starred.getInt(0);
}
if (starred != null)
starred.close();
}
You can drop the step of getting Contact ID and then querying for Starred value and directly query based on Display name
Something like this?
final private static class DataQuery {
public static final int COLUMN_MIMETYPE = 1;
public static final int COLUMN_PHONE = 2;
public static final int COLUMN_RAWCONTACT_ID = 3;
public static final int COLUMN_PHONE_NUMBER = COLUMN_DATA1;
public static final String[] PROJECTION = new String[] { Data._ID, Data.MIMETYPE, Data.DATA1, Data.RAW_CONTACT_ID };
public static final String SELECTION_PHONE = Data.DATA1 + "=?";
}
long findContact(Context context, String number) {
long rawContactId = -1;
final Cursor cursor = context.getContentResolver().query(Data.CONTENT_URI, DataQuery.PROJECTION, DataQuery.SELECTION_PHONE, new String[] { number }, null);
try {
if (cursor.moveToFirst()) {
rawContactId = cursor.getLong(DataQuery.COLUMN_RAWCONTACT_ID);
}
} finally {
if (cursor != null)
cursor.close();
}
return rawContactId;
}
Ok let's try with this...
private static final Uri DATAGROUP_CONTENT_URI = ContactsContract.Data.CONTENT_URI.buildUpon().appendQueryParameter(Data.MIMETYPE, GroupMembership.CONTENT_ITEM_TYPE).build();
public static void querytGroups(Context context) {
final ContentResolver resolver = context.getContentResolver();
long groupid=getGroupId(resolver, "Family");
final Cursor c = resolver.query(DATAGROUP_CONTENT_URI, DataQueryForContactsInGroup.PROJECTION, DataQueryForContactsInGroup.SELECTION, new String[] {ContactsContract.CommonDataKinds.GroupMembership.CONTENT_ITEM_TYPE, String.valueOf(groupid)}, null);
try {
while (c.moveToNext()) {
final long rawContactId = c.getLong(DataQueryForContactsInGroup.RAW_CONTACT_ID);
//do something
}
}finally {
c.close();
}
}
private static long getGroupId(final ContentResolver resolver, String groupName) {
long groupid = -1;
Cursor cur = null;
try {
cur = resolver.query(Groups.CONTENT_URI, DataQueryForGroup.PROJECTION, DataQueryForGroup.SELECTION, new String[]{"%"+groupName+"%"}, null);
while (cur.moveToNext()) {
return groupid= cur.getLong(DataQueryForGroup.GROUP_ID);
}
}finally {
if (cur!=null) cur.close();
}
return groupid;
}
private interface DataQueryForGroup {
public final static String[] PROJECTION = new String[] {Groups._ID};
public static final String SELECTION = Groups.TITLE+" LIKE ?";
public final static int GROUP_ID = 0;
}
private interface DataQueryForContactsInGroup {
public final static String[] PROJECTION = new String[] { Data.RAW_CONTACT_ID };
public static final String SELECTION = "("+Data.MIMETYPE + "=?) and ("+ ContactsContract.CommonDataKinds.GroupMembership.GROUP_ROW_ID+ "=?)";
public final static int RAW_CONTACT_ID = 0;
}
Please consider that if your google account is not English you need to look for the proper group's name

How to get contacts from native phonebook in android

I want to display all native contacts in a list and make user to add contacts from the list (Multiple contacts)to my application database.How to dothis can any one give me idea or share some code..
thanks in advance..
I used this code on Android 2.1. It pulls down anyone who has a phone number (as defined by the String SELECTION variable) and returns a List of type Person. Person is an object that held the name and phone number of the user. You will have to implement a Person object in order to use this code, but it works perfectly:
public List<Person> getContactList(){
ArrayList<Person> contactList = new ArrayList<Person>();
Uri contactUri = ContactsContract.Contacts.CONTENT_URI;
String[] PROJECTION = new String[] {
ContactsContract.Contacts._ID,
ContactsContract.Contacts.DISPLAY_NAME,
ContactsContract.Contacts.HAS_PHONE_NUMBER,
};
String SELECTION = ContactsContract.Contacts.HAS_PHONE_NUMBER + "='1'";
Cursor contacts = getContentResolver().query(ContactsContract.Contacts.CONTENT_URI, PROJECTION, SELECTION, null, null);
if (contacts.getCount() > 0)
{
while(contacts.moveToNext()) {
Person aContact = new Person();
int idFieldColumnIndex = 0;
int nameFieldColumnIndex = 0;
int numberFieldColumnIndex = 0;
String contactId = contacts.getString(contacts.getColumnIndex(ContactsContract.Contacts._ID));
nameFieldColumnIndex = contacts.getColumnIndex(PhoneLookup.DISPLAY_NAME);
if (nameFieldColumnIndex > -1)
{
aContact.setName(contacts.getString(nameFieldColumnIndex));
}
PROJECTION = new String[] {Phone.NUMBER};
final Cursor phone = managedQuery(Phone.CONTENT_URI, PROJECTION, Data.CONTACT_ID + "=?", new String[]{String.valueOf(contactId)}, null);
if(phone.moveToFirst()) {
while(!phone.isAfterLast())
{
numberFieldColumnIndex = phone.getColumnIndex(Phone.NUMBER);
if (numberFieldColumnIndex > -1)
{
aContact.setPhoneNum(phone.getString(numberFieldColumnIndex));
phone.moveToNext();
TelephonyManager mTelephonyMgr;
mTelephonyMgr = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
if (!mTelephonyMgr.getLine1Number().contains(aContact.getPhoneNum()))
{
contactList.add(aContact);
}
}
}
}
phone.close();
}
contacts.close();
}
return contactList;
}
EDIT: A rudimentary Person class:
public class Person {
String myName = "";
String myNumber = "";
public String getName() {
return myName;
}
public void setName(String name) {
myName = name;
}
public String getPhoneNum() {
return myNumber;
}
public void setPhoneNum(String number) {
myNumber = number;
}
}
This code works perfectly in android 4.2. And it works much faster, because you don't make additional query for each contact
private static final String CONTACT_ID = ContactsContract.Contacts._ID;
private static final String DISPLAY_NAME = ContactsContract.Contacts.DISPLAY_NAME;
private static final String HAS_PHONE_NUMBER = ContactsContract.Contacts.HAS_PHONE_NUMBER;
private static final String PHONE_NUMBER = ContactsContract.CommonDataKinds.Phone.NUMBER;
private static final String PHONE_CONTACT_ID = ContactsContract.CommonDataKinds.Phone.CONTACT_ID;
public static ArrayList<Contact> getAll(Context context) {
ContentResolver cr = context.getContentResolver();
Cursor pCur = cr.query(
ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
new String[]{PHONE_NUMBER, PHONE_CONTACT_ID},
null,
null,
null
);
if(pCur != null){
if(pCur.getCount() > 0) {
HashMap<Integer, ArrayList<String>> phones = new HashMap<>();
while (pCur.moveToNext()) {
Integer contactId = pCur.getInt(pCur.getColumnIndex(PHONE_CONTACT_ID));
ArrayList<String> curPhones = new ArrayList<>();
if (phones.containsKey(contactId)) {
curPhones = phones.get(contactId);
}
curPhones.add(pCur.getString(pCur.getColumnIndex(PHONE_CONTACT_ID)));
phones.put(contactId, curPhones);
}
Cursor cur = cr.query(
ContactsContract.Contacts.CONTENT_URI,
new String[]{CONTACT_ID, DISPLAY_NAME, HAS_PHONE_NUMBER},
HAS_PHONE_NUMBER + " > 0",
null,
DISPLAY_NAME + " ASC");
if (cur != null) {
if (cur.getCount() > 0) {
ArrayList<Contact> contacts = new ArrayList<>();
while (cur.moveToNext()) {
int id = cur.getInt(cur.getColumnIndex(CONTACT_ID));
if(phones.containsKey(id)) {
Contact con = new Contact();
con.setMyId(id);
con.setName(cur.getString(cur.getColumnIndex(DISPLAY_NAME)));
con.setPhone(TextUtils.join(",", phones.get(id).toArray()));
contacts.add(con);
}
}
return contacts;
}
cur.close();
}
}
pCur.close();
}
return null;
}
Class Contact is similar to class Person from the answer.

List all camera images in Android

How do you get a list of all camera images of an Android device?
Is it through the MediaStore? How?
The Gallery app obtains camera images by using a content resolver over Images.Media.EXTERNAL_CONTENT_URI and filtering the results by Media.BUCKET_ID. The bucket identifier is determined with the following code:
public static final String CAMERA_IMAGE_BUCKET_NAME =
Environment.getExternalStorageDirectory().toString()
+ "/DCIM/Camera";
public static final String CAMERA_IMAGE_BUCKET_ID =
getBucketId(CAMERA_IMAGE_BUCKET_NAME);
/**
* Matches code in MediaProvider.computeBucketValues. Should be a common
* function.
*/
public static String getBucketId(String path) {
return String.valueOf(path.toLowerCase().hashCode());
}
Based on that, here's a snippet to get all camera images:
public static List<String> getCameraImages(Context context) {
final String[] projection = { MediaStore.Images.Media.DATA };
final String selection = MediaStore.Images.Media.BUCKET_ID + " = ?";
final String[] selectionArgs = { CAMERA_IMAGE_BUCKET_ID };
final Cursor cursor = context.getContentResolver().query(Images.Media.EXTERNAL_CONTENT_URI,
projection,
selection,
selectionArgs,
null);
ArrayList<String> result = new ArrayList<String>(cursor.getCount());
if (cursor.moveToFirst()) {
final int dataColumn = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
do {
final String data = cursor.getString(dataColumn);
result.add(data);
} while (cursor.moveToNext());
}
cursor.close();
return result;
}
For more info, review the ImageManager and ImageList classes of the Gallery app source code.

Categories

Resources