如何在Jetpack Compose中获取已安装应用的图标?
在Jetpack Compose中根据包名显示应用图标
步骤1:完善ViewModel,添加应用信息获取逻辑
将普通ViewModel替换为AndroidViewModel以获取上下文,同时补充获取应用图标、名称的逻辑,把包名转换为包含图标信息的实体类:
import android.app.Application import android.content.pm.PackageManager import androidx.lifecycle.AndroidViewModel import androidx.lifecycle.viewModelScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.launch import kotlinx.coroutines.withContext data class AppInfo( val packageName: String, val appName: String, val appIcon: android.graphics.drawable.Drawable? ) class MalwareListViewModel(application: Application) : AndroidViewModel(application) { private val _appInfoList = MutableStateFlow<List<AppInfo>>(emptyList()) val appInfoList: StateFlow<List<AppInfo>> = _appInfoList // 这里替换成你获取恶意软件包名的原有逻辑 private fun getMalwarePackageNames(): List<String> { return mutableListOf("com.example.test1", "com.example.test2") } fun loadAppInfo() { viewModelScope.launch { val packageNames = getMalwarePackageNames() val appInfos = withContext(Dispatchers.IO) { packageNames.mapNotNull { packageName -> try { val packageManager = getApplication<Application>().packageManager val appInfo = packageManager.getApplicationInfo(packageName, 0) AppInfo( packageName = packageName, appName = packageManager.getApplicationLabel(appInfo).toString(), appIcon = packageManager.getApplicationIcon(appInfo) ) } catch (e: PackageManager.NameNotFoundException) { // 处理包名不存在的情况 null } } } _appInfoList.value = appInfos } } }
步骤2:在Compose中展示应用图标与信息
推荐使用Coil库简化Drawable的加载与显示,也可以手动转换Drawable为Bitmap:
可选:添加Coil依赖
在Module级别的build.gradle.kts中引入Coil:
implementation("io.coil-kt:coil-compose:2.5.0")
Compose UI实现代码
import androidx.compose.foundation.Image import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.collectAsState import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.asImageBitmap import androidx.compose.ui.unit.dp import coil.compose.AsyncImage import android.graphics.BitmapDrawable @Composable fun MalwareListScreen(viewModel: MalwareListViewModel) { val appInfoList = viewModel.appInfoList.collectAsState() LaunchedEffect(Unit) { viewModel.loadAppInfo() } LazyColumn(modifier = Modifier.fillMaxSize()) { items(appInfoList.value) { appInfo -> Row(modifier = Modifier.fillParentMaxWidth()) { // 方式1:用Coil加载Drawable(推荐) AsyncImage( model = appInfo.appIcon, contentDescription = appInfo.appName, modifier = Modifier.size(48.dp) ) // 方式2:手动转换Drawable为Bitmap(无需Coil) /* appInfo.appIcon?.let { drawable -> val bitmap = (drawable as BitmapDrawable).bitmap Image( bitmap = bitmap.asImageBitmap(), contentDescription = appInfo.appName, modifier = Modifier.size(48.dp) ) } */ Spacer(modifier = Modifier.width(16.dp)) Column { Text(text = appInfo.appName) Text(text = appInfo.packageName) } } } } }
注意事项
- 权限配置:Android 11及以上版本需在
AndroidManifest.xml中添加<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />,可根据目标SDK版本调整权限范围 - 异常处理:务必处理应用图标为空、包名不存在的场景,可添加默认占位图
- 异步安全:使用
viewModelScope执行IO操作,避免内存泄漏 - 工具选择:Coil会自动处理缓存、缩放等逻辑,无需手动管理Bitmap,使用更便捷
内容的提问来源于stack exchange,提问作者acrux
相关产品推荐
相关产品推荐

