Launcher启动流程&&加载流程学习

来源:互联网 发布:php培训机构哪家好 编辑:程序博客网 时间:2024/06/06 14:21

 声明: 图片本来是有的 涉及到有些代码不能示人没有贴上,不过仅文字说也足够了,请广大老爷们自行下载源码参看流程分析阅读。

目录

一、认识Launcher 1

1、功能 1

2、样式 2

3Android.mk文件 3

3AndroidManifest文件 5

①权限: 5

②应用程序组件配置: 6

二、启动流程 7

1.从SystemserverAMS 7

2.将SystemServer进程加到AMS中调度管理 10

3.AMS systemReady过程 11

4.启动HomeActivity 11

三、加载流程 14

1.重要类认识 14

2.流程 15

加载绑定Workspace上的内容 18

加载绑定Allapps中的内容 23

总结 25

 

 

 

 

 

 

 

一、 认识Launcher

1、功能

① LauncherAndroid系统的启动器

② 应用程序的管理器

③ Android系统的桌面

 

 

2、样式

 

 

① 原生Launcher3经典的四种UI模式

 

 

 

Launcher桌面元素的角度来看,组件包括应用程序的快捷方式、文件夹、桌面小部件及相关组件,称这类组件为桌面组件。

 

3Android.mk文件

 

以上我们认识了其从功能到界面的了解,下面就是我们程序员上场的时候了

 

 

LOCAL_MODULE_TAGS := optional

// 编译选项何种模式编译,optional为在任种模式下均可编译(Userengtest三种模式)

LOCAL_SRC_FILES := $(call all-java-files-under, src) \

    $(call all-java-files-under, WallpaperPicker/src) \

$(call all-proto-files-under, protos)

//需要编译的资源文件

LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/WallpaperPicker/res $(LOCAL_PATH)/res

//需要编译的资源文件的路径

LOCAL_PROGUARD_FLAG_FILES := proguard.flags

//用于混淆代码的脚本文件名该处为proguard.flags(出于代码安全考虑的混淆工具可配置)

LOCAL_STATIC_JAVA_LIBRARIES := android-support-v4 android-support-v7-recyclerview

//需要依赖的Java

LOCAL_PROTOC_OPTIMIZE_TYPE := nano

LOCAL_PROTOC_FLAGS := --proto_path=$(LOCAL_PATH)/protos/

LOCAL_AAPT_FLAGS := --auto-add-overlay

//应用程序打包标示变量,设置为自动添加并覆盖

#LOCAL_SDK_VERSION := current

LOCAL_PACKAGE_NAME := Launcher3

LOCAL_PRIVILEGED_MODULE := true

#LOCAL_CERTIFICATE := shared

LOCAL_OVERRIDES_PACKAGES := Home Launcher2

//编译Launcher3Launcher2不会被加入编译系统

include $(BUILD_PACKAGE)

//当完成了本地编译环境变量的设置以后,通过该语句启动编译,生成目标

#

# Protocol Buffer Debug Utility in Java

#配置工具库依赖编译

include $(CLEAR_VARS)

 

LOCAL_SRC_FILES := $(call all-java-files-under, util) \

    $(call all-proto-files-under, protos)

 

LOCAL_PROTOC_OPTIMIZE_TYPE := nano

LOCAL_PROTOC_FLAGS := --proto_path=$(LOCAL_PATH)/protos/

 

LOCAL_MODULE_TAGS := optional

LOCAL_MODULE := launcher_protoutil_lib

LOCAL_IS_HOST_MODULE := true

LOCAL_JAR_MANIFEST := util/etc/manifest.txt

 

include $(BUILD_HOST_JAVA_LIBRARY)

 

#

# Protocol Buffer Debug Utility Wrapper Script

# Protocol Buffer的测试工具

include $(CLEAR_VARS)

LOCAL_IS_HOST_MODULE := true

LOCAL_MODULE_CLASS := EXECUTABLES

LOCAL_MODULE_TAGS := optional

