I am working with android device contacts. if android device contacts more than five thousand,Fetch data from contacts take too much time with blank screen. I have used bellow code to fetch data
private void fetchContacts1() {
String order = ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + " ASC";
Cursor cursor = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, null, null, order);
while (cursor.moveToNext()) {
String name = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
String phonenumber = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
}
cursor.close();
}
I show all the contacts to recycle view.There are some devices which has more than ten thousand contacts. can you suggest me how to handle it.
Use the Async task to load your contacts in the background. after loading for first-time store your list of contacts to your local database
below following links may help you
https://developer.android.com/guide/components/loaders
https://stackoverflow.com/a/40017905/10239870
class ContactLoader extends AsyncTask<Void, Void, List<Contact>> {
#Override
protected void onPreExecute() {
super.onPreExecute();
//visible your progress bar here
}
#Override
protected List<Contact> doInBackground(Void... voids) {
List<Contact> contacts = new ArrayList<>();
String order = ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + " ASC";
Cursor cursor = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, null, null, order);
while (cursor.moveToNext()) {
String name = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
String phonenumber = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
contacts.add(new Contact(name, phonenumber));
}
cursor.close();
return contacts;
}
#Override
protected void onPostExecute(List<Contact> contactList) {
super.onPostExecute(contactList);
//set list to your adapter
}
}
class Contact {
String name;
String number;
public Contact(String name, String number) {
this.name = name;
this.number = number;
}
public String getName() {
return name;
}
public String getNumber() {
return number;
}
public void setName(String name) {
this.name = name;
}
public void setNumber(String number) {
this.number = number;
}
}
Related
I can't find any solutions to read contacts from Android and save them in Realm. Anyone done that before?
I know that I will have to use Contacts Provider, but this is all I know. AFAIK, Realm doesn't support Cursor so...what else?
edit:
realm.executeTransaction(new Realm.Transaction() {
#Override
public void execute(Realm realm) {
Contact realmContact = new Contact();
String filter = "" + ContactsContract.Contacts.HAS_PHONE_NUMBER + " > 0 and "
+ ContactsContract.CommonDataKinds.Phone.TYPE +"="
+ ContactsContract.CommonDataKinds.Phone.TYPE_MAIN;
Cursor phones = getActivity()
.getContentResolver()
.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, filter, null, null);
while (phones.moveToNext()) {
String id = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone._ID));
String name = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
String phoneNumber = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
realmContact.setId(id);
realmContact.setName(name);
realmContact.setNumber(phoneNumber);
realmContact.setIsBeingSaved(true);
realm.insertOrUpdate(realmContact);
}
/** merge mechanism */
realm.where(Contact.class)
.equalTo("isBeingSaved", false)
.findAll()
.deleteAllFromRealm(); // delete all non-saved data
for(Contact contact : realm.where(Contact.class).findAll()) {
realmContact.setIsBeingSaved(false); // reset all save state
}
Contact.class
public class Contact extends RealmObject{
#PrimaryKey
private String id;
#Index
private String name;
#Index
private String number;
#Index
private boolean isBeingSaved;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
public boolean getIsBeingSaved() {
return isBeingSaved;
}
public void setIsBeingSaved(boolean beingSaved) {
isBeingSaved = beingSaved;
}
}
Create RealmObject, read the data from content provider, save data to RealmObject, save data in Realm:
// background thread
Realm realm = null;
try {
realm = Realm.getDefaultInstance();
realm.executeTransaction(new Realm.Transaction() {
#Override
public void execute(Realm realm) {
RealmContact realmContact = new RealmContact();
Cursor phones = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, null, null, null);
while (phones.moveToNext()) {
String name = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
String phoneNumber = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
realmContact.setName(name);
realmContact.setPhoneNumber(phoneNumber);
realm.insertOrUpdate(realmContact);
}
}
});
} finally {
if(realm != null) {
realm.close();
}
}
EDIT: okay, here's a trick to merging data and removing all data that's not in the list you've saving
public class RealmContract extends RealmObject {
#PrimaryKey
private long id;
#Index
private String name;
#Index
private String phoneNumber;
#Index
private boolean isBeingSaved;
//getters, setters
}
Then merge:
// background thread
Realm realm = null;
try {
realm = Realm.getDefaultInstance();
realm.executeTransaction(new Realm.Transaction() {
#Override
public void execute(Realm realm) {
RealmContact realmContact = new RealmContact();
Cursor phones = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, null, null, null);
while (phones.moveToNext()) {
String id = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds._ID));
String name = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
String phoneNumber = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
realmContact.setId(id);
realmContact.setName(name);
realmContact.setPhoneNumber(phoneNumber);
realmContact.setIsBeingSaved(true);
realm.insertOrUpdate(realmContact);
}
realm.where(RealmContact.class)
.equalTo(RealmContactFields.IS_BEING_SAVED, false) // compile 'dk.ilios:realmfieldnameshelper:1.0.0'
.findAll()
.deleteAllFromRealm(); // delete all non-saved data
for(RealmContact realmContact : realm.where(RealmContact.class).findAll()) { // realm 0.89.0+
realmContact.setIsBeingSaved(false); // reset all save state
}
}
});
} finally {
if(realm != null) {
realm.close();
}
}
EDIT: Refer to OP's other question for reading contact data reliably (because there's something up with the Contact LOOKUP_ID and making sure the IDs are correct): Obtaining contacts from content provider without duplicates or invalid contacts, and save to Realm
You can create a Model Class to store desired data from contact
then using Cursor get data and set data in model class.
Save the cursor data in list of model object.
Then insert all model object in single transaction as per object transaction has overhead and slow our app
I have this code (thankfully provided by #EpicPandaForce) and I have problem with deletion. When I add new contact it works like a charm while when I delete contact (or number from that contact if there are two of them) it stays persisted in Realm. How can I get it working properly?
realm.executeTransaction(new Realm.Transaction() {
#Override
public void execute(Realm realm) {
Contact realmContact = new Contact();
String filter = "" + ContactsContract.Contacts.HAS_PHONE_NUMBER + " > 0 and "
+ ContactsContract.CommonDataKinds.Phone.TYPE +"="
+ ContactsContract.CommonDataKinds.Phone.TYPE_MAIN;
Cursor phones = getActivity()
.getContentResolver()
.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, filter, null, null);
while (phones.moveToNext()) {
String id = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone._ID));
String name = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
String phoneNumber = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
realmContact.setId(id);
realmContact.setName(name);
realmContact.setNumber(phoneNumber);
realmContact.setIsBeingSaved(true);
realm.insertOrUpdate(realmContact);
}
/** merge mechanism */
realm.where(Contact.class)
.equalTo("isBeingSaved", false)
.findAll()
.deleteAllFromRealm(); // delete all non-saved data
for(Contact contact : realm.where(Contact.class).findAll()) {
realmContact.setIsBeingSaved(false); // reset all save state
}
Contact.class
public class Contact extends RealmObject{
#PrimaryKey
private String id;
#Index
private String name;
#Index
private String number;
#Index
private boolean isBeingSaved;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
public boolean getIsBeingSaved() {
return isBeingSaved;
}
public void setIsBeingSaved(boolean beingSaved) {
isBeingSaved = beingSaved;
}
}
EDIT - working code:
Contact realmContact = new Contact();
Uri uri = Contacts.CONTENT_URI;
String selection = "((" + CommonDataKinds.Phone.DISPLAY_NAME_PRIMARY + " NOTNULL) AND ("
+ Contacts.HAS_PHONE_NUMBER + "=1) AND ("
+ CommonDataKinds.Phone.DISPLAY_NAME_PRIMARY + " != '' ))";
Cursor phones = getActivity()
.getContentResolver()
.query(uri, null, selection, null, null);
String phoneNumber = "";
while (phones.moveToNext()) {
String id = phones.getString(phones.getColumnIndex(ContactsContract.Contacts.LOOKUP_KEY));
String name = phones.getString(phones.getColumnIndex(Contacts.DISPLAY_NAME_PRIMARY));
String lastTimeContacted = phones.getString(phones.getColumnIndex(Contacts.LAST_TIME_CONTACTED));
if(Integer.parseInt(phones.getString(phones.getColumnIndex(Contacts.HAS_PHONE_NUMBER))) > 0){
Cursor pCur = getActivity().getContentResolver().query(
CommonDataKinds.Phone.CONTENT_URI,
null,
CommonDataKinds.Phone.LOOKUP_KEY +" = ?",
new String[]{id}, null);
while (pCur.moveToNext()) {
phoneNumber += "/" + pCur.getString(pCur.getColumnIndex(CommonDataKinds.Phone.NUMBER));
realmContact.setNumber(phoneNumber);
}
phoneNumber = "";
pCur.close();
} else {
realmContact.setNumber("1234");
}
realmContact.setId(id);
realmContact.setName(lastTimeContacted);
realmContact.setIsBeingSaved(true);
realm.insertOrUpdate(realmContact);
}
Log.i("asd-size", realm.where(Contact.class).findAll().size() + "");
/** merge mechanism */
realm.where(Contact.class)
.equalTo("isBeingSaved", false)
.findAll()
.deleteAllFromRealm(); // delete all non-saved data
for(Contact contact : realm.where(Contact.class).findAll()) {
contact.setIsBeingSaved(false); // reset all save state
}
Okay, after quite long searching I found that there was a typo:
/** merge mechanism */
realm.where(Contact.class)
.equalTo("isBeingSaved", false)
.findAll()
.deleteAllFromRealm(); // delete all non-saved data
for(Contact contact : realm.where(Contact.class).findAll()) {
realmContact.setIsBeingSaved(false); <- here it is
}
It's realmContact when in fact it should be contact so it refers to contact iterated by for loop.
So, basically, it was setting Contact realmContact = new Contact(); to false. So the proper version is:
/** merge mechanism */
realm.where(Contact.class)
.equalTo("isBeingSaved", false)
.findAll()
.deleteAllFromRealm(); // delete all non-saved data
for(Contact contact : realm.where(Contact.class).findAll()) {
contact.setIsBeingSaved(false);
}
I can't find any solutions to read contacts from Android and save them in Realm. Anyone done that before?
I know that I will have to use Contacts Provider, but this is all I know. AFAIK, Realm doesn't support Cursor so...what else?
edit:
realm.executeTransaction(new Realm.Transaction() {
#Override
public void execute(Realm realm) {
Contact realmContact = new Contact();
String filter = "" + ContactsContract.Contacts.HAS_PHONE_NUMBER + " > 0 and "
+ ContactsContract.CommonDataKinds.Phone.TYPE +"="
+ ContactsContract.CommonDataKinds.Phone.TYPE_MAIN;
Cursor phones = getActivity()
.getContentResolver()
.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, filter, null, null);
while (phones.moveToNext()) {
String id = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone._ID));
String name = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
String phoneNumber = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
realmContact.setId(id);
realmContact.setName(name);
realmContact.setNumber(phoneNumber);
realmContact.setIsBeingSaved(true);
realm.insertOrUpdate(realmContact);
}
/** merge mechanism */
realm.where(Contact.class)
.equalTo("isBeingSaved", false)
.findAll()
.deleteAllFromRealm(); // delete all non-saved data
for(Contact contact : realm.where(Contact.class).findAll()) {
realmContact.setIsBeingSaved(false); // reset all save state
}
Contact.class
public class Contact extends RealmObject{
#PrimaryKey
private String id;
#Index
private String name;
#Index
private String number;
#Index
private boolean isBeingSaved;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
public boolean getIsBeingSaved() {
return isBeingSaved;
}
public void setIsBeingSaved(boolean beingSaved) {
isBeingSaved = beingSaved;
}
}
Create RealmObject, read the data from content provider, save data to RealmObject, save data in Realm:
// background thread
Realm realm = null;
try {
realm = Realm.getDefaultInstance();
realm.executeTransaction(new Realm.Transaction() {
#Override
public void execute(Realm realm) {
RealmContact realmContact = new RealmContact();
Cursor phones = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, null, null, null);
while (phones.moveToNext()) {
String name = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
String phoneNumber = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
realmContact.setName(name);
realmContact.setPhoneNumber(phoneNumber);
realm.insertOrUpdate(realmContact);
}
}
});
} finally {
if(realm != null) {
realm.close();
}
}
EDIT: okay, here's a trick to merging data and removing all data that's not in the list you've saving
public class RealmContract extends RealmObject {
#PrimaryKey
private long id;
#Index
private String name;
#Index
private String phoneNumber;
#Index
private boolean isBeingSaved;
//getters, setters
}
Then merge:
// background thread
Realm realm = null;
try {
realm = Realm.getDefaultInstance();
realm.executeTransaction(new Realm.Transaction() {
#Override
public void execute(Realm realm) {
RealmContact realmContact = new RealmContact();
Cursor phones = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, null, null, null);
while (phones.moveToNext()) {
String id = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds._ID));
String name = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
String phoneNumber = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
realmContact.setId(id);
realmContact.setName(name);
realmContact.setPhoneNumber(phoneNumber);
realmContact.setIsBeingSaved(true);
realm.insertOrUpdate(realmContact);
}
realm.where(RealmContact.class)
.equalTo(RealmContactFields.IS_BEING_SAVED, false) // compile 'dk.ilios:realmfieldnameshelper:1.0.0'
.findAll()
.deleteAllFromRealm(); // delete all non-saved data
for(RealmContact realmContact : realm.where(RealmContact.class).findAll()) { // realm 0.89.0+
realmContact.setIsBeingSaved(false); // reset all save state
}
}
});
} finally {
if(realm != null) {
realm.close();
}
}
EDIT: Refer to OP's other question for reading contact data reliably (because there's something up with the Contact LOOKUP_ID and making sure the IDs are correct): Obtaining contacts from content provider without duplicates or invalid contacts, and save to Realm
You can create a Model Class to store desired data from contact
then using Cursor get data and set data in model class.
Save the cursor data in list of model object.
Then insert all model object in single transaction as per object transaction has overhead and slow our app
In my android application I need to show the contact list in listview .. but when I am displaying contacts are repeating ..I am giving my code below if anyone can suggest what change I need to give please help... iam giving my code below
Cursor c = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, null, null, null);
while (c.moveToNext())
{
String contactName = c
.getString(c
.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
String phNumber = c
.getString(c
.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
boolean retval2 = contacts1.contains(contactName);
if (retval2 == false)
{
Contact con = new Contact(c.getString(c
.getColumnIndex(Contacts.DISPLAY_NAME)), c.getString(c
.getColumnIndex(Phone.NUMBER)));
contacts.add(con);
contacts1.add(contactName);
}
}
listView.setAdapter(new ContactsAdapter(this, contacts));
public class Contact
{
private String name;
private String mobile;
public Contact(String name, String mobile)
{
super();
this.name = name;
this.mobile = mobile;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public String getMobile()
{
return mobile;
}
public void setMobile(String mobile)
{
this.mobile = mobile;
}
}
This might help removing duplicates
if(!contacts.contains(con))
{
contacts.add(con);
}
I'm creating an app which require Contacts with their phone numbers. I'm able to get the Contact name list using following code
private Contact[] contact_read;
private Cursor mCursor;
String[] projection = new String[] { Contacts.HAS_PHONE_NUMBER,
Contacts._ID, Contacts.DISPLAY_NAME };
mCursor = managedQuery(Contacts.CONTENT_URI, projection,
Contacts.HAS_PHONE_NUMBER + "=?", new String[] { "1" },
Contacts.DISPLAY_NAME);
if (mCursor != null) {
mCursor.moveToFirst();
contact_read = new Contact[mCursor.getCount()];
int j = 0;
do {
contact_read[j] = new Contact(mCursor.getString(mCursor
.getColumnIndex(Contacts.DISPLAY_NAME)));
j++;
} while (mCursor.moveToNext());
} else {
System.out.println("Cursor is NULL");
}
The Contact class is
private static class Contact {
private String name = "";
public Contact() {
}
public Contact(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
But when I add the following code to get phone number, the app crashes
ContentResolver cr = getContentResolver();
String id = mCursor.getString(mCursor.getColumnIndex(Contacts._ID));
Cursor pCur = cr.query(Phone.CONTENT_URI,null,Phone.CONTACT_ID +" = ?", new String[]{id}, null);
pCur.moveToFirst();
int j = 0;
do {
contact_read[j] = new Contact(pCur.getString(pCur.getColumnIndex(Phone.NUMBER)));
j++;
} while (pCur.moveToNext());
Any suggestions from your side what changes need to be done to get the phone numbers??
This is the code for getting all the contacts from our phone
while (phones.moveToNext())
{
String name=phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
String phoneNumber = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
arraylist_connect.add(new Connect(name,phoneNumber,"Mobile"));
}
phones.close();