SkillAgentSearch skills...

Ksprefs

Kotlin SharedPreferences wrapper & cryptographic android library.

Install / Use

/learn @cioccarellia/Ksprefs

README

<p align="center"> <a href="https://github.com/cioccarellia/ksprefs" target="_blank"><img width="100" src="https://raw.githubusercontent.com/cioccarellia/ksprefs/master/extras/ksprefs.png"></a> </p> <h1 align="center">KsPrefs</h1> <p align="center">Secure SharedPreferences</p> <p align="center"> <a href="https://search.maven.org/artifact/com.github.cioccarellia/ksprefs"><img src="https://img.shields.io/maven-central/v/com.github.cioccarellia/ksprefs.svg?label=Maven%20Central" alt="Download from MavenCentral"></a> <a href="https://app.codacy.com/manual/cioccarellia/ksprefs/dashboard"><img src="https://api.codacy.com/project/badge/Grade/f10cdbdbe7b84d0ea7a03b755c104e03" alt="Codacy"></a> <a href="https://kotlinlang.org/docs/releases.html"><img src="https://img.shields.io/badge/kotlin-1.9.22-orange.svg" alt="Kotlin"></a> <a href="https://source.android.com/setup/start/build-numbers"><img src="https://img.shields.io/badge/min-19-00e676.svg" alt="Android Min Sdk"></a> <a href="https://source.android.com/setup/start/build-numbers"><img src="https://img.shields.io/badge/compile-34-00e676.svg" alt="Android Compile Version"></a> <a href="https://github.com/cioccarellia/ksprefs/blob/master/LICENSE.md"><img src="https://img.shields.io/badge/license-Apache%202.0-blue.svg" alt="License"></a> </p> <details open><summary>Gradle</summary>
dependencies {
    implementation 'com.github.cioccarellia:ksprefs:2.4.1'
}
</details> <details><summary>Kotlin DSL</summary>
dependencies {
    implementation("com.github.cioccarellia:ksprefs:2.4.1")
}
</details> <details><summary>Maven</summary>
<dependency>
    <groupId>com.github.cioccarellia</groupId>
    <artifactId>ksprefs</artifactId>
    <version>2.4.1</version>
    <type>pom</type>
</dependency>
</details>
  • Powerful SharedPreferences wrapper & API.
  • Easy to pick up & use right away.
  • Tested and production-ready.
  • Fully customizable behaviour.
  • Built-in cryptography & decoding engines (PlainText, Base64, AES-CBC, AES-ECB, Android KeyStore + AES-GCM / RSA KeyPair).
  • Extensive type & enum support.
val prefs = KsPrefs(applicationContext)
val count = prefs.pull<Int>("app_start_key")

To read from SharedPreferences, use pull(key, fallback).<br> To write to SharedPreferences, use push(key, value).

Introduction

<img src="https://raw.githubusercontent.com/cioccarellia/ksprefs/master/extras/dark/png/scheme.png"><br><br> KsPrefs (<b>K</b>otlin <b>S</b>hared <b>Pref</b>erences) is a wrapper for the default Android SharedPreferences (SP for short) implementation.<br> Its purposes are to bring security to preference storage through cryptography, to implement an elegant and practical SP API, and to do so with as little overhead as possible.<br> Ksprefs can be used as a replacement of direct SP usage, which lacks both security and practicality, and which even Google is moving away from with Jetpack DataStore.<br> On top of the SP API, KsPrefs extends with numerous features and extra bits which come pre-packed with the library, and can be used to enhance the development experience and productivity.

Basics

Initialization

You should create KsPrefs only once in your codebase.

val prefs = KsPrefs(applicationContext)

It is recommended to keep it inside your Application class, so that it's reachable everywhere from your code.

class App : Application() {

    companion object {
        lateinit var appContext: Context
        val prefs by lazy { KsPrefs(appContext) }
    }

    override fun onCreate() {
        super.onCreate()
        appContext = this
    }
}

Terminology

