在Android启动过程-万字长文(Android14)中介绍了Android系统的启动过程,本篇文章将继续介绍桌面应用Launcher。
Activity Manager Service (AMS)
加载的第一个应用程序git clone https://android.googlesource.com/platform/packages/apps/Launcher3
cd Launcher3
git checkout android14-release
使用AndroidStudio编译下载好的Launcher3工程
编译过程中遇到问题及解决方案可以参考以下博客:
在项目根目录的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>
ActivityTaskManagerService
的getHomeIntent
方法获取和启动桌面程序。具体可参见Android启动过程-万字长文(Android14)Launcher.java是Launcher的启动页面,负责资源初始化和桌面UI创建
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);
}
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);
}
}
/**
* 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);
}
}
在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);
}
}
}
最终通过frameworks/base/core/java/android/app/Activity.java 源码地址中的startActivity
方法启动了对应的应用程序。