I'm trying to fetch all the phone numbers and names of contact list. It's forking fine with small number of contact list But app crashes while fetching large number of contacts.
Here Is my code:
ContentResolver cr = getContentResolver();
Cursor cur = cr.query(ContactsContract.Contacts.CONTENT_URI,null, null, null, null);
int position=0;
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);
String phone=null;
while (pCur.moveToNext()) {
phone = pCur.getString(pCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
}
SearchGetterSetter searchContactList=new SearchGetterSetter();
searchContactList.setPosition(position);
searchContactList.setFist_name(name);
searchContactList.setContactNo(phone);
searchContactList.setChecked(false);
contactList.add(searchContactList);
originalList.add(searchContactList);
position++;
}
}
cur.close();
}
Is there any way to fetch contact list in batches?
Large processed like this should not be done on the UI Thread..do this inside
a Java's Thread. Or the better option is using AsyncTask in android API.
private class myAsyncTask extends AsyncTask<(inputParams),(returnTypeForProgressUpdate), (retunType)> {
protected Long doInBackground(inputParams... inputparam) {
int input = inputparam[0];
// Your Code In Here
return modifiedInput;
}
protected void onProgressUpdate(Integer... progress) {
// for update bar
setProgressPercent(progress[0]);
}
protected void onPostExecute(Long result) {
//this is in the ui thread so use the result
showDialog("Loaded");
}
For better info visit.. http://developer.android.com/reference/android/os/AsyncTask.html#doInBackground(Params...)
Related
My app is always slow and sometimes crashes because to access to contacts list, I am using getContentResolver() which is making my app to run another additional process to main process. Whenever that additional process is running, my app starts to slow down and crashing.
So, is there any idea of accessing to contacts list without passing to that getContentResolver()?
Use AsyncTaskLoader for fetching contact from device, it is recommended because it is asynchronous and also works well with activity lifecycle.
You should use an AsynTask to do this work in background thread
private class LoadContacts extends AsyncTask<Void, Boolean, Boolean> {
protected void onPreExecute() {
Log.e("LS", "Start !");
}
#Override
protected Boolean doInBackground(Void... params) {
ContentResolver cr = getContentResolver();
Cursor cur = cr.query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null);
try {
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 (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()) {
String phoneNo = pCur.getString(pCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
String data = "Name : " + name + " - Phone : " + phoneNo;
}
pCur.close();
}
}
}
cur.close();
} catch (NullPointerException | java.io.IOException e) {
Log.e("LS", e.getMessage());
}
return true;
}
protected void onPostExecute(Boolean result) {
Log.e("LS", "Done !");
}
}
I'm making a new application, one of the feature of this application is that a user can interact only with his phone contacts ( Same concept as WhatsApp).
I'm using Parse.com as a backend of my app, Users signed up first with their phone numbers, then I should compare all the user's contacts and contacts in backend, to retrieve only the commun contacts ( and store then in SQL)
So do you have any Idea how to make this function better, or any better idea to compare ? it consumes a lot of Bandwidth this function
public void sync_contacts(){
String phoneNo;
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()) {
phoneNo = pCur.getString(pCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
phoneNo = phoneNo.replace(" ", "");
phoneNo = phoneNo.replace("+33","0");
Log.d(name, phoneNo);
ParseQuery query = ParseUser.getQuery();
query.whereEqualTo("username",phoneNo);
query.getFirstInBackground(new GetCallback<ParseObject>() {
#Override
public void done(ParseObject parseObject, ParseException e) {
if (e == null ){
contacts c = new contacts();
if (!(parseObject.get("Name").toString()==null)) c.setName(parseObject.get("Name").toString());
if (!(parseObject.get("username").toString()==null)) c.setNumero(parseObject.get("username").toString());
ParseFile image = (ParseFile)parseObject.get("Profilepic");
if(!(image==null))
{
c.setProfil(image.getUrl());
}
c.setShow("true");
s.addcontact(c);
Log.d("Found","IO");
}
else {
Log.d("NotFound","IO");
}
}
});
}
pCur.close();
}
}
}
}
Am trying to use the ContactsProvider with my AutoCompleteTextview using a method that fetches the data (name and phone number) and stores them in a list. As expected, this method will always take time to complete as am calling the method in the onCreateView method of my Fragment class.
This is the method:
...
ArrayList<String> phoneValues;
ArrayList<String> nameValues;
...
private void readContactData() {
try {
/*********** Reading Contacts Name And Number **********/
String phoneNumber = "";
ContentResolver contentResolver = getActivity()
.getContentResolver();
//Query to get contact name
Cursor cursor = contentResolver
.query(ContactsContract.Contacts.CONTENT_URI,
null,
null,
null,
null);
// If data data found in contacts
if (cursor.getCount() > 0) {
int k=0;
String name = "";
while (cursor.moveToNext())
{
String id = cursor
.getString(cursor
.getColumnIndex(ContactsContract.Contacts._ID));
name = cursor
.getString(cursor
.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
//Check contact have phone number
if (Integer
.parseInt(cursor
.getString(cursor
.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER))) > 0)
{
//Create query to get phone number by contact id
Cursor pCur = contentResolver
.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
null,
ContactsContract.CommonDataKinds.Phone.CONTACT_ID
+ " = ?",
new String[] { id },
null);
int j=0;
while (pCur
.moveToNext())
{
// Sometimes get multiple data
if(j==0)
{
// Get Phone number
phoneNumber =""+pCur.getString(pCur
.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
// Add contacts names to adapter
autocompleteAdapter.add(name);
// Add ArrayList names to adapter
phoneValues.add(phoneNumber.toString());
nameValues.add(name.toString());
j++;
k++;
}
} // End while loop
pCur.close();
} // End if
} // End while loop
} // End Cursor value check
cursor.close();
} catch (Exception e) {
Log.i("AutocompleteContacts","Exception : "+ e);
}
}
Am sure there is a better way to accomplish this, but this method works and the suggestions are presented when I type into the AutocompleteTextview. Am just worried about the time it takes. How can I accomplish this without populating an ArrayList?
I have looked at this question: Getting name and email from contact list is very slow and applied the suggestions in the answer to my code, but now nothing is suggested when I type.How can I improve the performance of my current code?
This is how i have implemented AutoCompleteTextView and it works fine for me ..
final AutoCompleteTextView act=(AutoCompleteTextView)findViewById(R.id.autoCompleteTextView1);
ArrayList<String> alContacts = new ArrayList<String>();
ArrayList<String> alNames= new ArrayList<String>();
ContentResolver cr = this.getContentResolver(); //Activity/Application android.content.Context
Cursor cursor = cr.query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null);
if(cursor.moveToFirst())
{
do
{
String id = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID));
if(Integer.parseInt(cursor.getString(cursor.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())
{
String contactNumber = pCur.getString(pCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
String contactName=pCur.getString(pCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
alNames.add(contactName);
alContacts.add(contactNumber);
break;
}
pCur.close();
}
} while (cursor.moveToNext()) ;
}
String[] array=new String[alNames.size()];
array=(String[]) alNames.toArray(array);
ArrayAdapter<String> myArr= new ArrayAdapter<String>(this,android.R.layout.simple_dropdown_item_1line,array);
act.setAdapter(myArr);
act.setThreshold(1);
I got rid of the slow response by placing the method inside an AsynTask.
public class AutocompleteAsyncTask extends AsyncTask<Void, Void, Void> {
public Void doInBackground(Void...params) {
try {
/*********** Reading Contacts Name And Number **********/
String phoneNumber = "";
ContentResolver contentResolver = getActivity()
.getContentResolver();
//Query to get contact name
Cursor cursor = contentResolver
.query(ContactsContract.Contacts.CONTENT_URI,
null,
null,
null,
null);
// If data data found in contacts
if (cursor.getCount() > 0) {
int k=0;
String name = "";
while (cursor.moveToNext())
{
//...Rest of the same code as above
and then calling this in my onCreateView():
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
...
new AutocompleteAsyncTask().execute();
return rootView;
}
Now the task of inflating my view and fetching the data are separated into two different threads.
The CursorLoader option mentioned by Eugen Pechanec is kinda the best option, so I'll update this answer with that option when I can.
I'm having a problem with extracting phone numbers of some people in my contact list.
First I show all the contacts in a listview:
String[] projection = new String[] {
ContactsContract.Contacts._ID,
ContactsContract.CommonDataKinds.Phone.CONTACT_ID,
ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME,
ContactsContract.CommonDataKinds.Phone.NUMBER
};
mCursor = mContext.getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
projection, ContactsContract.CommonDataKinds.Phone.CONTACT_ID + "=?", new String[] {mContactId}, null);
When clicking on an item, this is how I fetch the contact_id:
#Override
public void onListItemClick(ListView l, View v, int position, long id) {
Cursor currentCursor = mContactsAdapter.getCursor();
if (currentCursor != null) {
notifyOnContactSelectedListeners(String.valueOf(id));
}
}
Then I create a new fragment, and while loading it I query for the contact's phone & display name:
if (cursor != null && cursor.getCount() > 0) {
cursor.moveToFirst();
String firstName = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
String number = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
}
So for some people that has a phone, I get the phone number this way and that's ok.
But for some people I can't get the phone number this way - but they do have phone number in the default's phone contacts book.
What went wrong?
I had a similar difficulty. I discovered that the numbers that I was unable to receive had all been imported from my linked Facebook account. You will be able to detect that the contact exists, and indeed that they have a phone number. However, when you try to retrieve said number with a SQL query the result returned will be null.
It transpired that Facebook restrict access to their contacts for security reasons. I am yet to find another provider (e.g. LinkedIn, Google) which hides phone numbers.
Further reading: Cannot find Facebook contacts in RawContacts
try this may it useful for you
public class Contact extends Activity implements OnItemClickListener{
private static final int PICK_CONTACT = 0;
Cursor c;
Cursor cursor,phones,emails,address;
String id,phoneNo,name;
String[] from;
int[] to;
ListView lv;
Cursor cur,pCur;
List<String> list1 = new ArrayList<String>();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.contact);
lv = (ListView)findViewById(R.id.contactlist);
displayContacts();
lv.setAdapter(new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, list1));
lv.setOnItemClickListener(this);
}
private void displayContacts() {
ContentResolver cr = getContentResolver();
cur = cr.query(ContactsContract.Contacts.CONTENT_URI,
null, null, null, null);
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) {
pCur = cr.query(
ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
null,
ContactsContract.CommonDataKinds.Phone.CONTACT_ID +" = ?",
new String[]{id}, null);
while (pCur.moveToNext()) {
phoneNo = pCur.getString(pCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
// setContact(name,phoneNo);
System.out.println("name"+name+"ph no"+phoneNo);
list1.add(name+"\n"+phoneNo);
// Toast.makeText(this, "Name: " + name + ", Phone No: " + phoneNo, Toast.LENGTH_SHORT).show();
}
pCur.close();
}
}
}
}
#Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
// TODO Auto-generated method stub
String s = lv.getItemAtPosition(arg2).toString();
Log.i("my msg", s.substring(0, s.indexOf("\n")));
Toast.makeText(this, s.substring(s.indexOf("\n")+1,s.length() ),1 ).show();
}
}
I received null in some contacts.
I verified my code to find out that when querying phone numbers I was using ContactsContract.CommonDataKinds.Phone.NORMALIZED_NUMBER then I changed to ContactsContract.CommonDataKinds.Phone.NUMBER that according to android docs it says.
The phone number as the user entered it.
and the code worked well.
I m making one app in which I want to have all records from my android mobile 4.0 to my android application. I have done this also. but problem is I have almost 200 contacts in my phonebook but I m getting only 90 records randomly in my application. I have tried a lot. but nothing solution I found out. can any one has solution? below is my code :
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)
{
//Query phone here. Covered next
Cursor pCur = cr.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
null,ContactsContract.CommonDataKinds.Phone.CONTACT_ID +" = ?", new
String[]{id}, null);
while (pCur.moveToNext())
{
// Do something with phones
String pnumber
=pCur.getString(pCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
contactids.add(id);
names.add(name.trim().toLowerCase());
PhoneNumbers.add(pnumber);
}
pCur.close();
}
else
{
String pnumber="";
contactids.add(id);
names.add(name);
PhoneNumbers.add(pnumber);
}
}
finally I have done with following code. But the problem with this is it can't fetch records if contacts are more then 1500. and till 1500 records process is very slow.
public class MyActivity extends Activity {
public Cursor cur;
public int j=0;
#Override
public void onCreate(Bundle savedInstanceState)
{
cur=getContacts();
startManagingCursor(cur);
cur.moveToFirst();
Button btn=(Button)findViewById(R.id.button1);
btn1.setOnClickListener(new OnClickListener()
{
public void onClick(View v)
{
contactids=new ArrayList<String>();
names=new ArrayList<String>();
PhoneNumbers=new ArrayList<String>();
try
{
new showdialog1(MyActivity.this).execute();
}
catch (Exception e)
{
// TODO: handle exception
e.printStackTrace();
}
}
});
}
class showdialog1 extends AsyncTask<Void, Void, Void>
{
public showdialog1(Activity act) {
super.onPreExecute();
}
#Override
protected void onPreExecute() {
dialog = ProgressDialog.show(MyActivity.this,"title", "message");
}
#Override
protected Void doInBackground(Void... params) {
if (cur.getCount() > 0)
{
do
{
String id = cur.getString(
cur.getColumnIndex(ContactsContract.Contacts._ID));
String name = cur.getString(
cur.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
Cursor pCur = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null,ContactsContract.CommonDataKinds.Phone.CONTACT_ID +"=" +id, null, null);
if(pCur.getCount()>0)
{
while (pCur.moveToNext())
{
// Do something with phones
String pnumber=pCur.getString(pCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
contactids.add(id);
names.add(name.trim().toLowerCase());
PhoneNumbers.add(pnumber);
}
pCur.close();
}
else
{
String pnumber="";
contactids.add(id);
names.add(name.trim().toLowerCase());
PhoneNumbers.add(pnumber);
}
}while (cur.moveToNext());
cur.close();
}
return null;
}
#Override
protected void onPostExecute(Void result) {
dialog.dismiss();
int contactidsize=contactids.size();
int namesize=contactids.size();
int numbersize=contactids.size();
saverecords();
return;
}
}
}
you get your contact list of your phone..
try this code and after that if you want to use contact from list you select that contace and use details of that contact (ex: number, name ,email.id etc..)
plz goto below link
/*** USE this CODE ******/
int PICK_CONTACT=1;
Intent intent = new Intent(Intent.ACTION_PICK, ContactsContract.Contacts.CONTENT_URI);
startActivityForResult(intent, PICK_CONTACT);`
You are using the condition:
Integer.parseInt(cur.getString(cur.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER ))) > 0)
which does not consider the contacts that doesnot have phone numbers .
Hope this works
See ContactManager http://developer.android.com/resources/samples/ContactManager/index.html
Create and initialize boolean variable mShowInvisible - if set to true, it will list all contacts regardless of user preference
/**
* Obtains the contact list for the currently selected account.
*
* #return A cursor for for accessing the contact list.
*/
private Cursor getContacts(){
// Run query
Uri uri = ContactsContract.Contacts.CONTENT_URI;
String[] projection = new String[] {
ContactsContract.Contacts._ID, ContactsContract.Contacts.DISPLAY_NAME
};
String selection = ContactsContract.Contacts.IN_VISIBLE_GROUP + " = '"(mShowInvisible ? "0" : "1") + "'";
String[] selectionArgs = null;
String sortOrder = ContactsContract.Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC";
return managedQuery(uri, projection, selection, selectionArgs, sortOrder);
}