Android Launcher分析和修改3——Launcher启动和初始化
前面两篇文章都是写有关Launcher配置文件的修改,代码方面涉及不多,今天开始进入Launcher代码分析。
我们开机启动Launcher,Launcher是由Activity Manager启动的,而Activity Manager是由system server启动。
原创博文,转载请标明出处:http://www.cnblogs.com/mythou/p/3157452.html
1、Launcher进程启动过程
可以由下面图看到Launcher进程是如何被创建启动:
Activity Manager通过发送Intend来启动Launcher。
//Edited by mythou
//http://www.cnblogs.com/mythou/
Intent intent = new Intent(mTopAction, mTopData != null ?
Uri.parse(mTopData) : null);
intent.setComponent(mTopComponent);
if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL)
{
intent.addCategory(Intent.CATEGORY_HOME);
}
startActivityLocked(null, intent, null, null, , aInfo,
null, null, , , , false, false);
因此,如果你要开机启动一个替换Launcher的程序,只要在程序<intent-filter>里面加入action.MAIN 、
category.HOME、category.DEFAULT就可以。如果出现多个程序都加入这种intent,系统会弹出让你选择
哪个作为启动器。
2、Launcher初始化——LauncherApplication。
Application类,我想大部分做Android应用的朋友都用过,每个Android应用默认都有一个Application类,
你也可以继承Application类,然后加入自己代码。Application是一个全局的应用类,在AndroidManifest.xml
我们也可以找到Application标签。
//Edited by mythou
//http://www.cnblogs.com/mythou/
<application
android:name="com.android.launcher2.LauncherApplication"
android:label="@string/application_name"
android:icon="@drawable/ic_launcher_home"
android:hardwareAccelerated="@bool/config_hardwareAccelerated"
android:largeHeap="@bool/config_largeHeap"
android:configChanges="locale">
</application>
Android四大组件的声明都需要放到application标签里面,默认使用的是系统的Application类,如果你在项目
里面重载了它。就需要在标签,name属性下写上你的新的Application类名。Launcher里面就是继承了Application
为LauncherApplication。应用启动的时候首先会加载Application。
我们可以看到Launcher主类Launcher.java的onCreate函数里面,第一个就是获取Application的实例。
LauncherApplication app = ((LauncherApplication)getApplication());
接下来我们看看LauncherApplication里面初始化,LauncherApplication大部分工作就是在初始化完成,剩下都是
一些返回接口。
//Edited by mythou
//http://www.cnblogs.com/mythou/
@Override
public void onCreate()
{
super.onCreate(); //获取屏幕大小,主要用来区分手机还是平板
final int screenSize = getResources().getConfiguration().screenLayout &
Configuration.SCREENLAYOUT_SIZE_MASK;
sIsScreenLarge = screenSize == Configuration.SCREENLAYOUT_SIZE_LARGE ||
screenSize == Configuration.SCREENLAYOUT_SIZE_XLARGE;
//屏幕密度
sScreenDensity = getResources().getDisplayMetrics().density;
//IconCahe里面保存了界面所有应用图标的绘画需要的数据,这个到时候具体分析再说。
//加入这东西的主要原因是为了提高绘画界面的效率
mIconCache = new IconCache(this);
//数据库加载类,LauncherModel是Launcher里面非常重要的一个类,相当于MVC模式里面的
//Model功能,管理数据和初始化数据
mModel = new LauncherModel(this, mIconCache); //下面注册了一些监听器,主要包含APK文件更新删除等数据变化的时候接收的通知
//接收通知后,主要是用来更新Launcher里面的数据库。因为桌面应用图标数据,只会加载一次
IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
filter.addDataScheme("package");
registerReceiver(mModel, filter);
filter = new IntentFilter();
filter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
filter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
filter.addAction(Intent.ACTION_LOCALE_CHANGED);
filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
registerReceiver(mModel, filter);
filter = new IntentFilter();
filter.addAction(SearchManager.INTENT_GLOBAL_SEARCH_ACTIVITY_CHANGED);
registerReceiver(mModel, filter);
filter = new IntentFilter();
filter.addAction(SearchManager.INTENT_ACTION_SEARCHABLES_CHANGED);
registerReceiver(mModel, filter);
//contentresolver则是用于管理所有程序的contentprovider实例
ContentResolver resolver = getContentResolver();
//注册内容观察者,监听application数据库变化,回调
resolver.registerContentObserver(LauncherSettings.Favorites.CONTENT_URI, true, mFavoritesObserver);
}
上面是LauncherApplication最主要的工作,初始化整个Launcher的一些关键类,和注册一些监听器。主要都是用
来监听应用的安装更新删除等导致Launcher数据库变化的操作。Launcher数据都是使用contentprovider来提供数据。
其中注册的监听接口是
//Edited by mythou
//http://www.cnblogs.com/mythou/
private final ContentObserver mFavoritesObserver = new ContentObserver(new Handler())
{
@Override
public void onChange(boolean selfChange)
{
//重新加载界面数据
mModel.startLoader(LauncherApplication.this, false);
}
};
LauncherSettings.Favorites.CONTENT_URI里面数据发生变化的时候,都会调用mModel.startLoader()接口,
重新加载Launcher的数据。startLoader的具体操作,我后面分析LauncherModel类的时候会分析。这一块涉及
Launcher所有数据加载。剩下的接都是返回初始化时候创建的对象或者获取屏幕密度、获取是否大屏幕。
后面很多处理都需要判断是否是大屏幕,4.0以后手机平板都共用一套系统,导致多了很多处理。
3、Launcher.java初始化
Launcher.java是Launcher里面最主要的类,是一个Activity。启动的第一个组件。既然是Activity,我们要分析它
初始化,毫无疑问,需要找到onCreate()里面分析。把主要一些分析用注释方式写在代码里面,这样比较方便阅读。
//Edited by mythou
//http://www.cnblogs.com/mythou/
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
//获取Application 实例
LauncherApplication app = ((LauncherApplication)getApplication());
//LauncherModel类里面获取Launcher的对象引用
mModel = app.setLauncher(this);
//获取IconCache,IconCache在Application里面初始化
mIconCache = app.getIconCache();
mDragController = new DragController(this);
mInflater = getLayoutInflater(); mAppWidgetManager = AppWidgetManager.getInstance(this);
//监听widget改变,以后在Model里面回调处理的结果
mAppWidgetHost = new LauncherAppWidgetHost(this, APPWIDGET_HOST_ID);
mAppWidgetHost.startListening();
//这个是设置Launcher的跟踪调试文件,下面很多信息会写到这个文件里面。
if (PROFILE_STARTUP)
{
android.os.Debug.startMethodTracing(
Environment.getExternalStorageDirectory() + "/launcher");
} //读取本地配置,保存更新配置,清空IconCache
checkForLocaleChange();
setContentView(R.layout.launcher); //对所有的UI控件进行加载和配置
setupViews(); //显示操作提示,第一次启动的时候才会显示
showFirstRunWorkspaceCling(); //注册监控Launcher数据库变化
registerContentObservers();
//锁住APP,初始化不能操作。
lockAllApps(); mSavedState = savedInstanceState;
restoreState(mSavedState); // Update customization drawer _after_ restoring the states
if (mAppsCustomizeContent != null)
{
mAppsCustomizeContent.onPackagesUpdated();
} if (PROFILE_STARTUP)
{
android.os.Debug.stopMethodTracing();
} //加载启动数据,所有界面数据(快捷方式、folder、widget、allApp)等在loader里面加载,这部分后面我会详细分析。
if (!mRestoring) {
mModel.startLoader(this, true);
} if (!mModel.isAllAppsLoaded())
{
ViewGroup appsCustomizeContentParent = (ViewGroup) mAppsCustomizeContent.getParent();
mInflater.inflate(R.layout.apps_customize_progressbar, appsCustomizeContentParent);
} // For handling default keys
mDefaultKeySsb = new SpannableStringBuilder();
Selection.setSelection(mDefaultKeySsb, ); IntentFilter filter = new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
registerReceiver(mCloseSystemDialogsReceiver, filter);
//下面这几个就是Android原生界面上的Market、搜索、声音输入按钮的默认图标显示。
boolean searchVisible = false;
boolean voiceVisible = false;
// If we have a saved version of these external icons, we load them up immediately
int coi = getCurrentOrientationIndexForGlobalIcons();
if (sGlobalSearchIcon[coi] == null || sVoiceSearchIcon[coi] == null ||
sAppMarketIcon[coi] == null) {
updateAppMarketIcon();
searchVisible = updateGlobalSearchIcon();
voiceVisible = updateVoiceSearchIcon(searchVisible);
}
if (sGlobalSearchIcon[coi] != null) {
updateGlobalSearchIcon(sGlobalSearchIcon[coi]);
searchVisible = true;
}
if (sVoiceSearchIcon[coi] != null)
{
updateVoiceSearchIcon(sVoiceSearchIcon[coi]);
voiceVisible = true;
}
if (sAppMarketIcon[coi] != null)
{
updateAppMarketIcon(sAppMarketIcon[coi]);
}
mSearchDropTargetBar.onSearchPackagesChanged(searchVisible, voiceVisible); // On large interfaces, we want the screen to auto-rotate based on the current orientation
if (LauncherApplication.isScreenLarge() || Build.TYPE.contentEquals("eng"))
{
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
} Log.i(TAG,"------------------------>Launcher init over") ;
}
上面就是Launcher.java的初始化,大部分我都写了注释。其实这里最主要的工作是加载界面数据:
mModel.startLoader(this, true); 这块实现是在LauncherModel里面实现的。下一篇文章,我会详细
说明如何加载和获取管理系统里面的APP相关数据。
今天就讲到这里,如发现问题,请留言指出,欢迎留言讨论。
相关系列文章:
Android Launcher分析和修改1——Launcher默认界面配置(default_workspace)
Android Launcher分析和修改2——Icon修改、界面布局调整、壁纸设置
Android Launcher分析和修改3——Launcher启动和初始化的更多相关文章
- Android Launcher分析和修改9——Launcher启动APP流程
本来想分析AppsCustomizePagedView类,不过今天突然接到一个临时任务.客户反馈说机器界面的图标很难点击启动程序,经常点击了没有反应,Boss说要优先解决这问题.没办法,只能看看是怎么 ...
- Android Launcher分析和修改1——Launcher默认界面配置(default_workspace)
最近工作都在修改Launcher,所以打算把分析源码和修改源码的过程记录下来,最近会写一些关于Launcher的分析和修改博文.因为我是修改4.0.3的Launcher,所以后面文章里面的Launch ...
- Android Launcher分析和修改13——实现Launcher编辑模式(1) 壁纸更换
已经很久没更新Launcher系列文章,今天不分析源码,讲讲如何在Launcher里面添加桌面设置的功能.目前很多第三方Launcher或者定制Rom都有简单易用的桌面设置功能.例如小米MIUI的La ...
- Android Launcher分析和修改10——HotSeat深入进阶
前面已经写过Hotseat分析的文章,主要是讲解如何在Launcher里面配置以及修改Hotseat的参数.今天主要是讲解一下如何在Hotseat里面的Item显示名称.这个小问题昨天折腾了半天,最后 ...
- Android Launcher分析和修改4——初始化加载数据
上面一篇文章说了Launcher是如何被启动的,Launcher启动的过程主要是加载界面数据然后显示出来, 界面数据都是系统APP有关的数据,都是从Launcher的数据库读取,下面我们详细分析Lau ...
- Android Launcher分析和修改5——HotSeat分析
今天主要是分析一下Launcher里面的快捷方式导航条——HotSeat,一般我们使用手机底下都会有这个导航条,但是如果4.0的Launcher放到平板电脑里面运行,默认是没有HotSeat的,刚好我 ...
- Android Launcher分析和修改6——页面滑动(PagedView)
本来打算分析CellLayout的源码,不过因为它们之间是容器包含关系,所以打算先把PagedView分析.PagedView代码很多,今天主要是分析跟核心功能相关的代码.PagedView主要实现一 ...
- Android Launcher分析和修改7——AllApp全部应用列表(AppsCustomizeTabHost)
今天主要是分析一下Launcher里面的所有应用列表.Android4.0 Launcher的所有应用列表跟2.X比较大的区别就是多了Widget的显示.下面会详细分析Launcher里面有关所有应用 ...
- Android Launcher分析和修改8——AllAPP界面拖拽元素(PagedViewWithDraggableItems)
接着上一篇文章,继续分析AllAPP列表界面.上一篇文章分析了所有应用列表的界面构成以及如何通过配置文件修改属性.今天主要是分析PagedViewWithDraggableItems类,因为在我们分析 ...
随机推荐
- python常用模块之时间模块
python常用模块之时间模块 python全栈开发时间模块 上次的博客link:http://futuretechx.com/python-collections/ 接着上次的继续学习: 时间模块 ...
- 网页图表Highcharts实践教程之图表代码构成
网页图表Highcharts实践教程之图表代码构成 Highcharts第一个实例 下面我们来实现本书的第一个Highcharts实例. [实例1-1]下面来制作北京连续一周最高温度折线图.操作过程如 ...
- IT 产品 需求 痛点
英文应该有个 汉语发音 标注 这样的平台软件.罗马音.
- BZOJ.4894.天赋(Matrix Tree定理 辗转相除)
题目链接 有向图生成树个数.矩阵树定理,复习下. 和无向图不同的是,度数矩阵改为入度矩阵/出度矩阵,分别对应外向树/内向树. 删掉第i行第i列表示以i为根节点的生成树个数,所以必须删掉第1行第1列. ...
- 潭州课堂25班:Ph201805201 MySQL第三课 (课堂笔记)
单表查询: select * from select sname from stu; 条件查询 select sname from stu where sid=2; select sname from ...
- E: Unable to locate package openjdk-8-jdk 及java version 切换
在unbuntu14.04系统上安装 Open JDK 8 时遇到了如下问题: $ -jdk Reading package lists... Done Building dependency tre ...
- ELASTIC 动态修改配置API
工作中使用ELASTIC,我们常有需要修改的配置项,但有时又不想重启elastic,这时候就需要elasticsearch内置的修改集群配置API上场了. 这个API非常的简单. curl -XPUT ...
- 2016年Godaddy最新域名转出教程
2016年Godaddy最新域名转出教程 http://godaddy.idcspy.com/godaddy-newest-domain-zhuanchu HostEase注册的域名转入和转出 htt ...
- Hessian学习总结(一)——Hessian入门
一.远程通讯协议的基本原理 网络通信需要做的就是将流从一台计算机传输到另外一台计算机,基于传输协议和网络 IO 来实现,其中传输协议比较出名的有 http . tcp . udp 等等, http . ...
- AngularJS中的ng-controller是什么东东
在AngularJS中,ng-controller是最常用的directive.比如: var app = angular.module("app",[]); app.contro ...