Android 创建桌面组件Widget——构建应用微件(二)

news2024/12/23 0:05:55

Android 创建桌面组件Widget——构建应用微件(二)

  • Android 创建桌面组件Widget——构建应用微件(二)
    • 概览
        • 使用 AppWidgetProvider 类
          • 接收应用微件广播 Intent
        • 固定应用微件
        • 设置预览图片
    • 完整代码

Android 创建桌面组件Widget——构建应用微件(一)

Android 创建桌面组件Widget——构建应用微件(二)

效果图:
创建一个可以改变大小的widget,包含一个Button和一个TextView,点击按钮跳转到指定的Activity。
请添加图片描述

概览

微件是自定义主屏幕的一个重要方面。您可以将微件想象成“一目了然”的视图,它们让最重要的应用数据和功能一览无余,从用户的主屏幕即可进行访问。用户可以在其主屏幕面板间移动微件,如果系统支持,用户还可以调整微件的大小,按照他们的偏好量身定制微件中的信息量。

使用 AppWidgetProvider 类

AppWidgetProvider类扩展了BroadcastReceiver作为一个辅助类来处理应用微件广播。AppWidgetProvider仅接收与应用微件有关的事件广播,例如当更新、删除、启用和停用应用微件时发出的广播。当发生这些广播事件时,AppWidgetProvider会接收以下方法调用:

  • onUpdate()
    调用此方法可以按AppWidgetProviderInfo中的updatePeriodMillis属性定义的时间间隔来更新应用微件。当用户添加应用微件时也会调用此方法,所以它应执行基本设置,如定义视图的事件处理脚本以及根据需要启动临时的 Service。不过,如果您已声明配置Activity,则当用户添加应用微件时不会调用此方法,但会调用它来执行后续更新。由配置Activity负责在配置完成后执行首次更新。
  • onAppWidgetOptionsChanged()
    当首次放置微件时以及每当调整微件的大小时,会调用此方法。您可以使用此回调来根据微件的大小范围显示或隐藏内容。您可以通过调用 getAppWidgetOptions() 来获取大小范围,该方法会返回包含以下各项的 Bundle
    • OPTION_APPWIDGET_MIN_WIDTH : 包含微件实例的当前宽度的下限(以 dp 为单位)。
    • OPTION_APPWIDGET_MIN_HEIGHT: 包含微件实例的当前高度的下限(以 dp 为单位)
    • OPTION_APPWIDGET_MAX_WIDTH: 包含微件实例的当前宽度的上限(以 dp 为单位)
    • OPTION_APPWIDGET_MAX_HEIGHT: 包含微件实例的当前高度的上限(以 dp 为单位)。
    • 此回调是在 API 级别 16 (Android 4.1) 中引入的。如果您实现此回调,请确保您的应用不依赖于它,因为在旧款设备上不会调用它。
  • onDeleted(Context, int[])
    每次从应用微件托管应用中删除应用微件时,都会调用此方法。
  • onEnabled(Context)
    首次创建应用微件的实例时,会调用此方法。例如,如果用户添加应用微件的两个实例,只有首次添加时会调用此方法。如果您需要打开一个新的数据库或执行只需要对所有应用微件实例执行一次的其他设置,则此方法非常合适。
  • onDisabled(Context)
    从应用微件托管应用中删除了应用微件的最后一个实例时,会调用此方法。您应使用此方法来清理在 onEnabled(Context)中完成的所有工作,如删除临时数据库。
  • ``
    针对每个广播调用此方法,并且是在上述各个回调方法之前调用。您通常不需要实现此方法,因为默认的 AppWidgetProvider 实现会过滤所有应用微件广播并视情况调用上述方法。

最重要的 AppWidgetProvider 回调是 onUpdate(),因为向托管应用添加每个应用微件时都会调用它(除非您使用配置 Activity)。如果应用微件接受任何用户交互事件,则您需要在此回调中注册事件处理脚本。如果应用微件未创建临时文件或数据库,或者未执行其他需要清理的工作,则 onUpdate() 可能是您需要定义的唯一一个回调方法。例如,如果您希望应用微件具有一个在用户点击时会启动 Activity 的按钮,则可以使用以下 AppWidgetProvider 实现:

public class ExampleAppWidgetProvider extends AppWidgetProvider {

    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
        final int N = appWidgetIds.length;

        // Perform this loop procedure for each App Widget that belongs to this provider
        for (int i=0; i<N; i++) {
            int appWidgetId = appWidgetIds[i];

            // Create an Intent to launch ExampleActivity
            Intent intent = new Intent(context, ExampleActivity.class);
            PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);

            // Get the layout for the App Widget and attach an on-click listener
            // to the button
            RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.appwidget_provider_layout);
            views.setOnClickPendingIntent(R.id.button, pendingIntent);

            // Tell the AppWidgetManager to perform an update on the current app widget
            appWidgetManager.updateAppWidget(appWidgetId, views);
        }
    }
}

