更新记录
1.0.0(2026-08-27) 下载此版本
首发版本。
功能
- 获取安卓设备已安装应用列表,支持
all(全部)/system(系统应用)/user(用户应用)三种筛选 - 获取单个应用信息(按包名查询)
- 返回字段:应用名称、包名、版本名称、版本号、是否系统应用、是否启用、应用图标本地路径(
file:///) - 应用图标自动提取并缓存(缩放至 96px + 按包名命名,二次查询复用)
- 全部耗时操作在后台 IO 线程执行,主线程不卡顿、杜绝 ANR 闪退
说明
- 支持平台:Android(仅 App 端)
- 无三方依赖,仅使用 Android 系统 API
- 需自定义基座运行(插件声明
QUERY_ALL_PACKAGES权限,Android 11+ 查询全部应用必需)
平台兼容性
uni-app x(4.66)
| Chrome | Safari | Android | iOS | 鸿蒙 | 微信小程序 |
|---|---|---|---|---|---|
| × | × | 5.0 | × | × | × |
其他
| 多语言 | 暗黑模式 | 宽屏模式 |
|---|---|---|
| √ | √ | √ |
losfer-appinfo 安卓应用信息列表插件
适用于 uni-app x(HBuilderX 4.66+,Android 平台),获取安卓设备已安装应用列表与应用详细信息。
获取手机中全部应用 / 系统应用 / 用户应用的列表,以及单个应用的信息,包括:应用图标、名称、包名、版本名称、版本号、是否系统应用、是否启用。
- 插件类型:UTS 插件(API)
- 支持平台:Android(仅 App 端)
- 无任何三方依赖,原生代码仅使用 Android 系统 API
- 所有耗时操作(遍历应用、读取版本号、压缩图标)均在后台线程执行,不会卡死主线程,杜绝闪退
一、功能特性
| 功能 | 说明 |
|---|---|
| 🔍 获取已安装应用列表 | 支持筛选:all 全部 / system 系统应用 / user 用户应用 |
| 📦 单个应用信息 | 根据包名查询单个应用详情 |
| 🖼️ 应用图标 | 自动提取应用图标并缓存到本地(file:/// 路径,可直接用于 <image>) |
| 📄 详细信息 | 应用名称、包名、版本名称、版本号(versionCode)、是否系统应用、是否启用 |
| ⚡ 异步执行 | 全部耗时操作在后台 IO 线程执行,主线程不卡顿 |
| 🚀 高性能 | 图标统一缩放至 96px + 按包名缓存,二次查询直接复用,零重复压缩 |
二、安装引入
将 uni_modules/losfer-appinfo 目录复制到项目 uni_modules/ 下即可。
在 .uvue 页面中引入:
// #ifdef APP-ANDROID
import { getInstalledApps, getAppInfo, AppInfo,
GetInstalledAppsOptions, GetInstalledAppsResult,
GetInstalledAppsFail, GetAppInfoOptions } from '@/uni_modules/losfer-appinfo'
// #endif
建议使用条件编译
#ifdef APP-ANDROID,插件仅支持安卓端 App。
三、API 说明
1. 获取已安装应用列表 getInstalledApps(options)
getInstalledApps(options : GetInstalledAppsOptions) : void
参数 options:
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
| type | string | 是 | 应用类型筛选:'all' 全部 / 'system' 系统应用 / 'user' 用户应用 |
| success | (res: GetInstalledAppsResult) => void | 否 | 成功回调 |
| fail | (err: GetInstalledAppsFail) => void | 否 | 失败回调 |
success 返回值 res:
{
list: Array<AppInfo>
}
2. 获取单个应用信息 getAppInfo(options)
getAppInfo(options : GetAppInfoOptions) : void
参数 options:
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
| packageName | string | 是 | 应用包名 |
| success | (res: AppInfo) => void | 否 | 成功回调 |
| fail | (err: GetInstalledAppsFail) => void | 否 | 失败回调 |
3. 数据结构
AppInfo(单个应用信息):
| 字段 | 类型 | 说明 |
|---|---|---|
| packageName | string | 应用包名(唯一标识) |
| appName | string | 应用名称 |
| versionName | string | 版本名称,如 1.0.0 |
| versionCode | number | 版本号(versionCode) |
| isSystemApp | boolean | 是否系统应用 |
| enabled | boolean | 是否处于启用状态 |
| iconPath | string | 应用图标本地路径(file:/// 格式),可直接用于 <image :src> |
GetInstalledAppsFail(失败信息):
| 字段 | 类型 | 说明 |
|---|---|---|
| errCode | number | 错误码 |
| errMsg | string | 错误描述 |
错误码:
| errCode | 说明 |
|---|---|
| 1002 | type 参数不合法,仅支持 all / system / user |
| 1003 | packageName 不能为空 |
| 1004 | 未找到指定包名的应用 |
四、使用示例
示例 1:获取全部应用列表并展示
<template>
<view class="page">
<button @click="loadApps">获取全部应用</button>
<view class="app-item" v-for="item in appList" :key="item.packageName">
<image class="app-icon" :src="item.iconPath"></image>
<view class="app-info">
<text class="app-name">{{ item.appName }}</text>
<text class="app-pkg">{{ item.packageName }} v{{ item.versionName }}</text>
</view>
<text class="app-tag">{{ item.isSystemApp ? '系统' : '用户' }}</text>
</view>
</view>
</template>
<script setup lang="uts">
import { ref } from 'vue'
// #ifdef APP-ANDROID
import { getInstalledApps, AppInfo,
GetInstalledAppsOptions, GetInstalledAppsResult,
GetInstalledAppsFail } from '@/uni_modules/losfer-appinfo'
// #endif
const appList = ref<Array<AppInfo>>([])
function loadApps() {
// #ifdef APP-ANDROID
const opts : GetInstalledAppsOptions = {
type: 'all',
success: (res : GetInstalledAppsResult) => {
appList.value = res.list
console.log('获取到 ' + res.list.length + ' 个应用')
},
fail: (err : GetInstalledAppsFail) => {
console.log('获取失败: ' + err.errMsg)
}
}
getInstalledApps(opts)
// #endif
}
</script>
<style>
.page { flex-direction: column; padding: 20rpx; }
.app-item { flex-direction: row; align-items: center; padding: 16rpx 0; }
.app-icon { width: 72rpx; height: 72rpx; border-radius: 12rpx; margin-right: 20rpx; }
.app-info { flex: 1; flex-direction: column; }
.app-name { font-size: 15px; font-weight: bold; }
.app-pkg { font-size: 12px; color: #888; margin-top: 4rpx; }
.app-tag { font-size: 12px; color: #409eff; }
</style>
示例 2:筛选系统应用 / 用户应用
// 仅系统应用
getInstalledApps({
type: 'system',
success: (res : GetInstalledAppsResult) => { /* ... */ }
})
// 仅用户应用
getInstalledApps({
type: 'user',
success: (res : GetInstalledAppsResult) => { /* ... */ }
})
示例 3:查询单个应用信息
// #ifdef APP-ANDROID
const opts : GetAppInfoOptions = {
packageName: 'cn.losfer.aitools',
success: (info : AppInfo) => {
console.log(info.appName, info.versionName, info.iconPath)
},
fail: (err : GetInstalledAppsFail) => {
uni.showToast({ title: err.errMsg, icon: 'none' })
}
}
getAppInfo(opts)
// #endif
五、典型案例页面代码
以下为「应用管理」页完整代码,演示:类型切换、列表获取、图标展示、单包名精确查询。
<template>
<view class="page">
<!-- 类型切换 -->
<view class="filter-bar">
<text :class="type == 'all' ? 'filter-item active' : 'filter-item'" @click="setType('all')">全部</text>
<text :class="type == 'system' ? 'filter-item active' : 'filter-item'" @click="setType('system')">系统</text>
<text :class="type == 'user' ? 'filter-item active' : 'filter-item'" @click="setType('user')">用户</text>
</view>
<!-- 应用列表 -->
<scroll-view class="list" :scroll-y="true">
<view class="app-item" v-for="(item, index) in appList" :key="item.packageName">
<image class="app-icon" :src="item.iconPath"></image>
<view class="app-info">
<text class="app-name">{{ item.appName }}</text>
<text class="app-pkg">{{ item.packageName }}</text>
<text class="app-ver">版本:{{ item.versionName }}({{ item.versionCode }})</text>
</view>
<view class="app-right">
<text :class="item.isSystemApp ? 'tag tag-system' : 'tag tag-user'">
{{ item.isSystemApp ? '系统' : '用户' }}
</text>
<text :class="item.enabled ? 'tag tag-on' : 'tag tag-off'">
{{ item.enabled ? '已启用' : '已禁用' }}
</text>
</view>
</view>
<view class="empty" v-if="appList.length == 0">
<text class="empty-text">暂无数据,点击获取</text>
</view>
</scroll-view>
<!-- 底部操作栏 -->
<view class="bottom-bar">
<button type="primary" @click="loadApps">获取列表</button>
<button @click="clearList">清空</button>
</view>
</view>
</template>
<script setup lang="uts">
import { ref } from 'vue'
// #ifdef APP-ANDROID
import { getInstalledApps, AppInfo,
GetInstalledAppsOptions, GetInstalledAppsResult,
GetInstalledAppsFail } from '@/uni_modules/losfer-appinfo'
// #endif
const type = ref<string>('all')
const appList = ref<Array<AppInfo>>([])
function setType(t : string) {
type.value = t
loadApps()
}
function loadApps() {
// #ifdef APP-ANDROID
const opts : GetInstalledAppsOptions = {
type: type.value,
success: (res : GetInstalledAppsResult) => {
appList.value = res.list
uni.showToast({ title: '共 ' + res.list.length + ' 个应用', icon: 'none' })
},
fail: (err : GetInstalledAppsFail) => {
uni.showToast({ title: err.errMsg, icon: 'none' })
}
}
getInstalledApps(opts)
// #endif
}
function clearList() {
appList.value = []
}
</script>
<style>
.page { flex: 1; flex-direction: column; background-color: #f7f8fa; }
.filter-bar { flex-direction: row; padding: 20rpx; }
.filter-item { margin-right: 30rpx; font-size: 14px; color: #666; }
.filter-item.active { color: #409eff; font-weight: bold; }
.list { flex: 1; padding: 0 20rpx; }
.app-item {
flex-direction: row;
align-items: center;
background-color: #fff;
border-radius: 16rpx;
padding: 20rpx;
margin-bottom: 16rpx;
}
.app-icon { width: 80rpx; height: 80rpx; border-radius: 14rpx; margin-right: 20rpx; }
.app-info { flex: 1; flex-direction: column; }
.app-name { font-size: 15px; font-weight: bold; color: #222; }
.app-pkg { font-size: 12px; color: #888; margin-top: 4rpx; }
.app-ver { font-size: 12px; color: #aaa; margin-top: 4rpx; }
.app-right { flex-direction: column; align-items: flex-end; }
.tag { font-size: 11px; padding: 4rpx 12rpx; border-radius: 8rpx; margin-top: 6rpx; }
.tag-system { color: #e6a23c; background-color: #fdf6ec; }
.tag-user { color: #409eff; background-color: #ecf5ff; }
.tag-on { color: #67c23a; background-color: #f0f9eb; }
.tag-off { color: #909399; background-color: #f4f4f5; }
.empty { align-items: center; padding: 80rpx 0; }
.empty-text { color: #bbb; }
.bottom-bar { flex-direction: row; justify-content: space-between; padding: 20rpx; }
</style>
六、运行要求
- HBuilderX 4.66+,uni-app x 项目,Android 平台
- 下列插件模块依赖原生配置或使用了
QUERY_ALL_PACKAGES权限,需要自定义基座才能生效:AndroidManifest.xml声明了android.permission.QUERY_ALL_PACKAGES(Android 11+ 查询所有已安装应用必需)- 首次在真机调试:HBuilderX 菜单「运行 → 运行到手机或模拟器 → 制作自定义调试基座」,安装自定义基座后运行
- 不依赖任何三方 SDK,云端打包无需额外配置
⚠️ Android 11(API 30)及以上:查询所有已安装应用需要
QUERY_ALL_PACKAGES权限。Google Play 对该权限有合规审核要求,若仅用于系统工具类 App 通常可过审;企业内部应用(AAB 私发)不受影响。
七、FAQ
Q1:为什么点击获取后列表为空?
- 确认已使用自定义基座运行(插件声明了原生权限)
- Android 11+ 确认已安装
QUERY_ALL_PACKAGES权限 - 查看 HBuilderX 控制台筛选插件日志
[losfer-appinfo]
Q2:图标不显示?
iconPath为file:///本地路径,<image>组件支持该格式- 首次生成图标需要几秒(后台线程),列表会先返回、图标路径待文件写入后即可使用
- 缓存目录在应用外部/内部缓存目录(
app_icons/),清缓存后会自动重新生成
Q3:会不会卡死 App?
- 不会。所有耗时操作在后台 IO 线程执行,主线程只负责收结果刷新界面
Q4:为什么有的应用版本号为 0?
- 部分系统内置应用(如系统设置)无法读取版本信息,属正常现象
八、更新日志
| 版本 | 说明 |
|---|---|
| 1.0.0 | 首发:获取应用列表(all/system/user)、单个应用信息、图标缓存、后台线程异步执行 |

收藏人数:
下载插件并导入HBuilderX
赞赏(0)
下载 27
赞赏 0
下载 12539660
赞赏 1947
赞赏
京公网安备:11010802035340号