【Android - 进阶】之RemoteViews简介
RemoteViews,顾名思义,就是远程的View,也就是可以运行在其他进程中的View。RemoteViews常用在通知和桌面小组件中。
一、RemoteViews应用到通知
首先来介绍一下系统自带的通知(Notification)的使用。Notification的使用有两种方法,分别是Notification直接创建的方式和使用Notification.Builder创建者模式创建的方式。
先来看一下使用Notification直接创建的方式的代码:
Notification notification = new Notification();
notification.icon = R.mipmap.ic_launcher; // 小图标
notification.largeIcon = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher_round); // 大图标
notification.defaults = Notification.DEFAULT_ALL; // 设置默认的提示音、振动方式、灯光等
notification.category = "Category";
notification.when = System.currentTimeMillis(); // 设置通知发送的时间戳
notification.tickerText = "Ticker Text"; // 设置通知首次弹出时,状态栏上显示的文本
notification.flags = Notification.FLAG_AUTO_CANCEL; // 点击通知后通知在通知栏上消失
notification.contentIntent = PendingIntent.getActivity(MainActivity.this, 0x001,
new Intent(MainActivity.this, TargetActivity.class), PendingIntent.FLAG_UPDATE_CURRENT); // 设置通知的点击事件
((NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE)).notify(1, notification); // 发送系统通知
通过上面的代码,就可以简单地发送一条通知到通知栏中。使用这种方式不需要有API版本的限制,但可以进行的操作比较少。
下面来看一下使用Notification.Builder创建者模式创建通知的代码:
PendingIntent pi = PendingIntent.getActivity(MainActivity.this, 0x001,
new Intent(MainActivity.this, TargetActivity.class), PendingIntent.FLAG_UPDATE_CURRENT);
Notification.Builder nb = new Notification.Builder(MainActivity.this)
.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher_round)) // 大图标
.setSmallIcon(R.mipmap.ic_launcher) // 小图标
.setContentText("Content Text") // 内容
.setSubText("Sub Text") // 在通知中,APP名称的副标题
.setContentTitle("Content Title") // 标题
.setTicker("Ticker") // 设置通知首次弹出时,状态栏上显示的文本
.setWhen(System.currentTimeMillis()) // 设置通知发送的时间戳
.setAutoCancel(true) // 点击通知后通知在通知栏上消失
.setDefaults(Notification.DEFAULT_ALL) // 设置默认的提示音、振动方式、灯光等
.setContentIntent(pi); // 设置通知的点击事件
((NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE)).notify(1, nb.build()); // build()方法需要的最低API为16
使用这种方式,需要注意对项目的API版本进行一定的控制,上面这段代码需要的API版本最低是16。
上面两种方式都是发送系统自带的通知。如果我们需要自定义通知的样式,就需要使用到 RemoteViews 了。RemoteViews给我们提供了一种可以在其他进程中生成View并进行更新的机制,但是它可以控制和操作的View有一定的限制,具体如下:
Layout:
FrameLayout、LinearLayout、RelativeLayout、GridLayout
View:
AnalogClock、Button、Chronometer、ImageButton、ImageView、ProgressBar、TextView、ViewFlipper、ListView、GridView、StackView、AdapterViewFlipper、ViewStub
使用RemoteViews发送一个自定义系统通知的代码如下:
PendingIntent pi = PendingIntent.getActivity(MainActivity.this, 0x001,
new Intent(MainActivity.this, TargetActivity.class), PendingIntent.FLAG_UPDATE_CURRENT);
RemoteViews remoteView = new RemoteViews(getPackageName(), R.layout.remoteview_main);
remoteView.setTextViewText(R.id.remoteview_main_title, "Title");
remoteView.setTextViewText(R.id.remoteview_main_content, "ContentContentContent");
remoteView.setImageViewResource(R.id.remoteview_main_icon, R.mipmap.ic_launcher_round);
remoteView.setOnClickPendingIntent(R.id.remoteview_main_view, pi);
Notification.Builder nb = new Notification.Builder(MainActivity.this)
.setSmallIcon(R.mipmap.ic_launcher) // 小图标
.setCustomContentView(remoteView) // 设置自定义的RemoteView,需要API最低为24
.setWhen(System.currentTimeMillis()) // 设置通知发送的时间戳
.setAutoCancel(true) // 点击通知后通知在通知栏上消失
.setDefaults(Notification.DEFAULT_ALL); // 设置默认的提示音、振动方式、灯光等
((NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE)).notify(1, nb.build()); // build()方法需要的最低API为16
可以看到,我们在自定义的通知布局中设置了TextView和ImageView,并在代码中动态地更新了其显示的内容。
二、RemoteViews应用到桌面小组件
RemoteViews也可以应用到桌面小组件中。这里我们通过一个例子来了解RemoteViews应用到桌面小组件的步骤,它总共分为五步,分别是:设置桌面小组件的布局、编写桌面小组件的配置文件、编写桌面小组件更新的Service、编写桌面小组件的控制类AppWidgetProvider、配置配置文件。
我们通过下面这个例子来介绍RemoteViews在桌面小组件中的应用。在这个例子中,我们向系统中添加一个小组件,在这个小组件中显示当前的日期和时间。
首先,设置桌面小组件的布局,具体代码如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"> <TextView
android:id="@+id/widget_main_tv_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@android:color/white"
android:textSize="22.0sp"
android:textStyle="bold" /> </LinearLayout>
然后,编写桌面小组件的配置文件,具体步骤是:在项目res文件夹下新建一个xml文件夹,在xml文件夹中创建一个XML文件,具体代码如下:
<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:initialLayout="@layout/widget_main"
android:minHeight="100.0dip"
android:minWidth="150.0dip"
android:updatePeriodMillis="8640000"> </appwidget-provider>
这个文件中的各个参数的解释如下:
initialLayout:桌面小组件的布局XML文件
minHeight:桌面小组件的最小显示高度
minWidth:桌面小组件的最小显示宽度
updatePeriodMillis:桌面小组件的更新周期。这个周期最短是30分钟
然后,编写一个Service,在这个Service中动态地获取到当前的时间并更新到桌面小组件中,代码如下:
import android.app.Service;
import android.appwidget.AppWidgetManager;
import android.content.ComponentName;
import android.content.Intent;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.widget.RemoteViews; import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask; /**
* 定时器Service
*/
public class TimerService extends Service {
private Timer timer;
private SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); @Override
public void onCreate() {
super.onCreate();
timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
updateViews();
}
}, 0, 1000);
} @Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
} private void updateViews() {
String time = formatter.format(new Date());
RemoteViews remoteView = new RemoteViews(getPackageName(), R.layout.widget_main);
remoteView.setTextViewText(R.id.widget_main_tv_time, time);
AppWidgetManager manager = AppWidgetManager.getInstance(getApplicationContext());
ComponentName componentName = new ComponentName(getApplicationContext(), WidgetProvider.class);
manager.updateAppWidget(componentName, remoteView);
} @Override
public void onDestroy() {
super.onDestroy();
timer = null;
}
}
然后,编写一个类继承自AppWidgetProvier,用来统一管理项目中的小组件,代码如下:
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.Context;
import android.content.Intent; /**
* AppWidgetProvider的子类,相当于一个广播
*/
public class WidgetProvider extends AppWidgetProvider {
/**
* 当小组件被添加到屏幕上时回调
*/
@Override
public void onEnabled(Context context) {
super.onEnabled(context);
context.startService(new Intent(context, TimerService.class));
} /**
* 当小组件被刷新时回调
*/
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
super.onUpdate(context, appWidgetManager, appWidgetIds);
}
/**
* 当widget小组件从屏幕移除时回调
*/
@Override
public void onDeleted(Context context, int[] appWidgetIds) {
super.onDeleted(context, appWidgetIds);
} /**
* 当最后一个小组件被从屏幕中移除时回调
*/
@Override
public void onDisabled(Context context) {
super.onDisabled(context);
context.stopService(new Intent(context, TimerService.class));
}
}
最后,在Manifest文件中配置刚刚编写的Service和BroadcastReceiver(AppWidgetProvider相当于一个广播),代码如下:
<service android:name=".TimerService" />
<receiver android:name=".WidgetProvider">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/widget" />
</receiver>
这里需要注意,<intent-filter>标签中的action的name和<meta-data>标签中的name的值是固定的,reousrce代表的是第二步中配置文件的位置。
编写完上述代码之后,运行结果如下图所示:

