Launcher3 如何获取系统上的所有应用程序?

Launcher3 如何获取系统上的所有应用程序?

通过 LoaderTask

在 Launcher#onCreate 中,运行 LoaderTask。

Java 复制代码
protected void onCreate(Bundle savedInstanceState) {
    mModel.addCallbacksAndLoad(this)
}

在 LauncherModel#addCallbacksAndLoad 中,使用 HandlerThread launcher-loader 运行 LoaderTask。

Kotlin 复制代码
fun addCallbacksAndLoad(callbacks: BgDataModel.Callbacks): Boolean {
    synchronized(mLock) {
        addCallbacks(callbacks)
        return startLoader(arrayOf(callbacks))
    }
}

private fun startLoader(newCallbacks: Array<BgDataModel.Callbacks>): Boolean {
    mLoaderTask = LoaderTask(mBgAllAppsList)
    MODEL_EXECUTOR.post(mLoaderTask)
}

在 model.LoaderTask#run 中加载所有应用程序。

Java 复制代码
public class LoaderTask implements Runnable {
    public void run() {
        Trace.beginSection("LoadAllApps");
        List<LauncherActivityInfo> allActivityList;
        try {
            allActivityList = loadAllApps();
        } finally {
            Trace.endSection();
        }
    }

    private List<LauncherActivityInfo> loadAllApps() {
        final List<UserHandle> profiles = mUserCache.getUserProfiles();
        List<LauncherActivityInfo> allActivityList = new ArrayList<>();
        for (UserHandle user : profiles) {
            final List<LauncherActivityInfo> apps = mLauncherApps.getActivityList(null, user);
            allActivityList.addAll(apps);
        }
        return allActivityList;
    }
}

产生以下两个问题。

问题一:UserHandle 有哪些?

全部来自 UserCache。

Java 复制代码
UserCache mUserCache = UserCache.INSTANCE.get(mApp.getContext());
final List<UserHandle> profiles = mUserCache.getUserProfiles();

pm.UserCache#getUserProfiles

Java 复制代码
public List<UserHandle> getUserProfiles() {
    return List.copyOf(mUserToSerialMap.keySet());
}

mUserToSerialMap 里的 Key 来自哪里?

Java 复制代码
private void updateCache() {
    mUserToSerialMap = ApiWrapper.INSTANCE.get(mContext).queryAllUsers();
}

util.ApiWrapper#queryAllUsers

Java 复制代码
public Map<UserHandle, UserIconInfo> queryAllUsers() {
    UserManager um = mContext.getSystemService(UserManager.class);
    Map<UserHandle, UserIconInfo> users = new ArrayMap<>();
    List<UserHandle> usersActual = um.getUserProfiles();
    if (usersActual != null) {
        for (UserHandle user : usersActual) {
            // UserIconInfo info
            users.put(user, info);
        }
    }
    return users;
}

即通过 UserManager 获取 UserHandle。

问题二:mLauncherApps 如何获取?

Java 复制代码
LauncherApps mLauncherApps = mApp.getContext().getSystemService(LauncherApps.class);

Context#getSystemService 即通过跨进程调用。

总结

  • android.os.UserManager#getUserProfiles
  • android.content.pm.LauncherApps#getActivityList(String packageName, UserHandle user)
  • android.content.pm.LauncherActivityInfo
相关推荐
循环不息优化不止4 小时前
Ktor Pipeline 机制深度解析
android
q***56384 小时前
Springboot3学习(5、Druid使用及配置)
android·学习
q***64974 小时前
SpringSecurity踢出指定用户
android·前端·后端
q***76664 小时前
SpringSecurity 实现token 认证
android·前端·后端
Chejdj4 小时前
ViewModel#onCleared的实现原理
android·源码阅读
CheungChunChiu5 小时前
Android 系统中的 NTP 服务器配置与选择逻辑详解
android·运维·服务器
q***49865 小时前
MySQL数据的增删改查(一)
android·javascript·mysql
aqi005 小时前
FFmpeg开发笔记(九十一)基于Kotlin的Android直播开源框架RootEncoder
android·ffmpeg·kotlin·音视频·直播·流媒体
鹏多多5 小时前
flutter睡眠与冥想数据可视化神器:sleep_stage_chart插件全解析
android·前端·flutter
勇气要爆发6 小时前
【第五阶段-高级特性和架构】第三章:高级状态管理—GetX状态管理篇
android·架构