LOCAL_MODULE := launcher_protoutil

 

include $(BUILD_SYSTEM)/base_rules.mk

 

$(LOCAL_BUILT_MODULE): | $(HOST_OUT_JAVA_LIBRARIES)/launcher_protoutil_lib.jar

$(LOCAL_BUILT_MODULE): $(LOCAL_PATH)/util/etc/launcher_protoutil | $(ACP)

@echo "Copy: $(PRIVATE_MODULE) ($@)"

$(copy-file-to-new-target)

$(hide) chmod 755 $@

 

INTERNAL_DALVIK_MODULES += $(LOCAL_INSTALLED_MODULE)

 

include $(call all-makefiles-under,$(LOCAL_PATH))

//这是一个递归的调用,意思是搜索Launcher3目录下是否还有其他的Android.mk文件,如果有则启动一次编译

 

 

3AndroidManifest文件

①权限:

<permission

        android:name="com.android.launcher.permission.INSTALL_SHORTCUT"

  //安装快捷方式      

        android:name="com.android.launcher3.permission.READ_SETTINGS"

        android:name="com.android.launcher3.permission.WRITE_SETTINGS"

                android:name="com.android.launcher3.permission.RECEIVE_LAUNCH_BROADCASTS"

//Launcher3对外提供一个内容提供者,应用程序可以通过鉴权信息来访问数据,为此读写这些数据时会申请该权限

 

        

android:name="com.android.launcher3.permission.RECEIVE_FIRST_LOAD_BROADCAST"

//Launcher3第一次加载的时候会向系统发一次广播,如果对此感兴趣则需要申请该权限。

 

② 应用程序组件配置:

Launcher3Activity配置

 

 

 

声明Launcher是一个单任务模式的Activity

<action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.HOME" />

两句尤为重要,体现了Launcher的特殊地位,说明这是桌面

 

壁纸桌面选择模块的配置

 

 

 

二、 启动流程

先从SystemServer开始。

systemserver最主要的作用: 

1) 就是初始化framework层各种service和其对应的特定servicemanager,并将他们注册到全局servicemanager,以便其他地方只需要通过servicemanager. getService(String servicename)就可以取得该service的实例。    

2)  2)调用各servicesystemready接口,启动service 这些service基本都是单例类,所以这种注册也是方便全局调用。

1 SystemserverAMS

 

SystemServer.Java

路径:/frameworks/base/services/java/com/android/server/SystemServer.java

 

之后在

 

 

方法中检查时间、地区、语言环境,首先判断系统当前时间,若当前时间小于197011日,则一些初始化操作可能会处所,所以当系统的当前时间小于197011日的时候,设置系统当前时间为该时间点。

 

 

 

······

 

 


面的主要是设置虚拟机运行内存,加载运行库,设置SystemServer的异步消息

 

 

 

 

可知可以看到在SystemServer进程中也存在着Context对象,然后通过SystemServiceManager的构造方法创建了一个新的SystemServiceManager对象,我们知道SystemServer进程主要是用来构建系统各种service服务的,而SystemServiceManager就是这些服务的管理对象。

 

 

 

 

里面主要涉及了是三个方法: 
startBootstrapServices() 主要用于启动系统Boot级服务 
startCoreServices() 主要用于启动系统核心的服务 
startOtherServices() 主要用于启动一些非紧要或者是非需要及时启动的服务

1BootstrapServices为引导服务,启动的service包括: 
Installer 系统安装apk时的一个服务类,启动完成Installer服务之后才能启动其他的系统服务 
ActivityManagerService 负责四大组件的启动、切换、调度。 
PowerManagerService 计算系统中和Power相关的计算,然后决策系统应该如何反应 
LightsService 管理和显示背光LED 
DisplayManagerService 用来管理所有显示设备 
UserManagerService 多用户模式管理 
SensorService 为系统提供各种感应器服务 
PackageManagerService 用来对apk进行安装、解析、删除、卸载等等操作