接收应用微件广播 Intent

AppWidgetProvider 只是一个辅助类。如果您希望直接接收应用微件广播,您可以实现自己的 BroadcastReceiver 或替换 onReceive(Context, Intent) 回调。您需要关注的 Intent 如下所示:

ACTION_APPWIDGET_UPDATE
ACTION_APPWIDGET_DELETED
ACTION_APPWIDGET_ENABLED
ACTION_APPWIDGET_DISABLED
ACTION_APPWIDGET_OPTIONS_CHANGED

固定应用微件

在搭载 Android 8.0(API 级别 26)及更高版本的设备上,允许您创建固定的快捷方式的启动器也允许您将应用微件固定到启动器上。与固定的快捷方式类似,这些固定的微件也能让用户访问应用中的特定任务。

在您的应用中,您可以创建一个请求,让系统将微件固定到支持的启动器上,只需完成下面一系列步骤即可:

  1. 在应用的清单文件中创建微件,如以下代码段所示:
    <manifest>
    ...
      <application>
        ...
        <receiver android:name="MyAppWidgetProvider">
            <intent-filter>
                <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
            </intent-filter>
            <meta-data android:name="android.appwidget.provider"
                       android:resource="@xml/my_appwidget_info" />
        </receiver>
      </application>
    </manifest>
    
  1. 调用 requestPinAppWidget() 方法,如以下代码段所示:
    AppWidgetManager appWidgetManager =
            context.getSystemService(AppWidgetManager.class);
    ComponentName myProvider =
            new ComponentName(context, MyAppWidgetProvider.class);

    if (appWidgetManager.isRequestPinAppWidgetSupported()) {
        // Create the PendingIntent object only if your app needs to be notified
        // that the user allowed the widget to be pinned. Note that, if the pinning
        // operation fails, your app isn't notified.
        Intent pinnedWidgetCallbackIntent = new Intent( ... );

        // Configure the intent so that your app's broadcast receiver gets
        // the callback successfully. This callback receives the ID of the
        // newly-pinned widget (EXTRA_APPWIDGET_ID).
        PendingIntent successCallback = PendingIntent.getBroadcast(context, 0,
                pinnedWidgetCallbackIntent, PendingIntent.FLAG_UPDATE_CURRENT);

        appWidgetManager.requestPinAppWidget(myProvider, null, successCallback);
    }
    

注意:如果无需通知您的应用系统是否已成功地将微件固定到受支持的启动器上,则您可以将 null 作为 requestPinAppWidget() 的第三个参数传入。

设置预览图片

Android 3.0 引入了 previewImage 字段,用于指定预览来描绘应用微件是什么样子的。此预览通过微件选择器显示给用户。如果未提供此字段,则应用微件的图标将用于预览。

在 XML 中指定此设置的方式如下:

<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
      ...
      android:previewImage="@drawable/preview">
    </appwidget-provider>

为了帮助创建应用微件的预览图片(在previewImage字段中指定),Android 模拟器包含一个名为“微件预览”的应用。要创建预览图片,请启动此应用,为您的应用选择应用微件并设置您希望如何显示预览图片,然后将其保存并放在您的应用的可绘制资源中。

完整代码

  1. ExampleAppWidgetProvider.java 文件
public class ExampleAppWidgetProvider extends AppWidgetProvider {

    private static final String TAG = "ExampleAppWidgetProvider";

    @Override
    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
        Log.i(TAG, "onUpdate: ");
        for (int appWidgetId : appWidgetIds) {
            updateAppWidget(context, appWidgetManager, appWidgetId);
        }
        time = System.currentTimeMillis();
    }

    private void updateAppWidget(Context context, AppWidgetManager appWidgetManager, int appWidgetId) {
        RemoteViews view = new RemoteViews(context.getPackageName(), R.layout.widget_content);

        // 点击桌面组件中的按钮,跳转到主界面
        Intent i = new Intent(context, MainActivity.class);
        PendingIntent intent = PendingIntent.getActivity(context, 0, i, PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT);
        view.setOnClickPendingIntent(R.id.btn_click, intent);
//        view.setTextViewText(R.id.tv_info, "clicked");

        appWidgetManager.updateAppWidget(appWidgetId, view);
    }
}
  1. layout/widget_content.xml布局文件
<?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="match_parent"
    android:orientation="vertical">

    <Button
        android:id="@+id/btn_click"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:text="click me"/>

    <TextView
        android:id="@+id/tv_info"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="hello, this is appwidget"
        android:layout_centerHorizontal="true"
        android:layout_alignParentBottom="true"/>

</RelativeLayout>
  1. xml/example_appwidget_info.xml文件
