0%
这是一片思考的空间 -- arthinking
Spring 重构&代码整洁之道 软件设计 JVM 并发编程 数据结构与算法 分布式 存储 网络 微服务 设计模式
Java技术栈 - 涉及Java技术体系

Android的桌面组件App Widget的使用方法 AppWidgetProvider RemoteViews

What is App Widget?

在手机桌面上放置的控件,即Android的桌面组件

AppWidgetProviderInfo

public class AppWidgetProviderInfo extends Object implements Parcelable

Describes the meta data for an installed AppWidget provider. The fields in this class correspond to the fields in the xml tag. AppWidgetProvider

public class AppWidgetProvider extends BroadcastReceiver

A convenience class to aid in implementing an AppWidget provider. Everything you can do with AppWidgetProvider, you can do with a regularBroadcastReceiver. AppWidgetProvider merely parses the relevant fields out of the Intent that is received in onReceive(Context,Intent), and calls hook methods with the received extras.

创建一个简单的App Widget的基本步骤:

① 在res文件夹下创建一个xml文件夹,里面创建一个xml文件(这里创建了一个test_appwidget_info.xml文件)用于提供元数据:

<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:minWidth="200dp"
android:minHeight="80dp"
android:updatePeriodMillis="10000"
android:initialLayout="@layout/test_appwidget"

其中的test_appwidget为App Widget的布局文件,在第二步创建。 ② 创建App Widget的布局文件test_appwidget.xml:



③ 创建一个类继承AppWidgetProvider并覆盖里面的几个常用的方法:

onDeleted(Context context, int[] appWidgetIds) 删除App Widget是调用此方法 onDisabled(Context context) 最后一个App Widget实例删除后调用此方法 onEnabled(Context context) App WIdget实例第一次被创建是调用此方法 onReceive(Context context, Intent intent) 接收广播事件 onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) 到达指定更新时间或用户向桌面添加了App Widget时调用此方法

import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.Context;

public class TestAppWidgetProvider extends AppWidgetProvider{

@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
		int[] appWidgetIds) {
	System.out.println("onUpdate");
	super.onUpdate(context, appWidgetManager, appWidgetIds);
}
@Override
public void onDeleted(Context context, int[] appWidgetIds) {
	System.out.println("onDeleted");
	super.onDeleted(context, appWidgetIds);
}
@Override
public void onDisabled(Context context) {
	System.out.println("onDisabled");
	super.onDisabled(context);
}
@Override
public void onEnabled(Context context) {
	System.out.println("onEnabled");
	super.onEnabled(context);
}

}

④ 在AndroidManifest.xml文件中声明一个receiver,注意intent和meta-data子标签的设置:

PendingIntent

public final class PendingIntent extends Object implements Parcelable

A description of an Intent and target action to perform with it. Instances of this class are created with getActivity(Context, int, Intent, int),getBroadcast(Context, int, Intent, int), getService(Context, int, Intent, int); the returned object can be handed to other applications so that they can perform the action you described on your behalf at a later time. RemoteViews

public class RemoteViews extends Object implements Parcelable LayoutInflater.Filter

A class that describes a view hierarchy that can be displayed in another process. The hierarchy is inflated from a layout resource file, and this class provides some basic operations for modifying the content of the inflated hierarchy.

使用PendingIntent和RemoteViews对App Widget绑定监听器:

创建PendingIntent的基本方法:

getActivity(Context context, int requestCode, Intent intent, int flags) getBroadcast(Context context, int requestCode, Intent intent, int flags) getService(Context context, int requestCode, Intent intent, int flags)

在创建一个简单的App Widget的基本步骤基础之上进行一下操作: ① 在test_appwidget.xml文件中添加一个按钮

② 通过RemoteViews在TestAppWidgetProvider的onUpdate()方法中为Botton绑定监听器

@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
for (int i = 0; i < appWidgetIds.length; i++) {
//这里TargetActivity为Intent跳转到的Activity,这个Activity类需要另外编写,在第三步创建
Intent intent = new Intent(context,TargetActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);
RemoteViews remoteViews = new RemoteViews(context.getPackageName(),R.layout.test_appwidget);
//PendingIntent为事件触发是所要执行的PendingIntent
remoteViews.setOnClickPendingIntent(R.id.widgetButtonId, pendingIntent);
appWidgetManager.updateAppWidget(appWidgetIds[i], remoteViews);
}
super.onUpdate(context, appWidgetManager, appWidgetIds);
}

