Android启动过程-万字长文(Android14)中介绍了Android系统的启动过程,本篇文章将继续介绍桌面应用Launcher。

一、Launcher介绍

  • Android启动过程-万字长文(Android14)中提到Launcher是Android系统启动后,由SystemServerActivity Manager Service (AMS)加载的第一个应用程序
  • Launcher又被称为桌面程序,负责Android桌面的启动和管理
  • 用户使用的应用程序(App)都是通过Launcher来启动的

二、下载及编译

2.1 下载

  • 使用Git下载Launcher源码:
git clone https://android.googlesource.com/platform/packages/apps/Launcher3
  • 进入项目目录
cd Launcher3
  • 切换到Android14分支
git checkout android14-release

2.2 编译

使用AndroidStudio编译下载好的Launcher3工程

编译过程中遇到问题及解决方案可以参考以下博客:

三、源码解析

3.1 AndroidManifest.xml

在项目根目录的AndroidManifest.xml,定义了Launcher做为桌面程序的属性:

<application>
<activity
android:name="com.android.launcher3.Launcher"
android:launchMode="singleTask">
<intent-filter>
<category android:name="android.intent.category.HOME" />
</intent-filter>
</activity>
</application>
  • android.intent.category.HOME: 告诉系统这是一个启动器(Launcher)应用程序,系统在初始化完成后会通过ActivityTaskManagerServicegetHomeIntent方法获取和启动桌面程序。具体可参见Android启动过程-万字长文(Android14)
  • 开发人员也可以自己开发一个桌面程序(如微软桌面),用户安装完成后,可以在系统设置中修改默认启动的桌面程序

3.2 Launcher.java

Launcher.java是Launcher的启动页面,负责资源初始化和桌面UI创建

3.2.1 onCreate方法

protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); // 获取 LauncherAppState 实例和模型
LauncherAppState app = LauncherAppState.getInstance(this);
mModel = app.getModel(); // 初始化不变的设备配置文件
InvariantDeviceProfile idp = app.getInvariantDeviceProfile();
initDeviceProfile(idp);
idp.addOnChangeListener(this); // 获取共享首选项和图标缓存
mSharedPrefs = LauncherPrefs.getPrefs(this);
mIconCache = app.getIconCache(); // 创建无障碍代理
mAccessibilityDelegate = createAccessibilityDelegate(); // 初始化拖动控制器
initDragController(); // 创建所有应用程序控制器
mAllAppsController = new AllAppsTransitionController(this); // 创建状态管理器
mStateManager = new StateManager<>(this, NORMAL); // 创建引导首选项
mOnboardingPrefs = createOnboardingPrefs(mSharedPrefs); // 设置视图
setupViews(); // 初始化Widget
mAppWidgetManager = new WidgetManagerHelper(this);
mAppWidgetHolder = createAppWidgetHolder();
mAppWidgetHolder.startListening(); // 设置内容视图
setContentView(getRootView());
ComposeInitializer.initCompose(this); }

3.2.2 setupViews方法

protected void setupViews() {
// 创建根视图
inflateRootView(R.layout.launcher); // 获取拖动层和焦点处理器
mDragLayer = findViewById(R.id.drag_layer);
mFocusHandler = mDragLayer.getFocusIndicatorHelper(); // 获取工作区、总览面板和Hotseat
mWorkspace = mDragLayer.findViewById(R.id.workspace);
mWorkspace.initParentViews(mDragLayer);
mOverviewPanel = findViewById(R.id.overview_panel);
mHotseat = findViewById(R.id.hotseat);
// 将工作区设置为Hotseat
mHotseat.setWorkspace(mWorkspace); // 设置拖动层
mDragLayer.setup(mDragController, mWorkspace); // 设置工作区
mWorkspace.setup(mDragController);
// 在工作区绑定之前,确保我们将壁纸偏移锁定到默认状态,否则在RTL中我们将更新错误的偏移量
mWorkspace.lockWallpaperToDefaultPage();
mWorkspace.bindAndInitFirstWorkspaceScreen();
mDragController.addDragListener(mWorkspace); // 获取搜索/删除/卸载栏
mDropTargetBar = mDragLayer.findViewById(R.id.drop_target_bar); // 设置应用程序视图
mAppsView = findViewById(R.id.apps_view);
mAppsView.setAllAppsTransitionController(mAllAppsController); // 设置拖动控制器(拖动目标必须按优先级的相反顺序添加)
mDropTargetBar.setup(mDragController);
mAllAppsController.setupViews(mScrimView, mAppsView); // 如果启用了点分页,则设置工作区的分页指示器
if (SHOW_DOT_PAGINATION.get()) {
mWorkspace.getPageIndicator().setShouldAutoHide(true);
mWorkspace.getPageIndicator().setPaintColor(
Themes.getAttrBoolean(this, R.attr.isWorkspaceDarkText)
? Color.BLACK
: Color.WHITE);
}
}
  • Workspace:工作区,也是我们常说的桌面区域,包括搜索框,桌面,壁纸
  • AppsView:应用程序列表
  • Widget:小组件

