feat(android): add data models, DataStore settings, Application class

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Sanju Sivalingam
2026-02-17 17:40:56 +05:30
parent e22326cbd3
commit 78b605bc86
6 changed files with 228 additions and 0 deletions

View File

@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<application
android:name=".DroidClawApp"
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.DroidClaw">
<activity
android:name=".MainActivity"
android:exported="true"
android:label="@string/app_name"
android:theme="@style/Theme.DroidClaw">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>

View File

@@ -0,0 +1,14 @@
package com.thisux.droidclaw
import android.app.Application
import com.thisux.droidclaw.data.SettingsStore
class DroidClawApp : Application() {
lateinit var settingsStore: SettingsStore
private set
override fun onCreate() {
super.onCreate()
settingsStore = SettingsStore(this)
}
}

View File

@@ -0,0 +1,55 @@
package com.thisux.droidclaw.data
import android.content.Context
import androidx.datastore.core.DataStore
import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.core.booleanPreferencesKey
import androidx.datastore.preferences.core.edit
import androidx.datastore.preferences.core.stringPreferencesKey
import androidx.datastore.preferences.preferencesDataStore
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "settings")
object SettingsKeys {
val API_KEY = stringPreferencesKey("api_key")
val SERVER_URL = stringPreferencesKey("server_url")
val DEVICE_NAME = stringPreferencesKey("device_name")
val AUTO_CONNECT = booleanPreferencesKey("auto_connect")
}
class SettingsStore(private val context: Context) {
val apiKey: Flow<String> = context.dataStore.data.map { prefs ->
prefs[SettingsKeys.API_KEY] ?: ""
}
val serverUrl: Flow<String> = context.dataStore.data.map { prefs ->
prefs[SettingsKeys.SERVER_URL] ?: "wss://localhost:8080"
}
val deviceName: Flow<String> = context.dataStore.data.map { prefs ->
prefs[SettingsKeys.DEVICE_NAME] ?: android.os.Build.MODEL
}
val autoConnect: Flow<Boolean> = context.dataStore.data.map { prefs ->
prefs[SettingsKeys.AUTO_CONNECT] ?: false
}
suspend fun setApiKey(value: String) {
context.dataStore.edit { it[SettingsKeys.API_KEY] = value }
}
suspend fun setServerUrl(value: String) {
context.dataStore.edit { it[SettingsKeys.SERVER_URL] = value }
}
suspend fun setDeviceName(value: String) {
context.dataStore.edit { it[SettingsKeys.DEVICE_NAME] = value }
}
suspend fun setAutoConnect(value: Boolean) {
context.dataStore.edit { it[SettingsKeys.AUTO_CONNECT] = value }
}
}

View File

@@ -0,0 +1,30 @@
package com.thisux.droidclaw.model
enum class ConnectionState {
Disconnected,
Connecting,
Connected,
Error
}
enum class GoalStatus {
Idle,
Running,
Completed,
Failed
}
data class AgentStep(
val step: Int,
val action: String,
val reasoning: String,
val timestamp: Long = System.currentTimeMillis()
)
data class GoalSession(
val sessionId: String,
val goal: String,
val steps: List<AgentStep>,
val status: GoalStatus,
val timestamp: Long = System.currentTimeMillis()
)

View File

@@ -0,0 +1,75 @@
package com.thisux.droidclaw.model
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.JsonObject
@Serializable
data class AuthMessage(
val type: String = "auth",
val apiKey: String,
val deviceInfo: DeviceInfoMsg? = null
)
@Serializable
data class DeviceInfoMsg(
val model: String,
val androidVersion: String,
val screenWidth: Int,
val screenHeight: Int
)
@Serializable
data class ScreenResponse(
val type: String = "screen",
val requestId: String,
val elements: List<UIElement>,
val screenshot: String? = null,
val packageName: String? = null
)
@Serializable
data class ResultResponse(
val type: String = "result",
val requestId: String,
val success: Boolean,
val error: String? = null,
val data: String? = null
)
@Serializable
data class GoalMessage(
val type: String = "goal",
val text: String
)
@Serializable
data class PongMessage(
val type: String = "pong"
)
@Serializable
data class ServerMessage(
val type: String,
val requestId: String? = null,
val deviceId: String? = null,
val message: String? = null,
val sessionId: String? = null,
val goal: String? = null,
val success: Boolean? = null,
val stepsUsed: Int? = null,
val step: Int? = null,
val action: JsonObject? = null,
val reasoning: String? = null,
val screenHash: String? = null,
val x: Int? = null,
val y: Int? = null,
val x1: Int? = null,
val y1: Int? = null,
val x2: Int? = null,
val y2: Int? = null,
val duration: Int? = null,
val text: String? = null,
val packageName: String? = null,
val url: String? = null,
val code: Int? = null
)

View File

@@ -0,0 +1,26 @@
package com.thisux.droidclaw.model
import kotlinx.serialization.Serializable
@Serializable
data class UIElement(
val id: String = "",
val text: String = "",
val type: String = "",
val bounds: String = "",
val center: List<Int> = listOf(0, 0),
val size: List<Int> = listOf(0, 0),
val clickable: Boolean = false,
val editable: Boolean = false,
val enabled: Boolean = false,
val checked: Boolean = false,
val focused: Boolean = false,
val selected: Boolean = false,
val scrollable: Boolean = false,
val longClickable: Boolean = false,
val password: Boolean = false,
val hint: String = "",
val action: String = "read",
val parent: String = "",
val depth: Int = 0
)