前提:公司应用需要开发插件,奈何我实在没有块的开发经验,查阅了一些资料,花了几天时间,完成了插件的开发。
开发桌面插件需要了解AppWidgetProvider,RemoteViewsService,RemoteViewsFactory,appwidget-provider
插件的更新主要是AppWidgetProvider,列表性的需要RemoteViewsService,RemoteViewsFactory,界面由appwidget-provider提供
首先是appwidget-provider,这个网上有很多的说明,我就不一一说了,我这里主要用了
initialLayout:加载我们插件的布局
updatePeriodMillis:插件的更新频率
previewImage:插件预览图片
configure:当 widget 创建时,会自动启动该 Activity
然后是AppWidgetProvider
public class MyAppWidgetProvider extends AppWidgetProvider {
/**
* 当第1个 widget 的实例被创建时触发。
*/
@Override
public void onEnabled(Context context) {
super.onEnabled(context);
}
/**
* 接收到任意广播时触发,并且会在上述的方法之前被调用。
*/
@Override
public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent);
/**
* 如果你的Widget要求并不是很特殊,一般情况下,在此接收广播,即可处理相应事务,但在此就放弃该方法了。
*/
}
/**
* 当 widget 更新时被执行。每次创建Widget,或者刚开机等情况下,都会被执行。
*/
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
/**
* 由于Widget本身不支持执行太过耗时的操作,所以,为了实现开机刷新和每次添加的时候刷新数据,开启服务,
* 让数据在后台下载,等下载完成之后,在进行更新Widget的操作。
*
*/
Intent intent = new Intent(context, MyService.class);
intent.putExtra("appWidgetIds", appWidgetIds);
context.startService(intent);
}
/**
* 当 widget 被删除时被触发。
*/
@Override
public void onDeleted(Context context, int[] appWidgetIds) {
super.onDeleted(context, appWidgetIds);
}
/**
* 当最后1个 widget 的实例被删除时触发。
*/
@Override
public void onDisabled(Context context) {
super.onDisabled(context);
}
}
更新操作都在update中进行,
@Override
public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent);
//将界面应用到插件中
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
int[] ids = appWidgetManager.getAppWidgetIds(new ComponentName(context, WidgetA.class));
onUpdate(context, appWidgetManager, ids);
}
在onreceive中最后加入这个三行代码,外部发出的update操作都会经过onreceive。
Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
Bundle extras = new Bundle();
intent.putExtras(extras);
sendBroadcast(intent);
其他文件中使用该代码就会更新插件。
如果你有在插件中使用listview,gridview这类控件,就需要RemoteViewsService,RemoteViewsFactory进行数据更新,和adapter一样
public class WidgetGridService extends RemoteViewsService {
@Override
public RemoteViewsFactory onGetViewFactory(Intent intent) {
return new GridRemoteViewFactory(this, intent);
}
private class GridRemoteViewFactory implements RemoteViewsFactory {
private Context context;
private int appWidgetId;
private List<WidgetEntity.NewslistBean> newslist = new ArrayList<>();
public GridRemoteViewFactory(Context context, Intent intent) {
this.context = context;
this.appWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
AppWidgetManager.INVALID_APPWIDGET_ID);
}
/**
* 首次执行,初始化数据时执行onCreate();数据是从数据库里拿的。
*/
@Override
public void onCreate() {
try {
newslist = MyApplication.getMyApp().getDbUtils().findAll(WidgetEntity.NewslistBean.class);
} catch (DbException e) {
e.printStackTrace();
}
}
/**
* 当数据源发生变化时,AppWidgetManager调用了 notifyAppWidgetViewDataChanged();方法时执行
*/
@Override
public void onDataSetChanged() {
try {
newslist = MyApplication.getMyApp().getDbUtils().findAll(WidgetEntity.NewslistBean.class);
} catch (DbException e) {
e.printStackTrace();
}
}
/**
* 销毁数据源
*/
@Override
public void onDestroy() {
newslist.clear();
}
/**
* 返回Gridview的Item条目数
*/
@Override
public int getCount() {
return newslist.size();
}
/**
* 给Gridview设置数据
*/
@Override
public RemoteViews getViewAt(int position) {
RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.item_grid);
if (newslist != null) {//item的xml文件
remoteViews.setTextViewText(R.id.item_text, newslistBean.getTitle());
//给item设置响应事件
Intent intent = new Intent();
intent.putExtra("url", newslistBean.getUrl());
remoteViews.setOnClickFillInIntent(R.id.item_widget, intent);
}
return remoteViews;
}
@Override
public RemoteViews getLoadingView() {
return null;
}
/**
* 无特殊要求,返回的View类型数 ==1;
*/
@Override
public int getViewTypeCount() {
return 1;
}
/**
* 返回item的id
*/
@Override
public long getItemId(int position) {
return position;
}
@Override
public boolean hasStableIds() {
return true;
}
}
}
然后在mainfest注册改插件
<receiver android:name=".MyAppWidgetProvider">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/widget_main" />
</receiver>
<service
android:name=".WidgetGridService"
android:exported="false"
android:permission="android.permission.BIND_REMOTEVIEWS"/>
到这里基本都已经完成了插件的基本开发。具体的操作需要在开发中使用时根据自己的情况在进行处理。