Android AppWidget实践
前面
业务工作需要,需要为App增加AppWidget功能,做到不打开App也能完成部分功能使用
一般情况下,按照官网或其它技术文章都可以得到相关的使用
这里将实践过程中的一些知识点记录
关于AppWidgetProvider
它是一个AppWIdget的最重要的元素,就像页面与Activity之间的关系,
观察它的父类,它就是一个BroadcastReceiver,通过接收广播来触发内部多个方法的回调,比如onUpdate、onDelete等
App内部有更新需求的时候,其中一种就是通过发送Intent来触发AppWidgetProvider的onUpdate方法 (另外一种是直接通过Manager.update(remoteview))
有的App提供多种AppWidget,来说京东App就提供了4种,在实现方式上就需要提供4个AppWidgetProvider
每种AppWidget都有一个名字,可以通过AndroidManifest.receiver标签下的label来指定
每种AppWIdget,在桌面上可以重复添加,体现在代码上的影响就是多个WidgetId
关于RemoteView
观察它的父类,没有继承至View,所以不能认为它是一个View
它只是一个对View的描述,也可以对View进行操作,而最终View是在其他进程上显示的
对于它的操作,需要使用特定的方法,观察其内部方法的调用,每个动作都涉及到序列化和反射
对于没有提供的方法,可以直接通过告知方法名和参数的方法
remoteViews.setFloat(R.id.controlLayout, "setWeightSum", weightSum)
关于PendingIntent
AppWidget的View上的元素,肯定会存在点击事件,其事件都需要包装成PendingIntent
PendingIntent和RemoteView 他两很搭配
这里的注意点是,构建PendingIntent的时候,提供的RequestCode最好是具备唯一性的,不然他会被后面添加的事件覆盖。
整体实现的一些设计
AppWidget上的点击事件,做包装成指令/命令之后,发送给一个新的BroadcastReceiver,由这个新的Broadcast对其进行业务处理
处理过程中,或处理结束之后,需要将结果体现在AppWidget上,这个时候就再次发送action: AppWidgetManager.ACTION_APPWIDGET_UPDATE (携带一些构建View需要的参数) 给 KeyAppWidgetProvider 触发它的onUpdate方法
举例一个业务:
点击一个按钮,按钮点击之后需要转圈圈,后台还会发送网络请求,请求响应结束之后,转圈圈关闭,展示Toast(执行成功)
代码实现上是,按钮点击的时候,上文提供的新的BroadcastReceiver接收到指令,进行处理
1. 向KeyAppWidgetProvider发送一个更新指令,其内部包含的参数告知他 需要让某个View上展示转圈圈
2. 网络请求调用
3. 得到网络请求的响应之后,向KeyAppWidgetProvider发送一个更新指令,其内部包含的参数告知他 需要让转圈圈结束,展示toast
4. 1秒之后,向KeyAppWidgetProvider发送一个更新指令,其内部包含的参数告知他 隐藏toast
补充一个解决问题的思路
项目中遇到的一个bug,期望构建的Widget是一个4x2的尺寸,但是在一台华为手机上的表现是3x2,属于适配上的问题,从参数配置上,已经完全按照官网教程添加的尺寸参数,但是出现这样的问题很懵逼
后来解决的办法是,从网络上下载其他具有相同尺寸Widget的APK,再通过反编译,查看其中AppWidgetProvider的配置,进行对照的修改,最后成功解决这个问题
借助对竞品APK的反编译或其它手段的分析/学习,也是一个解决问题的很好办法
我日常常用的反编译工具是jadx-gui,很方便
最后
中间有看过一些开源项目/Demo,回顾本次对AppWidget的使用还是比较浅的,
比如RemoteViewsService都还没用到,看注释是服务于列表类的控件;
每次刷新都是整个的刷新,比较希望存在一种局部刷新的方法
RemoteViewsService