Android Widget

参考链接
https://blog.csdn.net/Jason_Lee155/article/details/124476447
原文代码有多处问题 且有些信息似乎没有提供 本篇文章只是做了些整理
本文除了一些图片没有提供 其他资料应该是比较齐全的,图片可以随意下载一些
AppWidget 即桌面小部件,也叫桌面控件,就是能直接显示在Android系统桌面上的小程序。图中用黄色箭头指示的即为AppWidget,一些用户使用比较频繁的程序,可以做成AppWidget,这样能方便地使用。典型的程序有时钟、天气、音乐播放器等。AppWidget 是Android 系统应用开发层面的一部分,有着特殊用途,使用得当的话,的确会为app 增色不少,它的工作原理是把一个进程的控件嵌入到别外一个进程的窗口里。需要说明的是,AppWidgetProvider本质是一个广播,即BroadcastReceiver,在实际的使用中,把AppWidgetProvider当成一个BroadcastReceiver即可。
手动创建AppWidget的步骤:

1. 为AppWidget提供一个xml文件,定义小控件的基本配置信息

在资源文件夹res目录下新建xml文件夹,假设名字为my_widget.xml,文件内容为:

<?xml version="1.0" encoding="utf-8"?><!--小控件宽高
    android:minWidth="40dp"
    android:minHeight="40dp"
    更新时间
    android:updatePeriodMillis="86400000"
    用于指定预览图片。即搜索到widget时,查看到的图片。若没有设置的话,系统为指定一张默认图片。(多半是ic_launcher)
    android:previewImage="@drawable/widget_flashlight"
    widget 添加到手机主屏幕中的layout
    android:initialLayout="@layout/flash_light_widget"
    android:resizeMode : widget可以被拉伸的方向。horizontal表示可以水平拉伸,vertical表示可以竖直拉伸
    android:resizeMode="horizontal|vertical"-->
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
    android:initialLayout="@layout/widget_layout"
    android:minWidth="100dp"
    android:minHeight="100dp"
    android:previewImage="@drawable/img"
    android:resizeMode="horizontal|vertical"
    android:updatePeriodMillis="86400000" />

2. 创建一个MyAppWidgetProvider继承自AppWidgetProvider

package com.example.testapp


import android.app.PendingIntent
import android.appwidget.AppWidgetManager
import android.appwidget.AppWidgetProvider
import android.content.Context
import android.content.Intent
import android.util.Log
import android.widget.RemoteViews


const val TAG = "MyAppWidgetProvider"

class MyAppWidgetProvider : AppWidgetProvider() {
    //每接收一次广播消息就调用一次,使用频繁
    override fun onReceive(context: Context?, intent: Intent?) {
        super.onReceive(context, intent)
        Log.i(TAG, "onReceive: ")
    }

    //每次更新都调用一次该方法,使用频繁
    override fun onUpdate(
        context: Context?, appWidgetManager: AppWidgetManager?,
        appWidgetIds: IntArray?
    ) {
        Log.i(TAG, "onUpdate: ")
        for (appWidgetId in appWidgetIds!!) {
            val views = RemoteViews(context!!.packageName, R.layout.widget_layout)
            val intent = Intent(context, MainActivity::class.java)
            val pi = PendingIntent.getActivity(
                context,
                200,
                intent,
                PendingIntent.FLAG_UPDATE_CURRENT
            )
            views.setOnClickPendingIntent(R.id.widget_led, pi)
            appWidgetManager!!.updateAppWidget(appWidgetId, views)
        }
    }



    //每删除一个就调用一次
    override fun onDeleted(context: Context?, appWidgetIds: IntArray?) {
        super.onDeleted(context, appWidgetIds)
        Log.i(TAG, "onDeleted: ")
    }

    //当该Widget第一次添加到桌面是调用该方法,可添加多次但只第一次调用
    override fun onEnabled(context: Context?) {
        super.onEnabled(context)
        Log.i(TAG, "onEnabled: ")
    }

    //当最后一个该Widget删除是调用该方法,注意是最后一个
    override fun onDisabled(context: Context?) {
        super.onDisabled(context)
        Log.i(TAG, "onDisabled: ")
    }
}

3. 为 WidgetProvider创建一个布局文件

该布局是widget被放到launcher时的布局
布局就是正常布局,假设名字为widget_layout.xml:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:padding="20dp"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">

    <ImageButton
        android:id="@+id/widget_led"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@drawable/ic_launcher_background2"
        android:scaleType="center"
        android:src="@drawable/icon" />
</RelativeLayout>

4. 注册Manifest.xml

配置基本和广播一样,在清单文件中activity同级节点添加如下代码

        <receiver android:name=".MyAppWidgetProvider"
            android:exported="true">
            <intent-filter>
                <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
            </intent-filter>
            <meta-data
                android:name="android.appwidget.provider"
                android:resource="@xml/my_widget" />
        </receiver>

使用receiver 节点,节点指向第二部的provider,meta-data 节点的name 为固定格式,resource为第一步定义的配置信息,intent-filter节点的action也是固定格式:
这样一个静态的home widget就创建好了 点击widget还可以进行跳转
Android 官网的代码很多都是Android 12 新增的功能 在低版本设备上不生效,因此本文使用的代码都是适应低版本的代码,与Android官方文档的代码有许多不同