三、Workspace、AppsView和Widget示例

3.1 Workspace(工作区)

  • 结构说明

3.2 AppsView(应用程序视图)

3.3 Widget(小组件)

四、点击App图标的事件响应

4.1 触发ItemClickHandler的onClick方法

  • ItemClickHandler负责处理桌面应用图标的点击事件。
  • 桌面图标的点击事件最终会触发ItemClickHandleronClick方法
  • onClick方法最终会触发startAppShortcutOrInfoActivity方法
/**
* Class for handling clicks on workspace and all-apps items
*/
public class ItemClickHandler {
private static void onClick(View v) {
startAppShortcutOrInfoActivity(v, (AppInfo) tag, launcher);
} // 通知launcher启动Activity
private static void startAppShortcutOrInfoActivity(View v, ItemInfo item, Launcher launcher) {
launcher.startActivitySafely(v, intent, item);
}
}

4.2 Launcher通知系统启动App

Launcher.java的startActivitySafely方法中调用ActivityContext.java的startActivitySafely方法

public RunnableList startActivitySafely(View v, Intent intent, ItemInfo item) {
RunnableList result = super.startActivitySafely(v, intent, item);
}

ActivityContext.java的startActivitySafely方法中调用了

public interface ActivityContext {
default RunnableList startActivitySafely(
View v, Intent intent, @Nullable ItemInfo item) {
if (isShortcut) {
// Shortcuts need some special checks due to legacy reasons.
startShortcutIntentSafely(intent, optsBundle, item);
}
} default void startShortcutIntentSafely(Intent intent, Bundle optsBundle, ItemInfo info) {
if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT) {
// 通过快捷方式启动
startShortcut(packageName, id, intent.getSourceBounds(), optsBundle, info.user);
} else {
// 普通方式启动,应用程序走这个分支
((Context) this).startActivity(intent, optsBundle);
}
}
}

Android 应用快捷方式(Shortcut)官方文档

最终通过frameworks/base/core/java/android/app/Activity.java 源码地址中的startActivity方法启动了对应的应用程序。

Android桌面Launcher源码浅析的更多相关文章

  1. android添加账户源码浅析

    上篇粗略的分析android添加账号的流程,本篇深入的解析下执行步骤.先来看图片,取自深入理解android卷2: 上图详细的分析了addAccount的流程,下面我们结合源码来理解它 1.addAc ...

  2. Android源码浅析(二)——Ubuntu Root,Git,VMware Tools,安装输入法,主题美化,Dock,安装JDK和配置环境

    Android源码浅析(二)--Ubuntu Root,Git,VMware Tools,安装输入法,主题美化,Dock,安装JDK和配置环境 接着上篇,上片主要是介绍了一些安装工具的小知识点Andr ...

  3. Android 手势识别类 ( 三 ) GestureDetector 源码浅析

    前言:上 篇介绍了提供手势绘制的视图平台GestureOverlayView,但是在视图平台上绘制出的手势,是需要存储以及在必要的利用时加载取出手势.所 以,用户绘制出的一个完整的手势是需要一定的代码 ...

  4. Android开发之Theme、Style探索及源码浅析

    1 背景 前段时间群里有伙伴问到了关于Android开发中Theme与Style的问题,当然,这类东西在网上随便一搜一大把模板,所以关于怎么用的问题我想这里也就不做太多的说明了,我们这里把重点放在理解 ...

  5. Android手势源码浅析-----手势绘制(GestureOverlayView)

    Android手势源码浅析-----手势绘制(GestureOverlayView)

  6. Android源码浅析(六)——SecureCRT远程连接Linux,配置端点和字节码

    Android源码浅析(六)--SecureCRT远程连接Linux,配置端点和字节码 需要编译源码的同学,一般都是win+虚拟机吧,但是再虚拟机里体验并不是很好,所有市面上有很多的软件能够做到在wi ...

  7. Android源码浅析(五)——关于定制系统,如何给你的Android应用系统签名

    Android源码浅析(五)--关于定制系统,如何给你的Android应用系统签名 今天来点简单的我相信很多定制系统的同学都会有一些特定功能的需求,比如 修改系统时间 静默安装 执行某shell命令 ...

  8. Android源码浅析(四)——我在Android开发中常用到的adb命令,Linux命令,源码编译命令

    Android源码浅析(四)--我在Android开发中常用到的adb命令,Linux命令,源码编译命令 我自己平时开发的时候积累的一些命令,希望对你有所帮助 adb是什么?: adb的全称为Andr ...

  9. Android源码浅析(三)——Android AOSP 5.1.1源码的同步sync和编译make,搭建Samba服务器进行更便捷的烧录刷机

    Android源码浅析(三)--Android AOSP 5.1.1源码的同步sync和编译make,搭建Samba服务器进行更便捷的烧录刷机 最近比较忙,而且又要维护自己的博客,视频和公众号,也就没 ...

  10. Android源码浅析(一)——VMware Workstation Pro和Ubuntu Kylin 16.04 LTS安装配置

    Android源码浅析(一)--VMware Workstation Pro和Ubuntu Kylin 16.04 LTS安装配置 最近地方工作,就是接触源码的东西了,所以好东西还是要分享,系列开了这 ...

