第一部分:Launcher APP 组成分析(一)
2014-04-07 15:49
204 查看
为何会分析小米系统?
我算是个米粉吧,从10年开始就用HTC G7刷MIUI系统。从此就一直使用MIUI,对于小米系统MIUI,我还是给予很高的评价。好了,这里不是广告。
继续回答问题:第一,感觉MIUI系统从更新V5版本以后没有再大的更新,似我这种对新鲜事物和技术的渴求,让我挺失望。第二,MIUI系统号称是开源了PatchROM, 实质这是开放了一些APK。对于我,远远不能满足。虽说,在学习Android的几年过程中也对MIUI有过分析,但是毕竟公司的事情也是非常多,对MIUI系统的分析总是不够完整和系统。
近期,努力的抽出时间来对MIUI做一个系统的分析。
废话不多说,开始我们的MIUI系统之旅。
话在开头:本博客仅对MIUI系统做学习交流使用,不存在商业行为。如若本博客中的文字及图片对MIUI系统有侵权行为还请及时通知与我,我会根据相关规定做出处理。谢谢大家的支持!
简介:
1. MIUI系统分析的内容基于MIUI PatchROM- ICS的版本,不能完全适应于最新的V5系统;
2. 分析过程中会针对Android原生的源代码进行相互的比较,分析出各自的优势及其缺点;
第一章: MIUI系统之Launcher分析
首先,读者最好对Launcher的源码有过简单的阅读和了解。
分析的源码会在http://github.com/mimijava/MKHome逐步上传。
第一部分:Launcher APP 组成分析
一、从Android四大组件开始介绍,我们都知道Android四大组件: Activity,Service服务,Content Provider内容提供者,BroadcastReceiver广播接收器;
1. Activity:MIUI系统有哪些主要的Activity呢?
4. Content Provider内容提供者:
此处关注一个桌面最重要的三处,mModel, startLoader、 setupViews();、mDragController,
第一个是桌面上的数据,第二个是桌面的布局,第三个是对桌面的操作及控制。虽然这样说是很简单,一个桌面不外乎这几点,但是慢慢分析才会知道其中的复杂,三者之间的互相联系及依赖的关系往往让阅读代码的人头疼。大道至简,我们就慢慢的分析,一丝一丝的剥离出来。
(2). Launcher的布局,MIUI的布局由Launcher.xml来做为整体的布局,其文件在res/layout/launcher.xml中,可以在我的Github中找到。其组成如下:
1. DragLayer 实际就是一个FrameLayout;
2. Workspace及WorkspaceThumbnailView实际为一个ViewGroup;
3. Hotseat及DeleteZone
以上这个只是桌面的一个整体布局,桌面上比如图标,WIDGET,文件夹等都有各自的布局格式,这些最后都会作为 Workspace的子控件放入其中,这部分等以后慢慢再道来。
(3). setupViews();
(图1)Launcher布局概略图
上图中其中Workspace为ViewGroup布局,APP、FLODER、WIDGET/GADGET为其子视图,都有各自的视图结构,此处不做介绍,等介绍到时再做分析;
三、Launcher Provider
为了后续读取的桌面布局及手机中的APP、WIDGET摆放位置,首先需要建立一个SQL数据表来保存这些数据,在Provider中创建一个Favorites表。其数据结构如上所示。
PS: 由于以前没有系统完整的写过博客,使用起来比较生疏,第一章节博客布局和格式问题花了点时间在弄好。觉得我分析的不好或者进度太慢的同学请到我的Github下载代码自己研究研究。地址为: http://github.com/mimijava/MKHome/
我的微博: http://weibo.com/ison7 欢迎关注!
我算是个米粉吧,从10年开始就用HTC G7刷MIUI系统。从此就一直使用MIUI,对于小米系统MIUI,我还是给予很高的评价。好了,这里不是广告。
继续回答问题:第一,感觉MIUI系统从更新V5版本以后没有再大的更新,似我这种对新鲜事物和技术的渴求,让我挺失望。第二,MIUI系统号称是开源了PatchROM, 实质这是开放了一些APK。对于我,远远不能满足。虽说,在学习Android的几年过程中也对MIUI有过分析,但是毕竟公司的事情也是非常多,对MIUI系统的分析总是不够完整和系统。
近期,努力的抽出时间来对MIUI做一个系统的分析。
废话不多说,开始我们的MIUI系统之旅。
话在开头:本博客仅对MIUI系统做学习交流使用,不存在商业行为。如若本博客中的文字及图片对MIUI系统有侵权行为还请及时通知与我,我会根据相关规定做出处理。谢谢大家的支持!
简介:
1. MIUI系统分析的内容基于MIUI PatchROM- ICS的版本,不能完全适应于最新的V5系统;
2. 分析过程中会针对Android原生的源代码进行相互的比较,分析出各自的优势及其缺点;
第一章: MIUI系统之Launcher分析
首先,读者最好对Launcher的源码有过简单的阅读和了解。
分析的源码会在http://github.com/mimijava/MKHome逐步上传。
第一部分:Launcher APP 组成分析
一、从Android四大组件开始介绍,我们都知道Android四大组件: Activity,Service服务,Content Provider内容提供者,BroadcastReceiver广播接收器;
1. Activity:MIUI系统有哪些主要的Activity呢?
<!-- 主界面 --> <activity android:name="cn.minking.launcher.Launcher" android:clearTaskOnLaunch="true" android:stateNotNeeded="true" android:theme="@style/Theme" android:launchMode="singleTask" android:screenOrientation="sensorPortrait" android:configChanges="mcc|mnc|keyboard|keyboardHidden|navigation|orientation|uiMode|screenSize"> <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"/> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <!-- 设置界面 --> <activity android:label="@string/preferences_title" android:name="cn.minking.launcher.LauncherPreferenceActivity" > </activity>
2. Service 服务,MIUI Launcher中是有一个服务的,但是不是特别重要,在此不做介绍。 3.BroadcastReceiver广播接收器:
<!-- 安装APP --> <receiver android:name="cn.minking.launcher.InstallShortcutReceiver" android:permission="com.android.launcher.permission.INSTALL_SHORTCUT"> <intent-filter > <action android:name="com.android.launcher.action.INSTALL_SHORTCUT"/> </intent-filter> </receiver> <!-- 删除APP --> <receiver android:name="cn.minking.launcher.UninstallShortcutReceiver" android:permission="com.android.launcher.permission.UNINSTALL_SHORTCUT"> <intent-filter > <action android:name="com.android.launcher.action.UNINSTALL_SHORTCUT"/> </intent-filter> </receiver> <!-- 安装Widget --> <receiver android:name="cn.minking.launcher.InstallWidgetReceiver" android:permission="com.android.launcher.permission.INSTALL_WIDGET"> <intent-filter> <action android:name="com.android.launcher.action.INSTALL_WIDGET" /> </intent-filter> </receiver> <!-- 存储信息 --> <receiver android:name="cn.minking.launcher.RestoreFinishedReceiver"> <intent-filter> <action android:name="android.intent.action.RESTORE_FINISH" /> </intent-filter> </receiver>
4. Content Provider内容提供者:
<!-- 数据存储 --> <provider android:name="cn.minking.launcher.LauncherProvider" android:readPermission="com.android.launcher.permission.READ_SETTINGS" android:writePermission="com.android.launcher.permission.WRITE_SETTINGS" android:authorities="cn.minking.launcher.settings"/>
二、Launcher Activity的布局分析; 首先看onCreate函数, 下面这个部分是根据MIUI系统及Android原生代码写出的几个重要方法入口及变量的初始化,
/******* 数据 ********/ private LauncherModel mModel; private IconCache mIconCache; /******* 桌面内容 ********/ private DragLayer mDragLayer; private DragController mDragController; private Workspace mWorkspace; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Log.d(TAG, "onCreate"); Window localWindow = getWindow(); localWindow.setFlags(WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN, WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN); // 是否全屏显示,不带状态栏 //localWindow.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, //WindowManager.LayoutParams.FLAG_FULLSCREEN); //mIsHardwareAccelerated = ((Window)(localWindow)).getWindowManager().isHardwareAccelerated(); LauncherApplication launcherApplication = (LauncherApplication)getApplication(); // MODEL与 LAUNCHER APP 绑定 mModel = launcherApplication.setLauncher(this); mIconCache = launcherApplication.getIconCache(); // 分配拖动控制器 mDragController = new DragController(this); registerContentObservers(); // 应用消息 mApplicationsMessage = new ApplicationsMessage(this); setWallpaperDimension(); // 设置Launcher布局 setContentView(R.layout.launcher); setupViews(); if (!mRestoring) { /// M: 如果本地信息变更了,设置为重新装载所有信息 if (sLocaleChanged) { mModel.resetLoadedState(true, true); sLocaleChanged = false; } mIsLoadingWorkspace = true; if (sPausedFromUserAction) { // 如果用户离开了launcher, 只需要在回到launcher的时候异步的完成装载 mModel.startLoader(getApplicationContext(), true); } else { // 如果用户旋转屏幕或更改配置,则同步装载 mModel.startLoader(getApplicationContext(), true); } } }
此处关注一个桌面最重要的三处,mModel, startLoader、 setupViews();、mDragController,
第一个是桌面上的数据,第二个是桌面的布局,第三个是对桌面的操作及控制。虽然这样说是很简单,一个桌面不外乎这几点,但是慢慢分析才会知道其中的复杂,三者之间的互相联系及依赖的关系往往让阅读代码的人头疼。大道至简,我们就慢慢的分析,一丝一丝的剥离出来。
(2). Launcher的布局,MIUI的布局由Launcher.xml来做为整体的布局,其文件在res/layout/launcher.xml中,可以在我的Github中找到。其组成如下:
<?xml version="1.0" encoding="utf-8"?> <cn.minking.launcher.DragLayer android:id="@id/drag_layer" android:layout_width="fill_parent" android:layout_height="fill_parent" xmlns:android="http://schemas.android.com/apk/res/android"> <!-- 整个桌面的显示,包括背景,不包括小图标状态栏 --> <FrameLayout android:id="@id/screen" android:layout_width="fill_parent" android:layout_height="fill_parent"> <!-- 桌面背景 --> <cn.minking.launcher.Background android:id="@id/drag_layer_background" android:layout_width="fill_parent" android:layout_height="fill_parent" /> <!-- 所有内容显示区 --> <cn.minking.launcher.Workspace android:id="@id/workspace" android:paddingTop="@dimen/status_bar_height" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_marginBottom="@dimen/workspace_margin_bottom" /> <!-- 缩略图显示 --> <cn.minking.launcher.WorkspaceThumbnailView android:id="@id/workspace_preview" android:paddingTop="@dimen/status_bar_height" android:visibility="invisible" android:layout_width="fill_parent" android:layout_height="fill_parent" /> <!-- 桌面HOTSEAT区 --> <cn.minking.launcher.HotSeats android:id="@id/hot_seats" android:gravity="center" android:layout_gravity="bottom" android:background="@drawable/hotseat_background" android:paddingLeft="@dimen/hotseats_padding_side" android:paddingRight="@dimen/hotseats_padding_side" android:paddingTop="@dimen/hotseats_padding_top" android:paddingBottom="@dimen/hotseats_padding_bottom" android:animationCache="false" android:layout_width="fill_parent" android:layout_height="wrap_content" /> <!-- 删除区 --> <cn.minking.launcher.DeleteZone android:id="@id/delete_zone" android:layout_gravity="top" android:background="@null" android:orientation="horizontal" android:visibility="invisible" android:layout_width="fill_parent" android:layout_height="wrap_content" > <!-- 动画显示删除图标 --> <ImageView android:id="@id/trash" android:background="@drawable/delete_zone_selector" android:visibility="invisible" android:layout_width="fill_parent" android:layout_height="wrap_content" android:src="@drawable/delete_zone_01" android:scaleType="center" /> <!-- 删除提示 --> <TextView android:id="@id/editing_tips" android:layout_gravity="top|center" android:paddingTop="13.0dip" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/editing_tips" style="@style/WorkspaceIconTitle.notification" /> </cn.minking.launcher.DeleteZone> </FrameLayout> <include layout="@layout/folder_cling" /> <!-- 小图标状态栏显示区域 --> <FrameLayout android:paddingTop="@dimen/status_bar_height" android:layout_width="1.0px" android:layout_height="fill_parent"> <FrameLayout android:id="@id/default_position" android:layout_width="1.0px" android:layout_height="fill_parent" /> </FrameLayout> </cn.minking.launcher.DragLayer>
1. DragLayer 实际就是一个FrameLayout;
2. Workspace及WorkspaceThumbnailView实际为一个ViewGroup;
3. Hotseat及DeleteZone
以上这个只是桌面的一个整体布局,桌面上比如图标,WIDGET,文件夹等都有各自的布局格式,这些最后都会作为 Workspace的子控件放入其中,这部分等以后慢慢再道来。
(3). setupViews();
private void setupViews() { // Drag 控制器 DragController dragController = mDragController; // Drag 层 mDragLayer = (DragLayer)findViewById(R.id.drag_layer); mDragLayerBackground = (Background)findViewById(R.id.drag_layer_background); mDragLayer.setDragController(dragController); mDragLayer.setLauncher(this); mScreen = findViewById(R.id.screen); // 桌面布局 mWorkspace = (Workspace)mDragLayer.findViewById(R.id.workspace); Workspace workspace = mWorkspace; mWorkspacePreview = (WorkspaceThumbnailView)mDragLayer.findViewById(R.id.workspace_preview); workspace.setHapticFeedbackEnabled(false); workspace.setOnLongClickListener(this); workspace.setDragController(dragController); workspace.setLauncher(this); workspace.setThumbnailView(mWorkspacePreview); // 删除区 mDeleteZone = (DeleteZone)mDragLayer.findViewById(R.id.delete_zone); mDeleteZone.setLauncher(this); mDeleteZone.setDragController(dragController); // HOTSEAT mHotSeats = (HotSeats)mDragLayer.findViewById(R.id.hot_seats); mHotSeats.setLauncher(this); mHotSeats.setDragController(dragController); mFolderCling = (FolderCling)findViewById(R.id.folder_cling); mFolderCling.setLauncher(this); mFolderCling.setDragController(dragController); // 设置拖动控制 dragController.setDragScoller(workspace); dragController.addDragListener(mDeleteZone); dragController.setScrollView(mDragLayer); dragController.setMoveTarget(workspace); dragController.addDropTarget(mHotSeats); dragController.addDropTarget(workspace); dragController.addDropTarget(mDeleteZone); setupAnimations(); mPositionSnap = mDragLayer.findViewById(R.id.default_position); }
(图1)Launcher布局概略图
上图中其中Workspace为ViewGroup布局,APP、FLODER、WIDGET/GADGET为其子视图,都有各自的视图结构,此处不做介绍,等介绍到时再做分析;
三、Launcher Provider
@Override public void onCreate(SQLiteDatabase db) { mMaxId = 1L; // 创建 favorites 数据库表 db.execSQL("DROP TABLE IF EXISTS favorites"); db.execSQL("CREATE TABLE favorites(" + "_id INTEGER PRIMARY KEY," + "title TEXT," + "intent TEXT," + "container INTEGER," + "screen INTEGER," + "cellX INTEGER," + "cellY INTEGER," + "spanX INTEGER," + "spanY INTEGER," + "itemType INTEGER," + "appWidgetId INTEGER NOT NULL DEFAULT -1," + "isShortcut INTEGER," + "iconType INTEGER," + "iconPackage TEXT," + "iconResource TEXT," + "icon BLOB," + "uri TEXT," + "displayMode INTEGER," + "launchCount INTEGER NOT NULL DEFAULT 1," + "sortMode INTEGER," + "itemFlags INTEGER NOT NULL DEFAULT 0" + ");"); if (mAppWidgetHost != null) { mAppWidgetHost.deleteHost(); sendAppWidgetResetNotify(); } // 读取XML中的预设配置 loadFavorites(db); // 创建WORKSPACE中的Screen表 createScreensTable(db); }
为了后续读取的桌面布局及手机中的APP、WIDGET摆放位置,首先需要建立一个SQL数据表来保存这些数据,在Provider中创建一个Favorites表。其数据结构如上所示。
// 创建 screens 数据库表 db.execSQL("DROP TABLE IF EXISTS screens"); db.execSQL("CREATE TABLE screens(" + "_id INTEGER PRIMARY KEY," + "title TEXT," + "screenOrder INTEGER NOT NULL DEFAULT -1);");
PS: 由于以前没有系统完整的写过博客,使用起来比较生疏,第一章节博客布局和格式问题花了点时间在弄好。觉得我分析的不好或者进度太慢的同学请到我的Github下载代码自己研究研究。地址为: http://github.com/mimijava/MKHome/
我的微博: http://weibo.com/ison7 欢迎关注!
相关文章推荐
- 使用ViewPager实现高仿launcher左右拖动效果
- Launcher源码初探
- Andorid Launcher程序代码分析
- MIUI v5 UI设计七宗罪:去Android努力注定失败
- Android4.2 使preinstall中的所有应用正常显示在launcher的默认布局中
- Launcher中配置文件夹方法
- 学习 miui 移值
- 小米手机-米1 wifi密码输入正确但还是被提示密码错误
- laucher研究(一)
- Android 拿到所有 Launcher app icon
- 简单的Launcher
- Android开机自启动Launcher定制
- Android获取快捷方式图标信息
- Launcher与普通Activity的区别
- Launcher修改默认壁纸(default_wallpaper.drawable)
- Android 入门 - 系统启动简介
- android图标的制作
- 金立E6刷MIUI V5教程
- Android常用适配器分析(如何制作简易Launcher)