Android之RemoteViews篇上————通知栏和桌面小控件

一.目录

文章目录

  • Android之RemoteViews篇上————通知栏和桌面小控件
    • 一.目录
    • 二.RemoteViews的概述
    • 三.RemoteViews在通知栏上的应用
      • 1.通知栏的基本用法
      • 2.添加点击事件
      • 3.通知栏更多的设置
    • 四.RemoteViews在桌面小控件的应用
      • 1.定义小部件界面
      • 2.定义小部件配置信息
      • 3.定义小部件的实现类
      • 4.AndroidManifest.xml中声明小部件
    • 五. PendingIntent
    • 六.参考资料

二.RemoteViews的概述

RemoteView从名字看即为远程的View,RemoteViews表示一个View结构,它可以在其他进程中显示,为了能够更新它的界面,RemoteViews提供了一组基础的操作用于跨进程更新它的界面。

RemoteViews在Android的使用场景有两种:通知栏和桌面小控件。通知栏是通过NotificationManager的notify方法实现,它除了默认效果,还可以自定义布局。桌面小部件则是通过AppWidgetProvider来实现,AppWidget本质是一个广播。这两个都无法像在Activity中那样直接更新小部件。因为两者都是运行在系统的SystemServer进程。

三.RemoteViews在通知栏上的应用

1.通知栏的基本用法

创建一个Notification对象,并进行设置

Notification notification = new NotificationCompat.Builder(content) //创建.setContentTitle("冰炭不投day") //设置标题.setContentText("啦啦啦啦啦") //设置正文.setWhen(System.currentTimeMillis()) //指定被创建时间.setSmallIcon(R.drawable.ic_launcher_foreground) //设置通知的小图标.setLargeIcon(BitmapFactory.decodeResource(getResources(),R.drawable.icon)) //设置大图标.build();
NotificationManager manager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
manager.notify(1,notification); //启动该通知

左上角为设置的小图标

大图标 标题 正文如下:

2.添加点击事件

  Intent intent = new Intent(this,NotificationActiviy.class);PendingIntent pi = PendingIntent.getActivity(this,0,intent,0);Notification notification = new NotificationCompat.Builder(this) //创建.setContentTitle("冰炭不投day") //设置标题.setContentText("啦啦啦啦啦") //设置正文.setWhen(System.currentTimeMillis()) //指定被创建时间.setSmallIcon(R.drawable.ic_launcher_foreground) //设置通知的小图标.setLargeIcon(BitmapFactory.decodeResource(getResources(),R.drawable.icon)) //设置大图标.setContentIntent(pi).setAutoCancel(true) //点击图标后,通知消失.build();NotificationManager manager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);manager.notify(1,notification);

3.通知栏更多的设置

.setSound(Uri.fromFile(new File("/system/media/audio/ringtones/luna.agg"))) //通知时播放音频
.setVibrate(new long[]{0,1000,1000,1000})//通知使手机震动 数组中的参赛分别表示静止和震动的时长  需要添加权限
.setLights(Color.GREEN,1000,1000) //通知使led灯亮 三个参数分别表示led等的颜色,led等亮起来的时长 led灯灭起来的时常
.setDefaults(NotificationCompat.DEFAULT_ALL ) //使用系统默认效果
.setStyle(new NotificationCompat.BigTextStyle().bigText(",,,,,,,,,")) //设置大段文字
.setStyle(new NotificationCompat.BigPictureStyle().bigPicture(BitmapFactory.decodeResource(getResources(),R.drawable.big_image))) //设置大图片

四.RemoteViews在桌面小控件的应用

1.定义小部件界面

在res/layout下新建一个XML文件,命名为widget
内容如下:

<?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"><ImageViewandroid:id="@+id/image"android:layout_width="wrap_content"android:layout_height="wrap_content"android:src="@drawable/icon" />
</LinearLayout>

