I am trying to save a name in SharedPreferences
. The app is set up so that it recognizes devices by their MAC address. There's an EditText
view that populates with the advertised name of the BLE peripheral, and then the user can alter the name inside of the EditText
. Once the EditText
loses focus, the Data class is supposed to save the user input in SharedPreferences
, where the address of the device is the key and the name of the device is the value. Instead, when the EditText
loses focus, the name just reverts to the original name found in the BLE advertisement.
I have already looked for answers from these resources (1, 2, 3, 4, 5).
As far as I can tell, I have everything set up correctly in my application, but I am not getting the results I'm looking for. I have three main classes: MainActivity, ScanResultAdapter, and Data. MainActivity is the driver of the program, ScanResultAdapter manages the incoming BLE advertisements from peripheral devices, and Data is a singleton class that manages information for the entire application.
This is how I have it set up in my application:
MainActivity
...
// declaration of the myPrefs variable
lateinit var myPrefs: SharedPreferences
...
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// instantiation of the myPrefs variable
myPrefs = PreferenceManager.getDefaultSharedPreferences(this)
// passing the context to the data-tracking Data class so that it can access MainActivity's SharedPreferences
data = Data.getInstance(this)
mainBinding.saveNamesButton.onClick {
mainBinding.saveNamesButton.requestFocusFromTouch()
}
rowScanResultBinding.deviceName.onFocusChangeListener = OnFocusChangeListener { v, hasFocus ->
if (!hasFocus) {
val name = rowScanResultBinding.deviceName.text.toString()
val address = rowScanResultBinding.macAddress.text.toString()
if (data.sharedPref.contains(address) && rowScanResultBinding.deviceName.text.toString() != data.sharedPref.getString(address, null)) {
rowScanResultBinding.deviceName.setText(data.sharedPref.getString(address, null))
}
}
}
}
...
override fun onPause() {
super.onPause()
// TODO: Fix this line to resolve an initialization error
data.saveSharedPreference()
}
ScanResultAdapter
...
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
if (items[position].device.name == "EES-TEMP-1") {
val item = items[position]
if (!data.names.contains(item.device.address)) {
data.names[item.device.address] = item.device.name
data.sharedPref.edit().putString(item.device.address, item.device.name).apply()
}
println(data.names)
holder.bind(item)
} else return
}
...
inner class ViewHolder(
private val view: View,
private val onClickListener: ((device: ScanResult) -> Unit)
) : RecyclerView.ViewHolder(view) {
...
with(view) {
if (data.hasName(result.device.address) && !device_name.hasFocus()) {
device_name.setText(data.getName(result.device.address))
} else if (!data.hasName(result.device.address) && !device_name.hasFocus()) {
device_name.setText(result.device.address)
}
}
Data
class Data(private val context: Context) {
companion object {
private var instance: Data? = null
fun getInstance(context: Context): Data {
return instance ?: synchronized(this) {
instance ?: Data(context.applicationContext).also { instance = it }
}
}
}
val names: MutableMap<String, String> = mutableMapOf()
val sharedPref: SharedPreferences = context.getSharedPreferences("MySharedPreferencesFile", Context.MODE_PRIVATE)
val addresses = mutableSetOf<String>()
fun saveSharedPreference() {
sharedPref.edit {
for ((key, value) in names) {
if (!sharedPref.contains(key)) {
putString(key, value)
apply()
}
}
}
}
fun getName(address: String): String? {
if (sharedPref.contains(address)) {
return sharedPref.getString(address, "Unnamed")
}
return "failed"
}
fun hasName(key: String): Boolean {
return sharedPref.contains(key)
}
fun addName(key: String, value: String) {
names[key] = value
}
fun addAddress(address: String) {
addresses.add(address)
}
fun addItem(address: String, name: String) {
sharedPref.edit().putString(address, name).apply()
}
}