如果没有使用SP来存储数据,而是用datastore的话
但是datastore存储是个文件,所以我们需要再加密。
先展示没有加密的存储方式,然后再结合上一节的加密,再将存储的数据进行加密
使用datastore存储数据
添加依赖库
implementation "androidx.datastore:datastore-preferences:1.0.0" implementation 'org.jetbrains.kotlinx:kotlinx-serialization-json:1.3.2'
定义数据类型
定义data class,添加 @Serializable 标签
@Serializable
data class UserSettings(
val username: String? = null,
val password: String? = null
)
定义Serializer
这里先展示没有加密的的序列化
存储的时候,将实例值转换成json string,再转换成bytearray写出到输出流,就可以保存到datastore的文件上了
读取的时候,从输入流中读取转成json string, 再通过json解析成 UserSetting实例
//继承datastore的Serializer,类型是我们定义的UserSettings
@RequiresApi(Build.VERSION_CODES.M)
class UserSettingsSerializer() : Serializer<UserSettings> {
override val defaultValue: UserSettings
get() = UserSettings()
override suspend fun readFrom(input: InputStream): UserSettings {
//将输入端的内容先转换成string
//再将string通过json的解析再转换成UserSettings
return try {
Json.decodeFromString(
deserializer = UserSettings.serializer(),
string = inputStreamToByteArray(input).decodeToString()//decryptedBytes.decodeToString()
)
} catch(e: SerializationException) {
e.printStackTrace()
defaultValue
}
}
private fun inputStreamToByteArray(inputStream: InputStream): ByteArray {
val dataInputStream = DataInputStream(inputStream)
val byteArrayOutputStream = ByteArrayOutputStream()
val buffer = ByteArray(1024)
var length: Int
while ((dataInputStream.read(buffer).also { length = it }) != -1) {
byteArrayOutputStream.write(buffer, 0, length)
}
return byteArrayOutputStream.toByteArray()
}
override suspend fun writeTo(t: UserSettings, output: OutputStream) {
//把值为t的UserSettings,通过序列化转换成json string,再写出到输出流
val bytes =Json.encodeToString(serializer=UserSettings.serializer(), value = t)
.encodeToByteArray()
output.write(bytes)
}
}
初始化datastroe
datastore的文件名,传入我们前面定义的普通的序列化器UserSettingsSerializer,
定义的是Context.dataStore,这在Context中都可以访问到datastore。例如activity中就可以直接使用datastore
private val Context.dataStore by dataStore(
fileName = "user-settings.json",
serializer = UserSettingsSerializer()
)
跟新数据到datastore
dataStore.updateData {
UserSettings(
username = username,
password = password
)
}
读取数据
settings = dataStore.data.first()
直接就可以读取到 UserSetting类型的数据
查看文件
从data-data-packagename下可以看到文件
直接可以看到JSON格式的内容,这样就不是很安全,所以,存储到datastore中的内容需要加密
这个就连接上一篇中的AES加密
https://blog.csdn.net/github_35581409/article/details/142894715
只要对UserSettingsSerializer进行改造,在写入的时候,把JSON string进行加密
在读取的时候,先对string解密,然后再JSON解析
加密改造
添加加密管理
class UserSettingsSerializer(
private val cryptoManager: CryptoManager //添加加密管理
) : Serializer<UserSettings>
写入
写入的时候,将实例值通过json编码,然后转换成byte。然后再通过cryptoManager进行加密,再写入输出流,输出流会把加密后的数据存储到datastore的文件中
override suspend fun writeTo(t: UserSettings, output: OutputStream) {
cryptoManager.encrypt(
bytes = Json.encodeToString(
serializer = UserSettings.serializer(),
value = t
).encodeToByteArray(),
outputStream = output
)
// val bytes =Json.encodeToString(serializer=UserSettings.serializer(), value = t)
// .encodeToByteArray()
// output.write(bytes)
}
读取
把输入流中的内容,先进行解码,解码后的byte,在通过json组装成实例
override suspend fun readFrom(input: InputStream): UserSettings {
val decryptedBytes = cryptoManager.decrypt(input) //将输入流进行加密,生成加密后的bytes
return try {
Json.decodeFromString(
deserializer = UserSettings.serializer(),
// string = inputStreamToByteArray(input).decodeToString()
decryptedBytes.decodeToString()
)
} catch(e: SerializationException) {
e.printStackTrace()
defaultValue
}
}
在datastore初始化的时候,补上加密管理器
private val Context.dataStore by dataStore(
fileName = "user-settings.json",
serializer =UserSettingsSerializer(CryptoManager())
)
再运行看看,加解密显示没有问题,
文件内容也变成了加密的了