1.Launcher的启动过程

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

Linuxkernel 启动以后会通过 a pp_main 进程来初始化androidRuntimeJava运行环境,而 zygote A ndroid的第一个进程。所有的android的应用以及大部分系统服务都是通过zygotefork出来的子进程( 我现在看到的只有native的servicemanager不是zygotefork出来的) 。在systemserver中启动的若干系统服务中与我们启动进程相关的就是 AcitivityManager

当systermserver启动好所有服务以后,系统就进入”systemready”状态,这个时候ActivityManager就登场了。ActivityManager光看代码行就知道是一个重量级的服务,它主要管理Activity之间的跳转,以及进程的生命周期。当ActivityManager发现系统已经启动好以后它就会发出一个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,ActivityManager就会通过:
 startActivityLocked(null, intent, null, null, 0, aInfo,  null, null, 0, 0, 0, false, false);

启动 Home 进程了。而这个启动Home进程的过程实际上还是去通过zygotefork出的一个子进程。 因此只要在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会在开始的时候有个选择,至于这个选择好像是packagemanager来实现的,没有仔细研究过。

2.UI结构

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

整个homescreen是一个包含三个childview的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)LauncherHomeScreenActivity

<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>

上面这段代码就标志着它是开机启动后HomeActivity。通过Launcher.javaonCreat()的分析我们可以大致把握屏幕的主要活动:

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上增加shortcutappwidgeLivefolder

方法onSaveInstantceState()onRestoreInstanceState():为了防止SensorLandPort布局自动切换时数据被置空,通过onSaveInstanceState方法可以保存当前窗口的状态,在即将布局切换前将当前的Activity压入历史堆栈。如果我们的Activity在后台没有因为运行内存吃紧被清理,则切换时回触发onRestoreIntanceState()


(2)WallpaperChooser:设置墙纸。

同理我们从onCreat()作为入口来分析这个活动的主要功能。

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系统默认的searchUI


(4)InstallShortcutReceiver

继承自BroadcastReceiver,重写onReceier()方法,对于发送来的Broadcast(这里指Intent)进行过滤(IntentFilt)并且响应(这里是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) {       //接受并过滤Intentif (!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负责将桌面上所有的对象从contentprovider中提取。

线程privateApplicationsLoadermApplicationsLoader负责从包管理器中获取系统中安装的应用列表。(之后显示在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装载的。




更多相关文章

  1. Android单元测试初探——Instrumentation
  2. Android布局文件属性笔记
  3. 自定义实现圆形播放进度条(android,飞一般的感觉)
  4. Android基础(一)
  5. 进入android项目组的第一天
  6. Android之四大布局
  7. android:layout_weight总有你不知道的用法.
  8. Android控件编辑时键盘弹起与关闭处理
  9. Android声音管理方法

随机推荐

  1. 自定义progressbar 样式
  2. Android(安卓)listview 制作表格样式+由
  3. android Intent在活动之间穿梭
  4. Android中如何让手机屏幕不待机
  5. Android(安卓)中文API (91) ―― GestureDe
  6. Android(安卓)SDK代理服务器解决国内不能
  7. Failed to fetch URL https://dl-ssl.goo
  8. Jsoup使用教程(一)
  9. Android在layout xml中使用include
  10. android 使用openCV编译.so库