Android中launcher的详细分析
- 格式:docx
- 大小:17.15 KB
- 文档页数:9
android launcher3的基础知识整体概述Launcher3是Android系统中的一个基础组件,用于实现用户手机桌面的布局、图标的显示和点击等功能。
下面是Launcher3的基础知识的概述:1. 桌面布局:Launcher3负责管理和展示用户手机桌面上的各个应用程序图标。
它通过GridView或者LinearLayout等布局管理器将图标进行排列,并支持滑动、放大缩小等手势操作。
用户可以通过Launcher3来创建新的桌面、删除桌面、调整桌面的顺序等。
2. 图标显示:Launcher3负责加载应用程序的图标,并在桌面上进行显示。
它会通过PackageManager获取应用程序的信息,并将图标加载到桌面上的相应位置,同时可以根据应用程序的状态(例如新安装的应用程序)进行一些特殊的显示效果。
3. 图标点击:当用户点击桌面上的应用程序图标时,Launcher3会负责相应该点击事件,并将用户导航到相应的应用程序界面。
它通过包名和Activity名来启动应用程序,并传递一些额外的参数信息。
4. 文件夹管理:Launcher3还支持将多个应用程序图标放入文件夹中进行管理。
用户可以将相似类型的应用程序图标拖动到一起,并创建一个文件夹。
当用户点击文件夹时,Launcher3会展示文件夹中的所有应用程序,并支持文件夹的打开、关闭等操作。
5. 主题和自定义:Launcher3支持用户自定义桌面的主题和样式。
用户可以更改桌面的背景图像、图标的样式、字体的颜色等。
同时,Launcher3还支持第三方主题的安装和使用。
总之,Launcher3是Android系统中负责管理桌面布局、图标显示和点击等功能的核心组件,它为用户提供了方便的手机桌面操作和个性化的定制化选项。
转自:/wdaming1986/article/details/7585649/wdaming1986/article/details/7671318最近研究ICS4.0的Launcher,发现4.0和2.3有稍微点区别,但是区别不是特别大,所以我就先整理一下Launcher启动的大致流程。
Launcher其实是贯彻于手机的整个系统的,时时刻刻都在运行,要是Launcher不运行了,手机就得黑屏了。
Launcher的LauncherMode=singletask,所以说不管Launcher启动了哪个应用,总有个Launcher的实例在堆栈中,并且位于栈底。
点击Home键进入到Launcher,上篇Android的全局键(home键/长按耳机键)详解【android源码解析八】中有详细的介绍。
大致思路其实就是启动launcher的时候,新启动一个task。
大致先说这么多,先看截图:大明原创,转载请标明出处:/wdaming1986/article/details/7585649图(1)上图是4.0的Launcher界面,下面我们分步来解析一下Launcher的启动过程。
Step 0:首先要给大家介绍一下Launcher的数据库,这个数据库中存放着待机界面的图标,主屏底部的应用程序图标和桌面folder中各应用程序的图标,ICS4.0的folder中只能放应用程序的快捷方式,shortcut 不能放到这个folder中,先看截图:图(2)说说各字段的含义:title:表示桌面应用程序的名字,有的title为空,表示是widget的快捷方式;intent:表示启动这个图标的intent放到数据库中,当click的时候就会调用这个字段,启动相应的应用程序;container:表示应用程序的容器,folder的容器为整数,-100:表示在桌面的程序,-101:表示是主屏底部的程序;screen:表示在第几个屏,folder的screen都是0, container=-101的为0,1,3,4;2为allapp的按钮;cellX:表示在屏幕X轴的位置,(0,1,2,3),左上角为0点,往右依次增加;cellY:表示在屏幕Y轴的位置,(0,1,2,3),左上角为0点,往下依次增加;spallX:表示占X轴几个格;spallY:表示占Y轴几个格;itemType:应用程序用0表示,shortcut用1表示,folder用2表示,widget用4表示;appWidgetId:-1表示不是widget,数字大于0表示才是widget;isShortCut:值为0表示不是应用程序的ShortCut,值为1表示是应用程序的ShortCut;iconType:值为0表示图标的名字被定义为包名的资源id,值为1表示图标用bitmap保存;icon:表示应用程序的图标,二进制的;显示为一张图片;说明:folder中的应用快捷方式绑定folder---->是用container的值绑定folder的id的;详细的讲解请参考LauncherSettings.java这个类,有数据库字段的详细讲解;手机是在第一次烧机完成后,数据库的值还没有,这时候launcher解析default_workspace.xml把这个值存到数据库中;所以说想定制什么样的开机桌面就在default_workspace.xml中做相应的配置,具体参照我前面的博客:Android中源码Launcher主屏幕程序排列详解【安卓Launcher进化一】中有详细的介绍:i f (!convertDatabase(db)) {// Populate favorites table with initial favoritesloadFavorites(db, R.xml.default_workspace);}Step 1:开机后先启动LauncherApplication.java这个类的onCreate()方法,下面看代码:[java]view plaincopyprint?1.@Override2.public void onCreate() {3.super.onCreate();4.5.// set sIsScreenXLarge and sScreenDensity *before* creating icon cache6.// 在创建图标缓存之前先设置sIsScreenXLarge和屏幕设备的分辨率7.final int screenSize = getResources().getConfiguration().screenLayout &8.Configuration.SCREENLAYOUT_SIZE_MASK;9.sIsScreenLarge = screenSize == Configuration.SCREENLAYOUT_SIZE_LARGE ||10.screenSize == Configuration.SCREENLAYOUT_SIZE_XLARGE;11.sScreenDensity = getResources().getDisplayMetrics().density;12.13.// 实例化图标缓存区的对象14.mIconCache = new IconCache(this);15.// 实例化一个LauncherModel对象,这个类是保存Launcher的内存启动状态,更新Launcher的数据库的作用16.mModel = new LauncherModel(this, mIconCache);17.18.// Register intent receivers19.// 注册监听,应用package增加,删除,改变的监听。
本文将详细分析Launcher应用程序的启动过程。
Android系统的Home应用程序Launcher是由ActivityManagerService启动的,而ActivityManagerService和PackageManagerService一样,都是在开机时由SystemServer组件启动的,SystemServer组件首先是启动ePackageManagerServic,由它来负责安装系统的应用程序,具体可以参考前面一篇文章Android应用程序安装过程源代码分析,系统中的应用程序安装好了以后,SystemServer 组件接下来就要通过ActivityManagerService来启动Home应用程序Launcher了,Launcher在启动的时候便会通过PackageManagerServic把系统中已经安装好的应用程序以快捷图标的形式展示在桌面上,这样用户就可以使用这些应用程序了,整个过程如下图所示:点击查看大图下面详细分析每一个步骤。
Step 1. SystemServer.main这个函数定义在frameworks/base/services/java/com/android/server/SystemServer.java文件中,具体可以参考前面一篇文章Android应用程序安装过程源代码分析的Step 1。
Step 2. SystemServer.init1这个函数是一个JNI方法,实现在 frameworks/base/services/jni/com_android_server_SystemServer.cpp文件中,具体可以参考前面一篇文章Android应用程序安装过程源代码分析的Step 2。
Step 3. libsystem_server.system_init函数system_init实现在libsystem_server库中,源代码位于frameworks/base/cmds/system_server/library/system_init.cpp文件中,具体可以参考前面一篇文章Android应用程序安装过程源代码分析的Step 3。
AndroidLauncher3简单分析Launcher 3的界⾯主要由SearchDropTargetBar、Workspace、CellLayout、PageIndicator、Hotseat组成。
如下图:Launcher 3 最主要的是⼀个Activity,基本上所有操作都集中在这个Activity上。
这个Activity⽂件为Launcher.java,他的布局⽂件为launcher.xml。
下⾯为竖屏的布局⽂件,路径为res/layout-port/launcher.xml。
1<?xml version="1.0" encoding="utf-8"?>23<!-- Full screen view projects under the status bar and contains the background -->4<uncherRootView xmlns:android="/apk/res/android"5 xmlns:launcher="/apk/res-auto"6 android:id="@+id/launcher"7 android:layout_width="match_parent"8 android:layout_height="match_parent"9 android:fitsSystemWindows="true">1011<uncher3.DragLayer12android:id="@+id/drag_layer"1314 android:layout_width="match_parent"15 android:layout_height="match_parent">1617<uncher3.FocusIndicatorView18android:id="@+id/focus_indicator"19 android:layout_width="22dp"20 android:layout_height="22dp"/>2122<!-- The workspace contains 5 screens of cells -->23<!-- DO NOT CHANGE THE ID -->24<uncher3.Workspace25android:id="@+id/workspace"26 android:layout_width="match_parent"27 android:layout_height="match_parent"28 launcher:defaultScreen="@integer/config_workspaceDefaultScreen"29 launcher:pageIndicator="@+id/page_indicator"></uncher3.Workspace>3031<!-- DO NOT CHANGE THE ID -->32<include33android:id="@+id/hotseat"34 layout="@layout/hotseat"3536 android:layout_width="match_parent"37 android:layout_height="match_parent"/>3839<include40android:id="@+id/overview_panel"41 layout="@layout/overview_panel"42 android:visibility="gone"/>4344<!-- Keep these behind the workspace so that they are not visible when45 we go into AllApps -->46<include47android:id="@+id/page_indicator"48 layout="@layout/page_indicator"49 android:layout_width="wrap_content"50 android:layout_height="wrap_content"51 android:layout_gravity="center_horizontal"/>5253<include54android:id="@+id/search_drop_target_bar"5556 layout="@layout/search_drop_target_bar"/>5758<include59android:id="@+id/widgets_view"60 layout="@layout/widgets_view"61 android:layout_width="match_parent"62 android:layout_height="match_parent"63 android:visibility="invisible"/>6465<include66android:id="@+id/apps_view"67 layout="@layout/all_apps"68 android:layout_width="match_parent"69 android:layout_height="match_parent"70 android:visibility="invisible"/>71</uncher3.DragLayer>7273<ViewStub74android:id="@+id/launcher_overlay_stub"75 android:layout_width="match_parent"76 android:layout_height="match_parent"77 android:inflatedId="@+id/launcher_overlay"78 android:layout="@layout/launcher_overlay"/>79</uncherRootView>SearchDropTargetBar屏幕最上⽅有个搜索框,在我们拖动图标的时候,搜索框会替换成“删除“Workspace就是屏幕上左右滑的好⼏屏幕的容器CellLayoutWorkspace⾥⾯可以滑动的单独⼀屏,CellLayout负责图标和⼩部件的显⽰和整齐摆放。
要看launcher这部分,不记笔记没啥头绪。
这里先记录下来看到的东西,还是按各个文件来记。
一、与界面关系不是太大的部分主要是些数据的东西,为界面显示提供资料不直接参与到界面中。
LauncherApplication.java每个应用只能有一个application,而且应用起来第一个运行的就是application。
所以看Launcher第一个看这个java。
在这里onCreate()函数做了应用初始化的一堆活,其他几个函数做的活到可以不太去注意。
在onCreate()主要做了以下一些工作。
1. 获取屏幕的属性。
主要是大小和密度(分辨率)。
2. 初始化IconCache,这里主要保持各个应用对于的icon。
3. 初始化LauncherModel,在Launcher中界面无关的活大部分在这里面处理。
在这里同时还注册一堆事件给LauncherModel,包含应用删除,安装,变换事件(ACTION_PACKAGE_ADDED/REMOVED/CHANGED);外置存储卡的应用是否可用事件,这个事件可能会携带哪些应用的介绍(ACTION_EXTERNAL_APPLICATIONS_AVAILABLE/UNAVAILABLE);手机环境变换比如语言横竖屏之类的东西(ACTION_LOCALE_CHANGED/ ACTION_CONFIGURATION_CHANGED);搜索管理相关的变换(INTENT_GLOBAL_SEARCH_ACTIVITY_CHANGED/SEARCHABLES_CHANGED);还有个自身定义的消息(LauncherModel.SWITCH_SCENE_ACTION)。
4. 监控LauncherSettings.Favorites.CONTENT_URI。
这个发生变化时调用mModel.startLoader。
IconCache.javaINITIAL_ICON_CACHE_CAPACITYCacheEntry 结构体对于一个应用。
Hi,大家好:之前我在《Launcher简介》的文档中,写了关于Launcher的相关介绍。
但是,有地方没有完善,因此,我在这里添加以下,希望能帮助到你们!如果有新的添加,我会在以后逐渐加入,希望对大家有所帮助,谢谢~!一、主要文件和类uncher.java:launcher中主要的activity。
2.DragLayer.java:launcher layout的rootview。
DragLayer实际上也是一个抽象的界面,用来处理拖动和对事件进行初步处理然后按情况分发下去,角色是一个controller。
它首先用onInterceptTouchEvent(MotionEvent)来拦截所有的touch事件,如果是长按item拖动的话不把事件传下去,直接交由onTouchEvent()处理,这样就可以实现item的移动了,如果不是拖动item的话就把事件传到目标view,交有目标view的事件处理函数做相应处理。
如过有要对事件的特殊需求的话可以修改onInterceptTouchEvent(MotionEvent)来实现所需要的功能。
3. DragController.java:为Drag定义的一个接口。
包含一个接口,两个方法和两个静态常量。
接口为DragListener(包含onDragStart(),onDragEnd()两个函数),onDragStart()是在刚开始拖动的时候被调用,onDragEnd()是在拖动完成时被调用。
在launcher中典型的应用是DeleteZone,在长按拖动item时调用 onDragStart()显示,在拖动结束的时候onDragEnd()隐藏。
两个函数包括startDrag()和 setDragItemInfo().startDrag()用于在拖动是传递要拖动的item的信息以及拖动的方式,setDragItemInfo()用于传递item的参数信息(包括位置以及大小)。
LauncherLauncher主要修改涉及以下几个方面:一、默认界面配置,主要包括以下几个部分:1、桌面分屏个数,基础界面配置。
Android launcher 默认的界面配置是在default_workspace.xml中定制的,Launcher在第一次显示时会加载这个xml的数据。
default_workspace.xml主要是配置APP快捷方式、widget等,他里面常用的语法如下://default_workspace.xml中,支持的标签有:favorite:应用程序快捷方式。
shortcut:链接,如网址,本地磁盘路径等。
search:搜索框。
clock:桌面上的钟表Widget//支持的属性有:launcher:title:图标下面的文字,目前只支持引用,不能直接书写字符串;launcher:icon:图标引用;launcher:uri:链接地址,链接网址用的,使用shortcut标签就可以定义一个超链接,打开某个网址。
launcher:packageName:应用程序的包名;launcher:className:应用程序的启动类名;launcher:screen:图标所在的屏幕编号;launcher:x:图标在横向排列上的序号;launcher:y:图标在纵向排列上的序号;Launcher的默认分屏个数是可以定制的,这个是在workspace.xml中定制的,默认的是五个分屏,其实是包含了五个CellLayout。
也可以在Launcher.java中定制。
static final int SCREEN_COUNT = 5;static final int DEFAULT_SCREEN = 2;这里的意思是五个默认屏幕,将第三个屏幕作为默认页面,在xml中定义也是一样。
2、桌面图标定制Android原生图标大小都是可以定制的,配置路径在/res/values/dimens.xml。
Android中launcher的详细分析之前一度为如何判断当前所处的界面就是home主桌面而伤脑筋的,后来找到的方法也不是很理想,由此到现在看了launcher的分析,觉得很有帮助哈~这边给大家分享下哈~~~Linux kernel启动以后会通过app_main进程来初始化android Runtime Java运行环境,而zygote是Android的第一个进程。
所有的android的应用以及大部分系统服务都是通过zygote fork出来的子进程(我现在看到的只有native的service manager不是zygote fork出来的)。
在system server中启动的若干系统服务中与我们启动进程相关的就是Acitivity Manager。
当systerm server启动好所有服务以后,系统就进入”system ready”状态,这个时候Activity Manager就登场了。
Activity Manager光看代码行就知道是一个重量级的服务,它主要管理Activity之间的跳转,以及进程的生命周期。
当Activity Manager发现系统已经启动好以后它就会发出一个intent:java代码:1Intent intent = new Intent(mTopAction, mTopData != null ?Uri.parse(mTopData) : null);2intent.setComponent(mTopComponent);3if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) { 4intent.addCategory(Intent.CATEGORY_HOME);5}通过这个category类型为home的intent,Activity Manager就会通过:java代码:6startActivityLocked(null, intent, null, null, 0, aInfo, null, null, 0, 0, 0, false, false);启动Home进程了。
而这个启动Home进程的过程实际上还是去通过zygote fork出的一个子进程。
因此只要在manifest中具备这样的intent-filter都可以在开机的时候作为Home启动:java代码:7<intent-filter>8<action android:name="android.intent.action.MAIN" />9<category android:name="android.intent.category.HOME"/>10<category android:name="android.intent.category.DEFAULT" /> 11</intent-filter>多个home之间的switch会在开始的时候有个选择,至于这个选择好像是package manager来实现的,没有仔细研究过。
2.UI结构通过launcher/Res/Layout-land/launcher.xml分析可以得到主屏幕的UI结构:整个homescreen是一个包含三个child view的FrameLayout(uncher.DragLayer).第一个child就是桌面uncher.Workspace.这个桌面又包含三个child.每个child就对应一个桌面.这就是你在Android上看到的三个桌面.每个桌面上可以放置下列对象:应用快捷方式,appwidget和folder.第二个child是一个SlidingDrawer控件,这个控件由两个子控件组成.一个是uncher.HandleView,就是Android桌面下方的把手,当点击这个把手时,另一个子控件,uncher.AllAppsGridView就会弹出,这个子控件列出系统中当前安装的所有类型为uncher的Activity.第三个child是uncher.DeleteZone.当用户在桌面上长按一个widget时,把手位置就会出现一个垃圾桶形状的控件,就是这个控件.3.应用程序代码分析由Launcher中的AndroidManifest.xml可以看出整个Launcher的代码结构.首先,是一些权限的声明。
例如:java代码:12<uses-permission android:name="android.permission.CALL_PHONE" /> 13<uses-permissionandroid:name="android.permission.EXPAND_STATUS_BAR" />这部分可以略过;其次,Application的构成,如上图:(1)Launcher:HomeScreen的Activity。
java代码:14<intent-filter>15<action android:name="android.intent.action.MAIN" />16<category android:name="android.intent.category.HOME"/>17<category android:name="android.intent.category.DEFAULT" /> 18<category android:name="android.intent.category.MONKEY" /> </intent-filter>上面这段代码就标志着它是开机启动后Home的Activity。
通过Launcher.java中onCreat()的分析我们可以大致把握屏幕的主要活动:java代码:19protected void onCreate(Bundle savedInstanceState) {20super.onCreate(savedInstanceState);21//把xml文件的内容实例化到View中22mInflater = getLayoutInflater();23//监听应用程序控件改变事件24mAppWidgetManager = AppWidgetManager.getInstance(this);25mAppWidgetHost = new LauncherAppWidgetHost(this, APPWIDGET_HOST_ID);26mAppWidgetHost.startListening();27// 用于调试?28if (PROFILE_STARTUP) {29android.os.Debug.startMethodTracing("/sdcard/launcher");30}31//监听locale,mcc,mnc是否改变,如果改变,则重写新配置32//mcc:mobile country code(国家代码China 460); mnc:mobile network code(网络代码)33checkForLocaleChange();34/*This allows such applications to have a virtual wallpaper that is larger than the physical screen, matching the size of their workspace.*/35setWallpaperDimension();36//显示主屏幕UI元素,workspace,slidingdrawer(handleview andappgridview),deletezone37setContentView(uncher);38//Finds all the views we need and configure them properly.39//完成workspace,slidingdrawer,deletezone的各种事件操作和监听40setupViews();41//Registers various intent receivers.42//允许其他应用对本应用的操作43registerIntentReceivers();44//Registers various content observers.45//例如,注册一个内容观察者跟踪喜爱的应用程序46registerContentObservers();47//重新保存前一个状态(目的??)48mSavedState = savedInstanceState;49restoreState(mSavedState);50//调试?51if (PROFILE_STARTUP) {52android.os.Debug.stopMethodTracing();53}54//Loads the list of installed applications in mApplications.55if (!mRestoring) {56startLoaders();57}58// For handling default keys??59mDefaultKeySsb = new SpannableStringBuilder();60Selection.setSelection(mDefaultKeySsb, 0);61}方法onActivityResult():完成在workspace上增加shortcut,appwidge和Livefolder;方法onSaveInstantceState()和onRestoreInstanceState():为了防止Sensor、Land和Port布局自动切换时数据被置空,通过onSaveInstanceState方法可以保存当前窗口的状态,在即将布局切换前将当前的Activity压入历史堆栈.如果我们的Activity在后台没有因为运行内存吃紧被清理,则切换时回触发onRestoreIntanceState().(2)WallpaperChooser:设置墙纸.同理我们从onCreat()作为入口来分析这个活动的主要功能.java代码:62public void onCreate(Bundle icicle) {63super.onCreate(icicle);64//设置允许改变的窗口状态,需在 setContentView 之前调用65requestWindowFeature(Window.FEATURE_NO_TITLE);66/ /添加墙纸资源,将资源标识符加入到动态数组中67findWallpapers();68//显示墙纸设置屏幕的UI元素,Imageview,Gallery and Button(LinearLayout)69setContentView(yout.wallpaper_chooser);70//图片查看功能的实现71mGallery = (Gallery) findViewById(R.id.gallery);72mGallery.setAdapter(new ImageAdapter(this));73 mGallery.setOnItemSelectedListener(this);74 mGallery.setCallbackDuringFling(false);75//Button事件监听,点击选择setWallpaper(Resid)76 findViewById(R.id.set).setOnClickListener(this);77 mImageView = (ImageView) findViewById(R.id.wallpaper);78 }(3)default_searchable对于home中任意的Acitivty,使能系统缺省Search模式,这样就可以使用android 系统默认的search UI.(4)InstallShortcutReceiver:继承自BroadcastReceiver,重写onReceier()方法,对于发送来的Broadcast(这里指Intent)进行过滤(IntentFilt)并且响应(这里是InstallShortcut()).这里分析下onReceive():java代码:79<!-- Enable system-default search mode for any activity in Home --> 80<!-- Intent received used to install shortcuts from other applications -->81public void onReceive(Context context, Intent data) {82 //接受并过滤Intent83if (!ACTION_INSTALL_SHORTCUT.equals(data.getAction())) {84return;85}86 //获取屏幕87 int screen = Launcher.getScreen();88//安装快捷方式89if (!installShortcut(context, data, screen)) {90//如果屏幕已满,搜寻其他屏幕91for (int i = 0; i < Launcher.SCREEN_COUNT; i++) {92 if (i != screen && installShortcut(context, data, i)) break;93}94}95}其中IntallShortcut()方法:首先,对传入的坐标进行判断(findEmptyCell()),如果是空白位置,则可以放置快捷方式;其次,缺省情况下,我们允许创建重复的快捷方式,具体创建过程(addShortcut())就是把快捷方式的信息传入数据库(addItemToDatabase ()).(5)UninstallShortcutReceiver:同理,UninstallShortcutReceiver()继承自BroadcastReceiver(),实现onReceiver()方法.定义一个ContentResolver对象完成对数据库的访问和操作(通过URI定位),进而删除快捷方式 .(6)LauncherProvider:继承自ContentProvider(),主要是建立一个数据库来存放HomeScreen中的数据信息,并通过内容提供者来实现其他应用对launcher中数据的访问和操作.重写了ContentProvider()中的方法:getType():返回数据类型.如果有自定义的全新类型,通过此方法完成数据的访问.query():查询数据.传入URI,返回一个Cursor对象,通过Cursor完成对数据库数据的遍历访问.Insert():插入一条数据.bulkInsert():大容量数据的插入.delete():删除一条数据.update():更改一条数据.sendNotify():发送通知.类DatabaseHelper继承自一个封装类SQLiteOpenHelper(),方便了数据库的管理和维护.重写的方法:onCreate():创建一个表.其中db.execSQL()方法执行一条SQL语句,通过一条字符串执行相关的操作.当然,对SQL基本语句应该了解.onUpgrade():升级数据库.对HomeScreen数据库操作的一些方法:addClockWidget(),addSearchWidget,addShortcut,addAppShortcut,loadFavorites(),launcherAppWidgetBinder(),convertWidget(),updateContactsShortcuts(),copyFromCursor()补充:类AddAdapter(AddAdapter.java)列出了这四个类型对象。