2 CoreServices为核心服务,包括: 
BatteryService 管理电池相关的服务 
UsageStatsService 收集用户使用每一个APP的频率、使用时常 
WebViewUpdateService WebView更新服务

3OtherServices其他服务,包括很多服务,比如: 
CameraService 摄像头相关服务 
AlarmManagerService 全局定时器管理服务 
InputManagerService 管理输入事件 
WindowManagerService 窗口管理服务 
VrManagerService VR模式管理服务 
BluetoothService 蓝牙管理服务 
NotificationManagerService 通知管理服务 
DeviceStorageMonitorService 存储相关管理服务 
LocationManagerService 定位管理服务 
AudioService 音频相关管理服务

 

······

 

 模块SystemUI启动···

 

接下来我们转移战地到ActivityManagerService

 

SystemServer进程加到AMS中调度管理

ActivityManagerService.java

/frameworks /base/services/core/java/com/android/server/am/ActivityManagerService.java

 

 

······

 

 

·  setSystemProcess意义:

    这一步就是给SystemServer进程创建ProcessRecord,adj值,就是将SystemServer进程加入到AMS进程管理机制中,跟应用进程一致;

 

 

3 AMS systemReady过程

 

 

······

 

 

启动HomeActivity

 

 

······

 


 

getHomeIntent函数中创建了Intent,并将mTopActionmTopData传入。mTopAction的值为Intent.ACTION_MAIN,并且如果系统运行模式不是低级工厂模式则将intentCategory设置为Intent.CATEGORY_HOME。我们再回到ActivityManagerServicestartHomeActivityLocked函数,假设系统的运行模式不是低级工厂模式,符合ActionIntent.ACTION_MAINCategoryIntent.CATEGORY_HOME的应用程序是否已经启动

这个被启动的应用程序就是Launcher,因为LauncherManifest文件中的intent-filter标签匹配了ActionIntent.ACTION_MAINCategoryIntent.CATEGORY_HOME。这样,应用程序Launcher就会被启动起来,并执行它的onCreate函数。

 

/frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java

ActivityStackSupervisor.java

 

 

一张图总结Launcher启动流程:

 

 

 

 

 

三、 加载流程

在上述的Launcher启动流程已经理清之后,我们接下来就可以进行对Launcher的加载捋捋了。

1.重要类认识

首先对一些文件进行认识。

Launcher:主界面Activity,最核心且唯一的Activity

LauncherAppState:单例对象,构造方法中初始化对象、注册应用安装、卸载、更新,配置变化等广播。这些广播用来实时更新桌面图标等,其receiver的实现在LauncherModel类中,LauncherModel也在这里初始化。

LauncherModel:数据处理类,保存桌面状态,提供读写数据库API,内部类LoaderTask用来初始化桌面。

InvariantDeviceProfile:一些不变的设备相关参数管理类,其内部包涵了横竖屏模式的DeviceProfile

WidgetPreviewLoader:存储Widget信息的数据库,内部创建了数据库widgetpreviews.db

LauncherAppsCompat:获取已安装App列表信息的兼容抽象基类,子类依据不同版本API进行兼容性处理。

AppWidgetManagerCompat:获取AppWidget列表的兼容抽象基类,子类依据不同版本API进行兼容性处理。

LauncherStateTransitionAnimation:各类动画总管处理执行类,负责各种情况下的各种动画效果处理。

IconCache:图标缓存类,应用程序icontitle的缓存,内部类创建了数据库app_icons.db

LauncherProvider:核心数据库类,负责launcher.db的创建与维护。

LauncherAppWidgetHostAppWidgetHost子类,是桌面插件宿主,为了方便托拽等才继承处理的。

LauncherAppWidgetHostViewAppWidgetHostView子类,配合LauncherAppWidgetHost得到HostView

LauncherRootView:竖屏模式下根布局,继承了InsettableFrameLayout,控制是否显示在状态栏等下面。

