How to read contacts in Android using Realm?
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
Obtaining contacts from content provider without duplicates or invalid contacts, and save to Realm
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);
}
How to read data from Realm
You're doing an asynchronous network call before accessing your data. The network call has not completed yet, therefore your data is empty. Put your data access code in the onSuccess()
callback.
public class MainActivity extends AppCompatActivity {
...
public void onLogin() {
...
RequestHandle post = client.post(
"https://example.com/api/v1/auth",
rp,
new JsonHttpResponseHandler() {
@Override
public void onSuccess(
int statusCode,
Header[] headers,
JSONObject response) {
try {
String tokenString = response.getString("token");
mRealm.beginTransaction();
Config myConfig = mRealm.createObject(Config.class);
myConfig.name = "token";
myConfig.tokenValue = tokenString;
mRealm.commitTransaction();
populateData();
} catch (NullPointerException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
}
@Override
public void onFailure(
int statusCode,
Header[] headers,
String res,
Throwable t) {
// called when response HTTP status is "4XX" (eg. 401, 403, 404)
}
});
}
private void populateData() {
TextView tvHello = (TextView)findViewById(R.id.tvHello);
try {
RealmResults User =
mRealmInstance.where(Config.class).equalTo("name", "token").findAll();
if (User.size() > 0) {
String nameOfUser = User.get(0).toString();
tvHello.setText(nameOfUser);
} else if (User.size() == 0) {
Log.e("query","query size is "+User.size());
}
} catch (Exception e) {
e.printStackTrace();
}
}
Also note that you should use findAll()
instead of findAllAsync()
. Read the documentation for more information on the difference: https://realm.io/blog/realm-java-0-84-0/
Direct field access in Realm for Android
Emanuele from Realm here. Realm has been supporting public fields with no accessors since 0.88.0 https://realm.io/news/realm-java-0.88.0/
Loading contacts and saving to realm taking a very long time
You should be using a single write transaction for all of your updates rather than one per insertion, and you should not be dispatching your updates to the UI thread.
Realm has some per-transaction overhead, and when you're inserting just a single object per transaction this overhead will be massively larger than the time spent actually inserting that object. Inserting 100 objects in a single transaction will probably take less time than two transactions which each insert just a single object.
Dispatching your updates to the UI thread is the exact opposite of what you want to do; you should be trying to avoid performing write transaction on the UI thread, not going out of your way to do so when there's no reason to.
Error while reading data from Realm in android
You should be passing a RealmConfiguration
to Realm.getInstance()
not getApplicationContext()
. It should look something like this.
RealmConfiguration config = new RealmConfiguration.Builder(context)
.name("myrealm.realm")
.build();
Realm realm = Realm.getInstance(config);
use realm instance across different activities which using predefined realm database
To be able to get a default, you have to set a default:
RealmConfiguration config1 = new RealmConfiguration.Builder(this)
.name("test")
.schemaVersion(1)
.migration(new Migration())
.build();
Realm.setDefaultConfiguration(config1); // <-- here
Now you can get it with
Realm.getDefaultInstance();
Realm in an Android Background Service
In an IntentService, you're supposed to treat the onHandleIntent
method like the doInBackground
method of an AsyncTask.
So it runs on the background thread and you should make sure you close the Realm in a finally block.
public class PollingService extends IntentService {
@Override
public void onHandleIntent(Intent intent) {
Realm realm = null;
try {
realm = Realm.getDefaultInstance();
// go do some network calls/etc and get some data
realm.executeTransaction(new Realm.Transaction() {
@Override
public void execute(Realm realm) {
realm.createAllFromJson(Customer.class, customerApi.getCustomers()); // Save a bunch of new Customer objects
}
});
} finally {
if(realm != null) {
realm.close();
}
}
}
// ...
}
onCreate
runs on the UI thread, so your initialization of the Realm happens on a different thread, which is a no-go.
Related Topics
Android Alarmmanager Not Waking Phone Up
How to Create Context Menu for Recyclerview
Certpathvalidatorexception:Trust Anchor for Certificate Path Not Found - Retrofit Android
Gridlayout and Row/Column Span Woe
Getting Data from Android Play Store
Android Check Permission for Locationmanager
A Failure Occurred While Executing Org.Jetbrains.Kotlin.Gradle.Internal.Kaptexecution
Save Data and Change Orientation
How to Read Contacts in Android Using Realm
How to Decompile an APK or Dex File on Android Platform
How to Change Color of Android Listview Separator Line
Best Ocr (Optical Character Recognition) Example in Android
Streaming Audio from a Url in Android Using Mediaplayer
How to Use the Android Volley API
Android Phone Orientation Overview Including Compass
Are Parameters in Strings.Xml Possible