之前在公司项目中开发过图片widget,现在回故一下appwidget架构。
AppWidgetService:系统service之一,主要在后台负责所有appwidget的管理工作。Widget的添加,删除,更新等。
AppWidgetManager:Widgets管理类
AppWidgetProvider :继承自 BroadcastRecevier , 在AppWidget 应用 update、enable、disable 和 delete 时接收通知。其中,onUpdate、onReceive 是最常用到的方法,它们接收更新通知。
AppWidgetProvderInfo:描述 AppWidget 的大小、更新频率和初始界面等信息,以XML 文件形式存在于应用的 res/xml/目录下。
RemoteViews :一个可以在其他应用进程中运行的类,描述widget的视图
AppWidgetHost:提供了其他可以在自己UI嵌入widgets的应用程序和AppWidgetService的交互,如Home screen
AppWidgetHostView:用来显示app widget的视图
AppWidgetPickActivity:显示widgets的列表
其实在我们实际开发中只需要实现AppWidgetProvider ,AppWidgetProvderInfo,RemoteViews ,就可以开发出自己的小插件。
另外我们知道android widget所支持的布局很有限:
-
AnalogClock
-
Button
-
Chronometer
-
ImageButton
-
ImageView
-
ProgressBar
-
TextView
-
ViewFlipper
-
ListView
-
GridView
-
StackView
-
AdapterViewFlipper
// When we're inflating the initialLayout for a AppWidget, we only allow
// views that are allowed in RemoteViews.
static final LayoutInflater.Filter sInflaterFilter = new LayoutInflater.Filter() {
public boolean onLoadClass(Class clazz) {
return clazz.isAnnotationPresent(RemoteViews.RemoteView.class);
}
};
protected View getDefaultView() {
if (LOGD) {
Log.d(TAG, "getDefaultView");
}
View defaultView = null;
Exception exception = null;
try {
if (mInfo != null) {
Context theirContext = mContext.createPackageContext(
mInfo.provider.getPackageName(), Context.CONTEXT_RESTRICTED);
mRemoteContext = theirContext;
LayoutInflater inflater = (LayoutInflater)
theirContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater = inflater.cloneInContext(theirContext);
inflater.setFilter(sInflaterFilter);
defaultView = inflater.inflate(mInfo.initialLayout, this, false);
} else {
Log.w(TAG, "can't inflate defaultView because mInfo is missing");
}
} catch (PackageManager.NameNotFoundException e) {
exception = e;
} catch (RuntimeException e) {
exception = e;
}
if (exception != null) {
Log.w(TAG, "Error inflating AppWidget " + mInfo + ": " + exception.toString());
}
if (defaultView == null) {
if (LOGD) Log.d(TAG, "getDefaultView couldn't find any view, so inflating error");
defaultView = getErrorView();
}
return defaultView;
}
要想支持复杂View,不但要考虑修改这里, 当然还要考虑一些触摸事件的派发,然widget的视图响应。
当然这样修改对支持添加widget的应用程序安全性是一个很大的威胁。