// Save data
val prefs = getSharedPreferences("app_prefs", Context.MODE_PRIVATE)
prefs.edit().apply {
putString("username", "Alice")
putInt("age", 30)
putBoolean("isLoggedIn", true)
apply() // Async
}
// Read data
val username = prefs.getString("username", "")
val isLoggedIn = prefs.getBoolean("isLoggedIn", false)
// DataStore (modern replacement)
val dataStore = context.createDataStore(name = "settings")
val EXAMPLE_COUNTER = intPreferencesKey("example_counter")
val exampleCounterFlow: Flow<Int> = dataStore.data.map { it[EXAMPLE_COUNTER] ?: 0 }
suspend fun incrementCounter() {
dataStore.edit { it[EXAMPLE_COUNTER] = (it[EXAMPLE_COUNTER] ?: 0) + 1 }
}
Room is the recommended abstraction layer over SQLite.
// Entity
@Entity(tableName = "notes")
data class Note(
@PrimaryKey(autoGenerate = true) val id: Int = 0,
val title: String,
val content: String,
val timestamp: Long = System.currentTimeMillis()
)
// DAO
@Dao
interface NoteDao {
@Query("SELECT * FROM notes ORDER BY timestamp DESC")
fun getAllNotes(): LiveData<List<Note>>
@Insert
suspend fun insert(note: Note)
@Update
suspend fun update(note: Note)
@Delete
suspend fun delete(note: Note)
@Query("SELECT * FROM notes WHERE id = :id")
suspend fun getNoteById(id: Int): Note?
}
// Database
@Database(entities = [Note::class], version = 1)
abstract class NoteDatabase : RoomDatabase() {
abstract fun noteDao(): NoteDao
companion object {
@Volatile
private var INSTANCE: NoteDatabase? = null
fun getInstance(context: Context): NoteDatabase {
return INSTANCE ?: synchronized(this) {
Room.databaseBuilder(
context.applicationContext,
NoteDatabase::class.java,
"note_database"
).build().also { INSTANCE = it }
}
}
}
}
// Usage
val dao = NoteDatabase.getInstance(this).noteDao()
viewModelScope.launch {
dao.insert(Note(title = "My Note", content = "Hello Room!"))
}
// Internal storage (private to the app)
fun writeToInternalFile(filename: String, content: String) {
openFileOutput(filename, Context.MODE_PRIVATE).use {
it.write(content.toByteArray())
}
}
fun readFromInternalFile(filename: String): String {
return openFileInput(filename).bufferedReader().readText()
}
// External storage (requires permission for public files)
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="28" />
fun saveToDownloads(content: String, filename: String) {
val downloadsDir = Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_DOWNLOADS
)
val file = File(downloadsDir, filename)
file.writeText(content)
}
// Scoped storage (Android 10+)
fun saveToAppSpecificExternal() {
val file = File(context.getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS), "data.txt")
file.writeText("Hello, scoped storage!")
}
// JSON with Gson/Moshi
// implementation("com.squareup.moshi:moshi-kotlin:1.15.0")
@JsonClass(generateAdapter = true)
data class User(val id: Int, val name: String, val email: String)
val moshi = Moshi.Builder().build()
val adapter = moshi.adapter(User::class.java)
// Serialize
val user = User(1, "Alice", "alice@example.com")
val json = adapter.toJson(user)
// Deserialize
val userFromJson = adapter.fromJson(json)
// XML Pull Parser
fun parseXml(xml: String) {
val parser = XmlPullParserFactory.newInstance().newPullParser()
parser.setInput(StringReader(xml))
var eventType = parser.eventType
while (eventType != XmlPullParser.END_DOCUMENT) {
if (eventType == XmlPullParser.START_TAG && parser.name == "item") {
val name = parser.getAttributeValue(null, "name")
println("Item: $name")
}
eventType = parser.next()
}
}