| Term | Description | |------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------| | SP | Android Shared Preferences | | Entry | Key-Value pair stored by SP. Thus the basic data entity which can be pushed and pulled | | Persistent XML Storage | SP XML file containing actual entries. Stored in the application private storage | | | | | | |

Read <small>(Pull)</small>

To retrieve saved values from SP you use pull().<br> Key uniquely identifies a record, fallback is the default value if none is found in SP.

val uname = prefs.pull(key = "username", fallback = nobody)

There are 4 different variants of pull. <!-- helo -->

  • pull<T>(key, fallback<T>): Scans the preferences with the given key. If a record is found, the value is read from the persistent XML storage, deserialized as the requested type and returned. If the key isn't contained inside the storage, the fallback value is returned.
  • pull<T>(key): No fallback value is supplied
  • pull<T>(key, kclass<T>)
  • pull<T>(key, jclass<T>)

A function is defined safe when you supply the fallback (Android SharedPreferences defines it default) value, so that, for any given key, you always have a concrete in-memory value to return.<br> A function is unsafe because there is no guarantee it will return a concrete value, as it only relies on the supplied key to pull the value from the persistent XML storage<br>

Even though the standard SharedPreferences API always forces you to provide a default (KsPrefs defines it fallback) value, KsPrefs allows you to leave that out, because supplying an actual instance of an object, in some contexts is verbose and redundant if you are know that the key is present inside the persistent storage, or if for some clever intuition you know that the key holds a value at some specific time.

val username = prefs.pull("username")

:pushpin: #1: Using an unsafe version of pull() isn't dangerous, as long as you are sure the target key holds a value.<br> :pushpin: #2: The 3 unsafe functions accept the type parameter as a kotlin class, as a java class or as a kotlin generic. For the latter, the bytecode of the function is inlined, in order for the generic type to be reified.<br>

Write <small>(Push)</small>

To save values to the preference storage you use push()<br> Push takes a key and a value, and stores them inside the preferences, according to the commitStrategy, autoSavePoliciy.

prefs.push("username", viewModel.username)

Configuration

KsPrefs is configurable at initialization time with specific parameters.<br> Each parameters has a default value which will be used unless you specify otherwise.<br> Each parameter changes the internal behaviour and the algorithms used, so it is vital to choose the appropriate settings.<br>

val prefs = KsPrefs(applicationContext) {
    // Configuration Parameters Lambda
    encryptionType = PlainText()
    autoSave = AutoSavePolicy.MANUAL
    commitStrategy = CommitStrategy.COMMIT
}

| Field | Type | Description | Default Value | |----------------|----------------|-----------------------------------------------------------------------------------------------------------------------------------|--------------------------| | encryptionType | EncryptionType | Encryption technique used to encrypt and decrypt data | PlainText() | | commitStrategy | CommitStrategy | Strategy to use at the moment of writing preferences entries to the persistent XML storage | CommitStrategy.APPLY | | autoSave | AutoSavePolicy | Whether after a push() operation changes are saved to the persistent XML storage; saving strategy depending on commitStrategy | AutoSavePolicy.AUTOMATIC | | mode | Int | SharedPreferences access mode | Context.MODE_PRIVATE | | charset | Charset | Charset used for string-to-byte and byte-to-string conversions | Charsets.UTF_8 | | keyRegex | Regex? | Regular Expression which, if non null, every key must match. | null |

Saving, Auto Save Policies & Commit Strategies

A pending transaction is a change which is registered in-memory, but not yet on the XML preference file. Android SharedPreferences works that way; indeed, you can stack up pending transactions, but at some point you have to actually save them. If the app were to shut down unexpectedly, those changes would be lost.<br> To commit any pending transaction to the persistent XML storage, in ksprefs you use save(). This matches commit() and apply() SharedPreferences behaviour you may be accustomed to.<br>

Auto Save Policy

By default, autoSave is set to AutoSavePolicy.AUTOMATIC, and therefore changes are automatically synchronized with

View on GitHub
GitHub Stars228
CategoryDevelopment
Updated1mo ago
Forks22

Languages

Kotlin

Security Score

100/100

Audited on Feb 26, 2026

No findings