DragLayer:一个用来负责分发事件的ViewGroup

DragControllerDragLayer只是一个ViewGroup,具体的拖拽的处理都放到了DragController中。

BubblTextView:图标都基于他,继承自TextView

DragView:拖动图标时跟随手指移动的View

Folder:打开文件夹展示的View

FolderIcon:文件夹图标。

DragSource/DropTarget:拖拽接口,DragSource表示图标从哪开始拖,DropTarget表示图标被拖到哪去。

ItemInfo:桌面上每个Item的信息数据结构,包括在第几屏、第几行、第几列、宽高等信息;该对象与数据库中记录一一对应;该类有多个子类,譬如FolderIconFolderInfoBubbleTextViewShortcutInfo等。

2.流程

App的启动是从Application开始的,但是我们最新的Launcher3,谷歌工程师把这个类移除,再次之前的版本都是有这个类的

们手头的LauncherApplication了,现在讲解的是基于最新的Launcher3代码,因此我们这个Launcher中没有Application,所以程序启动最开始的是ContentProvideronCreate方法,代码如下:

/alps/packages/apps/Launcher3/src/com/android/launcher3/LauncherProvider.java

LauncherProvider.java

 

 

严苛模式:

1. 启用严苛模式,StrictMode可以用于捕捉发生在应用程序主线程 中耗时的磁盘、网络访问或函数调用,  

2. 可以帮助开发者使其改进程序,使主线程处理UI和动画在磁盘读写和网络操作时变得更平滑,避免主线程被阻塞,导致ANR窗口的发生。  

 

代码中处理的事情不多,主要是启动严苛模式和创建数据库

 

 

接下来就是启动Launcher,我么看一下Launcher中的onCreate方法中的代码:

/alps/packages/apps /Launcher3/src/com/android/launcher3/Launcher.java

Launcher.java

 

······

 

 

······

 

 

这一段代码是用来异步加载桌面的应用快捷图标、小部件和所有应用图标,是最重要的一步

./Launcher3/src/com/android/launcher3/LauncherModel.java

LauncherModel.java

 

 

执行run方法。

 

① 加载绑定Workspace上的内容

 

并没有直接进行加载,只是对一些状态进行了更新和条件判断,loadWorkspacebindWorkspace才是实际操作。

 

我们看真正的加载WorkSpace。代码敲长的~

 

初始化后面要用到的对象实例

······

 

/Launcher3/src/com/android/launcher3/LauncherProvider.java

 

 

 

如果数据库还没有创建,就会加载默认的配置(default_workspace_xxx.xml),并保存到数据库中。

······

 

 

在加载过后就要开始绑定了

 

 

先是各种初始化以及各对象的实例化

······

 

执行runnable里面回调在Launcher中的方法准备进行绑定

 


 

 

然后是真正的绑定

startBinding类似

 

·······

 

······

同样调用Launcher的回调

 

 

以及类似的bindWorkspaceItemsbindAddScreensbindFoldersbindAppWidget是运用的同样的套路。加载文件夹、item、空白页等有大量的细节,感兴趣可以跟踪代码。(不行了,累死了,不想写了···)

 

最后通知其绑定完成。

 


 

 

 

这样整个loadAndBindWorkspace过程就结束了,接着下一步。

② 加载绑定Allapps中的内容

第二步:loadAndBindAllApps

 

 


 

 

 

 

······

 

······

 

依旧是回调Launcher.Java中的回调方法

小结:

1.获取需要显示到Launcher中的app列表,创建app图标

2.绑定app—bindAllApplications

 

至此 Allapps也加载绑定结束。

接着会执行onPackagesUpdatedpackage的更新操作,就不再展开了。Widget也是类似的。这样加载allapp的过程就结束了。

 

 

 

 

 

 

回到launcherOncreate方法。

 

 

在这里执行第一次开机的用户向导(可定制化)

 

③ 总结

 

最后,借用一张图来总结其从Oncreate以来的执行步骤。

 


原创粉丝点击