Android Launcher 分析

1. Launcher的启动过程

从网络上找了一段关于Launcher的启动过程的文章,作为学习Launcher的背景知识:

Linux kernel启动以后会通过app_main进程来初始化android Runtime Java运行环境,而zygoteAndroid的第一个进程。所有的android的应用以及大部分系统服务都是通过zygote fork出来的子进程(我现在看到的只有native的service manager不是zygote fork出来的)。在system server中启动的若干系统服务中与我们启动进程相关的就是Acitivity Manager

  当systerm server启动好所有服务以后,系统就进入”system ready”状态,这个时候Activity Manager就登场了。Activity Manager光看代码行就知道是一个重量级的服务,它主要管理Activity之间的跳转,以及进程的生命周期。当Activity Manager发现系统已经启动好以后它就会发出一个intent:

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);  
}  
通过这个category类型为home的intent,Activity Manager就会通过:

startActivityLocked(null, intent, null, null, 0, aInfo,  
 null, null, 0, 0, 0, false, false);  
启动Home进程了。而这个启动Home进程的过程实际上还是去通过zygote fork出的一个子进程。
因此只要在manifest中具备这样的intent-filter都可以在开机的时候作为Home启动:
<intent-filter>  
<action android:name="android.intent.action.MAIN" />  
<category android:name="android.intent.category.HOME"/>  
<category android:name="android.intent.category.DEFAULT" />  
</intent-filter> 

多个home之间的switch会在开始的时候有个选择,至于这个选择好像是package manager来实现的,没有仔细研究过。

2.UI结构
通过launcher/Res/Layout-land/launcher.xml分析可以得到主屏幕的UI结构:



整个homescreen是一个包含三个child view的FrameLayout(com.android.launcher.DragLayer)。


第一个child就是桌面com.android.launcher.Workspace。这个桌面又包含三个child。每个child就对应一个桌面。这就是你在Android上看到的三个桌面。每个桌面上可以放置下列对象:应用快捷方式,appwidget和folder。


第二个child是一个SlidingDrawer控件,这个控件由两个子控件组成。一个是com.android.launcher.HandleView,就是Android桌面下方的把手,当点击这个把手时,另一个子控件,com.android.launcher.AllAppsGridView就会弹出,这个子控件列出系统中当前安装的所有类型为category.launcher的Activity。


第三个child是com.android.launcher.DeleteZone。当用户在桌面上长按一个widget时,把手位置就会出现一个垃圾桶形状的控件,就是这个控件。

3.应用程序代码分析
由Launcher中的AndroidManifest.xml可以看出整个Launcher的代码结构。


首先,是一些权限的声明。例如:

<uses-permission android:name="android.permission.CALL_PHONE" />  
<uses-permission android:name="android.permission.EXPAND_STATUS_BAR" />  

这部分可以略过;


其次,Application的构成,如上图:

(1)Launcher:HomeScreen的Activity。

<intent-filter>  
 <action android:name="android.intent.action.MAIN" />  
 <category android:name="android.intent.category.HOME"/>  
 <category android:name="android.intent.category.DEFAULT" />  
<category android:name="android.intent.category.MONKEY" /> 
</intent-filter>  
上面这段代码就标志着它是开机启动后Home的Activity。通过Launcher.java中onCreate()的分析我们可以大致把握屏幕的主要活动:
protected void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
//把xml文件的内容实例化到View中  
        mInflater = getLayoutInflater();  
//监听应用程序控件改变事件  
        mAppWidgetManager = AppWidgetManager.getInstance(this);  
        mAppWidgetHost = new LauncherAppWidgetHost(this, APPWIDGET_HOST_ID);  
        mAppWidgetHost.startListening();  
// 用于调试?      
        if (PROFILE_STARTUP) {  
            android.os.Debug.startMethodTracing("/sdcard/launcher");  
        }  
  //监听locale,mcc,mnc是否改变,如果改变,则重写新配置  
      //mcc:mobile country code(国家代码China 460); mnc:mobile network code(网络代码)  
        checkForLocaleChange();  
       /*This allows such applications to have a virtual wallpaper that is larger than the physical screen, matching the size of their workspace.*/  
        setWallpaperDimension();  
//显示主屏幕UI元素,workspace,slidingdrawer(handleview and appgridview),deletezone  
        setContentView(R.layout.launcher);  
//Finds all the views we need and configure them properly.  
//完成workspace,slidingdrawer,deletezone的各种事件操作和监听  
        setupViews();  
//Registers various intent receivers.  
//允许其他应用对本应用的操作  
        registerIntentReceivers();  
//Registers various content observers.  
//例如,注册一个内容观察者跟踪喜爱的应用程序  
        registerContentObservers();  
//重新保存前一个状态(目的??)  
        mSavedState = savedInstanceState;  
        restoreState(mSavedState);  
//调试?  
        if (PROFILE_STARTUP) {  
            android.os.Debug.stopMethodTracing();  
        }  
//Loads the list of installed applications in mApplications.  
        if (!mRestoring) {  
            startLoaders();  
        }  
        // For handling default keys??  
        mDefaultKeySsb = new SpannableStringBuilder();  
        Selection.setSelection(mDefaultKeySsb, 0);  
    }  
