假如你要实现在即的APPWidgethost,下面几个class,你必须了解.
AppWidgetsHost:为app提供与appwidget service交互。一个APPWidgethost必须有一个独特ID
App Widget ID:每一个app widget被赋予一个独特的ID,这个ID 可以调用allocateAPPWidgetId()获得,这个id在widget整个生命周期都存在,除非被host删掉.host的安装包应该保存widget在host上的size 和位置这些信息用options bundle表示,你可以使用updateAPPWidgetOption()和updateAPPWidgetSize() 来修改widget的bundle信息,且这些信息会与app widget id相关联.
AppWidgetHostView:是widget显示的容器。
下例是launcher中增加app widget的例子。
private static final int REQUEST_CREATE_APPWIDGET = 5;
private static final int REQUEST_PICK_APPWIDGET = 9;
...
public void onClick(DialogInterface dialog, int which) {
switch (which) {
...
case AddAdapter.ITEM_APPWIDGET: {
...
int appWidgetId =
Launcher.this.mAppWidgetHost.allocateAppWidgetId();
Intent pickIntent =
new Intent(AppWidgetManager.ACTION_APPWIDGET_PICK);
pickIntent.putExtra
(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
...
startActivityForResult(pickIntent, REQUEST_PICK_APPWIDGET);
break;
}
...
}
通过allocateAPPWidgetId()申请一个id,然后通过startActivityForResult来开始.需要通过实现onActivityResult来得到结果如下所示:
public final class Launcher extends Activity
implements View.OnClickListener, OnLongClickListener {
...
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
mWaitingForResult = false;
if (resultCode == RESULT_OK && mAddItemCellInfo != null) {
switch (requestCode) {
...
case REQUEST_PICK_APPWIDGET:
addAppWidget(data);
break;
case REQUEST_CREATE_APPWIDGET:
completeAddAppWidget(data, mAddItemCellInfo, !mDesktopLocked);
break;
}
}
...
}
}
void addAppWidget(Intent data) {
int appWidgetId = data.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1);
String customWidget = data.getStringExtra(EXTRA_CUSTOM_WIDGET);
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);
startActivityForResult(intent, REQUEST_CREATE_APPWIDGET);
} else {
// Otherwise, finish adding the widget.
}
}
需要在manifest文件中添加权限
<uses-permission android:name="android.permission.BIND_APPWIDGET" />
在runtime时还需要通过bindAppWidgetIdIfAllowed()检查是否可以添加widget,返回值为true 表示运行添加,
607 public boolean bindAppWidgetIdIfAllowed(
608 String packageName, int appWidgetId, ComponentName provider, Bundle options) {
609 try {
610 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BIND_APPWIDGET, null);
611 } catch (SecurityException se) {
612 if (!callerHasBindAppWidgetPermission(packageName)) {
613 return false;
614 }
615 }
616 bindAppWidgetIdImpl(appWidgetId, provider, options);
617 return true;
618 }
只要enforceCallingOrSelfPermission 不发生异常,就认为是有权限的
flase 表示拒绝添加,这时我们一般显示一个dialog以鼓励用于同意
Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_BIND);intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_PROVIDER, info.componentName);
// This is the options bundle discussed above
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_OPTIONS, options);
startActivityForResult(intent, REQUEST_BIND_APPWIDGET);