③ 创建一个TargetActivity用作Botton的跳转到的Activity

接收来自AppWidget中的广播消息:

在创建一个简单的App Widget的基本步骤基础之上进行一下操作: 1、 在AndroidManifest.xml文件中为TestAppWidgetProvider注册新的intent

2、 在TestAppWidgetProvider中定义一个常量:

private static final String UPDATE_ACTION = "com.test.UPDATE_APP_WIDGET";

3、 在TestAppWidgetProvider的onUpdate()方法中使用getBroadcast()方法创建一个PendingIntent;并为AppWidget当中的控件注册监听器

@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
Intent intent = new Intent();
intent.setAction(UPDATE_ACTION);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0,
intent, 0);
RemoteViews remoteViews = new RemoteViews(context.getPackageName(),
R.layout.test_appwidget);
remoteViews.setOnClickPendingIntent(R.id.widgetButtonId, pendingIntent);
appWidgetManager.updateAppWidget(appWidgetIds, remoteViews);
}

4、 在onReceive()方法中接收所需要的广播:

public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent);
String action = intent.getAction();
if (UPDATE_ACTION.equals(action)) {
System.out.println(UPDATE_ACTION);
}
}

如果需要改变App Widget中控件的状,可以在TestAppWidgetProvider的onReceive()方法中通过RemoteViews对象去改变:

@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (UPDATE_ACTION.equals(action)) {
RemoteViews remoteViews = new RemoteViews(context.getPackageName(),
R.layout.test_appwidget);
remoteViews.setTextViewText(R.id.widgetTextId, "change");
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
//区分:RemoteViews代表App Widget中的所有空间,而ComponentName代表整个App Widget对象
ComponentName componentName = new ComponentName(context,ExampleAppWidgetProvider.class);
appWidgetManager.updateAppWidget(componentName, remoteViews);
} else {
super.onReceive(context, intent);
}
}

(特别说明:本文部分内容是在观看marschen的Android视频教程时做的笔记,感谢marschen推出的视频教程,这里也推荐给大家:http://www.marschen.com/portal.php)

欢迎关注我的其它发布渠道

订阅IT宅
内功修炼
Java技术栈
Java架构杂谈是IT宅精品文章公众号,欢迎订阅:
📄 网络基础知识:两万字长文50+张趣图带你领悟网络编程的内功心法 📄 HTTP发展史:三万长文50+趣图带你领悟web编程的内功心法 📄 HTTP/1.1:可扩展,可靠性,请求应答,无状态,明文传输 📄 HTTP/1.1报文详解:Method,URI,URL,消息头,消息体,状态行 📄 HTTP常用请求头大揭秘 📄 HTTPS:网络安全攻坚战 📄 HTTP/2:网络安全传输的快车道 📄 HTTP/3:让传输效率再一次起飞 📄 高性能网络编程:图解Socket核心内幕以及五大IO模型 📄 高性能网络编程:三分钟短文快速了解信号驱动式IO 📄 高性能网络编程:彻底弄懂IO复用 - IO处理杀手锏,带您深入了解select,poll,epoll 📄 高性能网络编程:异步IO:新时代的IO处理利器 📄 高性能网络编程:网络编程范式 - 高性能服务器就这么回事 📄 高性能网络编程:性能追击 - 万字长文30+图揭秘8大主流服务器程序线程模型
📄 Java内存模型:如果有人给你撕逼Java内存模型,就把这些问题甩给他 📄 一文带你彻底理解同步和锁的本质(干货) 📄 AQS与并发包中锁的通用实现 📄 ReentrantLock介绍与使用 📄 ReentrantReadWriteLock介绍与使用 📄 ReentrantLock的Condition原理解析 📄 如何优雅的中断线程 📄 如何优雅的挂起线程 📄 图解几个好玩的并发辅助工具类 📄 图解BlockingQueue阻塞队列
📄 消息队列那么多,为什么建议深入了解下RabbitMQ? 📄 高并发异步解耦利器:RocketMQ究竟强在哪里? 📄 Kafka必知必会18问:30+图带您看透Kafka
📄 洞悉MySQL底层架构:游走在缓冲与磁盘之间 📄 SQL运行内幕:从执行原理看调优的本质 📄 洞悉Redis技术内幕:缓存,数据结构,并发,集群与算法