<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:initialKeyguardLayout="@layout/widget_content"
    android:initialLayout="@layout/widget_content"
    android:minHeight="110dp"
    android:minWidth="180dp"
    android:previewImage="@drawable/ic_launcher_foreground"
    android:resizeMode="vertical|horizontal"
    android:updatePeriodMillis="600000"
    android:widgetCategory="home_screen">

</appwidget-provider>
  1. AndroidManifest.xml文件
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.csu.mywidget">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.MyExample">
        <receiver
            android:name=".ExampleAppWidgetProvider"
            android:enabled="true"
            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/example_appwidget_info"/>
        </receiver>

        <activity
            android:name=".MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

参考:
https://developer.android.google.cn/guide/practices/ui_guidelines/widget_design
https://developer.android.google.cn/guide/topics/appwidgets#collection_sample
https://blog.csdn.net/tracydragonlxy/article/details/127231654?csdn_share_tail=%7B%22type%22%3A%22blog%22%2C%22rType%22%3A%22article%22%2C%22rId%22%3A%22127231654%22%2C%22source%22%3A%22tracydragonlxy%22%7D

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/46703.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Spark学习(7)-SparkSQL函数定义

1 SparkSQL 定义UDF函数 目前在SparkSQL中&#xff0c;仅仅支持UDF和UDAF函数&#xff0c;python仅支持UDF。 1.1 定义方式 定义方式有两种&#xff1a; sparksession.udf.register() 注册的UDF可以用于DSL和SQL&#xff0c;返回值用于DSL风格&#xff0c;传参内的名字用于SQ…

如何在Odoo中添加水印?

为了防止信息的泄露&#xff0c;水印作为一种防泄密的方式&#xff0c;被使用的频率越来越高。 那么在Odoo中&#xff0c;如何添加水印呢&#xff1f;其实添加的方法有很多&#xff0c;如利用svg生成背景图&#xff0c;重复的dom元素覆盖等等。 本文主要讲解利用canvas输出背…

不懂单链表? 这篇文章就帮你搞明白

坚持看完&#xff0c;结尾有思维导图总结 链表对指针的操作要求不低链表的概念链表的特性链表的功能(最重要)定义和初始化头插头删细节说明尾插尾删寻找链表元素与打印链表在 某位置后插入删除在某位置的插入删除销毁链表链表的概念 什么是链表 官方概念&#xff1a;链表是一种…

链表(1)

我们以前学过的线性数据结构底层原理都是依托静态数组来实现的&#xff0c;今天我们讲学习一个最简单的动态数据结构---->链表&#xff01; 掌握链表有助于学习更加复杂的数据结构&#xff0c;例如&#xff1a;二叉树、trie 链表的优点是不需要处理固定的问题&#xff0c;…

mavon-editor的使用

vue3vitets下安装mavon-editor 3.0.0-beta版本&#xff0c;效果如下&#xff1a; 安装 //引入样式 import mavon-editor/dist/css/index.css; import mavonEditor from mavon-editor; app.use(router).use(mavonEditor).mount(#app);<template><div class"rich…

zabbix主动监控和被动监控

目录 一、环境准备 1、搭建zabbix基础环境 二、主动监控与被动监控介绍 三、设置客户端为主动监控 1、给web2主机安装zabbix_agent 2、修改主动监控配置 四、设置zabbix管理端主动监控 1、克隆模板 2、给目标主机绑定主动监控模板 3、查看主动监控的数据 一、环境准备…

【HIT-OSLAB-实验中的碎碎念】

文章目录应该养成的好习惯删除 替换 修改 内容时 记得留备份遇到问题要通过文字 图片 等多种途径去记录不同的项目应该在不同的文件夹进行处理代码文档 记得添加一些注释用于说明功能多输出有区别度的提示信息s找bug 先定位错误 再改当一份代码有不同版本的时候 记得说明每份代…

109376-05-8,Boc-QRR-AMC, Hepsin substrate

Boc-QRR-AMC是跨膜丝氨酸蛋白酶hepsin的底物&#xff0c;也用于测定酿酒酵母中的可辛(Kex2内蛋白酶)。Boc-QRR-AMC的库存解决方案最好在DMSO中准备。 编号: 187545中文名称: Hepsin substrate&#xff1a;Boc-Gln-Arg-Arg-7-氨基-4-甲基香豆素英文名: Boc-Gln-Arg-Arg-AMCCAS号…

全球No.1集装箱人工智能企业CIMCAI中集飞瞳,集装箱信息识别铅封号识别API免费,集装箱识别率99.98%高泛化性,全球两千+企业用户使用

全球No.1集装箱人工智能企业CIMCAI中集飞瞳&#xff0c;先进人工智能AI科技打造飞瞳引擎™AI集装箱检测云服务&#xff0c;集装箱信息识别铅封号识别API免费&#xff0c;集装箱识别率99.98%高泛化性&#xff0c;全球两千企业用户使用。CIMCAI中集飞瞳成熟港航人工智能核心技术及…

