探秘 widget 之 launcher 添加 widget 的流程分析
来源:互联网 发布:环球人物和看天下知乎 编辑:程序博客网 时间:2024/05/22 09:48
最近打算研究下android的widget相关问题,并把一些心得在此稍作记录,哈哈,等研究完成了,如果有必要的话,也会把改动的源码贴出来,以飨读者。今天先来看看launcher2中添加widget的流程。
添加widget首先需要在laucher的空白处长按,所以首先定位在laucher的 public boolean onLongClick(View v) 中,看到:
01
if
(mWorkspace.allowLongPress()) {
02
if
(cellInfo.cell ==
null
) {
03
if
(cellInfo.valid) {
04
// User long pressed on empty space
05
mWorkspace.setAllowLongPress(
false
);
06
mWorkspace.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS,
07
HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
08
showAddDialog(cellInfo);
09
}
10
}
else
{
11
if
(!(cellInfo.cell
instanceof
Folder)) {
12
// User long pressed on an item
13
mWorkspace.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS,
14
HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
15
mWorkspace.startDrag(cellInfo);
16
}
17
}
18
}
可以看到跳转到了showAddDialog(cellInfo),寻找到:
1
private
void
showAddDialog(CellLayout.CellInfo cellInfo) {
2
mAddItemCellInfo = cellInfo;
3
mWaitingForResult =
true
;
4
showDialog(DIALOG_CREATE_SHORTCUT);
5
}
可以看到他携带着DIALOG_CREATE_SHORTCUT参数创建了一个Dialog,携带参数跳入Launcher.java的父类Activity.java的showDialog()方法,最终到达Launcher.java的onCreateDialog(int id)方法,代码如下:
01
@Override
02
protected
Dialog onCreateDialog(
int
id) {
03
switch
(id) {
04
case
DIALOG_CREATE_SHORTCUT:
05
return
new
CreateShortcut().createDialog();
06
case
DIALOG_RENAME_FOLDER:
07
return
new
RenameFolder().createDialog();
08
}
09
10
return
super
.onCreateDialog(id);
11
}
跳转到了CreateShortcut()的createDialog()方法:
01
Dialog createDialog() {
02
mWaitingForResult =
true
;
03
mAdapter =
new
AddAdapter(Launcher.
this
);
04
final
AlertDialog.Builder builder =
new
AlertDialog.Builder(Launcher.
this
);
05
builder.setTitle(getString(R.string.menu_item_add_item));
06
builder.setAdapter(mAdapter,
this
);
07
builder.setInverseBackgroundForced(
true
);
08
AlertDialog dialog = builder.create();
09
dialog.setOnCancelListener(
this
);
10
dialog.setOnDismissListener(
this
);
11
dialog.setOnShowListener(
this
);
12
13
return
dialog;
14
}
这里可以看到一个 AddAdapter类,跳转去看看,这个就是定义长按后出现的对话框的内容:
1
public
static
final
int
ITEM_SHORTCUT =
0
;
2
public
static
final
int
ITEM_APPWIDGET =
1
;
3
public
static
final
int
ITEM_LIVE_FOLDER =
2
;
4
public
static
final
int
ITEM_WALLPAPER =
3
;
如果我们需要在原来的对话框中添加新的内容,那么首先需要修改的就是这里,我们回到之前的地方接着往下走,dialog响应的点击事件,public void onClick(DialogInterface dialog, int which) :
01
case
AddAdapter.ITEM_APPWIDGET: {
02
int
appWidgetId = Launcher.
this
.mAppWidgetHost.allocateAppWidgetId();
03
//这里生成了一个appWidgetId,供后面绑定AppWidgetProvider使用
04
Intent pickIntent =
new
Intent(AppWidgetManager.ACTION_APPWIDGET_PICK);
05
//新建一个intent,该intent是打开一个现实Widgets列表的activity,该activity对应类AppWidgetPickActivity
06
pickIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
07
// start the pick activity
08
//设置EXTRA_APPWIDGET_ID
09
startActivityForResult(pickIntent, REQUEST_PICK_APPWIDGET);
10
break
;
11
}
这里看到点击widget条目之后,跳转打开一个新的pickIntent,其实际运行的为packages/apps/Settings/src/com/android/settings/AppWidgetPickActivity.java:
先在onCreate方法中创建了一个InstalledAppWidgets列表,该列表就是我们在界面上能见到的所有widgets。
在点击一个widgets,进入AppWidgetPickActivity.onClick事件监听,注意阅读该方法代码,它会进入else:
1
if
(intent.getExtras() !=
null
) {
2
// If there are any extras, it's because this entry is custom.
3
// Don't try to bind it, just pass it back to the app.
4
setResultData(RESULT_OK, intent);
5
}
else
{
6
try
{
7
mAppWidgetManager.bindAppWidgetId(mAppWidgetId, intent.getComponent());
8
//绑定选中的桌面组件与mAppWidgetId
9
result = RESULT_OK;
//设置返回结果为ok
activity执行结束后面都会进入launcher.onActivityResult,查看该函数方法有两个关键的case:
1
case
REQUEST_PICK_APPWIDGET:
2
addAppWidget(data);
3
break
;
4
case
REQUEST_CREATE_APPWIDGET:
5
completeAddAppWidget(data, mAddItemCellInfo);
接着跳转到launcher的addAppWidget(Intent data)里data为传递来的appWidgetId:
01
void
addAppWidget(Intent data) {
02
// TODO: catch bad widget exception when sent
03
int
appWidgetId = data.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -
1
);
04
AppWidgetProviderInfo appWidget = mAppWidgetManager.getAppWidgetInfo(appWidgetId);
05
//先判断是否有配置页
06
if
(appWidget.configure !=
null
) {
07
// Launch over to configure widget, if needed
08
Intent intent =
new
Intent(AppWidgetManager.ACTION_APPWIDGET_CONFIGURE);
09
intent.setComponent(appWidget.configure);
10
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
11
startActivityForResultSafely(intent, REQUEST_CREATE_APPWIDGET);
12
}
else
{
13
// Otherwise just add it
14
onActivityResult(REQUEST_CREATE_APPWIDGET, Activity.RESULT_OK, data);
15
}
16
}
通过onActivityResult(REQUEST_CREATE_APPWIDGET, Activity.RESULT_OK, data);跳转回launcher.onActivityResult的
case REQUEST_CREATE_APPWIDGET:
completeAddAppWidget(data, mAddItemCellInfo);
1
@param
data The intent describing the appWidgetId.
2
*
@param
cellInfo The position on screen where to create the widget.
3
*/
4
private
void
completeAddAppWidget(Intent data, CellLayout.CellInfo cellInfo)
在 completeAddAppWidget(data, mAddItemCellInfo)中完成widget的添加。
01
private
void
completeAddAppWidget(Intent data, CellLayout.CellInfo cellInfo) {
02
Bundle extras = data.getExtras();
03
int
appWidgetId = extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, -
1
);
04
if
(LOGD) Log.d(TAG,
"dumping extras content="
+ extras.toString());
05
//由appWidgetId获取widget的信息,例如大小等
06
AppWidgetProviderInfo appWidgetInfo = mAppWidgetManager.getAppWidgetInfo(appWidgetId);
07
// Calculate the grid spans needed to fit this widget
08
CellLayout layout = (CellLayout) mWorkspace.getChildAt(cellInfo.screen);
09
int
[] spans = layout.rectToCell(appWidgetInfo.minWidth, appWidgetInfo.minHeight);
10
// Try finding open space on Launcher screen
11
final
int
[] xy = mCellCoordinates;
12
if
(!findSlot(cellInfo, xy, spans[
0
], spans[
1
])) {
13
if
(appWidgetId != -
1
) mAppWidgetHost.deleteAppWidgetId(appWidgetId);
14
return
;
15
}
16
// Build Launcher-specific widget info and save to database
17
LauncherAppWidgetInfo launcherInfo =
new
LauncherAppWidgetInfo(appWidgetId);
18
launcherInfo.spanX = spans[
0
];
19
launcherInfo.spanY = spans[
1
];
20
LauncherModel.addItemToDatabase(
this
, launcherInfo,
21
LauncherSettings.Favorites.CONTAINER_DESKTOP,
22
mWorkspace.getCurrentScreen(), xy[
0
], xy[
1
],
false
);
23
if
(!mRestoring) {
24
mDesktopItems.add(launcherInfo);
25
// Perform actual inflation because we're live
26
launcherInfo.hostView = mAppWidgetHost.createView(
this
, appWidgetId, appWidgetInfo);
27
launcherInfo.hostView.setAppWidget(appWidgetId, appWidgetInfo);
28
launcherInfo.hostView.setTag(launcherInfo);
29
mWorkspace.addInCurrentScreen(launcherInfo.hostView, xy[
0
], xy[
1
],
30
launcherInfo.spanX, launcherInfo.spanY, isWorkspaceLocked());
31
}
- 探秘widget之launcher添加widget的流程分析
- 探秘widget之launcher添加widget的流程分析
- 探秘 widget 之 launcher 添加 widget 的流程分析
- 探秘 widget 之 launcher 添加 widget 的流程分析
- launcher widget 添加过程分析
- 探秘widget之widget背后的故事
- 探秘widget之widget背后的故事
- Launcher3源码分析之Widget添加流程
- launcher widget 添加过程分析2
- Launcher开发之添加widget(一)
- app widget添加流程
- android Widget添加过程和android添加widget不更新的问题分析解决
- android Widget添加过程和android添加widget不更新的问题分析解决
- widget添加
- Launcher预设Widget
- Android launcher widget配置
- 添加自定义View的Widget
- Yii框架分析之widget与action的关系
- 为何程序员完成最后20%的工作需要的时间跟之前的80%一样多?
- C++ STL — 第4章 Utilities
- Oracle一个中文汉字占用几个字节
- POJ 1852 Ants
- 信号
- 探秘 widget 之 launcher 添加 widget 的流程分析
- <Linux+Qt>时间控制事件触发
- 杭电水题之1076
- 共享内存(System V)
- 探究一道字符串模式匹配问题
- 信号量(System V)
- hdu 1542 Atlantis(线段树,扫描线)
- hdu 4036 Rolling Hongshu
- 线程安全