Widget开发中遇到的坑
1.在Manifest文件中声明
这个就相当于一个广播接收者,然后android:name属性指定在第四步的时候创建的文件名
android:resource="@xml/example_appwidget_info"/>是widget的配置文件
2.添加Widget配置信息
在项目的 res/xml/ 目录下。如果没有xml目录,需要新建一个
initialLayout是widget的布局文件
previewImage就是widget的预览效果
3.新建一个appwidget_layout文件
…
4.新建一个AppWidgetProvider类
这个类其实是继承至广播接收者的
public class AppWidgetProvider extends BroadcastReceiver {
然后呢,我们一般只需要用到onUpdate()方法,这个方法的更新时间,是你在example_appwidget_info配置文件中设置的android:updatePeriodMillis属性决定的,这个地方有个坑,稍候再说
public class GoldWidgetProvider extends AppWidgetProvider {
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { final int N = appWidgetIds.length; for (int i=0; i
5.开发中的一些坑
1. updateMillies更新时间低于30分钟,系统默认为30分钟。如果想要自己更新widget,将这个值设置为0,然后自己开timer或者通过广播去更新。我是通过广播去更新的
// 重写OnReceiver方法
@Override
public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent);
String action = intent.getAction();
// 需要在Manifest中注册这个Action if (ACTION_UPDATE_WIDGET.equals(action)) { // update widget RemoteViews views = getRemoteViews(context, null); ComponentName name = new ComponentName(context, GoldWidgetProvider.class); AppWidgetManager.getInstance(context).updateAppWidget(name, views); }else if (ACTION_CLICK_UPDATE_WIDGET.equals(action)){ RemoteViews remoteViews = getRemoteViews(context, "正在刷新..."); ComponentName name = new ComponentName(context, GoldWidgetProvider.class); AppWidgetManager.getInstance(context).updateAppWidget(name, remoteViews); Intent goldPrice = new Intent(context, GoldPriceService.class); context.startService(goldPrice); } }public static RemoteViews getRemoteViews(Context context, String updating) { RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.goldwidget); //1,设置金价 if (TextUtils.isEmpty(updating)) { String buyGoldPrice = ShaPreUtils.getBuyGoldPrice(context); views.setTextViewText(R.id.widget_tv_goldprice, buyGoldPrice); } else { views.setTextViewText(R.id.widget_tv_goldprice, updating); } //2,设置持有金 if (GoldApplication.getInstance().isLogined()) { String total = GoldApplication.getInstance().getUserLoginInfo().getAccountInfo().getTotal(); ShaPreUtils.putTotalGold(context,total); views.setTextViewText(R.id.widget_tv_total, total); views.setViewVisibility(R.id.widget_total_layout,View.VISIBLE); }else if (TextUtils.isEmpty(ShaPreUtils.getTotalGold(context))){ views.setViewVisibility(R.id.widget_total_layout,View.GONE); }else{ views.setViewVisibility(R.id.widget_total_layout,View.VISIBLE); views.setTextViewText(R.id.widget_tv_total,ShaPreUtils.getTotalGold(context)); } //3,点击事件 Intent toStartActivity = new Intent(context, AppStart.class); views.setOnClickPendingIntent(R.id.widget_to_app, PendingIntent.getActivity(context, 0, toStartActivity, 0)); // 买金的时候发送一个广播,当前类接收 Intent to_buygold = new Intent(context, GoldWidgetProvider.class); to_buygold.setAction(ACTION_TO_BUYGOLD); views.setOnClickPendingIntent(R.id.widget_to_buygold, PendingIntent.getBroadcast(context, 0,to_buygold , 0)); // 主动刷新广播 Intent layout = new Intent(context, GoldWidgetProvider.class); layout.setAction(ACTION_CLICK_UPDATE_WIDGET); views.setOnClickPendingIntent(R.id.widget_layout, PendingIntent.getBroadcast(context, 0, layout, 0)); return views;}
2.appwidget_info里的android:configure属性
一开始的时候照着官方文档在appwidget_info xml文件里设置了这个属性,在添加到桌面上的时候总是不成功,将这个属性去掉就可以了,不知道这个属性具体怎么用,有知道的麻烦告诉我一声,感激不尽...
查看官方文档法相这个属性是给widget设置一个config,具体怎么使用可以查看官方文档
3.appWidgetManager更新的两个方法
updateAppWidget(int[] appWidgetIds, RemoteViews views)
updateAppWidget(ComponentName provider, RemoteViews views) {
updateAppWidget(int[] appWidgetIds, RemoteViews views)代码如下:
// 更新 widget 的广播对应的actionprivate final String ACTION_UPDATE_ALL = "com.skywang.widget.UPDATE_ALL";// 保存 widget 的id的HashSet,每新建一个 widget 都会为该 widget 分配一个 id。private static Set idsSet = new HashSet();@Overridepublic void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { Log.d(TAG, "onUpdate(): appWidgetIds.length="+appWidgetIds.length); // 每次 widget 被创建时,对应的将widget的id添加到set中 for (int appWidgetId : appWidgetIds) { idsSet.add(Integer.valueOf(appWidgetId)); } } @Override public void onDeleted(Context context, int[] appWidgetIds) { Log.d(TAG, "onDeleted(): appWidgetIds.length="+appWidgetIds.length); // 当 widget 被删除时,对应的删除set中保存的widget的id for (int appWidgetId : appWidgetIds) { idsSet.remove(Integer.valueOf(appWidgetId)); } super.onDeleted(context, appWidgetIds); }//接收广播的回调函数@Override public void onReceive(Context context, Intent intent) { final String action = intent.getAction(); if (ACTION_UPDATE_ALL.equals(action)) { // “更新”广播 updateAllAppWidgets(context, AppWidgetManager.getInstance(context), idsSet); } } // 更新所有的 widget private void updateAllAppWidgets(Context context, AppWidgetManager appWidgetManager, Set set) { Log.d(TAG, "updateAllAppWidgets(): size="+set.size()); // widget 的id int appID; // 迭代器,用于遍历所有保存的widget的id Iterator it = set.iterator(); while (it.hasNext()) { appID = ((Integer)it.next()).intValue(); if (DEBUG) Log.d(TAG, "onUpdate(): index="+index); // 获取 example_appwidget.xml 对应的RemoteViews RemoteViews remoteView = getRemoteViews(context,""); // 更新 widget appWidgetManager.updateAppWidget(appID, remoteView); } }
上面这些代码有个隐患,在应用退出后,或是被第三方软件杀死,点击桌面widget就不会更新了。原因是updateid我是用static的set集合保存的,应用退出后,这个set集合就被清空了,后面又换成了updateAppWidget(ComponentName)方法后就好了。
RemoteViews views = getRemoteViews(context, null);
ComponentName name = new ComponentName(context, GoldWidgetProvider.class);
AppWidgetManager.getInstance(context).updateAppWidget(name, views);
4.在用setOnClickPendingIntent()方法设置点击事件发送Broadcast时,不能直接new Intent(acton)
Intent intent = new Intent(ACTION_CLICK_UPDATE_WIDGET);
views.setOnClickPendingIntent(R.id.widget_layout, PendingIntent.getBroadcast(context, 0, intent, 0));
上面这种写法在应用退出后在有些手机上收不到广播,然后换成下面这种写法
Intent layout = new Intent(context, GoldWidgetProvider.class);
layout.setAction(ACTION_CLICK_UPDATE_WIDGET);
views.setOnClickPendingIntent(R.id.widget_layout, PendingIntent.getBroadcast(context, 0, layout, 0));
关键字:widget
版权声明
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处。如若内容有涉嫌抄袭侵权/违法违规/事实不符,请点击 举报 进行投诉反馈!