feat: app repository for list and launch apps

This commit is contained in:
2026-08-16 16:08:37 +08:00
parent df0f9a2615
commit c4c19b610c
3 changed files with 75 additions and 0 deletions
@@ -0,0 +1,41 @@
package top.yeij.hearth.app
import android.content.Context
import android.content.Intent
import android.util.Log
data class AppInfo(val packageName: String, val label: String, val iconBase64: String?)
interface AppSource {
fun queryLaunchableApps(): List<AppInfo>
fun launch(packageName: String): Boolean
}
class AndroidAppSource(private val context: Context) : AppSource {
override fun queryLaunchableApps(): List<AppInfo> {
val pm = context.packageManager
val intent = Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_LAUNCHER)
return pm.queryIntentActivities(intent, 0).map { ri ->
val pkg = ri.activityInfo.packageName
AppInfo(pkg, ri.loadLabel(pm).toString(), null /* 图标 base64 在 Task 5 补 */)
}
}
override fun launch(packageName: String): Boolean {
val i = context.packageManager.getLaunchIntentForPackage(packageName) ?: return false
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
context.startActivity(i)
return true
}
}
class AppRepository(private val source: AppSource) {
private val gson = com.google.gson.Gson()
fun listApps(): String {
Log.d("HearthBridge", "listApps: ${source.queryLaunchableApps().size} apps")
return gson.toJson(source.queryLaunchableApps())
}
fun launchApp(packageName: String): Boolean = source.launch(packageName)
}
@@ -0,0 +1,21 @@
package top.yeij.hearth.app
import org.junit.Assert.assertEquals
import org.junit.Assert.assertTrue
import org.junit.Test
class AppRepositoryTest {
@Test
fun listApps_returnsLauncherAppsJson() {
val repo = AppRepository(FakeAppSource(listOf(FakeApp("com.x.music", "音乐"))))
val json = repo.listApps()
assertTrue(json.contains("\"packageName\":\"com.x.music\""))
assertTrue(json.contains("\"label\":\"音乐\""))
}
@Test
fun launchApp_unknownPackage_returnsFalse() {
val repo = AppRepository(FakeAppSource(emptyList()))
assertEquals(false, repo.launchApp("com.nope"))
}
}
@@ -0,0 +1,13 @@
package top.yeij.hearth.app
// 测试用假源:返回固定应用列表,避免依赖 Android Context/PackageManager
// Test fake source: returns a fixed app list, avoiding dependency on Android Context/PackageManager
class FakeAppSource(private val apps: List<AppInfo>) : AppSource {
override fun queryLaunchableApps(): List<AppInfo> = apps
override fun launch(packageName: String): Boolean = apps.any { it.packageName == packageName }
}
// 测试用 AppInfo 构造辅助函数
// Test helper to construct an AppInfo
fun FakeApp(packageName: String, label: String): AppInfo = AppInfo(packageName, label, null)