简单Launcher学习和实现

什么是Launcher

通俗理解
Launcher就是Android手机的"桌面"应用
用户按Home键看到的界面
显示所有应用图标的地方
用户与系统交互的主要入口

技术定义
特殊的Android应用,负责:
获取和显示已安装应用列表
启动其他应用程序
管理桌面布局和用户交互
处理系统级权限和API调用

关键特点:
Launcher需要在AndroidManifest.xml中声明特殊的Intent Filter,包含HOME和DEFAULT category

demo架构设计

核心组件职责分工
MainActivity:生命周期管理、服务初始化、应用加载控制
AppEntry:封装应用的包名、名称、图标等信息
AppAdapter:实现数据与UI的绑定,处理用户点击事件

com.example.launcher/ 
├── MainActivity.java # 主界面控制器 
├── AppEntry.java # 应用信息数据模型 
├── AppAdapter.java # RecyclerView适配器 
	└── layout/ 	
	├── activity_main.xml # 主界面布局     
	└── item_app.xml # 应用项布局

核心业务逻辑

Launcher的核心就在于获取应用列表以及应用的启动,这里分两点来看一下。

获取AppList

必须权限<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />
否则拿不全
方法一. 使用packageManager获取应用列表
Intent launcherIntent = new Intent(Intent.ACTION_MAIN); 
launcherIntent.addCategory(Intent.CATEGORY_LAUNCHER); 

ACTION_MAIN:表示"主入口"action;
CATEGORY_LAUNCHER:表示"桌面可启动"的类别

List<ResolveInfo> resolveInfos = pm.queryIntentActivities(
                launcherIntent, PackageManager.MATCH_ALL);

获取所有能匹配该Intent的组件信息(封装在ResolveInfo中)
MATCH_ALL flag参数:确保获取到完整的Activity信息

方法二. 使用LauncherApps API获取应用列表
特性 PackageManager LauncherApps API
最低 API 版本 API 1 API 21 (Android 5.0)
多用户支持 有限 完整支持
工作资料支持
应用图标自适应 需手动处理 自动处理
应用状态监听
快捷方式管理 有限 完整支持
权限要求 无特殊权限 需要是默认启动器

laucherApps API为launcher的开发封装了更多方法,只需要设置为默认启动器即可实现。

// 获取LauncherApps服务 
LauncherApps launcherApps = (LauncherApps)getSystemService(Context.LAUNCHER_APPS_SERVICE); 
// 获取当前用户 
UserHandle user = Process.myUserHandle(); 
// 获取所有可启动应用
List<LauncherActivityInfo> apps = launcherApps.getActivityList(null, user);

UI更新

因为获取应用列表本质上也是一个耗时操作,所以需要使用线程通信

可以看https://blog.csdn.net/giaoho/article/details/150497784?spm=1001.2014.3001.5501

public class MainActivity extends AppCompatActivity {
    // 创建与主线程关联的 Handler
    private Handler mainHandler = new Handler(Looper.getMainLooper());
    // 创建单线程池用于后台任务
    private ExecutorService executorService = Executors.newSingleThreadExecutor();
    
    private void loadApps() {
        // Step 1: 在主线程显示加载提示
        mainHandler.post(new Runnable() {
            @Override
            public void run() {
                // 这段代码在主线程执行
                emptyStateView.setText("正在加载应用...");
            }
        });
        
        // Step 2: 在后台线程执行耗时操作
        executorService.execute(new Runnable() {
            @Override
            public void run() {
                // 这段代码在后台线程执行
                List<AppEntry> apps = getInstalledApps(); // 耗时操作
                
                // Step 3: 切换回主线程更新UI
                mainHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        // 这段代码在主线程执行
                        updateAppList(apps); // 更新UI
                    }
                });
            }
        });
    }
}

Logo

纵情码海钱塘涌,杭州开发者创新动! 属于杭州的开发者社区!致力于为杭州地区的开发者提供学习、合作和成长的机会;同时也为企业交流招聘提供舞台!

更多推荐