今天接到部门头头给下达的一个任务:研究如何让桌面上的AppWidget不能删除。仔细研究AppWidget包的文档后发现,如果不修改桌面程序的代码不可能实现。OK,那就看看桌面程序的源代码吧。
Android中默认桌面的代码包为com.android.launcher。源代码网址为http://git.android.kernel.org/platform/packages/apps/launcher.git . 下载下来啃吧。
分析代码结构,首先是分析AndroidManifest.xml文件,看看哪个类是桌面程序的入口。在该文件中发现如下代码。
代码
1 <activity
2 android:name="Launcher"
3 android:launchMode="singleTask"
4 android:clearTaskOnLaunch="true"
5 android:stateNotNeeded="true"
6 android:theme="@style/Theme"
7 android:screenOrientation="nosensor"
8 android:windowSoftInputMode="stateUnspecified|adjustPan">
9 <intent-filter>
10 <action android:name="android.intent.action.MAIN" />
11 <category android:name="android.intent.category.HOME"/>
12 <category android:name="android.intent.category.DEFAULT" />
13 <category android:name="android.intent.category.MONKEY" />
14 </intent-filter>
15 </activity>
这说明,Launcher这个类是桌面的主要类。 而联想到添加和删除Widget的操作过程可以确定长点击事件的处理是这两个功能的起始点。下面请看onLongClick函数
代码
1 public boolean onLongClick(View v) {
2 if (mDesktopLocked) {
3 return false;
4 }
5
6 if (!(v instanceof CellLayout)) {
7 v = (View) v.getParent();
8 }
9
10 CellLayout.CellInfo cellInfo = (CellLayout.CellInfo) v.getTag();
11
12 // This happens when long clicking an item with the dpad/trackball
13 if (cellInfo == null) {
14 return true;
15 }
16
17 if (mWorkspace.allowLongPress()) {
18 if (cellInfo.cell == null) {
19 if (cellInfo.valid) {
20 // User long pressed on empty space
21 mWorkspace.setAllowLongPress(false);
22 showAddDialog(cellInfo);//从这里开始添加Widget的动作
23 }
24 } else {
25 Log.i(LOG_TAG_TEST, cellInfo.cell.getClass().getName());
26 if (!(cellInfo.cell instanceof Folder)) {
27 // User long pressed on an item
28 if(cellInfo.cell instanceof AppWidgetHostView)
29 {
30 AppWidgetHostView adv=(AppWidgetHostView)cellInfo.cell;
31 if(adv.getAppWidgetInfo().provider.getClassName().equals("AdAppWidgetProvider"))
32 {
33 Log.i(LOG_TAG_TEST, "Cannot Remove Advertisment Widget");
34 return false;
35 }
36 }
37
38 //下面这一句是删除动作的开始,因此在其前边添加了代码处理Widget信息
39 mWorkspace.startDrag(cellInfo);
40 }
41 }
42 }
43 return true;
44 }
45
OK,任务完成!
那么接下来不妨仔细看看AppWidget到底是怎么添加到桌面上的。开始跟踪代码:
1、使用如下代码打开系统的选择Widget的Activity
代码
1 int appWidgetId = Launcher.this.mAppWidgetHost.allocateAppWidgetId();
2 Intent pickIntent = new Intent(AppWidgetManager.ACTION_APPWIDGET_PICK);
3 pickIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
4 // add the search widget
5 ArrayList customInfo =
6 new ArrayList();
7 AppWidgetProviderInfo info = new AppWidgetProviderInfo();
8 info.provider = new ComponentName(getPackageName(), "XXX.YYY");
9 info.label = getString(R.string.group_search);
10 info.icon = R.drawable.ic_search_widget;
11 customInfo.add(info);
12 pickIntent.putParcelableArrayListExtra(
13 AppWidgetManager.EXTRA_CUSTOM_INFO, customInfo);
14 ArrayList customExtras = new ArrayList();
15 Bundle b = new Bundle();
16 b.putString(EXTRA_CUSTOM_WIDGET, SEARCH_WIDGET);
17 customExtras.add(b);
18 pickIntent.putParcelableArrayListExtra(
19 AppWidgetManager.EXTRA_CUSTOM_EXTRAS, customExtras);
20 // start the pick activity
21 startActivityForResult(pickIntent, REQUEST_PICK_APPWIDGET);
22
2、从返回的Intent中得到AppWidget详细信息,如果需要config则显示config activity。
3、由AppWidgetHost根据AppWidgetID和provider info生成AppWidgetHostView,然后将AppWidgetHostView添加到桌面的Viewgroup中。