Home > front end >  Save data to local storage using Room
Save data to local storage using Room

Time:05-08

I apologize in advance if the question seems incomprehensible, since android development and kotlin are not my main stack. I will try to explain in as clear a language as possible.

I have a class that is responsible for intercepting data from HTTP-request. This implementation reflects the following code

    class PocketScoutInterceptor() : Interceptor {
    @Throws(IOException::class)
    override fun intercept(chain: Interceptor.Chain): Response {
        val timestamp = System.currentTimeMillis()
        val request: Request = chain.request()
        val requestTime = System.nanoTime()
        val response: Response = chain.proceed(request)
        val responseTime = System.nanoTime()
        val duration = ((responseTime - requestTime) / 10e6) // in milliseconds

        buildPacket(timestamp, duration, request, response)
        return response
    }

    fun buildPacket(timestamp: Long, duration: Double, request: Request, response: Response) {
        val reqBody = request.body
        val respBody = response.body?.string()

        val packet = Packet(
            id = 0,
            userId = PocketScoutConfig.userId,
            deviceId = PocketScoutConfig.deviceId,
            sessionId = PocketScoutConfig.sessionId,
            timestamp = timestamp,
            duration = duration.roundToInt(),
            protocol = "http",
            request = room.entities.Request(
                request_method = request.method,
                request_url = request.url.toUrl().toString(),
                request_headers = request.headers.toMultimap() as Mapping,
                request_body = (reqBody?.toString() ?: ""),
                request_size = (reqBody?.toString()?.length ?: 0),
            ),
            room.entities.Response(
                response_code = response.code,
                response_headers = response.headers.toMultimap() as Mapping,
                response_body = (respBody ?: ""),
                response_size = (respBody?.length ?: 0),
            )
        )
    }
}

Further, I need to save this data in a local database, I chose room. Created the following implementation:

    data class Mapping (
    val header: Map<String, List<String>>
)

data class Request(
    val request_method: String?,
    val request_url: String?,
    val request_headers: Mapping?,
    val request_body: String,
    val request_size: Int,
)

data class Response(
    val response_code: Int?,
    val response_headers: Mapping?,
    val response_body: String?,
    val response_size: Int?,
)

@Entity(
    tableName = "packets"
)
data class Packet(
    @PrimaryKey val id: Int,
    val userId: String,
    val deviceId: String,
    val sessionId: String,
    val timestamp: Long?,
    val duration: Int?,
    val protocol: String?,
    @Embedded val request: Request?,
    @Embedded val response: Response?,
)

Next I created a database class

    @TypeConverters(value = [RoomTypeConverters::class])
@Database(
    version = 1,
    entities = [Packet::class],
    exportSchema = false
)
abstract class NetworkDatabase : RoomDatabase() {
    abstract fun packetDao(): PacketDao
}

And himself Dao class that is responsible for all actions with the database

    @Dao
interface PacketDao {
    @Insert(onConflict = OnConflictStrategy.REPLACE)
    fun add(vararg packet: Packet)

    @Delete
    fun del(vararg packet: Packet)

    @Query("SELECT * FROM packets")
    fun getAll(): Array<Packet>

    @Query("SELECT * FROM packets WHERE userId LIKE :userId")
    fun findByUser(userId: String): List<Packet>

    @Query("SELECT * FROM packets WHERE sessionId LIKE :deviceId")
    fun findByDevice(deviceId: String): List<Packet>

    @Query("SELECT * FROM packets WHERE sessionId LIKE :sessionId")
    fun findBySession(sessionId: String): List<Packet>

    @Query("SELECT * FROM packets WHERE userId LIKE :userId AND deviceId LIKE :deviceId")
    fun findByUserAndDevice(userId: String, deviceId: String): List<Packet>
}

I just have to learn how to save data in local storage. I've watched several videos on this topic and read the documentation several times, but as far as my example is concerned, I can't find an answer. Maybe you can help me

CodePudding user response:

1). You need to build the database via the Room databaseBuilder function/method. The following change to the @Database annotated class would do this and would return a singleton:-

@TypeConverters(value = [RoomTypeConverters::class])
@Database(entities = [Packet::class], version = 1, exportSchema = false)
abstract class NetworkDatabase: RoomDatabase() {
    abstract fun packetDao(): PacketDao

    companion object {
        @Volatile
        private var instance: NetworkDatabase? = null;
        fun getInstance(context: Context): NetworkDatabase {
            if (instance == null) {
                instance = Room.databaseBuilder(context,NetworkDatabase::class.java,"the_database.db")
                    .allowMainThreadQueries() /* for brevity/convenience but shouldn't really run stuff on the main thread */
                    .build()
            }
            return instance as NetworkDatabase
        }
    }
}
  • Note ideally you would access the database off the main thread. However the above allows the database access to be via the main thread and thus easier to demonstrate.

2). The next stage is to actually use the above, as an example consider the following activity code (working example):-

class MainActivity : AppCompatActivity() {
    lateinit var db: NetworkDatabase
    lateinit var dao: PacketDao
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        /* Get an instance of NetworkDatabase  and the packetDao */
        db = NetworkDatabase.getInstance(this)
        dao = db.packetDao()

        /* add some data (1 row)*/
        val m1 = Mapping(header = mapOf())
        dao.add(
            Packet(
                id = 10,
                deviceId =
                "device10",
                sessionId = "session100",
                timestamp = System.currentTimeMillis(),
                protocol = "HTML",
                request = Request(requestMethod = "the method", requestUrl = "blah", requestHeaders = m1,
                    requestBody = "ReqBody", requestSize = 10),
                userId = "userxxx",
                duration = 200,
                response = Response(100,m1,"RspBody",210)
        )
        )
        /* Extract all rows and write to the log */
        for(p in dao.getAll()) {
            Log.d("DBINFO","Packet ID is ${p.id} DeviceId is ${p.deviceId} Duration is ${p.duration} ....")
        }
    }
}

The above, when run (for the first time) results in the log containing :-

D/DBINFO: Packet ID is 10 DeviceId is device10 Duration is 200 ....

Obviously you would build the Packet(s) via your Interceptor

  • Related