Android Datastore IOException could not be renamed to

Viewed 1580

I am trying to implement Jetpack Datastore in my project. I was using the apha-01 version and the code was working fine. Then I saw in the Gradle file that there is a new version so I updated it to alpha-03.

After starting my app, I encountered another issue. I found that Proto library is not found in the alpha-03 version so I rolled back to version alpha-01. Also, I tried alpha-02. Since then I am having the error below:

 Process: com.montymobile.sands, PID: 19928
    java.io.IOException: /data/user/0/com.montymobile.sands/files/datastore/sns_preferences.preferences_pb.tmp could not be renamed to /data/user/0/com.montymobile.sands/files/datastore/sns_preferences.preferences_pb
        at androidx.datastore.SingleProcessDataStore.writeData$datastore_core_release(SingleProcessDataStore.kt:304)
        at androidx.datastore.SingleProcessDataStore.transformAndWrite(SingleProcessDataStore.kt:282)
        at androidx.datastore.SingleProcessDataStore$actor$1.invokeSuspend(SingleProcessDataStore.kt:165)
        at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
        at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:56)
        at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:571)
        at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:738)
        at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:678)
        at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:665)

I noticed that this happens because I was saving two different key one after another, each in a coroutine. When i comment the 2nd action, it works. Can anyone explain why this happens? and how to save as many values as I Want?

Any help would be appreciated.

2 Answers

Screenshot of the sime UI Check the following code.

class DataStoreClass(private val context: Context) {

    private fun dataStore(): DataStore<Preferences> = context.createDataStore("settings")

    suspend  fun <T> save(key: Preferences.Key<T>, value: T) {
        dataStore().edit {
            it[key] = value
        }
    }

    suspend fun <T> read(key: Preferences.Key<T>, defaultValue: T): T {
        val pre = dataStore().data.first()
        return pre[key] ?: defaultValue
    }

}

open class BaseActivity : AppCompatActivity() {

    inline fun <reified T> getSavedValue(key: String, defaultValue:T): Any {
         var savedValue = Any()
         runBlocking {
             val operation = async {
                 val savedStr = DataStoreClass(this@BaseActivity).read(preferencesKey(key),
                     defaultValue!!).let {
                     it
                 }
                 savedValue = savedStr
             }
             operation.await()
         }
         return savedValue
     }

    fun <T> saveDesiredValue(key: Preferences.Key<T>, value: T) {
        runBlocking {
            CoroutineScope(Dispatchers.IO).launch {
                DataStoreClass(this@BaseActivity).save(key, value)
            }.join()
        }
    }
}

class MainActivity : BaseActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val bnt = findViewById<Button>(R.id.btnSave)
        val btnRead = findViewById<Button>(R.id.btnRead)
        val key = findViewById<EditText>(R.id.key)
        val etValue = findViewById<EditText>(R.id.etValue)
        val value = findViewById<TextView>(R.id.value)

        bnt.setOnClickListener {
            saveDesiredValue(preferencesKey(key.text.toString()),etValue.text.toString())
            saveDesiredValue(preferencesKey("test"), Random.nextInt(100))

        }

        btnRead.setOnClickListener {
            value.text = "${getSavedValue(key.text.toString(),"")} " +
                    "${getSavedValue("test",0)}"
        }
    }
}

I think this issue is due to the renamed version of latest datastore saved files. You can either try uninstalling the app and reinstalling it again, which will delete all the related datastore files and create new ones.

Or else you can implement a button to clear cache (storage) in your app and call

dataStore.edit {
        it.clear()
    }

on click of the button. This would delete all the pre-saved data for your application, which you can recreate on the next launch.

Related