Android widget基础指南

widget的概念最早是由一名叫Rose的苹果工程师提出,后来经过多方面机缘巧合的发展下,便有了今天Android平台上的小组件widget,一般APP开发可能应用场景较少,最常见的莫过于天气APP的widget。但对于从事IOT或车载方向的同学,定制化Launcher涉及修改的widget的相关业务则可能不少。

Android widget,即桌面插件,如下图红框所选中皆是插件:

其启动、加载运行流程全在Launcher中,其实现细节我们可以不关注(如果想了解需翻阅Launcher源码),只需要了解如何使用即可。实现步骤如下:

1、创建布局

在res/layout/目录中创建相应布局:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="200dp"
    android:background="#cca">

    <ImageView
        android:id="@+id/icon"
        android:layout_width="60dp"
        android:layout_height="60dp"
        android:layout_centerInParent="true"
        android:src="@drawable/ic_launcher_round"/>

    <TextView
        android:id="@+id/tv_widget"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/icon"
        android:text="123"
        android:layout_centerHorizontal="true"/>

</RelativeLayout>

这里要注意的是,widget中并不支持所有布局控件,目前所支持的布局如下:

FrameLayout
LinearLayout
RelativeLayout
GridLayout

所支持的控件如下:

AnalogClock
Button
Chronometer
ImageButton
ImageView
ProgressBar
TextView
ViewFlipper
ListView
GridView
StackView
AdapterViewFlipper

不支持自定义View、这些类的子类,以及包括RecyclerView在内的其他没有声明的控件(是的,这些都不支持)。

2、创建配置文件

在res/xml/目录中创建相应文件:

<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
    android:minHeight="180dp"
    android:minWidth="300dp"
    android:previewImage="@drawable/ic_launcher_background"
    android:initialLayout="@layout/layout_widget_info"
    android:updatePeriodMillis="10000"
    android:resizeMode="horizontal|vertical"
    android:widgetCategory="home_screen">

</appwidget-provider>

其各参数含义如下:

·minWidth 、 minHeight:widget的最小宽、高,在Launcher上,widget可以通过拉伸宽高来改变尺寸大小。

·previewImage:添加widget前的预览图片。

·initialLayout:widget所使用的布局。

·updatePeriodMillis:widget更新周期时间。(在 1.6 以后的版本中,Google从省电的角度规定,当 updatePeriodMillis 设置的值小于30min时,就会失效。也就是通过设置这个属性值,最短的更新间隔是30min。)

·resizeMode:widget尺寸调整规格、拉伸方向,"horizontal"代表可以水平拉伸,"vertical"代表可以竖向拉伸,"none"代表不能拉伸;默认为"none"。

·widgetCategory:widget的显示区域,"home_screen" 或 "keyguard"。

3、创建AppWidgetProvider

widget的功能都是通过AppWidgetProvider实现的,先继承此类然后复写相关方法,例如:

public class MainWidgetProvider extends AppWidgetProvider {

    @Override
    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
        super.onUpdate(context, appWidgetManager, appWidgetIds);
    }

    @Override
    public void onEnabled(Context context) {
        super.onEnabled(context);
    }

    @Override
    public void onAppWidgetOptionsChanged(Context context, AppWidgetManager appWidgetManager, int appWidgetId, Bundle newOptions) {
        super.onAppWidgetOptionsChanged(context, appWidgetManager, appWidgetId, newOptions);
    }

    @Override
    public void onDeleted(Context context, int[] appWidgetIds) {
        super.onDeleted(context, appWidgetIds);
    }

    @Override
    public void onDisabled(Context context) {
        super.onDisabled(context);
    }

    @Override
    public void onReceive(Context context, Intent intent) {
        super.onReceive(context, intent);
    }
}

其个参数含义如下:

·onUpdate():用户添加widget时,或者根据updatePeriodMillis定义的刷新时间到了的时候,会调用此函数刷新,可以在此函数里进行部分初始化刷新业务,也可以在这里设置点击事件等。

·onEnabled():widget第一次被添加时调用,比如用户添加widget后再删除再添加一次,只有第一次添加的时候会回调。

·onDisabled():当最后一个widget在Launcher桌面上被移除后调用,这时候适合做一些数据重置归零业务。

·onReceive():广播接收时调用。

·onAppWidgetOptionsChanged():widget 第一次添加或者拉伸等引起大小尺寸发生变化时调用该方法

·onDeleted():小插件被移除时会调用。(亲测不是所有机型都有效)

这里面最常使用的也就是onUpdate()和onReceive()了。

4、在AndroidManifest.xml中添加相关信息

我们观察下AppWidgetProvider的源码,会发现这其实就是个广播类:

因此,我们的MainWidgetProvider 在清单文件中也要以广播的形式注册:

<receiver
    android:name=".MainWidgetProvider"
    android:label="小组件">
    <intent-filter>
        <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
    </intent-filter>
    <meta-data
        android:name="android.appwidget.provider"
        android:resource="@xml/widget_provider" />
</receiver>

这里的android.appwidget.action.APPWIDGET_UPDATE 动作的广播是所有widget都会接受到的广播,该广播根据android:updatePeriodMillis设定的间隔时间发出广播,用于定时更新桌面上的所有窗口小部件(部分机型可能无效)。resource指定xml 目录下widget对应的布局文件。

其效果(长按桌面,选择自己的小组件长按拖拽到桌面的过程)如下:

总结

widget所有流程基本上全在这里了,其余业务逻辑流程这里不再赘述。widget在部分机型上还拥有保活的功效(比如OV,没升鸿蒙之前的华为等),当然,你也有可能会发现在某些机型上部分API会失效,因为控制这部分API的Launcher是各大厂商必改的apk之一,如果想刷新widget,还是得通过广播的形式,同时注意进程的存活状态,但是考虑到很多方法不一定会生效,建议相关逻辑处理放到Service中。

相关推荐
拓端研究室8 分钟前
R基于贝叶斯加法回归树BART、MCMC的DLNM分布滞后非线性模型分析母婴PM2.5暴露与出生体重数据及GAM模型对比、关键窗口识别
android·开发语言·kotlin
zhangphil1 小时前
Android简洁缩放Matrix实现图像马赛克,Kotlin
android·kotlin
m0_512744641 小时前
极客大挑战2024-web-wp(详细)
android·前端
lw向北.1 小时前
Qt For Android之环境搭建(Qt 5.12.11 Qt下载SDK的处理方案)
android·开发语言·qt
不爱学习的啊Biao1 小时前
【13】MySQL如何选择合适的索引?
android·数据库·mysql
Clockwiseee2 小时前
PHP伪协议总结
android·开发语言·php
mmsx8 小时前
android sqlite 数据库简单封装示例(java)
android·java·数据库
众拾达人11 小时前
Android自动化测试实战 Java篇 主流工具 框架 脚本
android·java·开发语言
吃着火锅x唱着歌12 小时前
PHP7内核剖析 学习笔记 第四章 内存管理(1)
android·笔记·学习
_Shirley13 小时前
鸿蒙设置app更新跳转华为市场
android·华为·kotlin·harmonyos·鸿蒙