Related
I am building an SQLite DB. One of the tables consists of 2 columns - term and definition.
My question is : How can I query the DB, in order the pair term-definition to be returned in order to be able to insert the data in the activity after that (the term and data are in ExpandableListView, the term is the Key, the data - the value).
Here is the code of the data source so far:
public class TermDataSource extends DAO {
//constants
public static final String TABLE_NAME = "terms";
public static final String TERM = "term";
public static final String DEFINITION = "definition";
//columns in the table
public static final int FIELD_ID_ID = 0;
public static final int FIELD_ID_TERM = 1;
public static final int FIELD_ID_DEFINITION = 2;
public TermDataSource (Context context){
super(context);
}
private String [] selectFields = {_ID, TERM, DEFINITION};
public Cursor getTermsData(){
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.query(TABLE_NAME, selectFields, null, null, null, null, null);
return cursor;
}
public List<Term> getTerms(){
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.query(TABLE_NAME, selectFields, null, null, null, null, null);
List<Term> terms = new ArrayList<Term>();
if(cursor!=null){
Term term = null;
while(cursor.moveToNext()){
term = getTermFromCursor(cursor);
terms.add(term);
}
cursor.close();
}
db.close();
return terms;
}
private Term getTermFromCursor (Cursor cursor){
Term term = new Term();
term.setTermId(cursor.getInt(FIELD_ID_ID));
term.setTerm(cursor.getString(FIELD_ID_TERM));
term.setDefinition(cursor.getString(FIELD_ID_DEFINITION));
return term;
}
}
Create a folder res>raw and put youfile.csv in that folder.
Use this method to insert data in Your Database from CSV file.
public void insertCSVData(Activity activity, InputStream is, String tableName) {
String colunmNames = null, str1 = null;
open();
try {
BufferedReader buffer = new BufferedReader(new InputStreamReader(is));
String line = "";
String str2 = ");";
db.beginTransaction();
int i = 0;
while ((line = buffer.readLine()) != null) {
i++;
if (i == 1) {
colunmNames = line;
str1 = "INSERT INTO " + tableName + " (" + colunmNames + ") values (";
} else {
StringBuilder sb = new StringBuilder(str1);
String[] str = line.split(",");
for (int h = 0; h < str.length; h++) {
if (h == str.length - 1) {
sb.append("'" + str[h] + "'");
} else {
sb.append("'" + str[h] + "',");
}
}
sb.append(str2);
db.execSQL(sb.toString());
}
}
db.setTransactionSuccessful();
db.endTransaction();
} catch (Exception e) {
close();
e.printStackTrace();
}
close();
}
Call this method by the below code :
insertCSVData(Activity.this, getResources().openRawResource(R.raw.yourfile),"Your Table Name");
EDIT:A list of what I consider important contact details:
1.NAME
2.PHONE NUMBER
3.EMAIL ADDRESS
4.WEBSITE
5.PHYSICAL ADDRESS
I would prefer to do this using a pre-fetched contactId...using only one cursor to get all of the data specified.I,preferably would like to find the right query to do this:
I would like to get all of the important details of a Contact at once,I am using the following code to do this:
public void getAllDataByContactId(int contactId)
{
Log.d(TAG, "Seriously scared it might not work");
String phoneNo="Phone disconnected";
String email="Email could not be delivered";
String website="Website 404";
String address="Number 13,Dark Street,Area 51,Bermuda Trianlge";
String name="Clint Eastwood";
int hasPhoneNumber;
String selection=ContactsContract.Data.CONTACT_ID+"=?";
String[] selectionArgs={String.valueOf(contactId)};
Cursor c=context.getContentResolver().query(ContactsContract.Data.CONTENT_URI, null,selection, selectionArgs,ContactsContract.Data.TIMES_CONTACTED);
if(c!=null && c.getCount()>0)
{
while(c.moveToNext())
{
phoneNo=c.getString(c.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
Log.d(TAG, "Phone number: "+phoneNo);
email=c.getString(c.getColumnIndex(ContactsContract.CommonDataKinds.Email.ADDRESS));
Log.d(TAG, "Email: "+email);
website=c.getString(c.getColumnIndex(ContactsContract.CommonDataKinds.Website.URL));
Log.d(TAG, "Website :"+website);
address=c.getString(c.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.FORMATTED_ADDRESS));
name=c.getString(c.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME));
Log.d(TAG, "Name :"+name);
}
}
}
However,although this does not throw an error it shows many rows consisting of an empty string interspresed with the actual values.How do I write a query that cuts out the noise?
I have tried this and this gets me all the values:
String selection=ContactsContract.Data.CONTACT_ID+"=? AND "+ContactsContract.Data.MIMETYPE+"=? OR "+ContactsContract.Data.MIMETYPE+"=? OR "+ContactsContract.Data.MIMETYPE+"=? OR "+ContactsContract.Data.MIMETYPE+"=? OR "+ContactsContract.Data.MIMETYPE+"=?";
String[] selectionArgs={String.valueOf(contactId),ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE,ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE,ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE,ContactsContract.CommonDataKinds.Website.CONTENT_ITEM_TYPE,ContactsContract.CommonDataKinds.StructuredPostal.CONTENT_ITEM_TYPE};
Too late to answer, but maybe it can help someone in the future.
My solution for this question with only one while cycle and query:
private void fetchContacts(ContentResolver contentResolver) {
if (contentResolver == null) return;
Cursor cursor = contentResolver.query(ContactsContract.Data.CONTENT_URI,
null, null, null, null);
if (cursor == null || cursor.getCount() <= 0) {
return;
}
String prevId = "";
String contactId = "";
PersonContact personContact = null;
while (cursor.moveToNext()) {
String company = "";
String columnName = cursor.getString(cursor.getColumnIndex("mimetype"));
if (columnName.equals(ContactsContract.CommonDataKinds.Organization.CONTENT_ITEM_TYPE)) {
company = cursor.getString(cursor.getColumnIndex("data1"));
}
String email = "";
if (columnName.equals(ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE)) {
email = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA));
}
String phone = "";
if (columnName.equals(ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE)) {
phone = cursor.getString(cursor.getColumnIndex("data1"));
}
String first = "";
String last = "";
if (columnName.equals(ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)) {
first = cursor.getString(cursor.getColumnIndex("data2"));
last = cursor.getString(cursor.getColumnIndex("data3"));
}
if (!prevId.equals(contactId)) {
if (!TextUtils.isEmpty(prevId)) {
addFilteredList(personContact);
allContacts.put(prevId, personContact);
}
prevId = contactId;
personContact = new PersonContact();
} else {
if (personContact != null) {
personContact.id = prevId;
if (TextUtils.isEmpty(personContact.company)) personContact.company = company;
if (TextUtils.isEmpty(personContact.firstName)) personContact.firstName = first;
if (TextUtils.isEmpty(personContact.lastName)) personContact.lastName = last;
if (!TextUtils.isEmpty(email) && personContact.emails.size() == 0) {
personContact.emails.add(email);
}
if (!TextUtils.isEmpty(phone) && personContact.phoneNumbers.size() == 0) {
personContact.phoneNumbers.add(phone);
}
}
}
contactId = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.CONTACT_ID));
}
cursor.close();
}
As you can see, I used the prevId field, because cursor.moveToNext performs several times for one contact (once for first and last names, one for phone, etc.). After each iteration, I check the previous contact identifier with the current identifier and, if it is false, I update the fields in the personContact model.
May not be the best solution. But this is how I achieved it.
ArrayList<String> fnameList = new ArrayList<>();
ArrayList<String> lnameList = new ArrayList<>();
ArrayList<String> mnumList = new ArrayList<>();
ArrayList<String> hnumList = new ArrayList<>();
ArrayList<String> wnumList = new ArrayList<>();
ArrayList<String> mailList = new ArrayList<>();
final DynamoDBMapper dynamoDBMapper = AWSMobileClient.defaultMobileClient().getDynamoDBMapper();
final ContactsDO firstItem = new ContactsDO(); // Initialize the Notes Object
firstItem.setUserId(AWSMobileClient.defaultMobileClient().getIdentityManager().getCachedUserID());
String email = null;
Uri CONTENT_URI = ContactsContract.Contacts.CONTENT_URI;
String _ID = ContactsContract.Contacts._ID;
String HAS_PHONE_NUMBER = ContactsContract.Contacts.HAS_PHONE_NUMBER;
Uri EmailCONTENT_URI = ContactsContract.CommonDataKinds.Email.CONTENT_URI;
String EmailCONTACT_ID = ContactsContract.CommonDataKinds.Email.CONTACT_ID;
String DATA = ContactsContract.CommonDataKinds.Email.DATA;
StringBuffer output = new StringBuffer();
ContentResolver contentResolver = this.getContentResolver();
Cursor cursor = contentResolver.query(CONTENT_URI, null, null, null, null);
// Loop for every contact in the phone
if (cursor.getCount() > 0) {
while (cursor.moveToNext()) {
int hasPhoneNumber = Integer.parseInt(cursor.getString(cursor.getColumnIndex(HAS_PHONE_NUMBER)));
if (hasPhoneNumber > 0) {
String contact_id = cursor.getString(cursor.getColumnIndex(_ID));
// Query and loop for every phone number of the contact
Cursor pCur = contentResolver.query(
ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
null,
ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?",
new String[]{contact_id}, ContactsContract.CommonDataKinds.Phone.NUMBER);
int flag = 0;
assert pCur != null;
while (pCur.moveToNext()) {
String mobileNum = pCur.getString(pCur.getColumnIndex(
ContactsContract.CommonDataKinds.Phone.NUMBER));
if (flag == 0) {
if(mobileNum!=null){
mnumList.add(mobileNum);}
} else if (flag == 1) {
if(mobileNum!=null){
hnumList.add(mobileNum);}
} else if (flag == 2) {
if(mobileNum!=null){
wnumList.add(mobileNum);}
}
flag++;
}
if(flag==1){
hnumList.add("");
wnumList.add("");
Log.e("Set","Both added");
}
if(flag==2){
wnumList.add("");
Log.e("Set","W added");
}
pCur.close();
}
}
}
cursor.close();
String MIME = ContactsContract.Data.MIMETYPE + "=?";
String[] params = new String[]{ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE};
final Cursor nameCur = contentResolver.query(
ContactsContract.Data.CONTENT_URI,
null,
MIME,
params,
ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME);
assert nameCur != null;
int i = 0;
while (nameCur.moveToNext()){
String fname = "";
String lname = "";
fname = nameCur.getString(nameCur.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME));
lname = nameCur.getString(nameCur.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME));
Log.e("In While","All the time");
if(fname!=null){
fnameList.add(fname);
Log.e("Put","Value Fname "+fname);}
if(lname!=null) {
lnameList.add(lname);
Log.e("Put","Value Lname "+lname);
}
if(fname==null){
fnameList.add(" ");
}
if(lname==null){
lnameList.add(" ");
}
i++;
}
nameCur.close();
Cursor cursorB = contentResolver.query(CONTENT_URI, null, null, null, null);
// Loop for every contact in the phone
if (cursorB.getCount() > 0) {
while (cursorB.moveToNext()) {
// Query and loop for every email of the contact
String[] paramEmail = new String[]{ContactsContract.CommonDataKinds.Email.CONTENT_TYPE};
Cursor emailCursor = contentResolver.query(EmailCONTENT_URI, null, ContactsContract.CommonDataKinds.Email.CONTACT_ID + " = ?", paramEmail, ContactsContract.CommonDataKinds.Email.DISPLAY_NAME);
int j=0;
while (emailCursor.moveToNext()) {
email = emailCursor.getString(emailCursor.getColumnIndex(ContactsContract.CommonDataKinds.Email.ADDRESS));
mailList.add(email);
Log.e("Email",email);
j++;
}
if(j==0){
mailList.add("");
Log.e("Email","Dummy Added");
}
emailCursor.close();
output.append("\n");
}
}cursorB.close();
Cursor cursorD = contentResolver.query(CONTENT_URI, null, null, null, null);
// Loop for every contact in the phone
if (cursorD.getCount() > 0) {
while (cursorD.moveToNext()) {
String contact_id = cursorD.getString(cursorD.getColumnIndex(_ID));
//for url
String newNoteUrl = "";
String whereName3 = ContactsContract.Data.MIMETYPE + " = ?";
String[] whereNameParams3 = new String[]{ContactsContract.CommonDataKinds.Website.CONTENT_ITEM_TYPE};
ContentResolver contentResolverUrl = this.getContentResolver();
try {
Cursor cursorUrl = contentResolverUrl.query(ContactsContract.Data.CONTENT_URI, null, whereName3, new String[]{contact_id}, ContactsContract.CommonDataKinds.Website.URL);
while (cursorUrl.moveToNext()) {
newNoteUrl = cursorUrl.getString(cursorUrl.getColumnIndex(ContactsContract.CommonDataKinds.Website.URL));
Log.e("URL",newNoteUrl);
}
Log.e("URL","Not Getting");
output.append("\nurl " + newNoteUrl);
firstItem.setUrl(newNoteUrl);
cursorUrl.close();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}}cursorD.close();
Log.e("#######","##########################");
for(int m=0;m<fnameList.size();m++){
Log.e("Contact Val ",fnameList.get(m)+" , "+lnameList.get(m)+" , "+mnumList.get(m)+" , "+hnumList.get(m)+" , "+wnumList.get(m)+" , "+mailList.get(m));
ContactsDO item = new ContactsDO();
item.setUserId(AWSMobileClient.defaultMobileClient().getIdentityManager().getCachedUserID());
item.setFirstName(fnameList.get(m));
item.setLastName(lnameList.get(m));
item.setMobileNumber(mnumList.get(m));
item.setHomeNumber(hnumList.get(m));
item.setWorkNumber(wnumList.get(m));
item.setEmail(mailList.get(m));
try {
//saving to the database
dynamoDBMapper.save(item);
} catch (final AmazonClientException ex) {
Log.e(TAG, "Failed saving item : " + ex.getMessage(), ex);
}
}
public Cursor getsomething()
{
this.open();
Cursor c = database.rawQuery("SELECT content_id FROM " +
DatabaseHandler.Table_Name2 +
" where playlist_id==100813", null);
if (c != null ) {
if (c.moveToFirst()) {
do {
String path = c.getString(c.getColumnIndex("content_id"));
MainActivity.t1.append("\n");
MainActivity.t1.append(path);
}while (c.moveToNext());
}
}
this.close();
return null;
}
I am using the above code to get the values but it is showing all the values from he content_id column. What am I doing wrong?
this.open();
ContentValues values2 = new ContentValues();
String csvFilename = "/mnt/sdcard/playlist.csv";
CSVReader csvReader = new CSVReader(new FileReader(csvFilename));
String Rowst[] = null;
while((Rowst = csvReader.readNext()) != null) {
st1 = Rowst[0];
st2= Rowst[1];
st3= Rowst[2];
st4= Rowst[3];
st5= Rowst[4];
st6 = Rowst[5];
st7 = Rowst[6];
st8 = Rowst[7];
st9 = Rowst[8];
st10 = Rowst[9];
st11 = Rowst[10];
st12 = Rowst[11];
st13 = Rowst[12];
st14 = Rowst[13];
st15 = Rowst[14];
st16 = Rowst[15];
st17 = Rowst[16];
st18 = Rowst[17];
st19 = Rowst[18];
values2.put(DatabaseHandler.play1,st1);
values2.put(DatabaseHandler.play2,st2);
values2.put(DatabaseHandler.play3,st3);
values2.put(DatabaseHandler.play4,st4);
values2.put(DatabaseHandler.play5,st5);
values2.put(DatabaseHandler.play6,st6);
values2.put(DatabaseHandler.play7,st7);
values2.put(DatabaseHandler.play8,st8);
values2.put(DatabaseHandler.play9,st9);
values2.put(DatabaseHandler.play10,st10);
values2.put(DatabaseHandler.play11,st11);
values2.put(DatabaseHandler.play12,st12);
values2.put(DatabaseHandler.play13,st13);
values2.put(DatabaseHandler.play14,st14);
values2.put(DatabaseHandler.play15,st15);
values2.put(DatabaseHandler.play16,st16);
values2.put(DatabaseHandler.play17,st17);
values2.put(DatabaseHandler.play18,st18);
values2.put(DatabaseHandler.play19,st19);
database.insert(DatabaseHandler.Table_Name2, null, values2);
}
csvReader.close();
this.close();
this is my code to insert data in the this table,i am trying to read a csvfile on the sdcard and entering its data into table am i doing something wrong i have posted this also if it helps
public Cursor getsomething()
{
this.open();
Cursor c = db.query(DatabaseHandler.Table_Name2, null, "playlist_id=100813", null, null, null, null);
if (c.getCount() > 0)
{
if (c.moveToFirst())
{
do {
String path = c.getString(c.getColumnIndex("content_id"));
MainActivity.t1.append("\n");
MainActivity.t1.append(path);
}while (c.moveToNext());
}
}
this.close();
return null;
}
In my project getting contacts is taking a long time to load.
What are ways to reduce the time of getting contacts
Assume there are 1000 contacts in my phone.
Right now it is taking more than 2 minutes to load all the contacts
How can I reduce the time to load contacts ?
Any Thoughts?
I referred to the the following link when programming the initial method.
http://www.coderzheaven.com/2011/06/13/get-all-details-from-contacts-in-android/
BETTER SOLUTION HERE.....
private static final String[] PROJECTION = new String[] {
ContactsContract.CommonDataKinds.Phone.CONTACT_ID,
ContactsContract.Contacts.DISPLAY_NAME,
ContactsContract.CommonDataKinds.Phone.NUMBER
};
.
.
.
ContentResolver cr = getContentResolver();
Cursor cursor = cr.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, PROJECTION, null, null, null);
if (cursor != null) {
try {
final int nameIndex = cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME);
final int numberIndex = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER);
String name, number;
while (cursor.moveToNext()) {
name = cursor.getString(nameIndex);
number = cursor.getString(numberIndex);
}
} finally {
cursor.close();
}
}
CHEERS...:)
Total time will depend upon what fields you are trying to access from the Contacts table.
Accessing less field means less looping , less processing and hence faster results.
Also to speed up your contacts fetch operation you can use the ContentProvideClient instead of calling query on ContentResolver every time. This will make you query the specific table rather than querying first for the required ContentProvider and then to table.
Create an instance of ContentProviderClient
ContentResolver cResolver=context.getContextResolver();
ContentProviderClient mCProviderClient = cResolver.acquireContentProviderClient(ContactsContract.Contacts.CONTENT_URI);
Then reuse this mCProviderClient to get Contacts(data from any ContentProvider) data on your call.
For example in following method, I am accessing only one field.
private ArrayList<String> fetchContactsCProviderClient()
{
ArrayList<String> mContactList = null;
try
{
Cursor mCursor = mCProviderClient.query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null);
if (mCursor != null && mCursor.getCount() > 0)
{
mContactList = new ArrayList<String>();
mCursor.moveToFirst();
while (!mCursor.isLast())
{
String displayName = mCursor.getString(mCursor.getColumnIndexOrThrow(ContactsContract.Contacts.DISPLAY_NAME));
mContactList.add(displayName);
mCursor.moveToNext();
}
if (mCursor.isLast())
{
String displayName = mCursor.getString(mCursor.getColumnIndexOrThrow(ContactsContract.Contacts.DISPLAY_NAME));
mContactList.add(displayName);
}
}
mCursor.close();
}
catch (RemoteException e)
{
e.printStackTrace();
mContactList = null;
}
catch (Exception e)
{
e.printStackTrace();
mContactList = null;
}
return mContactList;
}
Load Contact faster like other apps doing.
I have tested this code with multiple contacts its working fine and faster like other apps within 500 ms (within half second or less) I am able to load 1000+ contacts.
Total time will depend upon what fields you are trying to access from the Contacts table.
Mange your query according to your requirement do not access unwanted fields. Accessing less field means less looping , less processing and hence faster results.
Accessing right table in contact it also help to reduce contact loading time.
Query Optimization to load contact more faster use projection
String[] projection = {
ContactsContract.Data.MIMETYPE,
ContactsContract.Data.CONTACT_ID,
ContactsContract.Contacts.DISPLAY_NAME,
ContactsContract.Contacts.PHOTO_URI,
ContactsContract.Contacts.STARRED,
ContactsContract.RawContacts.ACCOUNT_TYPE,
ContactsContract.CommonDataKinds.Contactables.DATA,
ContactsContract.CommonDataKinds.Contactables.TYPE
};
Selection and selection argument
String selection = ContactsContract.Data.MIMETYPE + " in (?, ?)" + " AND " /*+ ContactsContract.Contacts.IN_VISIBLE_GROUP + " = '" + 1 + "' AND "*/ +
ContactsContract.Data.HAS_PHONE_NUMBER + " = '" + 1 + "'";
String[] selectionArgs = {
ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE,
ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE,
};
To order contacts alphabetically use following code
try {
Collections.sort(listview_address, new Comparator<ContactBook>() {
#Override
public int compare(ContactBook lhs, ContactBook rhs) {
return lhs.name.toUpperCase().compareTo(rhs.name.toUpperCase());
}
});
} catch (Exception e) {
e.printStackTrace();
}
Following is complete source code
public void initeContacts() {
List<ContactBook> listview_address = new LinkedList<ContactBook>();
SparseArray<ContactBook> addressbook_array = null;
{
addressbook_array = new SparseArray<ContactBook>();
long start = System.currentTimeMillis();
String[] projection = {
ContactsContract.Data.MIMETYPE,
ContactsContract.Data.CONTACT_ID,
ContactsContract.Contacts.DISPLAY_NAME,
ContactsContract.Contacts.PHOTO_URI,
ContactsContract.Contacts.STARRED,
ContactsContract.RawContacts.ACCOUNT_TYPE,
ContactsContract.CommonDataKinds.Contactables.DATA,
ContactsContract.CommonDataKinds.Contactables.TYPE
};
String selection = ContactsContract.Data.MIMETYPE + " in (?, ?)" + " AND " /*+ ContactsContract.Contacts.IN_VISIBLE_GROUP + " = '" + 1 + "' AND "*/ +
ContactsContract.Data.HAS_PHONE_NUMBER + " = '" + 1 + "'";
String[] selectionArgs = {
ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE,
ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE,
};
String sortOrder = ContactsContract.Contacts.SORT_KEY_ALTERNATIVE;
Uri uri = null;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR2) {
uri = ContactsContract.CommonDataKinds.Contactables.CONTENT_URI;
} else {
uri = ContactsContract.Data.CONTENT_URI;
}
// we could also use Uri uri = ContactsContract.Data.CONTENT_URI;
// we could also use Uri uri = ContactsContract.Contact.CONTENT_URI;
Cursor cursor = getActivity().getContentResolver().query(uri, projection, selection, selectionArgs, sortOrder);
final int mimeTypeIdx = cursor.getColumnIndex(ContactsContract.Data.MIMETYPE);
final int idIdx = cursor.getColumnIndex(ContactsContract.Data.CONTACT_ID);
final int nameIdx = cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME);
final int dataIdx = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Contactables.DATA);
final int photo = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Contactables.PHOTO_URI);
final int typeIdx = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Contactables.TYPE);
final int account_type = cursor.getColumnIndex(ContactsContract.RawContacts.ACCOUNT_TYPE);
while (cursor.moveToNext()) {
int contact_id = cursor.getInt(idIdx);
String photo_uri = cursor.getString(photo);
String contact_name = cursor.getString(nameIdx);
String contact_acc_type = cursor.getString(account_type);
int contact_type = cursor.getInt(typeIdx);
String contact_data = cursor.getString(dataIdx);
ContactBook contactBook = addressbook_array.get(contact_id);
/* if (contactBook == null) {
//list contact add to avoid duplication
//load All contacts fro device
//to add contacts number with name add one extra veriable in ContactBook as number and pass contact_data this give number to you (contact_data is PHONE NUMBER)
contactBook = new ContactBook(contact_id, contact_name, getResources(), photo_uri, contact_acc_type, "phone number");
addressbook_array.put(contact_id, contactBook);
listview_address.add(contactBook);
}*/
String Contact_mimeType = cursor.getString(mimeTypeIdx);
//here am checking Contact_mimeType to get mobile number asociated with perticular contact and email adderess asociated
if (Contact_mimeType.equals(ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE)) {
if (contactBook != null) {
contactBook.addEmail(contact_type, contact_data);
}
} else {
if (contactBook == null) {
//list contact add to avoid duplication
//load All contacts fro device
//to add contacts number with name add one extra veriable in ContactBook as number and pass contact_data this give number to you (contact_data is PHONE NUMBER)
contactBook = new ContactBook(contact_id, contact_name, getResources(), photo_uri, contact_acc_type, "phone number");
addressbook_array.put(contact_id, contactBook);
listview_address.add(contactBook);
}
// contactBook.addPhone(contact_type, contact_data);
}
}
cursor.close();
try {
Collections.sort(listview_address, new Comparator<ContactBook>() {
#Override
public int compare(ContactBook lhs, ContactBook rhs) {
return lhs.name.toUpperCase().compareTo(rhs.name.toUpperCase());
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
You can use following code in above code that I have commented .It club the the single contact with its multiple number.To get all number associated with single contact use array in Object class.
if (contactBook == null) {
//irst contact add to avoid duplication
//load All contacts fro device
contactBook = new ContactBook(contact_id, contact_name, getResources(), photo_uri, contact_acc_type, "");
addressbook_array.put(contact_id, contactBook);
listview_address.add(contactBook);
}
String Contact_mimeType = cursor.getString(mimeTypeIdx);
//here am checking Contact_mimeType to get mobile number asociated with perticular contact and email adderess asociated
if (Contact_mimeType.equals(ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE)) {
contactBook.addEmail(contact_type, contact_data);
} else {
contactBook.addPhone(contact_type, contact_data);
}
Object class
public class ContactBook {
public int id;
public Resources res;
public String name;
public String photo;
public String contact_acc_type;
public SparseArray<String> emails;
public SparseArray<String> phones;
/* public LongSparseArray<String> emails;
public LongSparseArray<String> phones;*/
public String header = "";
public ContactBook(int id, String name, Resources res, String photo, String contact_acc_type, String header) {
this.id = id;
this.name = name;
this.res = res;
this.photo = photo;
this.contact_acc_type = contact_acc_type;
this.header = header;
}
#Override
public String toString() {
return toString(false);
}
public String toString(boolean rich) {
//testing method to check ddata
SpannableStringBuilder builder = new SpannableStringBuilder();
if (rich) {
builder.append("id: ").append(Long.toString(id))
.append(", name: ").append("\u001b[1m").append(name).append("\u001b[0m");
} else {
builder.append(name);
}
if (phones != null) {
builder.append("\n\tphones: ");
for (int i = 0; i < phones.size(); i++) {
int type = (int) phones.keyAt(i);
builder.append(ContactsContract.CommonDataKinds.Phone.getTypeLabel(res, type, ""))
.append(": ")
.append(phones.valueAt(i));
if (i + 1 < phones.size()) {
builder.append(", ");
}
}
}
if (emails != null) {
builder.append("\n\temails: ");
for (int i = 0; i < emails.size(); i++) {
int type = (int) emails.keyAt(i);
builder.append(ContactsContract.CommonDataKinds.Email.getTypeLabel(res, type, ""))
.append(": ")
.append(emails.valueAt(i));
if (i + 1 < emails.size()) {
builder.append(", ");
}
}
}
return builder.toString();
}
public void addEmail(int type, String address) {
//this is the array in object class where i am storing contact all emails of perticular contact (single)
if (emails == null) {
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
emails = new SparseArray<String>();
emails.put(type, address);
/*} else {
//add emails to array below Jelly bean //use single array list
}*/
}
}
public void addPhone(int type, String number) {
//this is the array in object class where i am storing contact numbers of perticular contact
if (phones == null) {
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
phones = new SparseArray<String>();
phones.put(type, number);
/* } else {
//add emails to array below Jelly bean //use single array list
}*/
}
}}
For loading the contacts with mininum time the optimum solution is to use the concept of projection and selection argument while querying the cursor for contacts.
this can be done in following way
void getAllContacts() {
long startnow;
long endnow;
startnow = android.os.SystemClock.uptimeMillis();
ArrayList arrContacts = new ArrayList();
Uri uri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;
String selection = ContactsContract.Contacts.HAS_PHONE_NUMBER;
Cursor cursor = ctx.getContentResolver().query(uri, new String[]{ContactsContract.CommonDataKinds.Phone.NUMBER, ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME, ContactsContract.CommonDataKinds.Phone._ID, ContactsContract.Contacts._ID}, selection, null, ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + " ASC");
cursor.moveToFirst();
while (cursor.isAfterLast() == false) {
String contactNumber = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
String contactName = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
int phoneContactID = cursor.getInt(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone._ID));
int contactID = cursor.getInt(cursor.getColumnIndex(ContactsContract.Contacts._ID));
Log.d("con ", "name " + contactName + " " + " PhoeContactID " + phoneContactID + " ContactID " + contactID)
cursor.moveToNext();
}
cursor.close();
cursor = null;
endnow = android.os.SystemClock.uptimeMillis();
Log.d("END", "TimeForContacts " + (endnow - startnow) + " ms");
}
With above method it took 400ms(less than second) to load contacts where as in normall way it was taking 10-12 sec.
For details imformation this post might help as i took help from it
http://www.blazin.in/2016/02/loading-contacts-fast-from-android.html
If your time increases with your data, then you are probably running a new query to fetch phones/emails for every contact. If you query for the phone/email field using ContactsContract.CommonDataKinds.Phone.NUMBER, then you will just retrieve 1 phone per contact.
The solution is to project the fields and join them by contact id.
Here is my solution in Kotlin (extracting id, name, all phones and emails):
val projection = arrayOf(
ContactsContract.Data.MIMETYPE,
ContactsContract.Data.CONTACT_ID,
ContactsContract.Contacts.DISPLAY_NAME,
ContactsContract.CommonDataKinds.Contactables.DATA
)
val selection = "${ContactsContract.Data.MIMETYPE} in (?, ?)"
val selectionArgs = arrayOf(
ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE,
ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE)
val contacts = applicationContext
.contentResolver
.query(ContactsContract.Data.CONTENT_URI, projection, selection, selectionArgs, null)
.run {
if (this == null) {
throw IllegalStateException("Cursor null")
}
val contactsById = mutableMapOf<String, LocalContact>()
val mimeTypeField = getColumnIndex(ContactsContract.Data.MIMETYPE)
val idField = getColumnIndex(ContactsContract.Data.CONTACT_ID)
val nameField = getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME)
val dataField = getColumnIndex(ContactsContract.CommonDataKinds.Contactables.DATA)
while (moveToNext()) {
val mimeType = getString(mimeTypeField)
val id = getString(idField)
var contact = contactsById[id]
if (contact == null) {
val name = getString(nameField)
contact = LocalContact(id = id, fullName = name, phoneNumbers = listOf(), emailAddresses = listOf())
}
val data = getString(dataField)
when(getString(mimeTypeField)) {
ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE ->
contact = contact.copy(emailAddresses = contact.emailAddresses + data)
ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE ->
contact = contact.copy(phoneNumbers = contact.phoneNumbers + data)
}
contactsById[id] = contact
}
close()
contactsById.values.toList()
}
And for reference, my LocalContact model:
data class LocalContact(
val id: String,
val fullName: String?,
val phoneNumbers: List<String>,
val emailAddresses: List<String>
)
I think this is a better solution:
public ContentValues getAllContacts() {
ContentValues contacts = new ContentValues();
ContentResolver cr = getContentResolver();
Cursor cur = cr.query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null);
if (cur != null && 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));
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);
if (pCur != null) {
while (pCur.moveToNext()) {
String phoneNo = pCur.getString(pCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
contacts.put(phoneNo, name);
}
pCur.close();
}
}
}
cur.close();
}
return contacts;
}
for use it you need to call this lines once:
ContentValues contacts = new ContentValues();
contacts = getAllContacts();
and when you want to get contact name by number, just use:
String number = "12345";
String name = (String) G.contacts.get(number);
this algorithm is a bit faster...
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