I have implemented Realm as my DB, and in my app I run a service on the phone contacts for checking any change in my phonebook. The service works for like 3 to 4 changes and then the app crashes with this error in my logcat.
Unrecoverable error. mremap(): failed: Out of memory in io_realm_internal_SharedGroup.cpp line 188
Here's my code:
public static void refreshingContactsDB()
{
createCountryDetailsArrayModel();
TelephonyManager tm = (TelephonyManager) ApplicationController.getInstance()
.getSystemService(Context.TELEPHONY_SERVICE);
String simCountryISO = tm.getSimCountryIso();
for (int i = 0; i < countryDetailsList.size(); i++) {
if (simCountryISO.equalsIgnoreCase(countryDetailsList.get(i)
.getCode())) {
dialCodePrefix = countryDetailsList.get(i).getDial_code();
}
}
AppPreferenceManager.getInstance().setContactUpdate(false);
Logger.debug("Contact Update Refreshing Contact Started -->");
Thread background = new Thread(new Runnable() {
public void run() {
Realm realmRefresh = Realm.getInstance(ApplicationController.getInstance());
ContentResolver cr = ApplicationController.getInstance()
.getContentResolver();
Cursor phones = cr.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, PROJECTION, null, null, null);
String duplicateName = "";
String duplicatePhone = "";
if (phones.getCount() > 0) {
final int nameIndex = phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME);
final int numberIndex = phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER);
while (phones.moveToNext()) {
String name = phones.getString(nameIndex);
String phoneNo = phones.getString(numberIndex);
if (phoneNo != null && !phoneNo.isEmpty()) {
phoneNo = phoneNo.replace(" ", "");
phoneNo = phoneNo.replace("(", "");
phoneNo = phoneNo.replace(")", "");
phoneNo = phoneNo.replace("-", "");
phoneNo = phoneNo.replace("\u00a0", "");
phoneNo = phoneNo.replace("\u202c", "");
phoneNo = phoneNo.replace("\u2011", "");
phoneNo = phoneNo.replace("\u202a", "");
phoneNo = phoneNo.replace("*", "");
phoneNo = phoneNo.replace("#", "");
if (phoneNo.length() >= 5) {
if (name.equalsIgnoreCase(duplicateName) && phoneNo.equalsIgnoreCase(duplicatePhone)) {
continue;
}
duplicateName = name;
duplicatePhone = phoneNo;
String formattedPhoneNumber;
formattedPhoneNumber = parseNumber(phoneNo);
// List<LocalContactDb> getContactsList = Select
// .from(LocalContactDb.class)
// .where(Condition.prop("PHONE").eq(
// formattedPhoneNumber))
// .list();
RealmResults<R_LocalContactDB> realmResults = realmRefresh.where(R_LocalContactDB.class).equalTo("phone", formattedPhoneNumber).findAll();
Logger.debug("Size: " + realmResults.size());
RealmResults<R_LocalContactDB> query = realmRefresh.where(R_LocalContactDB.class).findAll();
R_LocalContactDB rContacts = new R_LocalContactDB(null, null, false, 0);
if (realmResults.size() == 0) {
realmRefresh.beginTransaction();
R_LocalContactDB rCont = realmRefresh.copyToRealm(rContacts);
rCont.setName(name);
rCont.setPhone(formattedPhoneNumber);
rCont.setStatus(0);
rCont.setMatchedWithRecent(true);
Logger.debug("New Size: " + query.size());
realmRefresh.commitTransaction();
Logger.debug("Contact Update " + name
+ " saved");
} else {
realmRefresh.beginTransaction();
if (!name.equalsIgnoreCase(realmResults.get(0).getName())) {
realmResults.get(0).setName(name);
}
realmResults.get(0).setMatchedWithRecent(true);
// realmResults.get(0);
Logger.debug("New Size Else Condition: " + query.size());
realmRefresh.commitTransaction();
realmRefresh.close();
}
}
}
}
ContactsSyncService.contactUpdated= false ;
phones.close();
}
deleteExtraContacts();
getNumbersFromDBAndUpdate();
}
});
background.start();
}
I have read this, but can't seem to understand it fully from the documentation:
Please note that writes block each other, and will block the thread they are made on if other writes are in progress. This can cause ANR errors if you are doing writes from the UI thread while also doing writes from a background thread. To avoid this, first create objects in memory first outside a transaction, and only perform a simple Realm.copyToRealm() inside the transaction, which will keep blocking times to a minimum.