方法onActivityResult():完成在workspace上增加shortcut,appwidge和Livefolder;


方法onSaveInstantceState()和onRestoreInstanceState():为了防止Sensor、Land和Port布局自动切换时数据被置空,通过onSaveInstanceState方法可以保存当前窗口的状态,在即将布局切换前将当前的Activity压入历史堆栈。如果我们的Activity在后台没有因为运行内存吃紧被清理,则切换时回触发onRestoreIntanceState()。
(2)WallpaperChooser:设置墙纸。
同理我们从onCreate()作为入口来分析这个活动的主要功能。
public void onCreate(Bundle icicle) {  
        super.onCreate(icicle);  
//设置允许改变的窗口状态,需在 setContentView 之前调用  
        requestWindowFeature(Window.FEATURE_NO_TITLE);  
/ /添加墙纸资源,将资源标识符加入到动态数组中  
        findWallpapers();  
//显示墙纸设置屏幕的UI元素,Imageview,Gallery and Button(LinearLayout)  
        setContentView(R.layout.wallpaper_chooser);  
//图片查看功能的实现  
        mGallery = (Gallery) findViewById(R.id.gallery);  
        mGallery.setAdapter(new ImageAdapter(this));  
        mGallery.setOnItemSelectedListener(this);  
        mGallery.setCallbackDuringFling(false);  
//Button事件监听,点击选择setWallpaper(Resid)  
        findViewById(R.id.set).setOnClickListener(this);  
        mImageView = (ImageView) findViewById(R.id.wallpaper);  
    }  

(3)default_searchable

对于home中任意的Acitivty,使能系统缺省Search模式,这样就可以使用android系统默认的search UI

(4)InstallShortcutReceiver

继承自BroadcastReceiver,重写onReceiver()方法,对于发送来的Broadcast(这里指Intent)进行过滤(IntentFilter)并且响应(这里是InstallShortcut())。这里分析下onReceive():

<!-- Enable system-default search mode for any activity in Home -->  
<!-- Intent received used to install shortcuts from other applications -->  
public void onReceive(Context context, Intent data) {  
       //接受并过滤Intent  
if (!ACTION_INSTALL_SHORTCUT.equals(data.getAction())) {  
            return;  
        }  
      //获取屏幕  
        int screen = Launcher.getScreen();  
//安装快捷方式  
        if (!installShortcut(context, data, screen)) {  
            //如果屏幕已满,搜寻其他屏幕  
            for (int i = 0; i < Launcher.SCREEN_COUNT; i++) {  
                if (i != screen && installShortcut(context, data, i)) break;  
            }  
        }  
    }  

其中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)列出了这四个类型对象。当用户在桌面空白处长按时,下列函数序列被执行:
Launcher::onLongClick -->
Launcher::showAddDialog -->
Launcher::showDialog(DIALOG_CREATE_SHORTCUT); -->
Launcher::onCreateDialog -->
Launcher::CreateShortcut::createDialog:这个函数创建一个弹出式对话框,询问用户是要添加什么(快捷方式,appwidget, 文件夹和墙纸)其内容就来自AddAdapter。
类DesktopItemsLoader负责将桌面上所有的对象从content provider中提取。
线程private ApplicationsLoader mApplicationsLoader负责从包管理器中获取系统中安装的应用列表。(之后显示在AllAppsGridView上)。ApplicationsLoader::run实现:
1)通过包管理器列出系统中所有类型为Launcher,action为MAIN的activity;
2)对每一个Activity,
      a) 将Activity相关元数据信息,如title, icon, intent等缓存到appInfoCache;
        b) 填充到ApplicationsAdapter 中。填充过程中用到了一些小技巧,每填充4(UI_NOTIFICATION_RATE)个activity更新一下相应view。

