如果没有使用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: UserSettingsget() = UserSettings()override suspend fun readFrom(input: InputStream): UserSettings {//将输入端的内容先转换成string//再将string通过json的解析再转换成UserSettingsreturn 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: Intwhile ((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) //将输入流进行加密,生成加密后的bytesreturn 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()))
再运行看看,加解密显示没有问题,
文件内容也变成了加密的了