I am using contact provider to get all the all the phone numbers and names and displaying these in a listview.
Almost 4500 contacts are there in my phone.
It is taking almost 2-3 minutes to load all names and phone numbers .
Any suggestion how to reduce the loading time
Thanks
Ajeet
You can use content provider for this
ListAdapter list;
list=readContacts();
ListView lv=(ListView) findViewById(R.id.listView1);
lv.setAdapter(list);
And the readContacts() is
public ListAdapter readContacts(){
ContentResolver cr = getContentResolver();
ListAdapter cd = new ArrayList<Contact_getActivity>();
Cursor cur = cr.query(ContactsContract.Contacts.CONTENT_URI,
null, null, null, ContactsContract.Contacts.DISPLAY_NAME);
if (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 (Integer.parseInt(cur.getString(cur.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER))) > 0) {
// get the phone number
Cursor pCur = cr.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,null,
ContactsContract.CommonDataKinds.Phone.CONTACT_ID +" = ?",
new String[]{id}, null);
while (pCur.moveToNext()) {
String phone = pCur.getString(
pCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
// if (!Utils.isEmpty(phone)) {
// cd.add(new ContactData(id, name, phone));
// }
}
pCur.close();
}
}
}
return cd;
}
You should take a look at Loaders because they make it easy to asynchronously load data in an activity or fragment! It has many advantages as clearly mentioned in the official document here. The doc also has an example to load contacts.
I know this is not a direct answer to your question but you could load a certain amount of contacts, show them in a list and load the remaining contacts in a background thread. When the user scrolls to the end of the list with, for example, 20 contacts, you add the newly loaded 20 contacts. I think this technique is called paging but I'm not sure :)
Show only a few contacts at a time (Suppose 100 contacts).
When the user scrolls down the list, load another 100 and so on.
Just like Facebook new feed feature.
It loads a few news at one go and loads another when you scroll down further.
According to me this is the best option for optimising your application.
Related
I am creating an app in which I want to show my app icon in front of every contact if contact is associated with my app like in WhatsApp. I have searched a lot but didn't find any appropriate solution.
Fetch all the contacts from your phone like this.
public void getNumber(ContentResolver cr)
{
mItems = new ArrayList<String>();
Cursor phones = cr.query(Phone.CONTENT_URI, null, null, null, Phone.DISPLAY_NAME + " ASC");
while (phones.moveToNext())
{
String name=phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
String phoneNumberString = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
phoneNumberString.replace(" ", "");
contactName.add(name);
contactNumber.add(phoneNumberString);
mItems.add(name);
}
phones.close();
}
now send all these contacts to your server, compare each mobile number in your server database, and list only the contacts that are found in your server.
You need to maintain your own database, when registering user, save his number and while comparing, compare the fetched number to the register member's number in your own database
Lets say that i have 100 calls in my call log. I want to find the unique contacts (not numbers) that they have been called.
The problem is that if a contact has two phone numbers (e.g. for Contact A i have a number for home and another for mobile) i will count that contact twice!
I tried the following.
I am reading the call log. Then for each number of the call log i call the following custom function:
private String getContactID (String number)
{
String contactID = "";
ContentResolver context = getContentResolver();
/// number is the phone number
Uri lookupUri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI,Uri.encode(number));
String[] mPhoneNumberProjection = { PhoneLookup._ID };
Cursor cur = context.query(lookupUri,mPhoneNumberProjection, null, null, null);
try
{
if (cur.moveToFirst())
{
contactID = cur.getString(0);
return contactID;
}
}
finally
{
if (cur != null)
cur.close();
}
return contactID;
}
So then i have a calllog with contact ids and timestamp of the call and using a Set i get the unique...
The above code works fine BUT the performance if very poor! I tried it in a new Google Nexus 4 and it takes about 1600 msec! I don't want to think about older smart phones...
Any suggestions?
Use a background thread to lazy load the information in a ListView.
Initially fetch only about 10 results and display them in the list. That should happen fast. After that, in the background thread, keep on fetching information, 10 at a time, and keep on adding them to your list.
I'm trying to fetch all the Phone numbers and Emails in Android.by using this code.
enter code here
String KEY_NAME = "Name";
String KEY_NO = "No";
String selection = ContactsContract.CommonDataKinds.Phone.IN_VISIBLE_GROUP + " = 1";
String sortOrder = ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + " COLLATE LOCALIZED ASC";
String data="";
String name="";
ContactEntry contactObj;
String id;
List<String> temp = new ArrayList<String>();
final String[] projection = new String[]{ContactsContract.Contacts._ID , ContactsContract.Contacts.DISPLAY_NAME , ContactsContract.Contacts.HAS_PHONE_NUMBER};
final String[] email_projection = new String[] {ContactsContract.CommonDataKinds.Email.DATA , ContactsContract.CommonDataKinds.Email.TYPE};
final String[] phone_projection = new String[] {ContactsContract.CommonDataKinds.Phone.NUMBER, ContactsContract.CommonDataKinds.Phone.TYPE};
ContentResolver cr = context.getContentResolver();
Cursor cur = cr.query(ContactsContract.Contacts.CONTENT_URI , projection , selection , null , sortOrder);
if(cur.getCount()>0){
while(cur.moveToNext()){
id = cur.getString(cur.getColumnIndex(ContactsContract.Contacts._ID));
name = cur.getString(cur.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
if (Integer.parseInt(cur.getString(cur.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER))) > 0) {
// get the phone number
Cursor pCur = cr.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI , phone_projection ,
ContactsContract.CommonDataKinds.Phone.CONTACT_ID +" = ?",new String[]{id}, null);
while (pCur.moveToNext()){
data = pCur.getString(pCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
if(!temp.contains(data) && !data.equals(null)){
}
}
pCur.close();
}
Cursor emailCur = cr.query(ContactsContract.CommonDataKinds.Email.CONTENT_URI, email_projection,
ContactsContract.CommonDataKinds.Email.CONTACT_ID + " = ?", new String[]{id}, null);
while (emailCur.moveToNext()){
data = emailCur.getString(emailCur.getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA));
if(!temp.contains(data) && !data.equals(null)){
}
}
emailCur.close();
}
}
This code is working fine. but for the large number number of contacts let's say 5000 contacts then it blocks the UI thread.how to create a ListAdapter for displaying all these contacts.If i fetch all the contacts in background user will see the empty list for a long time.please suggest some solution
I had very similar problem some time ago even with significantly lower number of contacts.
I needed to populate all contacts in list view and allow the user to select from them. Initially I was loading all the contact information in the list view. However this required really a lot of queries, which is what actually is slow.
So I changed my design: I selected only the Contact name and the Contact id and recorded it in an object. Afterwards when the user of my app selected any contact I loaded only his data. This turned to be drastically faster (as expected). And in my case it worked perfectly, because I was querying a lot of information which I actually never needed (that is phone numbers and emails of all not-selected contacts).
Hopefully you will be able to redesign your app in similar way. However if you need to display the contents of the data variable in the listview right away, you really might turn to need lazy-loading list view with adapter (lets just hope it will perform smoothly even on fast scroll).
I want to get all phone contacts from device in android.i have used the following code.but the problem is it takes more time to return the results.is there any solution?
ContentResolver cr = getContentResolver();
int index=0;
Cursor cur = cr.query(ContactsContract.Contacts.CONTENT_URI,
null, null, null, null);
if (cur.getCount() > 0)
{
phoneNames=new String[cur.getCount()];
phoneNumbers=new String[cur.getCount()];
while (cur.moveToNext())
{
String id = cur.getString(
cur.getColumnIndex(ContactsContract.Contacts._ID));
name = cur.getString(
cur.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
if (Integer.parseInt(cur.getString(cur.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER))) > 0)
{
phoneNames[index]=name;
Cursor pCur = cr.query(
ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
null,
ContactsContract.CommonDataKinds.Phone.CONTACT_ID +" = ?",
new String[]{id}, null);
while (pCur.moveToNext())
{
phoneIndex++;
phoneNumbers[index] = pCur.getString(pCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
index++;
}
pCur.close();
}
}
After reading the code i assume that what you want is a list of contacts with DISPLAY NAMES and their respective phone numbers.
If you are specifically looking for data related to phone numbers i suggest you query on
android.provider.ContactsContract.PhoneLookup and fetch the results using a single cursor.
The following are the fields that you would be interested in:
DISPLAY_NAME
HAS_PHONE_NUMBER
NUMBER
TYPE
e.g
Uri uri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(phoneNumber));
resolver.query(uri, new String[]{PhoneLookup.DISPLAY_NAME,...
Further details please refer this
Please post your requirement if the assumptions are not true.
Some of quick checks:
Select only the required columns and not all in the first query.
Instead of using Integer.parseInt(cur.getString) use
cur.getInt()
Use PhoneLookup whenever dealing with phone numbers ( the number
field gives the raw phone number
instead of the value stored in
the database which can contain
-,),( appended with it)
Avoid using Cursor within a cursor. Use the API's which includes
joins already implemented in it like
RawContactsEntity, PhoneLookup.
Hope that helps.
Don't do complex database queries on the UI thread. What are you trying to do with the results? If you are displaying things in a list, use a CursorAdapter so that you only pull out what you need when you need it.
Well, I've been looking around and can't find a specific way to actually DISPLAY the contacts list. I've found tutorials such as higher pass's but it never actually discusses how to display them, just how to get them. I simply want to display the contacts list in a listView or something similar. I know it has to be a lot more simple than I'm making it out to be, because it seems to be a common thing. Specifically, all I want is the contact's name and phone numbers. I have my query set up, which I got the above mentioned tutorial, and I think it's right:
ContentResolver cr = getContentResolver();
Cursor cur = cr.query(ContactsContract.Contacts.CONTENT_URI,
null, null, null, null);
if (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 (Integer.parseInt(cur.getString(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()) {
}
pCur.close();
}
}
}
There is a built-in activity for this:
startActivity(new Intent(Intent.ACTION_VIEW, ContactsContract.Contacts.CONTENT_URI));
If you use startActivityForResult(), you can even get the user's chosen contact back.
If that's not what you're looking for, you want to cut back to a single query if possible, then create an Adapter for your ListView. Here is a sample project that shows querying the contacts to populate a ListView, showing either the contact's name, name and phone number, or name and email address. This gets a bit more complicated because the sample shows both the Android 1.6-and-lower and Android 2.0-and-higher contacts APIs.