随机推荐

  1. windows server 出现.net 3.5安装不上去

    前言 有人说为什么到了现在还有人用.net 3.5呢?其实我也不用,主要是mmsql安装的时候要用到. 正文 一般我们不同电脑在程序和功能中添加,如果添加不上会弹出一个自动获取的一个过程,这时我们点击 ...

  2. gitlib配置

    第1步:下载Java并安装Java.一般来说下载jdk对应的版本就行. 第2步:配置Java环境变量,具体如下: 1. 新建:变量名:JAVA_HOME:变量值:C:\Program Files\Ja ...

  3. 重新整理linux 系列 ——硬件的介绍(一)

    前言 打算重新整理linux,计划每天一更,希望能够按照计划执行吧. 正文 首先有一个疑惑,那就是一台手机是否是一台计算机? 来看下什么可以定义为一台计算机: 计算机为接收用户的输入,经由中央处理器的 ...

  4. 基于Material Design风格开源、易用、强大的WPF UI控件库

    前言 今天大姚给大家分享一款基于Material Design风格开源.免费(MIT License).易于使用.强大的WPF UI控件库:MaterialDesignInXamlToolkit. 项 ...

  5. 初探Mysql架构和InnoDB存储引擎

    前言 mysql相信大家都不陌生了,分享之前我们先思考几个面试题: 1.undo log和redo log了解过吗?它们的作⽤分别是什么? 2.redo log是如何保证事务不丢失的? 3.mysql ...

  6. 深度解读《深度探索C++对象模型》之数据成员的存取效率分析(一)

    接下来我将持续更新"深度解读<深度探索C++对象模型>"系列,敬请期待,欢迎关注!也可以关注公众号:iShare爱分享,自动获得推文和全部的文章列表. 在<深度解 ...

  7. Java面试题:为什么HashMap不建议使用对象作为Key?

    HashMap 是一种基于哈希表的动态数据结构,它允许使用任意不可变对象作为键(key)来存储和检索数据.然而,在某些情况下,使用对象作为 HashMap 的键可能会遇到一些问题. 首先,我们需要明确 ...

  8. IIncrementalGenerator 判断程序集的引用关系

    本文将告诉大家如何在 IIncrementalGenerator 增量 Source Generator 生成代码里面,在 Roslyn 分析器里面判断两个程序集是否存在引用关系 先上核心代码实现,核 ...

  9. GitHub 的 Action 判断仅在主仓库才执行脚本

    我有一个 GitHub 项目,这个项目配置了仅需要在源仓库才能执行的 Action 如推送 NuGet 等发布动作.如何在 Action 里面设置让 Fork 的仓库不执行 Action 的步骤 想要 ...

  10. 浅析mvvm模式和mvc模式的区别和联系

    三层架构与MVC模式 三层架构 三层架构是一种以实现"高内聚,底耦合"为目标,的代码架构方法,它将整个业务分为,表示层,业务层,数据访问层(Dao层). MVC模式 MVC模式是一 ...