@@ -116,6 +116,31 @@ export interface PackagesInfo {
116116 uid : number ; // 应用 UID
117117}
118118
119+ const ANDROID_UID_PER_USER = 100000 ;
120+
121+ /**
122+ * 合并 KernelSU 在应用分身场景下返回的重复记录。
123+ * 同一包名在不同 Android 用户中仍分别保留,与 userId:packageName 配置格式一致。
124+ */
125+ const normalizePackagesInfo = ( infos : PackagesInfo [ ] ) : PackagesInfo [ ] => {
126+ const unique = new Map < string , PackagesInfo > ( ) ;
127+
128+ infos . forEach ( info => {
129+ if ( ! info || typeof info . packageName !== 'string' || ! Number . isInteger ( info . uid ) || info . uid < 0 ) return ;
130+
131+ const packageName = info . packageName . trim ( ) ;
132+ if ( ! packageName ) return ;
133+
134+ const userId = Math . floor ( info . uid / ANDROID_UID_PER_USER ) ;
135+ const key = `${ userId } :${ packageName } ` ;
136+ if ( ! unique . has ( key ) ) {
137+ unique . set ( key , { ...info , packageName } ) ;
138+ }
139+ } ) ;
140+
141+ return Array . from ( unique . values ( ) ) ;
142+ } ;
143+
119144// ===================================================================
120145// 三、模块 CLI 调用
121146// ===================================================================
@@ -278,7 +303,7 @@ export const getAppIconUrl = (packageName: string): string => {
278303/**
279304 * 获取已安装应用列表(含名称 / 版本 / UID / 是否系统应用)。
280305 * 真机直接走 KernelSU 原生 listPackages + getPackagesInfo(无 pm fork、有类型)。
281- * 注:原生 API 仅返回主用户应用;不含工作资料 / 应用分身等多用户条目 。
306+ * KernelSU 在部分应用分身环境中可能返回重复条目,结果会按用户与包名归一化 。
282307 * 非真机环境返回 mock 列表。
283308 * @param filter 'user' | 'system' | 'all'(默认 'all')
284309 * @returns Promise<PackagesInfo[]>
@@ -304,8 +329,8 @@ export const getAppPackagesList = async (filter: 'user' | 'system' | 'all' = 'al
304329 const infos = getPackagesInfo ( names ) as PackagesInfo [ ] ;
305330 if ( ! infos ) return [ ] ;
306331
307- // 3. 过滤掉无效条目(getPackagesInfo 对找不到的包返回 {packageName, error})
308- return infos . filter ( info => info && info . packageName && typeof info . uid === 'number' ) ;
332+ // 3. 过滤无效条目,并合并同一用户下重复的应用分身记录
333+ return normalizePackagesInfo ( infos ) ;
309334 } catch ( err ) {
310335 console . error ( 'Failed to query apps via KernelSU listPackages/getPackagesInfo:' , err ) ;
311336 return [ ] ;
0 commit comments