Instruções Gerais:

  • Resolva as atividades em ordem progressiva de maturidade.
  • Cada nível adiciona requisitos técnicos, tratamento de erros e casos de borda reais.
  • Consulte o gabarito comentado ao final de cada questão para autoavaliação.

🎯 Nível 1: Fundamentos

Problema 14.1 — Gravação e Leitura Assíncrona com Preferences DataStore

Contexto: Gravação e Leitura Assíncrona com Preferences DataStore no contexto de Armazenamento de Preferências com Jetpack DataStore.

Requisitos de Execução:

  1. Salvar flag de tema escuro no Preferences DataStore utilizando edit { preferences -> ... }.

Resultado Esperado

Preferência de usuário persistida no DataStore.

📤 Instruções de Entrega (Microsoft Teams)

  1. Salve o arquivo como: Atividade_14_1_SeuNome
  2. Envie na tarefa: Atividade Cap 14 - Armazenamento de Preferências com Jetpack DataStore
🔑 Gabarito de Código & Solução Comentada
package com.empresa.mobile.data

import android.content.Context
import androidx.datastore.preferences.core.booleanPreferencesKey
import androidx.datastore.preferences.core.edit
import androidx.datastore.preferences.preferencesDataStore
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map

val Context.dataStore by preferencesDataStore(name = "config_usuario")

class PreferenciasRepository(private val context: Context) {
    private val CHAVE_DARK_MODE = booleanPreferencesKey("dark_mode")

    val darkModeFlow: Flow<Boolean> = context.dataStore.data.map { it[CHAVE_DARK_MODE] ?: false }

    suspend fun setDarkMode(ativo: Boolean) {
        context.dataStore.edit { it[CHAVE_DARK_MODE] = ativo }
    }
}

🔍 Nível 2: Prática

Problema 14.2 — Tratamento de Exceções de I/O no DataStore com catch

Contexto: Tratamento de Exceções de I/O no DataStore com catch no contexto de Armazenamento de Preferências com Jetpack DataStore.

Requisitos de Execução:

  1. Proteger fluxo do DataStore contra corrupção de arquivos emitindo emptyPreferences() em caso de falha.

Resultado Esperado

Leitura de preferências com resiliência a falhas de I/O.

📤 Instruções de Entrega (Microsoft Teams)

  1. Salve o arquivo como: Atividade_14_2_SeuNome
  2. Envie na tarefa: Atividade Cap 14 - Armazenamento de Preferências com Jetpack DataStore
🔑 Gabarito de Código & Solução Comentada
package com.empresa.mobile.data

import androidx.datastore.preferences.core.emptyPreferences
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.catch
import java.io.IOException

fun <T> Flow<T>.comTratamentoErro(): Flow<T> = this.catch { exception ->
    if (exception is IOException) {
        println("Erro de leitura no DataStore: ${exception.message}")
    } else {
        throw exception
    }
}

⚡ Nível 3: Integração

Problema 14.3 — Proto DataStore Tipado com Serializador Kotlinx

Contexto: Proto DataStore Tipado com Serializador Kotlinx no contexto de Armazenamento de Preferências com Jetpack DataStore.

Requisitos de Execução:

  1. Definir data class @Serializable de configurações e criar Serializer<Configuracoes> para persistência.

Resultado Esperado

Armazenamento de configurações fortemente tipadas com Proto DataStore.

📤 Instruções de Entrega (Microsoft Teams)

  1. Salve o arquivo como: Atividade_14_3_SeuNome
  2. Envie na tarefa: Atividade Cap 14 - Armazenamento de Preferências com Jetpack DataStore
🔑 Gabarito de Código & Solução Comentada
package com.empresa.mobile.data

import androidx.datastore.core.Serializer
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json
import java.io.InputStream
import java.io.OutputStream

@Serializable
data class AppSettings(val token: String = "", val sincronizacaoAutomatica: Boolean = true)

object AppSettingsSerializer : Serializer<AppSettings> {
    override val defaultValue: AppSettings = AppSettings()
    override suspend fun readFrom(input: InputStream): AppSettings =
        Json.decodeFromString(AppSettings.serializer(), input.readBytes().decodeToString())
    override suspend fun writeTo(t: AppSettings, output: OutputStream) =
        output.write(Json.encodeToString(AppSettings.serializer(), t).encodeToByteArray())
}

🏆 Nível 4: Desafio Corporativo

Problema 14.4 — Criptografia de Dados Sensíveis com Encrypted DataStore

Contexto: Criptografia de Dados Sensíveis com Encrypted DataStore no contexto de Armazenamento de Preferências com Jetpack DataStore.

Requisitos de Execução:

  1. Proteger tokens JWT e credenciais integrando Android KeyStore ao fluxo de persistência local.

Resultado Esperado

Cofre de credenciais seguro criptografado com chave de hardware.

📤 Instruções de Entrega (Microsoft Teams)

  1. Salve o arquivo como: Atividade_14_4_SeuNome
  2. Envie na tarefa: Atividade Cap 14 - Armazenamento de Preferências com Jetpack DataStore
🔑 Gabarito de Código & Solução Comentada
package com.empresa.mobile.security

import android.security.keystore.KeyGenParameterSpec
import android.security.keystore.KeyProperties

fun gerarParametrosCriptografia(): KeyGenParameterSpec {
    return KeyGenParameterSpec.Builder("ChaveMestraApp", KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT)
        .setBlockModes(KeyProperties.BLOCK_MODE_GCM)
        .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
        .build()
}

fun main() {
    println("Configuracao de seguranca KeyStore validada.")
}

⬅️ Voltar ao Índice de Exercícios 📚 Sumário de Tópicos