3年功能测试拿8K,被刚入职的应届生反超,其实你在假装努力

最近朋友给我分享了一个他公司发生的事 大概的内容呢&#xff1a;公司一位工作3年的测试工资还没有新人高&#xff0c;对此怨气不小&#xff0c;她来公司辛辛苦苦三年&#xff0c;三年内迟到次数都不超过5次&#xff0c;每天都是按时上下班&#xff0c;工作也按量完成&#xf…

PyQT6关联信号槽 (六) 百篇文章学PyQT6

本文章是百篇文章学PyQT6的第六篇&#xff0c;本文讲述如何使用PySide创建UI界面&#xff0c;并且关联入PyCharm 新建的项目中成功运行第一个PyQT程序&#xff0c;并且使用 信号槽 connect 到函数&#xff0c;在写博客和学习的过程中会遇到很多问题&#xff0c;例如&#xff1a…

Python实现点选验证码识别, B站模拟登陆

话不多说&#xff0c;今天就分享一下如何用Python实现点选验证码识别&#xff0c;小破站模拟登陆 开发环境 Python 3.8Pycharm 2021.2谷歌浏览器谷歌驱动 模块使用 selenium >>> pip install selenium3.141.0 指定版本安装time打码平台 模块安装问题: -如果安装…

Java注解(Annotation)

一、什么是注解 个人理解&#xff0c;注解就是代码中的特殊标记&#xff0c;这些标记可以在编译、类加载、运行时被读取&#xff0c;从而做相对应的处理。 注解跟注释很像&#xff0c;区别是注释是给人看的&#xff1b;而注解是给程序看的&#xff0c;它可以被编译器读取。 …

ERP软件定价策略与模型设计

ERP软件定价(价格)的高低是ERP厂商整体竞争力强弱的一个重要指针&#xff0c;也是影响客户购买行为的重要因素。客户购买某一ERP软件&#xff0c;总是面临不同的ERP厂商﹑不同渠道的多种选择&#xff0c;ERP软件价格往往成了除软件功能﹑售后服务态度、实施水平等因素外&#x…

web前端-Ajax基础学习

web前端-Ajax基础学习1. Ajax基础描述1.1 URL地址的概念1.2 客户端和服务器的通信过程1.3 Ajax1.3.1 $.get()函数1.3.2 $.post()1.3.3 $.ajax()1.4 接口1.4.1 GET、POST方式请求的过程1.4.2 接口文档2. form表单与模版引擎2.1 表单的基本介绍2.2 form表单同步提交的缺点2.3 通过…

stm32 笔记 外部中断以及HAL库应用

外部中断 由外部设备发起的中断请求&#xff0c;会使得设备暂停当前的主程序&#xff0c;保存标志位并把当前指令压入堆栈&#xff0c;转而去执行中断的子程序。执行完毕后再弹出执行堆栈&#xff0c;恢复标志位&#xff0c;继续执行主程序。 STM32 的外部中断线 STM32的每个…

嵌入式 C语言/C++ 常见笔试、面试题 难疑点汇总(经典100道)

#pragma comment。将一个注释记录放置到对象文件或可执行文件中。 #pragma pack。用来改变编译器的字节对齐方式。 #pragma code_seg。它能够设置程序中的函数在obj文件中所在的代码段。如果未指定参数&#xff0c;函数将放置在默认代码段.text中 #pragma once。保证所在文件只…

Pytest接口测试框架实战项目搭建(三)

一、前言 前面相当于已经讲完整体框架搭建了&#xff0c;本篇主要讲述在实际业务系统的接口请求中&#xff0c;如何运用好该接口自动化测试框架。 二、步骤演示 1、在conf/api_path.py新增需要测试的接口&#xff0c;标黄底色为新加 存放测试接口仅这一个文件就行&#xff0c…

吉时利2604B系列数字源表,双通道,3A直流/10A脉冲

作为2600B系列源表SMU系列产品的一部分&#xff0c;2602B源表SMU是全新改良版双通道SMU&#xff0c;具有紧密集成的4象限设计&#xff0c;能同步源和测量电压/电流以提高研发到自动生产测试等应用的生产率。除保留了2602A的全部产品特点外&#xff0c;2602B还具有6位半分辨率、…

Android 面试题收集:Handler+Binder+Activity+时间分发机制+View绘制流程+……等

一、Handler相关知识 一个线程只有一个Looper&#xff0c;一个Messagequeue&#xff0c;可以创建多个handler。 1、Handler与Looper的关联是怎样的? 实例化 Handler 的时候 Handler 会去检查当前线程的 Looper 是否存在&#xff0c;如果不存在则会报异常&#xff0c;也就是…