桌面小部件的布局不同于普通的布局,它是基于RemoteViews它不支持所有类型的布局或视图窗口小部件。

RemoteViews对象(以及App Widget)可以支持以下布局类:

FrameLayout
LinearLayout
RelativeLayout
GridLayout
__
AnalogClock
Button
Chronometer
ImageButton
ImageView
ProgressBar
TextView
ViewFlipper
ListView
GridView
StackView
AdapterViewFlipper

2.定义小部件配置信息

在res/xml下新建appwidget_provider_info.xml(名称随意),添加如下内容

<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"android:initialLayout="@layout/widget"android:minHeight="84dp"android:minWidth="84dp"android:updatePeriodMillis="86400000">
</appwidget-provider>

以下是appwidget-provider属性摘要:

  • minWidth和minHeight 属性的值指定App Widget 默认使用的最小空间量 。默认主屏幕根据具有已定义高度和宽度的单元格网格在其窗口中定位App Widgets。如果App Widget的最小宽度或高度的值与单元格的尺寸不匹配,则App Widget尺寸将向上舍 入到最接近的单元格大小。
  • 将minResizeWidth和minResizeHeight属性指定应用Widget的绝对最小尺寸。这些值应指定App Widget难以辨认或无法使用的大小。使用这些属性允许用户将窗口小部件的大小调整为可能小于minWidth和minHeight属性定义的默认窗口小部件大小的大小 。在Android 3.1中引入。
  • updatePeriodMillis属性定义了App Widget框架应该AppWidgetProvider通过调用 onUpdate() 回调方法来请求更新的频率。实际更新不能保证与此值准确地按时发生,我们建议尽可能不经常更新 - 可能每小时不超过一次以节省电池。您可能还允许用户调整配置中的频率 - 有些人可能希望股票代码每15分钟更新一次,或者一天只能更新四次。
  • initialLayout属性指向定义App Widget布局的布局资源。
  • configure属性定义在Activity用户添加App Widget时启动,以便他或她配置App Widget属性。这是可选的
  • previewImage属性指定应用小部件配置后的外观预览,用户在选择应用小部件时会看到该小部件。如果未提供,则用户会看到应用程序的启动器图标。该字段对应 于文件中元素的 android:previewImage属性。有关使用的更多讨论,请参阅设置预览图像。在Android 3.0中推出。AndroidManifest.xmlpreviewImage
  • autoAdvanceViewId属性指定应由窗口小部件主机自动提升的应用窗口小部件子视图的视图ID。在Android 3.0中推出
  • resizeMode属性指定可以调整窗口小部件的规则。您可以使用此属性使主屏幕小部件可以水平,垂直或在两个轴上进行调整。用户触摸按住窗口小部件以显示其调整大小手柄,然后拖动水平和/或垂直手柄以更改布局网格上的大小。resizeMode属性的值 包括“horizo​​ntal”,“vertical”和“none”。要将窗口小部件声明为水平和垂直可调整大小,请提供值“horizo​​ntal | vertical”。在Android 3.1中引入。

更多属性可查看官方文档,链接下文章最后。

3.定义小部件的实现类

public class MyWidgetProvider extends AppWidgetProvider {public static final String CLICK_ACTION = "com.heshucheng.remoteviews.click_action";private static final String TAG = "MyWidgetProvider";public MyWidgetProvider() {super();}@Overridepublic void onReceive(final Context context, Intent intent) {super.onReceive(context, intent);Log.d(TAG, "onReceive: " + intent.getAction());//这里判断是自己的action,做自己的事情,比如小部件被点击了要干什么if (intent.getAction().equals(CLICK_ACTION)) {Toast.makeText(context, "click it", Toast.LENGTH_SHORT).show();new Thread(new Runnable() {@Overridepublic void run() {Bitmap srcbBitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.icon);AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);for (int i = 0; i < 37; i++){float degree = (i*10)%360;RemoteViews remoteViews = new RemoteViews(context.getPackageName(),R.layout.widget);remoteViews.setImageViewBitmap(R.id.image, rotateBitmap(context,srcbBitmap,degree));Intent intentClick = new Intent();intentClick.setAction(CLICK_ACTION);PendingIntent pendingIntent = PendingIntent.getBroadcast(context,0,intentClick,0);remoteViews.setOnClickPendingIntent(R.id.image,pendingIntent);appWidgetManager.updateAppWidget(new ComponentName(context,MyWidgetProvider.class),remoteViews);SystemClock.sleep(30);}}}).start();}}//每次更新都会调用@Overridepublic void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {super.onUpdate(context, appWidgetManager, appWidgetIds);Log.i(TAG, "onUpdate");RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget);Intent intentClick = new Intent(CLICK_ACTION);PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intentClick, 0);remoteViews.setOnClickPendingIntent(R.id.image, pendingIntent);appWidgetManager.updateAppWidget(new ComponentName(context, MyWidgetProvider.class), remoteViews);}//动画 旋转一周private Bitmap rotateBitmap(Context context,Bitmap srcbitmap,float degree ) {Matrix matrix = new Matrix();matrix.reset();matrix.setRotate(degree);Bitmap temBitmap = Bitmap.createBitmap(srcbitmap,0,0,srcbitmap.getWidth(),srcbitmap.getHeight(),matrix,true);return temBitmap;}
}

AppWidgetProvider类广播接收器作为一个方便的类来处理应用的Widget广播延伸。AppWidgetProvider仅接收与App Widget相关的事件广播,例如更新,删除,启用和禁用App Widget时。当这些广播事件发生时,AppWidgetProvider会收到以下方法调用:

  • onUpdate() 这被调用以按updatePeriodMillis AppWidgetProviderInfo中的属性定义的间隔更新App Widget (请参阅上面的添加AppWidgetProviderInfo数据)。当用户添加App Widget时也会调用此方法,因此它应该执行基本设置,例如为视图定义事件处理程序并Service在必要时启动临时操作 。但是,如果已声明配置Activity,则在用户添加App Widget时不会调用此方法,但会为后续更新调用此方法。配置Activity负责在配置完成时执行第一次更新。(请参阅下面的“ 创建应用程序小组件配置活动”。)
  • onAppWidgetOptionsChanged():首次放置窗口小部件时以及窗口小部件调整大小时调用此方法。你可以使用此回调根据窗口小部件的大小范围显示或隐藏内容。
  • onDeleted(Context, int[]):每次从App Widget主机删除App Widget时都会调用此方法。
  • onEnabled(Context):当第一次创建App Widget的实例时调用此方法。
  • onDisabled(Context):当从App Widget主机删除App Widget的最后一个实例时调用此方法。这是您应该清理完成的任何工作的地方 onEnabled(Context),例如删除临时数据库。
  • onReceive(Context,Intent):在每个广播和每个上述回调方法之前调用此方法。您通常不需要实现此方法,因为默认的AppWidgetProvider实现过滤所有App Widget广播并根据需要调用上述方法。

4.AndroidManifest.xml中声明小部件

  <intent-filter><action android:name="com.heshucheng.remoteviews.click_action" /><action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>

上面代码中的两个Action,第一个是用来识别小部件的单击行为,第二个是作为小部件的标识而必须存在的。

五. PendingIntent

PendingIntent表示一种处于Pending状态的Intent,pending表示的是即将发生的意思,它是在将来的某个不确定的时刻放生,而Intent是立刻发生。

PendingIntent支持三种待定意图:启动Activity(getActivity),启动Service(getService),发送广播(getBroadcast)。

如图中所示,这三个方法的参数都是一样的,主要理解的是第二个参数requstCode和第四个参数flags,code代表的是发送码,多数情况下为0,而且code会影响到flag,flag常见的有几种我们下面会说,其实最主要是理解匹配规则。

PendingIntent的匹配规则为:如果两个PendingIntent他们内部的Intent相同并且requstCode也相同的话,那么PendingIntent就是相同的,code比较好理解,那什么情况下Intent相同呢,Intent的匹配规则是:如果两个Intent的ComponentName的匹配过程,只要Intent之间的ComponentName和intent-filter相同,那么这两个intent就相同,需要注意的是Extras不参与匹配过程,只要intent之间的name和intent-filter相同就行,我们再来说下flags的参数含义

  • FLAG_ONE_SHOT
    当前描述的PendingIntent只能被使用一次,然后他就会被cancel,如果后续还有相同的PendingIntent,那么他的send方法就会失败,对于通知栏的消息来说,如果采用此标记位,那么同类的通知只能使用一次,后续将无法打开

  • FLAG_NO_CREATE
    当前描述的PendingIntent不会主动去创建,如果当前PendingIntent之前不存在,那么getActivity等方法都会直接返回null,即获取PendingIntent失败,这个标记位很少见,他无法单独使用,因此在日常开发当中,并没有太多的意义,这里就不过多的介绍了

  • FLAG_CANCEL_CURRENT
    当前描述的PendingIntent如果已经存在,那么就会被cancel,然后系统创建一个新的PendingIntent,对于通知栏来说,那些被cancel的消息将无法被打开

  • FLAG_UPDATE_CURRENT
    当前描述的PendingIntent如果已经存在的话,那么他们就会被更新,他们的intent中的extras会被替换成新的

从上面的分析看还是不太好理解这四个标记位,下面结合实际的项目来,这里分析两种情况,如下代码,如果notify的第一个参数id是常量,那么多次通知就只能弹出一个通知,后续会把前面的替换掉,如果每次不一样,就会多弹出几个通知

如果notify方法的id是常量,那么不管PendingIntent是否匹配,后面的通知会替换前面的通知,这个很好理解

如果notify方法的id每次不同,那么当PendingIntent不匹配时,这里的匹配是指PendingIntent中Intent相同切requstCode相同,在这种情况下不管采用了何种标记位,这些通知之间不互相干扰。如果PendingIntent处于匹配状态,这个时候要分情况讨论,如果采用FLAG_ONE_SHOT标记位,那么后续通知中,PendingIntent会和第一条通知保持一致,包括其中的Extras,单击任何一条通知,剩余的都无法打开当所有的通知被清除后,会重复这个过程,如果采用FLAG_CANCEL_CURRENT标记位,那么只有最新的通知可以打开,之前弹出的所有通知均无法打开,如果采用FLAG_UPDATE_CURRENT标记位。那么之前弹出的通知PendingIntent会被更新,最终他们和最新的一条通知保持一致,包括其中的Extras,那么这些通知都可以被打开

六.参考资料

《第一行代码》
《android艺术开发探索》
官方文档

Android之RemoteViews篇上————通知栏和桌面小控件相关推荐

  1. 开发数字时钟桌面小控件

    随时随地技术实战干货,获取项目源码.学习资料,请关注源代码社区公众号(ydmsq666) 所谓桌面小控件,就是指能直接显示在Android系统桌面的小程序,比如模拟时钟等.桌面小控件是通过Broadc ...

  2. Android开发 入门篇(二) - 常用UI控件

    文章目录 控件 Button TextView EditText ImageView ProgressBar AlertDialog ProgressDialog 布局 LenearLayout an ...

  3. android 列表上拉加载更多,Android 下拉刷新,上拉加载更多控件–支持ListView,GridView和ScrollView...

    麦洛遇到这样一个需求,实现类似于IOS下拉刷新,上拉加载更多的控件.麦洛google,baidu了一番,网上有不少实现,比较常见的是国外牛人的实现,不过国外的实现基本上都是扩展于ListView,所以 ...

  4. linux桌面显示温度,请问ubuntu下有没有什么桌面小控件现实显卡温度cpu使用率之类的...

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 检测电脑中的传感器芯片: sudo sensors-detect 一路回车.执行完后会列出几个模块,将它们添加进启动模块里(我这里是下面2个). sudo ...

  5. android桌面时钟小控件开发记录

    所谓桌面小控件,就是能之间显示在Android系统桌面的小程序. 桌面小控件的实现是基于Broadcast的形式实现的,因此,每一个桌面小控件都对应于一个BroadcastReceiver类.Andr ...

  6. 如何在Android实现桌面清理内存简单Widget小控件

    如何在Android实现桌面清理内存简单Widget小控件 我们经常会看到类似于360.金山手机卫士一类的软件会带一个widget小控件,显示在桌面上,上面会显示现有内存大小,然后会带一个按键功能来一 ...

  7. (转)深入理解最强桌面地图控件GMAP.NET --- 原理篇

    前几篇介绍了一些国内地图的案例, 深入理解最强桌面地图控件GMAP.NET --- SOSO地图 深入理解最强桌面地图控件GMAP.NET --- 百度地图 我们以Google地图为例,这章介绍下地图 ...

  8. 深入理解最强桌面地图控件GMAP.NET --- 原理篇

    转 http://www.cnblogs.com/enjoyeclipse/archive/2013/01/18/2865700.html 前几篇介绍了一些国内地图的案例, 深入理解最强桌面地图控件G ...

  9. CropImageView android上的一个图片裁剪控件

    CropImageView **文前:**本文非常容易让读者看的云里雾里,建议直接看效果图,觉得有用就去看源码吧. CropImageView的原型来自Cropimage_demo,是android上 ...

最新文章

  1. C语言编程的几个小注意事项1
  2. 移动端网页打印代码_WEB移动端怎么是实现Console.log打印
  3. 大数据简介,技术体系分类整理
  4. java调C接口_java通过jni调用C程序接口
  5. 浅谈TCP优化(转)
  6. 字符串拼接的双引号和单引号问题,转义字符
  7. 10010序列检测器的三段式状态机实现(verilog)
  8. 试验设计——均匀试验设计·好格子点法
  9. H3C-H3CNE 华三网络工程师从入门到精通 自学视频课程[肖哥]-肖宗鹏-专题视频课程...
  10. office文档管理服务器编辑,office在线编辑方案
  11. 香港流行乐黄金二十年——经典歌手(音乐人)全面回顾(四)
  12. Android ImageView属性
  13. 微信小程序音频功能开发实(cai)践(keng)
  14. 【数据分析与挖掘】基于Apriori算法的中医证型的关联规则挖掘(有数据集和代码)
  15. 解决TeamViewer软件提示试用期已到期无法进行远程操作
  16. 机器学习实践系列之3 - 人脸对齐(上)
  17. js监听移动端返回键,从内页返回首页
  18. 论文阅读笔记:(2022.05) Observability-Aware Intrinsic and Extrinsic Calibration of LiDAR-IMU Systems
  19. ElementUI v2.15.0 使用手册
  20. 【NI Multisim 14.0原理图设计基础——查找元器件】

热门文章

  1. 使用O2OA二次开发搭建企业办公平台(十八)流程打印表单设置
  2. 又躺赚1亿?东方联盟创始人郭盛华,会的仅仅是技术吗?
  3. 帆软相同列合并_合并报表软件有哪些深受欢迎
  4. netlogo和java,Netlogo:Shapefile与Raster
  5. PS学习笔记8-画笔工具
  6. win7打印机共享出现错误0x000006d9如何解决
  7. Promethus(普罗米修斯)
  8. 普罗米修斯 软件_Prometheus(普罗米修斯)——适合k8s和docker的监控系统
  9. IF10 家系研究 | OGDHL变异导致神经发育谱系疾病,表现为癫痫、听力与视力障碍等...
  10. 同济大学提前面试MBA/MEM/MPA/MTA历年真题免费领取