feat: Introduce Network Functionality and Screen Time Implementation
- Implement `NetworkModule` for HTTP client management with JSON serialization.
- Add `kotlinx-serialization-json` and `ktor-client` dependencies.
- Update `Greeting` class to perform network requests to fetch and display time data.
- Add `NetworkResponse` and `TimeResponse` data classes for handling the remote API response.
- Introduce `ScreenTime` interface for platform-specific screen time data.
- Implement `ScreenTime` for Linux and Android, with basic or placeholder logic.
- Add `INTERNET` and `ACCESS_NETWORK_STATE` permissions to Android's `AndroidManifest.xml`.
- Add `ScreenTime.native.kt`, `ScreenTime.jvm.kt` and `ScreenTime.android.kt` to separate platform-specific code.
- Implement `kotlin("plugin.serialization")` plugin in shared module.
- Update dependencies.
- Add `ignoreUnknownKeys` and `coerceInputValues` for JSON serialization.
- Update `App` to display time data from remote API.
This commit is contained in:
parent
8acd72bd9e
commit
9550889bdf
@ -1,6 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<!-- 添加网络权限 -->
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<!-- 可选:访问网络状态权限 -->
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
|
||||
@ -19,15 +19,24 @@ import activityanalyzer.composeapp.generated.resources.compose_multiplatform
|
||||
fun App() {
|
||||
MaterialTheme {
|
||||
var showContent by remember { mutableStateOf(false) }
|
||||
var greetingText by remember { mutableStateOf("加载中...") }
|
||||
|
||||
LaunchedEffect(key1 = Unit) {
|
||||
greetingText = try {
|
||||
Greeting().greet()
|
||||
} catch (e: Exception) {
|
||||
"错误:${e.message}"
|
||||
}
|
||||
}
|
||||
|
||||
Column(Modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally) {
|
||||
Button(onClick = { showContent = !showContent }) {
|
||||
Text("Click me!")
|
||||
}
|
||||
AnimatedVisibility(showContent) {
|
||||
val greeting = remember { Greeting().greet() }
|
||||
Column(Modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally) {
|
||||
Image(painterResource(Res.drawable.compose_multiplatform), null)
|
||||
Text("Compose: $greeting")
|
||||
Text("Compose: $greetingText")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -6,17 +6,17 @@ android-targetSdk = "35"
|
||||
androidx-activityCompose = "1.10.1"
|
||||
androidx-appcompat = "1.7.0"
|
||||
androidx-constraintlayout = "2.2.1"
|
||||
androidx-core-ktx = "1.15.0"
|
||||
androidx-core-ktx = "1.16.0"
|
||||
androidx-espresso-core = "3.6.1"
|
||||
androidx-lifecycle = "2.8.4"
|
||||
androidx-material = "1.12.0"
|
||||
androidx-test-junit = "1.2.1"
|
||||
compose-multiplatform = "1.7.3"
|
||||
junit = "4.13.2"
|
||||
kotlin = "2.1.10"
|
||||
kotlin = "2.1.20"
|
||||
kotlinx-coroutines = "1.10.1"
|
||||
kotlinxSerializationJson = "1.6.2"
|
||||
ktorClientCore = "2.3.8"
|
||||
kotlinxSerializationJson = "1.8.0"
|
||||
ktorClientCore = "3.1.1"
|
||||
|
||||
[libraries]
|
||||
kotlin-test = { module = "org.jetbrains.kotlin:kotlin-test", version.ref = "kotlin" }
|
||||
|
||||
@ -4,6 +4,8 @@ import org.jetbrains.kotlin.gradle.dsl.JvmTarget
|
||||
plugins {
|
||||
alias(libs.plugins.kotlinMultiplatform)
|
||||
alias(libs.plugins.androidLibrary)
|
||||
|
||||
kotlin("plugin.serialization") version libs.versions.kotlin.get()
|
||||
}
|
||||
|
||||
kotlin {
|
||||
|
||||
@ -0,0 +1,8 @@
|
||||
package com.grtsinry43.activityanalyzer
|
||||
|
||||
actual fun getScreenTime(): ScreenTime {
|
||||
return object : ScreenTime {
|
||||
override val screenTime: Long
|
||||
get() = 0L // TODO: Implement the actual logic to get screen time on Android
|
||||
}
|
||||
}
|
||||
@ -8,29 +8,23 @@ import kotlinx.serialization.Serializable
|
||||
class Greeting {
|
||||
private val platform = getPlatform()
|
||||
|
||||
fun greet(): String {
|
||||
// val response: NetworkResponse =
|
||||
// NetworkModule.httpClient.get("https://wlbzx.grtsinry43.com/api/time").body()
|
||||
// println("response is : $response")
|
||||
return "Hello, ${platform.name}! "
|
||||
// +"Current time is ${response.data.time}"
|
||||
suspend fun greet(): String {
|
||||
val response: NetworkResponse =
|
||||
NetworkModule.httpClient.get("https://wlbzx.grtsinry43.com/api/time").body()
|
||||
println("response is : $response")
|
||||
return "Hello, ${platform.name}! " + "Current time is ${response.data.time}"
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable
|
||||
data class NetworkResponse(
|
||||
@SerialName("code")
|
||||
val code: Int,
|
||||
@SerialName("message")
|
||||
val message: String,
|
||||
@SerialName("data")
|
||||
val msg: String,
|
||||
val data: TimeResponse
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class TimeResponse(
|
||||
@SerialName("time")
|
||||
val time: String,
|
||||
@SerialName("count")
|
||||
val count: Int
|
||||
)
|
||||
@ -11,6 +11,8 @@ object NetworkModule {
|
||||
json(Json {
|
||||
prettyPrint = true
|
||||
isLenient = true
|
||||
ignoreUnknownKeys = true
|
||||
coerceInputValues = true // 尝试强制转换不匹配的值类型
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,12 @@
|
||||
package com.grtsinry43.activityanalyzer
|
||||
|
||||
/**
|
||||
* @author grtsinry43
|
||||
* @date 2025/4/14 16:13
|
||||
* @description 热爱可抵岁月漫长
|
||||
*/
|
||||
interface ScreenTime {
|
||||
val screenTime: Long
|
||||
}
|
||||
|
||||
expect fun getScreenTime(): ScreenTime
|
||||
@ -0,0 +1,38 @@
|
||||
package com.grtsinry43.activityanalyzer
|
||||
|
||||
import java.io.BufferedReader
|
||||
import java.io.InputStreamReader
|
||||
|
||||
/**
|
||||
* @author grtsinry43
|
||||
* @date 2025/4/14 16:30
|
||||
* @description 热爱可抵岁月漫长
|
||||
*/
|
||||
class LinuxScreenTime : ScreenTime {
|
||||
override val screenTime: Long
|
||||
get() {
|
||||
try {
|
||||
println("===")
|
||||
// Execute qdbus command to query active window information
|
||||
val process = Runtime.getRuntime().exec("qdbus org.kde.KWin /KWin queryWindowInfo")
|
||||
val reader = BufferedReader(InputStreamReader(process.inputStream))
|
||||
val output = reader.readLines()
|
||||
reader.close()
|
||||
|
||||
// Parse the output to find the caption (window title)
|
||||
val captionLine = output.find { it.trim().startsWith("caption:") }
|
||||
val windowTitle = captionLine?.substringAfter("caption:")?.trim()
|
||||
|
||||
if (windowTitle != null) {
|
||||
println("Active Window Title: $windowTitle")
|
||||
return 3600 // Example: Return dummy screen time
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
println("Failed to get active window title.")
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
actual fun getScreenTime(): ScreenTime = LinuxScreenTime()
|
||||
@ -0,0 +1,5 @@
|
||||
package com.grtsinry43.activityanalyzer
|
||||
|
||||
actual fun getScreenTime(): ScreenTime {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user