I am trying to store the user contacts on Parse.com dashboard. I run my project again & again to store contacts.
But everytime I see different number of contacts stored, some of the contacts(data ie friend & phone no) have been lost.
I am using all this code:
public class MainActivity extends Activity {
ParseObject testObject;
EditText et;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Parse.initialize(this, "2dSVesLx7lUKxhSb7B4bSmAOlIVAWONM8sIQTtZb", "CkikNpzXV2eR0QugHnZCQoQjbh6IDgHrESG0KIBS");
et = (EditText)findViewById(R.id.editText1);
et.setOnEditorActionListener(new OnEditorActionListener() {
#Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
boolean handled = false;
if (actionId == EditorInfo.IME_ACTION_DONE) {
// TODO do something
handled = true;
testObject = new ParseObject("India"+et.getText().toString());
readDistinctContacts("India"+et.getText().toString());
// readContacts();
}
return handled;
}
});
}
public void readDistinctContacts(String s) {
ContentResolver cr = getContentResolver();
Cursor cur = cr.query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null);
ArrayList<ParseObject> contacts = new ArrayList<ParseObject>();
ArrayList<String> list = new ArrayList<String>();
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))) == 1) {
System.out.println(name);
ParseObject testObject = new ParseObject(s);
testObject.put("names", name);
// 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));
System.out.println(phone);
testObject.put("phonenumber", phone);
if(!list.contains(phone)) {
contacts.add(testObject);
}
list.add(phone);
}
pCur.close();
testObject.saveInBackground();
}
}
}
cur.close();
}
public void readContacts(){
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))) ==1) {
System.out.println(name );
ParseObject testObject = new ParseObject("India"+et.getText().toString());
testObject.put("names", name);
// testObject.saveInBackground();
// 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));
System.out.println( phone);
testObject.put("phonenumber", phone);
}
pCur.close();
testObject.saveInBackground();
}
}
}
}
}
I have used both the methods like in code readcontacts(), readDistinctContacts() , but both are giving me the same problem. Look at the snapshot of my dashboard, it shows different number of contacts every time
Any solution to manage this problem?
Thanks in advance
UPDATE
Thanks to askoka, Using saveEventually() there was no data loss but it takes 3-4 minutes to store 400 parseobjects(ie. contacts) by 400 push request!. I want the storage should be fast and efficient, can anyone please tell me the best way to make it happen?
your saveInBackgroundmight be experiencing problems, try passing in a callback to see if there is an error.
saveInBackground(new SaveCallback() {
public void done(ParseException e) {
if (e != null) Log.e("ParseAPITest", "saveInBackground failed: " + e.toString());
}
});
and implement retry logic on your own or you can try :
replacing saveInBackground with saveEventually, which will retry if there is an error in message push.
batch your push messages by saving all the ParseObjects in a List and use saveAllInBackground preferably with callback, this will try to batch your push requests as discussed in saveAll
if your app use-case allows, you can create just one ParseObject and add all contacts to this single ParseObject and call saveEventually - this should only take one push request message to parse server, so the delay will be reduced.
In your readDistinctContacts function you already have contacts ArrayList, in which you save each contact as a ParseObject. You just need to save that list into one root ParseObject and call saveEventually() on it - this would result in just one request to the parse server.
Just before the while loop add ParseObject root = new ParseObject(s); and inside the while loop replace ParseObject testObject = new ParseObject(s); with ParseObject testObject = new ParseObject("Contact" + counter);. Get rid of testObject.saveInBackground();.
Finally add root.addAll(root.getClassName(), contacts);root.saveEventually(); after while loop. This should save all your contacts in one go (request), and saveEventually will handle any retries needed.
Related
When I click on fab to write a new SMS in my application, it is opening too slowly. When I comment readcontactData or adapter it is working Quickly. where is the problem
adapter =new ArrayAdapter<String>(this,android.R.layout.simple_dropdown_item_1line,new ArrayList<String>());
readContactData();
contactNumber.setThreshold(1);
//Set adapter to AutoCompleteTextView
contactNumber.setAdapter(adapter);
contactNumber.setOnItemClickListener(this);
private void readContactData() {
try {
ContentResolver contentResolver = getBaseContext().getContentResolver();
// Uri uri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(phoneNumber));
//Query to get contact name
Cursor cursor =contentResolver.query(ContactsContract.Contacts.CONTENT_URI,null,null,null,null);
// If data found in contacts
if (cursor.getCount() > 0) {
Log.i("AutocompleteContacts", "Reading contacts........");
int k=0;
while (cursor.moveToNext())
{
String name = cursor
.getString(cursor
.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
String id = cursor
.getString(cursor
.getColumnIndex(ContactsContract.Contacts._ID));
String hasPhone=cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER));
//Check contact have phone number
if ((Integer.parseInt(hasPhone) > 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
+ " = " + id,
null,
null);
int j=0;
while (pCur.moveToNext())
{
// Sometimes get multiple data
if(j==0)
{
// Get Phone number
String phoneNumber =pCur.getString(pCur
.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
// Add contacts names to adapter
adapter.add(name);
//adapter.add(phoneNumber);
// Add ArrayList names to adapter
phoneValueArr.add(phoneNumber.toString());
nameValueArr.add(name.toString());
j++;
//k++;
}
} // End while loop
pCur.close();
} // End if
} // End while loop
//} // End Cursor value check
cursor.close();
}
catch (Exception e)
{
e.printStackTrace();
Log.d("this is an error","akdjfkandkfj");
}
}**
You are loading data in Main thread. So its slow. Use Async Task for readContact.
Writing too much code in onCreate, slow the loading.
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 am successfully storing contacts in parse.com dashboard data browser by this code.
public void readContacts(){
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))) ==1) {
System.out.println(name );
ParseObject testObject = new ParseObject("Contacts");
testObject.put("names", name);
// 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));
System.out.println( phone);
testObject.put("phonenumber", phone);
}
pCur.close();
testObject.saveInBackground();
}
}
}
}
But there is no check for the duplicate contacts !
It stores all the contacts duplicate from sim / phone memory.
How can it be avoided ?
One possible method I think is to store distinct names(contact) in local database, & then retrieving that data to store it in parse.com
Is there exists a better way ?
Thanks in advance...
An easy approach could be to load the data to a MatrixCursor with no duplicate data. For example lets assume you have a cursor c1 will many contacts, but you need a cursor with no duplicate data. Here is what you could do:
MatrixCursor mc = new MatrixCursor(new String[] {
Phone._ID,
Phone.DISPLAY_NAME_PRIMARY,
Phone.NUMBER
});
String lastNumber = "";
while(c1.moveToNext()){
String id = c1.getString(c1.getColumnIndexOrThrow(Phone._ID));
String name = c1.getString(c1.getColumnIndexOrThrow(Phone.DISPLAY_NAME_PRIMARY)));
String number = c1.getString(c1.getColumnIndexOrThrow(Phone.NUMBER));
//Some condition to check previous data is not matched and only then add row
if(!lastNumber.contains(number)){
lastNumber = number;
mc.addRow(new String[]{id, name, number});
}
}
c1.close();
Make an instance of MatrixCursor with same columns, and then load if last number or contact name does not match that of the previous contact. The condition for checking is upto you. Query data in some order so that the duplicate contacts stay together first.
Once the MatrixCursor is loaded you can fetch data from it. You could also attach it to a view through a custom CursorLoader or CursorAdapter.
Please see the below method. You will get contacts list which does not have duplicate phone numbers.
public void readContacts() {
ContentResolver cr = getContentResolver();
Cursor cur = cr.query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null);
ArrayList<ParseObject> contacts = new ArrayList<ParseObject>();
ArrayList<String> list = new ArrayList<String>();
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))) == 1) {
System.out.println(name);
ParseObject testObject = new ParseObject("Contacts");
testObject.put("names", name);
// 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));
System.out.println(phone);
testObject.put("phonenumber", phone);
if(!list.contains(phone)) {
contacts.add(testObject);
}
list.add(phone);
}
pCur.close();
testObject.saveInBackground();
}
}
}
}
Set is a collection in java that does not allow duplicates. You can put your data into a set with number as a key and name as value, to avoid duplicate numbers.
And later you can take them back from set and put into your testObject with name as key and number as value.
Here is the Solution that i worked out for you....
You can go through the logcat for information about how it works 100%
import java.util.ArrayList;
import android.app.Activity;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.Contacts;
public class MainActivity extends Activity {
String ClsSimPhonename = null;
String ClsSimphoneNo = null;
public static ArrayList<String> phonecontact = new ArrayList<String>();
public static ArrayList<String> simcontact = new ArrayList<String>();
public static ArrayList<String> totalcontact = new ArrayList<String>();
public static ArrayList<String> repeatedcontact = new ArrayList<String>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// get phone contact...
getphonecontact();
// get sim contact...
getsimcard_contact();
System.out.println("phone??? " + phonecontact);
System.out.println("sim??? " + simcontact);
System.out.println("sim_size??? " + simcontact.size());
System.out.println("phone_size??? " + phonecontact.size());
System.out.println("totalcontact_size??? " + totalcontact.size());
// filter process beigins here....
nowFilterContact();
}
private void nowFilterContact() {
// TODO Auto-generated method stub
// determine which contact have more item....
if (simcontact.size() > phonecontact.size()) {
onemorefiltermethod(simcontact.size(), simcontact, phonecontact);
} else {
onemorefiltermethod(phonecontact.size(), phonecontact, simcontact);
}
}
private void onemorefiltermethod(int size, ArrayList<String> contacts,
ArrayList<String> contact2) {
// TODO Auto-generated method stub
// compare both contact and get repeated contacts....
for (int i = 0; i < size; i++) {
try {
if (contacts.contains(contact2.get(i))) {
// add repeated contacts to array....
repeatedcontact.add(contact2.get(i));
}
} catch (Exception e) {
}
}
System.out.println("repeatedcontact_size??? " + repeatedcontact.size());
// now delete repeated contact from total contact
now_deletedrepeated_contact_from_total();
}
private void now_deletedrepeated_contact_from_total() {
// TODO Auto-generated method stub
for (int i = 0; i < totalcontact.size(); i++) {
try {
if (totalcontact.contains(repeatedcontact.get(i))) {
totalcontact.remove(repeatedcontact.get(i));
}
} catch (Exception e) {
}
}
System.out.println("Final contact size" + totalcontact.size());
System.out.println("Final contact " + totalcontact);
}
private void getsimcard_contact() {
// TODO Auto-generated method stub
try {
Uri simUri = Uri.parse("content://icc/adn");
Cursor cursorSim = this.getContentResolver().query(simUri, null,
null, null, null);
while (cursorSim.moveToNext()) {
ClsSimPhonename = cursorSim.getString(cursorSim
.getColumnIndex("name"));
ClsSimphoneNo = cursorSim.getString(cursorSim
.getColumnIndex("number"));
ClsSimphoneNo.replaceAll("\\D", "");
ClsSimphoneNo.replaceAll("&", "");
ClsSimPhonename = ClsSimPhonename.replace("|", "");
/*
* add contact from phone to array phone array and total array
*/
phonecontact.add(ClsSimphoneNo);
totalcontact.add(ClsSimphoneNo);
}
} catch (Exception e) {
e.printStackTrace();
}
}
private void getphonecontact() {
// TODO Auto-generated method stub
try {
String[] PROJECTION = new String[] { Contacts._ID,
Contacts.DISPLAY_NAME, Phone.NUMBER };
Cursor c = managedQuery(Phone.CONTENT_URI, PROJECTION, null, null,
null);
if (c.moveToFirst()) {
String ClsPhonename = null;
String ClsphoneNo = null;
do {
ClsPhonename = c.getString(c
.getColumnIndex(Contacts.DISPLAY_NAME));
ClsphoneNo = c.getString(c.getColumnIndex(Phone.NUMBER));
/*
* add contact from sim to array sim array and total array
*/
simcontact.add(ClsphoneNo);
totalcontact.add(ClsphoneNo);
ClsphoneNo.replaceAll("\\D", "");
ClsPhonename = ClsPhonename.replaceAll("&", "");
ClsPhonename.replace("|", "");
String ClsPhoneName = ClsPhonename.replace("|", "");
} while (c.moveToNext());
}
} catch (Exception e) {
}
}
}
Permission
<uses-permission android:name="android.permission.READ_CONTACTS"/>
Your output is on now_deletedrepeated_contact_from_total() method.
Check totalcontact array value for Final output
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.