从网络上找了一段关于Launcher的启动过程的文章,作为学习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:
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出的一个子进程。
<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>
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.应用程序代码分析 首先,是一些权限的声明。例如:
<uses-permission android:name="android.permission.CALL_PHONE" /> <uses-permission android:name="android.permission.EXPAND_STATUS_BAR" />
<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;
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; } } }