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代码:

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就会通过:

java代码:

startActivityLocked(null, intent, null, null, 0, aInfo, null, null, 0, 0, 0, false, false); 

启动Home进程了。而这个启动Home进程的过程实际上还是去通过zygote fork出的一个子进程。

       因此只要在manifest中具备这样的intent-filter都可以在开机的时候作为Home启动:


java代码:

<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结构:

14.jpg


       整个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的代码结构.

15.jpg


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


java代码:

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

这部分可以略过;

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


       (1)Launcher:HomeScreenActivity


java代码:

<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中onCreat()的分析我们可以大致把握屏幕的主要活动:


java代码:

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:设置墙纸.
  同理我们从onCreat()作为入口来分析这个活动的主要功能.

java代码:

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,重写onReceier()方法,对于发送来的Broadcast(这里指Intent)进行过滤(IntentFilt)并且响应(这里是InstallShortcut()).这里分析下onReceive():

java代码:

<!-- 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
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值