三、RemoteViews原理
我们的通知和桌面小组件分别是由NotificationManager和AppWidgetManager管理的,而NotificationManager和AppWidgetManager又通过Binder分别和SystemServer进程中的NotificationManagerServer和AppWidgetService进行通信,这就构成了跨进程通信的场景。
RemoteViews实现了Parcelable接口,因此它可以在进程间进行传输。
首先,RemoteViews通过Binder传递到SystemServer进程中,系统会根据RemoteViews提供的包名等信息,去项目包中找到RemoteViews显示的布局等资源,然后通过LayoutInflator去加载RemoteViews中的布局文件,接着,系统会对RemoteViews进行一系列的更新操作,这些操作都是通过RemoteViews对象的set方法进行的,这些更新操作并不是立即执行的,而是在RemoteViews被加载完成之后才执行的,具体流程是:我们调用了set方法后,通过NotificationManager和AppWidgetManager来提交更新任务,然后在SystemServer进程中进行具体的更新操作。
【Android - 进阶】之RemoteViews简介的更多相关文章
- 我的Android进阶之旅------>经典的大牛博客推荐(排名不分先后)!!
本文来自:http://blog.csdn.net/ouyang_peng/article/details/11358405 今天看到一篇文章,收藏了很多大牛的博客,在这里分享一下 谦虚的天下 柳志超 ...
- Android进阶之路(1)-详解MVC
最近因为换工作的原因没有写博客,现在慢慢稳定了,我准备写一些关于Android 进阶的文章,也是为了督促自己学习,大家一起进步! 今天详细的分析一下Android APP架构之一:MVC ### MV ...
- Android进阶之路(2)-详解MVP
### MVP简介 >MVP 全称:Model-View-Presenter :MVP 是从经典的模式MVC演变而来,它们的基本思想有相通的[地方](https://baike.baidu.co ...
- Android 进阶 Android 中的 IOC 框架 【ViewInject】 (下)
上一篇博客我们已经带大家简单的吹了一下IoC,实现了Activity中View的布局以及控件的注入,如果你不了解,请参考:Android 进阶 教你打造 Android 中的 IOC 框架 [View ...
- 【Android进阶系列教程】前言
起因 因为初学Android的时候还没有写博客的意识,现在Android的门是入了,正在进阶的道路上行走,但是就这一路也走了不少的弯路.我想,总得来说Android入门还是比较容易的,网络资源比较丰富 ...
- Android开发面试经——4.常见Android进阶笔试题(更新中...)
Android开发(29) 版权声明:本文为寻梦-finddreams原创文章,请关注:http://blog.csdn.net/finddreams 关注finddreams博客:http:/ ...
- 【转】Android 防破解技术简介
http://www.cnblogs.com/likeandroid/p/4888808.html Android 防破解技术简介 这几年随着互联网的不断发展,Android App 也越来越多!但是 ...
- [置顶] 我的Android进阶之旅------>介绍一款集录制与剪辑为一体的屏幕GIF 动画制作工具 GifCam
由于上一篇文章:我的Android进阶之旅------>Android之动画之Frame Animation实例 中展示的是Frame动画效果,但是之前我是将图片截取下来,不好说明确切的动画过程 ...
- 《Android进阶》之第七篇 NDK的使用
<Android进阶>之第一篇 在Java中调用C库函数 这一篇列举的方法是在NDK没有出来时候用的方式 在Android发布NDK之后,可以这样使用 一.首先下载android-ndk ...
- 我的Android进阶之旅------> Android在TextView中显示图片方法
面试题:请说出Android SDK支持哪些方式显示富文本信息(不同颜色.大小.并包括图像的文本信息).并简要说明实现方法. 答案:Android SDK支持例如以下显示富文本信息的方式. 1.使用T ...
随机推荐
- 小白学 Python(15):基础数据结构(集合)(下)
人生苦短,我选Python 前文传送门 小白学 Python(1):开篇 小白学 Python(2):基础数据类型(上) 小白学 Python(3):基础数据类型(下) 小白学 Python(4):变 ...
- Java基础系列二:Java泛型
该系列博文会告诉你如何从入门到进阶,一步步地学习Java基础知识,并上手进行实战,接着了解每个Java知识点背后的实现原理,更完整地了解整个Java技术体系,形成自己的知识框架. 一.泛型概述 1.定 ...
- 智学网电脑端查分小工具 已更新V2.2
特别鸣谢这段代码的源作者,我的大佬同学\(MetalkgLZH\).由于我没有做什么工作,这篇随笔基本不含相关技术细节. 再次强调,这个程序的主要部分由\(MetalkgLZH\)完成.技术细节与源码 ...
- Ubuntu13.10编译android源码中遇到的问题
1. jdk的版本不对 我开始安装的是最新的jdk7,但是编译时会出现jdk的版本
- 总结:一些使用private 构造方法的类
第一个,就是单例模式,虽然分为"懒汉模式"和"醉汉模式",但在jvm中有且只有这样的一个对象!这样才能称为单例(详细请参照设计模式) 第二个,工具类,建义工具类 ...
- 『题解』洛谷P1993 小K的农场
更好的阅读体验 Portal Portal1: Luogu Description 小\(K\)在\(\mathrm MC\)里面建立很多很多的农场,总共\(n\)个,以至于他自己都忘记了每个农场中种 ...
- python、C++经典算法题:打印100以内的素数
题目 打印100以内的素数 思路1 素数的特点: 素数一定是奇数 一个数如果是合数,那么它一定能够被2到这个合数的开平方内的某个素数整除(这个特点是提升效率的关键) 一个数如果不能被从2到它自身开平方 ...
- VMware下Centos7-Minimal上网配置
1.Centos7下载 http://isoredirect.centos.org/centos/7/isos/x86_64/CentOS-7-x86_64-Minimal-1810.iso 2.推荐 ...
- HTML中的表格标签
表格是网页制作中使用最多的工具之一,在制作网页时,使用表格可以更清晰地排列数据.但是在实际制作过程中,表格更多用在网页布局的定位上.很多网页都是以表格布局的.这是因为表格在文本和图像的位置控制方面 ...
- SpringBoot学习(三)—— springboot快速整合swagger文档
目录 MyBatis 简介 引入mybatis组件 代码实战 MyBatis @ 简介 优点 最大的优点是SQL语句灵活,适合调优情景,业务复杂情景 劣势 最大的劣势是不同数据库之间的迁移 引入myb ...