`

探秘widget之launcher添加widget的流程分析

 
阅读更多
添加widget首先需要在laucher的空白处长按,所以首先定位在laucher的 public boolean onLongClick(View v) 中,看到:
[java] view plaincopy
if (mWorkspace.allowLongPress()) {    
    if (cellInfo.cell == null) {    
        if (cellInfo.valid) {    
            // User long pressed on empty space    
            mWorkspace.setAllowLongPress(false);    
            mWorkspace.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS,    
                    HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);    
            showAddDialog(cellInfo);    
        }    
    } else {    
        if (!(cellInfo.cell instanceof Folder)) {    
            // User long pressed on an item    
            mWorkspace.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS,    
                    HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);    
            mWorkspace.startDrag(cellInfo);    
        }    
    }    
}   

可以看到跳转到了showAddDialog(cellInfo),寻找到:
[java] view plaincopy
private void showAddDialog(CellLayout.CellInfo cellInfo) {    
    mAddItemCellInfo = cellInfo;    
    mWaitingForResult = true;    
    showDialog(DIALOG_CREATE_SHORTCUT);    
}   

可以看到他携带着DIALOG_CREATE_SHORTCUT参数创建了一个Dialog,携带参数跳入Launcher.java的父类Activity.java的showDialog()方法,最终到达Launcher.java的onCreateDialog(int id)方法,代码如下:
[java] view plaincopy
@Override   
protected Dialog onCreateDialog(int id) {    
    switch (id) {    
        case DIALOG_CREATE_SHORTCUT:    
            return new CreateShortcut().createDialog();    
        case DIALOG_RENAME_FOLDER:    
            return new RenameFolder().createDialog();    
    }    
   
    return super.onCreateDialog(id);    
}   

跳转到了CreateShortcut()的createDialog()方法:
[java] view plaincopy
Dialog createDialog() {    
    mWaitingForResult = true;     
    mAdapter = new AddAdapter(Launcher.this);     
    final AlertDialog.Builder builder = new AlertDialog.Builder(Launcher.this);       builder.setTitle(getString(R.string.menu_item_add_item));    
    builder.setAdapter(mAdapter, this);      
    builder.setInverseBackgroundForced(true);     
    AlertDialog dialog = builder.create();    
    dialog.setOnCancelListener(this);    
    dialog.setOnDismissListener(this);    
    dialog.setOnShowListener(this);    
   
    return dialog;    
}   

这里可以看到一个  AddAdapter类,跳转去看看,这个就是定义长按后出现的对话框的内容:
[c-sharp] view plaincopy
public static final int ITEM_SHORTCUT = 0; 
    public static final int ITEM_APPWIDGET = 1; 
    public static final int ITEM_LIVE_FOLDER = 2; 
    public static final int ITEM_WALLPAPER = 3; 

如果我们需要在原来的对话框中添加新的内容,那么首先需要修改的就是这里,我们回到之前的地方接着往下走,dialog响应的点击事件,public void onClick(DialogInterface dialog, int which) :
[java] view plaincopy
case AddAdapter.ITEM_APPWIDGET: { 
                    int appWidgetId = Launcher.this.mAppWidgetHost.allocateAppWidgetId(); 
//这里生成了一个appWidgetId,供后面绑定AppWidgetProvider使用 
                    Intent pickIntent = new Intent(AppWidgetManager.ACTION_APPWIDGET_PICK); 
//新建一个intent,该intent是打开一个现实Widgets列表的activity,该activity对应类AppWidgetPickActivity    
                pickIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId); 
                    // start the pick activity 
       //设置EXTRA_APPWIDGET_ID             startActivityForResult(pickIntent, REQUEST_PICK_APPWIDGET); 
                    break; 
                } 


这里看到点击widget条目之后,跳转打开一个新的pickIntent,其实际运行的为packages/apps/Settings/src/com/android/settings/AppWidgetPickActivity.java:
先在onCreate方法中创建了一个InstalledAppWidgets列表,该列表就是我们在界面上能见到的所有widgets。
在点击一个widgets,进入AppWidgetPickActivity.onClick事件监听,注意阅读该方法代码,它会进入else:
[java] view plaincopy
if (intent.getExtras() != null) { 
            // If there are any extras, it's because this entry is custom. 
            // Don't try to bind it, just pass it back to the app. 
            setResultData(RESULT_OK, intent); 
        } else { 
            try { 
                mAppWidgetManager.bindAppWidgetId(mAppWidgetId, intent.getComponent()); 
//绑定选中的桌面组件与mAppWidgetId 
        result = RESULT_OK;//设置返回结果为ok 

activity执行结束后面都会进入launcher.onActivityResult,查看该函数方法有两个关键的case:
[java] view plaincopy
case REQUEST_PICK_APPWIDGET: 
     addAppWidget(data); 
       break; 
case REQUEST_CREATE_APPWIDGET: 
     completeAddAppWidget(data, mAddItemCellInfo); 


接着跳转到launcher的addAppWidget(Intent data)里data为传递来的appWidgetId:
[java] view plaincopy
void addAppWidget(Intent data) { 
        // TODO: catch bad widget exception when sent 
        int appWidgetId = data.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1); 
        AppWidgetProviderInfo appWidget = mAppWidgetManager.getAppWidgetInfo(appWidgetId); 
//先判断是否有配置页 
        if (appWidget.configure != null) { 
            // Launch over to configure widget, if needed 
            Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_CONFIGURE); 
            intent.setComponent(appWidget.configure); 
            intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId); 
            startActivityForResultSafely(intent, REQUEST_CREATE_APPWIDGET); 
        } else { 
            // Otherwise just add it 
            onActivityResult(REQUEST_CREATE_APPWIDGET, Activity.RESULT_OK, data); 
        } 
    } 


通过onActivityResult(REQUEST_CREATE_APPWIDGET, Activity.RESULT_OK, data);跳转回launcher.onActivityResult的

case REQUEST_CREATE_APPWIDGET:
          completeAddAppWidget(data, mAddItemCellInfo);


[java] view plaincopy
@param data The intent describing the appWidgetId. 
     * @param cellInfo The position on screen where to create the widget. 
     */ 
    private void completeAddAppWidget(Intent data, CellLayout.CellInfo cellInfo) 

在 completeAddAppWidget(data, mAddItemCellInfo)中完成widget的添加。

[java] view plaincopy
private void completeAddAppWidget(Intent data, CellLayout.CellInfo cellInfo) { 
        Bundle extras = data.getExtras(); 
        int appWidgetId = extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, -1); 
        if (LOGD) Log.d(TAG, "dumping extras content=" + extras.toString()); 
//由appWidgetId获取widget的信息,例如大小等 
        AppWidgetProviderInfo appWidgetInfo = mAppWidgetManager.getAppWidgetInfo(appWidgetId); 
        // Calculate the grid spans needed to fit this widget 
        CellLayout layout = (CellLayout) mWorkspace.getChildAt(cellInfo.screen); 
        int[] spans = layout.rectToCell(appWidgetInfo.minWidth, appWidgetInfo.minHeight); 
        // Try finding open space on Launcher screen 
        final int[] xy = mCellCoordinates; 
        if (!findSlot(cellInfo, xy, spans[0], spans[1])) { 
            if (appWidgetId != -1) mAppWidgetHost.deleteAppWidgetId(appWidgetId); 
            return; 
        } 
        // Build Launcher-specific widget info and save to database 
        LauncherAppWidgetInfo launcherInfo = new LauncherAppWidgetInfo(appWidgetId); 
        launcherInfo.spanX = spans[0]; 
        launcherInfo.spanY = spans[1]; 
        LauncherModel.addItemToDatabase(this, launcherInfo, 
                LauncherSettings.Favorites.CONTAINER_DESKTOP, 
                mWorkspace.getCurrentScreen(), xy[0], xy[1], false); 
        if (!mRestoring) { 
            mDesktopItems.add(launcherInfo); 
            // Perform actual inflation because we're live 
            launcherInfo.hostView = mAppWidgetHost.createView(this, appWidgetId, appWidgetInfo); 
            launcherInfo.hostView.setAppWidget(appWidgetId, appWidgetInfo); 
            launcherInfo.hostView.setTag(launcherInfo); 
            mWorkspace.addInCurrentScreen(launcherInfo.hostView, xy[0], xy[1], 
                    launcherInfo.spanX, launcherInfo.spanY, isWorkspaceLocked()); 
        } 
     
分享到:
评论

相关推荐

    android Launcher添加widget源码

    本篇将深入探讨如何在自定义的Launcher中添加Widget,并通过源码分析来理解这一过程。 首先,我们来看“android Launcher添加widget”的核心概念。在Android中,Widget是一种轻量级的应用组件,可以在用户的主屏幕...

    Android代码-Launcher3

    Launcher3分析之拖动图标的流程——按下 Launcher3分析之拖动图标的流程——移动 Launcher3分析之拖动图标的流程——放下 PagedView的原理 – 滑动 如何给Launcher3添加左屏 IconCache原理 找个Launcher开发 ...

    launcher添加动态时钟和动态日历

    launcher添加动态时钟和动态日历. CalendarScript.java ClockScript.java IconScript.java 是新加入的类 其它的是launcher3本身有的 对比过去就好.在代码中搜索"动态时钟显示"就能找到我加入的东西

    Android中实现Launcher功能之二 ----- 添加窗口小部件以及AppWidget的创建详解.pdf

    在Android系统中,窗口小部件(AppWidget)是一种能够让用户在Home屏幕上获取应用信息和快捷操作的小部件,它也是实现Launcher功能的一部分。创建AppWidget主要涉及以下几个关键组件和概念: #### 1. ...

    android2.3 launcher分析二

    ### Android 2.3 Launcher分析之桌面组件与默认配置 #### 概述 本文将深入探讨Android 2.3版本中的Launcher系统,并重点分析LiveFolder的功能及其如何与Launcher交互,以及Launcher默认界面配置的方式和方法。 ##...

    android系统从systemserver开始的launcher启动详细流程

    ### android系统从systemserver开始的launcher启动详细流程 #### 概述: 在Android系统的启动过程中,用户首次交互的界面往往是Launcher应用,它作为系统主屏幕的主要组成部分,承载着展示应用程序图标、提供快捷...

    android2.3 launcher分析三

    【Android 2.3 Launcher 分析】 Android 2.3 的 Launcher 是用户界面的核心部分,它作为设备的主要入口,提供用户访问应用程序、小部件和设置的界面。在深入分析之前,我们先了解一下 Launcher 的基本架构。 **...

    android系统从systemserver开始的launcher启动详细流程.doc

    本文将详细介绍 Android 系统从 SystemServer 开始的 Launcher 启动流程,并对其中的关键组件和服务进行分析。 概述 Android 系统启动流程可以分为两个阶段:第一个阶段是从 SystemServer 开始到 Launcher 的启动,...

    net.qihoo.launcher.widget.clockweather.apk

    net.qihoo.launcher.widget.clockweather.apk

    android安卓app开发之widget界面控件使用教程.zip

    了解了基本概念后,开发者可以通过阅读《Android 之桌面组件 App Widget 案例》、《Android Launcher开发之桌面小部件AppWidget详解》以及相关的博客文章来深入学习。这些资料提供了丰富的实例和代码解析,帮助理解...

    android launcher桌面数字时钟控件

    1. **Android Widget API**:Android提供了一套Widget API,允许开发者创建可添加到用户主屏幕的小部件,包括数字时钟。开发者需要创建一个继承自`AppWidgetProvider`的类,并在XML布局文件中定义控件的外观。 2. *...

    android2.3 launcher分析

    ### Android 2.3 Launcher分析 #### 架构概述 Android 2.3 版本中的Launcher采用的是经典的MVC(Model-View-Controller)架构模式。这种模式将应用程序分为三个核心部分:模型(Model)、视图(View)以及控制器...

    一个支持listview的widget

    本资源包含了一个专门支持ListView显示的Widget,以及与之相关的ADW源码和Launcher Plus源码。这将帮助开发者深入了解如何在Widget中集成ListView,提升用户体验,并且可以借鉴源码来优化自己的应用设计。 首先,...

    android 4.0 launcher分析

    AppWidget是可添加到桌面的小部件,扩展了Launcher的功能。 回到Android 4.0 Launcher的启动流程。系统启动后,App_main进程初始化Android运行时环境,zygote进程作为所有Android应用和服务的父进程。SystemServer...

    Android11.0 Launcher3 添加负一屏(谷歌Feed屏方案)

    包含客户端 Launcher3 修改 包含服务端 OverlayScreen(可替换成你自己客需定制负一屏View) 基于android11.0 绝对好用,网上目前最全代码 实现效果图 ...

    Launcher2源码分析

    《Launcher2源码分析》 在Android系统中,Launcher作为用户与系统交互的起点,扮演着至关重要的角色。本文将深入探讨Android 4.0版本的Launcher2源码,主要涉及桌面快捷图标的拖拽机制、Workspace切换到AllApps流程...

    launcher源码分析

    **动态添加和移除图标**:当安装或卸载应用时,`BroadcastReceiver`监听到系统广播,`Launcher`会更新UI以反映变化。 **个性化设置**:`SharedPreferences`用于存储用户设置,如主屏幕布局、壁纸等。`...

    系统桌面源码 Launcher

    Launcher作为系统的桌面,允许用户启动应用程序、管理屏幕布局、添加小部件(Widget)以及欣赏各种动画效果。本篇文章将深入探讨其核心概念、实现原理以及涉及的关键技术。 首先,Launcher的主要功能是提供一个可视...

    launcher3流程图2

    "launcher3"是Android...通过分析"launcher3流程图2",我们可以深入理解launcher3如何实现其核心功能,以及在各种操作背后的逻辑流程。这份图解对于开发者优化性能、调试问题或者扩展launcher3功能具有重要参考价值。

Global site tag (gtag.js) - Google Analytics