1.在Manifest文件中声明

<receiver android:name=".receiver.GoldWidgetProvider"><intent-filter><action android:name="android.appwidget.action.APPWIDGET_UPDATE" /><action android:name="com.fuqi.gold.action_updatewidget" /><action android:name="com.fuqi.gold.action_click_updatewidget" /><action android:name="com.fuqi.gold.action_to_buygold" /></intent-filter><meta-dataandroid:name="android.appwidget.provider"android:resource="@xml/goldwidget_provider_info" />
</receiver>

这个就相当于一个广播接收者,然后android:name属性指定在第四步的时候创建的文件名

android:resource="@xml/example_appwidget_info"/>是widget的配置文件

2.添加Widget配置信息

在项目的 res/xml/ 目录下。如果没有xml目录,需要新建一个

<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"android:minWidth="40dp"android:minHeight="40dp"android:updatePeriodMillis="86400000"android:previewImage="@drawable/preview"android:initialLayout="@layout/example_appwidget"android:resizeMode="horizontal|vertical"android:widgetCategory="home_screen">
</appwidget-provider>
  • initialLayout是widget的布局文件

  • previewImage就是widget的预览效果

3.新建一个appwidget_layout文件

<FrameLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"android:padding="@dimen/widget_margin"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"android:orientation="horizontal"android:background="@drawable/my_widget_background">…</LinearLayout></FrameLayout>

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<N; i++) {int appWidgetId = appWidgetIds[i];Intent intent = new Intent(context, ExampleActivity.class);PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.appwidget_provider_layout);views.setOnClickPendingIntent(R.id.button, pendingIntent);widgetappWidgetManager.updateAppWidget(appWidgetId, views);}}
}

5.开发中的一些坑

1. updateMillies更新时间低于30分钟,系统默认为30分钟。如果想要自己更新widget,将这个值设置为0,然后自己开timer或者通过广播去更新。我是通过广播去更新的
// 重写OnReceiver方法@Overridepublic void onReceive(Context context, Intent intent) {super.onReceive(context, intent);String action = intent.getAction();// 需要在Manifest中注册这个Actionif (ACTION_UPDATE_WIDGET.equals(action)) { // update widgetRemoteViews 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的idfor (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 的idint appID;// 迭代器,用于遍历所有保存的widget的idIterator 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,"");// 更新 widgetappWidgetManager.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开发中遇到的坑相关推荐

  1. celery开发中踩的坑

    celery开发中踩的坑 celery连接redis 当使用redis做broker,redis连接需要密码时: BROKER_URL='redis://:xxxxx@127.0.0.1:6379/0 ...

  2. 前端项目开发中碰到的坑、移动端兼容性问题

    前端开发中碰到的坑.移动端兼容性问题 1.ios兼容input光标高度 问题:input输入光标,在安卓手机上显示没有问题,但是在苹果手机上当点击输入的时候,光标的高度和父盒子的高度一样. **出现问 ...

  3. 记一次ios内购开发中踩的坑

    记一次ios内购开发中踩的坑 前段时间好不容易把APP中的非续期内购上架成功了,过程也是一波三折,各种问题,但最终还是内购审核通过了 通过后我以为就没问题了,但第二天打开xcode运行应用后,准备验证 ...

  4. javaweb开发中的那些坑

    最近电脑有点问题,没办法就重装系统了,花了一个晚上重装IDE.,配置环境,好不容易把eclipse的环境弄好,加载之前的项目时却又到各种问题,一怒之下,写一篇记录下在javaweb开发中遇到的各种坑 ...

  5. 细数移动IM开发中的那些坑

    移动互联网时代的来临促使我们所有的开发者都要从用户视角出发,基于某一特定场景来创建应用,满足用户需求.通常,在这些应用中,沟通环节都是必不可少的.这就要求创业者不仅要花时间和精力来琢磨用户在某一特定场 ...

  6. 微信小程序开发中遇到的坑

    博主也是一个新入坑的萌新,从上个月20多号开始开发微信小程序,总体感觉入手快,门槛低. 开发中使用的办法比较老土. 下面一一介绍下我在开发中遇到的问题与解决方法 1.下拉刷新与上拉加载 下拉刷新微信提 ...

  7. 你踩过几个?盘点微信H5小游戏开发中的那些坑

    眼下小游戏特别火,不少团队也陆续启动了微信小游戏的项目,并于立项前期进行技术预研究.但从微信官方文档看 , 却能发现不少坑. 一.运行环境的坑 首先微信小游戏是一个不同于浏览器的 JavaScript ...

  8. 由安卓开发中的一个坑引发的问题解决之道浅析

    博客: 安卓之家 微博: 追风917 CSDN: 蒋朋的家 简书: 追风917 扯扯 最近发生了好多事情,两会,google AI alphaGo 大战李世石,俘获无数少男少女心的韩国电视剧<太 ...

  9. 你踩过几个?微信H5小游戏开发中的那些坑

    眼下小游戏特别火,不少团队也陆续启动了微信小游戏的项目,并于立项前期进行技术预研究.但从微信官方文档看 , 却能发现不少坑. 一.运行环境的坑 1.API兼容性 1.1.网络API BOM的核心是wi ...

最新文章

  1. OKR 怎么突然火起来了?
  2. 服务稳定性及应用防护方案
  3. 微信扫码下载iosAPP
  4. Win7搭建NodeJs开发环境以及HelloWorld展示—图解
  5. 2021年SWPUACM暑假集训day3最小生成树算法
  6. oracle数据库技术_创建 pdb数据库
  7. 通过相关系数和自由度求置信度
  8. oracle去空格和换行,ORACLE 中去回车、空格、TAB的函数
  9. Excel-VBA基础(7):VBE开发环境的主要优化配置
  10. 阿里巴巴助攻腾讯破6.2亿微商传销第一大案!涉案公众号粉丝2400
  11. 蛮荒搜神记服务器在维护,蛮荒搜神记法宝洗练图文教程 蛮荒搜神记如何提升战斗力?-游侠网...
  12. 《算法导论》学习(十七)----动态规划之钢条切割(C语言)
  13. 衣服挂牌 挂牌吊牌(麻绳,五彩绳,尼龙绳等)
  14. ⌨RK61键盘使用方法
  15. 【国内博客】国内常见的 博客 主页 (IT)
  16. golang之切片的操作详解
  17. 常见的网络状态检测及分析工具
  18. IT培训讲师的亲身感受
  19. [011量化交易] python根据收盘价计算涨跌百分比
  20. php下载图片excel过大,PHPExcel导出图片大小设置问题

热门文章

  1. VS2008 快捷键 大全
  2. 蓝桥杯第八届省赛JAVA真题----油漆面积
  3. 查找算法——折半查找(JAVA)
  4. python可视化报表制作教程_如何使用Python快速制作可视化报表
  5. Golang——文件创建和写入、OpenFile追加写入、Open读取文件、ReadBytes缓冲区读取、os.Args、flag
  6. oracle leg函数,oracle对象 约束索引 游标 函数
  7. 实现光晕效果_马自达6车灯升级激光四透镜实现四近四远光
  8. linux录制远程麦克风声音,在Linux上录制麦克风到wav或mp3文件?
  9. java中常用API、Scanner类、匿名对象、Random类、ArrayList类、对象数组
  10. 机器学习笔记(十九)——最大熵原理和模型定义