在Launcher::onCreate中,函数startLoaders被调用。而该函数接着调用loadApplications和loadUserItems,分别获取系统的应用列表,以及显示在桌面上的对象列表(快捷方式,appwidget,folder等)。
Launcher上排列的所有应用图标由AllAppsGridView对象呈现。这个对象是一个GridView。其对应的Adapter是ApplicationsAdapter,对应的model则是ApplicationInfo数组。数组内容是由ApplicationsLoader装载的。





  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Android LauncherAndroid系统中的一个应用程序,它是用户与设备交互的主要界面。它提供了桌面、应用程序列表、小部件等功能,用户可以通过它来启动应用程序、查看通知、管理设备等。 Android Launcher的源码分析主要包括以下几个方面: 1. 桌面布局:Android Launcher的桌面布局是通过GridView实现的,它可以显示应用程序图标和小部件。在源码中,可以看到GridView的相关代码,包括布局、适配器等。 2. 应用程序列表:Android Launcher应用程序列表是通过ListView实现的,它可以显示所有安装的应用程序。在源码中,可以看到ListView的相关代码,包括布局、适配器等。 3. 搜索功能:Android Launcher提供了搜索功能,用户可以通过输入关键字来搜索应用程序、联系人等。在源码中,可以看到搜索框的相关代码,包括布局、事件处理等。 4. 桌面小部件:Android Launcher支持桌面小部件,用户可以在桌面上添加各种小部件,如天气、时钟、日历等。在源码中,可以看到小部件的相关代码,包括布局、事件处理等。 5. 动画效果:Android Launcher提供了各种动画效果,如应用程序图标的放大缩小、桌面的动等。在源码中,可以看到动画效果的相关代码,包括属性动画、插值器等。 总之,Android Launcher的源码分析涉及到很多方面,需要深入研究才能掌握。 ### 回答2: Android launcher是一个重要的应用程序,它是用户的桌面界面,负责管理应用程序、小部件、壁纸等的展示和操作。在Android开发中,我们可以使用默认的系统Launcher也可以自定义Launcher,下面就来分析一下Android Launcher的源码。 1. Launcher的结构分析 Launcher的展示分为三个层次:桌面、工作区和屏幕。在源码中,它们分别对应着Launcher、Workspace和CellLayout。Launcher类是整个应用程序的外壳,它管理了整个应用程序的生命周期。Workspace管理着桌面上的工作区,它可以管理多个屏幕。而CellLayout则是每个工作区上的单元格容器,用于展示应用程序和小部件的图标。 2. Launcher的主界面 Launcher的主界面一般包括一个搜索栏、一个Dock栏和一个应用程序列表。其中搜索栏和Dock栏是Launcher的核心部分,它们的实现都是需要注意的: 2.1 搜索栏 Launcher的搜索栏是通过SearchView实现的,需要处理SearchView的监听事件和搜索逻辑。其中监听事件可以根据具体需求进行定制,比如支持模糊搜索、联想搜索等。 2.2 Dock栏 Dock栏是一个固定在桌面底部的横向图标栏,它可以管理常用的应用程序和快捷方式。Dock栏的实现需要考虑如下几个问题: - 图标的布局 - 图标的拖动 - 图标的排序 - 图标的管理 3. Workspace实现分析 Workspace是Launcher的核心部分,它基本实现了所有的界面交互逻辑。在Workspace上,用户可以添加、移动、删除应用程序和小部件。Workspace的实现需要考虑如下几个问题: 3.1 桌面上的应用程序和小部件布局 Workspace上的每个屏幕都是通过CellLayout实现的,它负责管理应用程序和小部件的布局和显示。 3.2 图标的拖动和排序 用户可以通过拖动来移动和排序图标,需要考虑如下几个问题: - 拖动的实现逻辑 - 动过程的动画效果 - 拖动时的图标缩放效果 3.3 图标的删除和添加 用户可以通过长按图标来触发删除操作,也可以通过添加菜单来添加新的应用程序和小部件。 4. 总结 以上是针对Android Launcher源码的分析,这些内容只是基础的使用方法和思路,具体的实现还需要根据自己的需求和场景进行定制和优化。在实现Launcher的时候,需要注意性能问题,尽量避免不必要的计算和操作;同时,还需要考虑到用户的交互体验,保证操作的流畅和直观。 ### 回答3: Android LauncherAndroid手机主屏幕上最常见的应用,它提供了一个桌面环境和一些关键功能,如快速访问应用程序、设置壁纸、小部件和通知中心等。本文将对Android Launcher源码进行分析,重点关注Launcher的核心组件:Workspace、Folder、App Drawer和Widget。 首先,Workspace是Launcher中最核心的组件之一,它是桌面上的容器,用于展示应用程序图标和小部件。Workspace是一个基于GridView组件自定义的ViewGroup,用于支持动手势和快捷方式的编辑管理。Framework层通过Workspace类读取和更新数据,它通过扩展Adapter来创建UI元素,并通过GridLayoutManager装填与交换元素。 其次,Folder是Launcher用于存储和管理应用程序快捷方式的组件。Folder的UI元素扩展自ViewGroup,可以包含多个应用快捷方式,在Folder中用户可以自由地添加、删除和排序快捷方式。Folder同时提供一个搜索框,用于帮助用户快速搜索自己的应用程序。 其次,App Drawer是Launcher的另一个核心组件,它是一个垂直滚动的列表,用于展示所有的应用程序。App Drawer是按字母排序的,同时可以通过搜索框查找用户需要的特定应用程序。App Drawer实现类似于Workspace,只不过它只横向的有一个方向轴且没有操作修改排序功能。 最后,Widget是一个独特的组件,它是一些非小部件的快捷方式,用户可以将它们放置在桌面上。Widget允许用户在主屏幕上快速访问特定功能或信息,例如天气、电子邮件和日历等。Widget UI元素的设计与Folder和App Drawer不同,它们提供更多信息和控制,通常需要桌面空间大才能放下。 总体而言,Android Launcher的源码分析需要涉及多个关键组件,Workspace、Folder、App Drawer和Widget是其中最重要的几个。这些组件深度整合在Launcher中,可以帮助用户快速访问他们需要的应用程序和信息。因此,熟练掌握这些核心组件的基本实现和逻辑是Android开发者不可或缺的技能之一。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值