widget宿主端进程(比如Launcher) :AppWidgetService AppWidgetManager AppWidgetHostView AppWidgetHost
widget客户端进程:RmoteViews AppWidgetProviderInfo AppWidgetProvider(extends BroadcastReceiver)
这是widget framework的核心类,是系统service之一,它承担着所有widget的
管理工作。Widget安装,删除,更新等等都需要经过AppWidgetService.它是开机就启动的.3)注册了三个消息:ACTION_BOOT_COMPLETED(系统启动到桌面就会发送此消息),ACTION_PACKAGE_ADDED(有新APK包安装到系统),ACTION_PACKAGE_REMOVED(有APK包被删除)。当系统启动到桌面后,AppWidgetService接收到了ACTION_BOOT_COMPLETED消息,它会去检查本地数据成员,如果有已经安装到桌面的widget,它会上发ACTION_APPWIDGET_ENABLED和ACTION_APPWIDGET_UPDATE消息。如果有widget设置了updatePeriodMillis的属性,它就会开始计时(这个是通过AlarmManager来实现的),到时间时,就会再次上发ACTION_APPWIDGET_UPDATE消息。
是AppWidgetService的客户端代理,是标准的AIDL通讯。IAppWidgetService.java
并不是一个真正的View,它没有实现View的接口,而只是一个用于描述View的实体。比如:创建View需要的资源ID和各个控件的事件响应方法。RemoteViews会通过进程间通信机制传递给AppWidgetHost。
是真正的View,但它只是一个容器,用来容纳实际的AppWidget的View。这个AppWidget的View是根据RemoteViews的描述来创建。这是在updateAppWidget里做的:
remoteViews.apply创建了实际的View
是真正容纳AppWidget的地方,它的主要功能有两个:
o 监听来自AppWidgetService的事件:
o 另外一个功能就是创建AppWidgetHostView。
如何创建一个AppWidget网上有大量的资料和代码,我这里就不赘述了。
下面来看看如何在自己的程序中添加appWidget(仿Launcher)
一共有三个源文件
public class LauncherAppWidgetHostView extends AppWidgetHostView { private LayoutInflater mInflater; private Context mContext; private int mPreviousOrientation; public LauncherAppWidgetHostView(Context context) { super(context); mContext = context; // mLongPressHelper = new CheckLongPressHelper(this); mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); } // @Override // protected View getErrorView() { // return mInflater.inflate(R.layout.appwidget_error, this, false); // } @Override public void updateAppWidget(RemoteViews remoteViews) { mPreviousOrientation = mContext.getResources().getConfiguration().orientation; super.updateAppWidget(remoteViews); } public boolean orientationChangedSincedInflation() { int orientation = mContext.getResources().getConfiguration().orientation; if (mPreviousOrientation != orientation) { return true; } return false; } public boolean onInterceptTouchEvent(MotionEvent ev) { // return true :Consume any touch events for ourselves after longpress is triggered // Otherwise continue letting touch events fall through to children return false; } }
public class LauncherAppWidgetHost extends AppWidgetHost { public LauncherAppWidgetHost(Context context, int hostId) { super(context, hostId); } @Override protected AppWidgetHostView onCreateView(Context context, int appWidgetId, AppWidgetProviderInfo appWidget) { return new LauncherAppWidgetHostView(context); } @Override public void stopListening() { super.stopListening(); clearViews(); } }
public class HelloActivity extends Activity { private ArrayList<AppWidgetProviderInfo> mWidgets = new ArrayList<AppWidgetProviderInfo>(); private LauncherAppWidgetHost mAppWidgetHost; private PackageManager mPackageManager; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Get the list of widgets updatePackages(); mPackageManager = this.getPackageManager(); mAppWidgetHost = new LauncherAppWidgetHost(this, 1001); //startListening AppWidgetChanged mAppWidgetHost.startListening(); int appWidgetId = mAppWidgetHost.allocateAppWidgetId(); final AppWidgetProviderInfo widgetInfo = mWidgets.get(4); //获取RemoteView描述的对应的View LauncherAppWidgetHostView hostView = (LauncherAppWidgetHostView) mAppWidgetHost.createView( this, appWidgetId, widgetInfo); final LinearLayout layout2 = new LinearLayout(this); layout2.setOrientation(LinearLayout.VERTICAL); layout2.addView(hostView); setContentView(layout2); } // 取自 AppsCustomizePagedView public void updatePackages() { mWidgets.clear(); List<AppWidgetProviderInfo> widgets = AppWidgetManager.getInstance(this).getInstalledProviders(); // Intent shortcutsIntent = new Intent(Intent.ACTION_CREATE_SHORTCUT); // List<ResolveInfo> shortcuts = // mPackageManager.queryIntentActivities(shortcutsIntent, 0); for (AppWidgetProviderInfo widget : widgets) { if (widget.minWidth > 0 && widget.minHeight > 0) { Log.d("yzy", widget.label); mWidgets.add(widget); } } // mWidgets.addAll(shortcuts); } }