Uploaded image for project: 'Realm Java SDK'
  1. Realm Java SDK
  2. RJAVA-1021

Android realm data lost/corrupted randomly

      Goal

      Stable working database

      Actual Results

      Realm database behaves strangely, because at different times of using the application (most often after opening), after executing the query, we get null although the data in the database exists. The database file cannot be opened in realm studio, and whether the data exists in the database is confirmed by a hexeditor. The same happens for both encrypted and non-encrypted database.

      Steps & Code to Reproduce

      In the given example, I am saving the user entity after login. Every time I open the application, I have to get user data and this is where the problem appears, because it sometimes happens that the database returns null and so every time until I completely delete the application.

      For more information:

      • App constantly makes read/write every 5 seconds for another data
      • For every transaction there is new connection to database and ofc closed after.
      • The only one place I delete user entity from database is after logout
      • Migrations are empty
      • There is no such a thing like "delete database file" anywhere
      private fun initRealm(application: Application) {
           Realm.init(application).also {
               getAppSharedPreferences().run {
                   getSharedValue<ByteArray>("RealmKey").let { key ->
                       if (key == null) {
                           val newKey = ByteArray(64)
                           val random: Random = SecureRandom()
                           random.nextBytes(newKey)
                           putSharedValue("RealmKey", newKey)
                           newKey
                       } else {
                           key
                       }
                   }
               }.also { key ->
                   RealmConfiguration.Builder()
                       .name("AppNameRealmDB.realm")
                       .encryptionKey(key)
                       .allowQueriesOnUiThread(false)
                       .allowWritesOnUiThread(false)
                       .schemaVersion(1)
                       .migration(AppRealmMigrations())
                       .build().run {
                           Realm.setDefaultConfiguration(this)
                       }
               }
           }
       }
      
      class UnitOfWork {
          fun <TResult> queryRealm(action: Realm.() -> TResult): Single<TResult> {
              return Single.create<TResult> { emitter ->
                  Realm.getDefaultInstance().run {
                      try {
                          emitter.onSuccess(action.invoke(this)!!)
                      } catch (ex: Exception) {
                          close()
                          emitter.onError(ex)
                      } finally {
                          close()
                      }
                  }
              }.subscribeOn(Schedulers.io())
          }
      }
      
      class CurrentUserHelper(private val unitOfWork: UnitOfWork) {
          
          //This fun is sample original user entity comes after login request
          fun saveCurrentUser(): Single<OperationResult> {
              return unitOfWork.queryRealm {
                  executeTransaction {
                      copyToRealmOrUpdate(UserEntity().apply {
                          isCurrentUser = true
                      })
                  }
              }.map {
                  OperationResult.Success()
              }
          }
      
          fun getCurrentUser(): Single<UserEntity> {
              return unitOfWork.queryRealm {
                  copyFromRealm(
                      where(UserEntity::class.java).equalTo(
                          UserEntity::isCurrentUser.name,
                          true
                      ).findFirst()!! <-- Null pointer exception
                  )
              }
          }
      }
      
      fun clear(): Single<OperationResult> {
              return unitOfWork.queryRealm {
                  executeTransaction {
                      where(UserEntity::class.java).findAll().deleteAllFromRealm()
                  }
              }.map {
                  OperationResult.Success()
              }
          }
      
      @RealmClass
      open class UserEntity() : RealmModel {
          @PrimaryKey
          var id: String = UUID.randomUUID().toString()
      
          var isCurrentUser: Boolean = false
      }
      

      Version of Realm and tooling

      Realm version(s): 10.7.1 and lower

      Realm Sync feature enabled: No

      Android Studio version: Arctic Fox | 2020.3.1 and lower

      Android Build Tools version: 7.0.0 and lower

      Gradle version: 7.1.1 and lower

      Which Android version and device(s): Android(8, 9, 10), Devices(Hammer IRON 3 LTE, Galaxy A5, Redmi Note 8 Pro) and probably more but I don't have more data

      https://stackoverflow.com/questions/68817291/android-realm-data-lost-corrupted-randomly

            Assignee:
            Unassigned Unassigned
            Reporter:
            unitosyncbot Unito Sync Bot
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated:
              Resolved: