对于通知栏的使用,Android各个版本其实都有比较大的调整。例如老版本的不兼容,大小图标问题以及自定义通知栏适配问题,这些都是比较头大的事,当然弄懂了就清楚了,本篇就处理下这些疑惑。

通知栏的使用

显示一个普通的通知栏

public static void showNotification(Context context) {Notification notification = new NotificationCompat.Builder(context)/**设置通知左边的大图标**/.setLargeIcon(BitmapFactory.decodeResource(context.getResources(), R.mipmap.ic_launcher))/**设置通知右边的小图标**/.setSmallIcon(R.mipmap.ic_launcher)/**通知首次出现在通知栏,带上升动画效果的**/.setTicker("通知来了")/**设置通知的标题**/.setContentTitle("这是一个通知的标题")/**设置通知的内容**/.setContentText("这是一个通知的内容这是一个通知的内容")/**通知产生的时间,会在通知信息里显示**/.setWhen(System.currentTimeMillis())/**设置该通知优先级**/.setPriority(Notification.PRIORITY_DEFAULT)/**设置这个标志当用户单击面板就可以让通知将自动取消**/.setAutoCancel(true)/**设置他为一个正在进行的通知。他们通常是用来表示一个后台任务,用户积极参与(如播放音乐)或以某种方式正在等待,因此占用设备(如一个文件下载,同步操作,主动网络连接)**/.setOngoing(false)/**向通知添加声音、闪灯和振动效果的最简单、最一致的方式是使用当前的用户默认设置,使用defaults属性,可以组合:**/.setDefaults(Notification.DEFAULT_VIBRATE | Notification.DEFAULT_SOUND).setContentIntent(PendingIntent.getActivity(context, 1, new Intent(context, MainActivity.class), PendingIntent.FLAG_CANCEL_CURRENT)).build();NotificationManager notificationManager = (NotificationManager) context.getSystemService(context.NOTIFICATION_SERVICE);/**发起通知**/notificationManager.notify(0, notification);
}

显示一个下载带进度条的通知

public static void showNotificationProgress(Context context) {//进度条通知final NotificationCompat.Builder builderProgress = new NotificationCompat.Builder(context);builderProgress.setContentTitle("下载中");builderProgress.setSmallIcon(R.mipmap.ic_launcher);builderProgress.setTicker("进度条通知");builderProgress.setProgress(100, 0, false);final Notification notification = builderProgress.build();final NotificationManager notificationManager = (NotificationManager) context.getSystemService(context.NOTIFICATION_SERVICE);//发送一个通知notificationManager.notify(2, notification);/**创建一个计时器,模拟下载进度**/Timer timer = new Timer();timer.schedule(new TimerTask() {int progress = 0;@Overridepublic void run() {Log.i("progress", progress + "");while (progress <= 100) {progress++;try {Thread.sleep(100);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}//更新进度条builderProgress.setProgress(100, progress, false);//再次通知notificationManager.notify(2, builderProgress.build());}//计时器退出this.cancel();//进度条退出notificationManager.cancel(2);return;//结束方法}}, 0);
}

显示一个悬挂式的通知

悬挂式,部分系统厂商可能不支持。

public static void showFullScreen(Context context) {NotificationCompat.Builder builder = new NotificationCompat.Builder(context);Intent mIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://blog.csdn.net/linglongxin24"));PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, mIntent, 0);builder.setContentIntent(pendingIntent);builder.setSmallIcon(R.mipmap.ic_launcher);builder.setLargeIcon(BitmapFactory.decodeResource(context.getResources(), R.mipmap.ic_launcher));builder.setAutoCancel(true);builder.setContentTitle("悬挂式通知");//设置点击跳转Intent hangIntent = new Intent();hangIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);hangIntent.setClass(context, MainActivity.class);//如果描述的PendingIntent已经存在,则在产生新的Intent之前会先取消掉当前的PendingIntent hangPendingIntent = PendingIntent.getActivity(context, 0, hangIntent, PendingIntent.FLAG_CANCEL_CURRENT);builder.setFullScreenIntent(hangPendingIntent, true);NotificationManager notificationManager = (NotificationManager) context.getSystemService(context.NOTIFICATION_SERVICE);notificationManager.notify(3, builder.build());
}

显示一个折叠式的通知

public static void shwoNotify(Context context) {//先设定RemoteViewsRemoteViews view_custom = new RemoteViews(context.getPackageName(), R.layout.view_custom);//设置对应IMAGEVIEW的ID的资源图片view_custom.setImageViewResource(R.id.custom_icon, R.mipmap.icon);view_custom.setTextViewText(R.id.tv_custom_title, "今日头条");view_custom.setTextColor(R.id.tv_custom_title, Color.BLACK);view_custom.setTextViewText(R.id.tv_custom_content, "金州勇士官方宣布球队已经解雇了主帅马克-杰克逊,随后宣布了最后的结果。");view_custom.setTextColor(R.id.tv_custom_content, Color.BLACK);NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(context);mBuilder.setContent(view_custom).setContentIntent(PendingIntent.getActivity(context, 4, new Intent(context, MainActivity.class), PendingIntent.FLAG_CANCEL_CURRENT)).setWhen(System.currentTimeMillis())// 通知产生的时间,会在通知信息里显示.setTicker("有新资讯").setPriority(Notification.PRIORITY_HIGH)// 设置该通知优先级.setOngoing(false)//不是正在进行的   true为正在进行  效果和.flag一样.setSmallIcon(R.mipmap.icon);Notification notify = mBuilder.build();NotificationManager notificationManager = (NotificationManager) context.getSystemService(context.NOTIFICATION_SERVICE);notificationManager.notify(4, notify);
}

低版本不兼容处理

Android在appcompat-v7库中提供了一个NotificationCompat类来处理新老版本的兼容问题,我们在编写通知功能时都使用NotificationCompat这个类来实现,appcompat-v7库就会自动帮我们做好所有系统版本的兼容性处理了。一段基本的触发通知代码如下所示:

NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
Notification notification = builder
.setContentTitle("这是通知标题")
.setContentText("这是通知内容")
.setWhen(System.currentTimeMillis())
.setSmallIcon(R.mipmap.ic_launcher)
.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher))
.build();
manager.notify(1, notification);

现在我们的app直接面对的设备一般都在android 5.0以上,所以也不需要做这种处理了。

大小图标问题

注意看一下我们给通知设置的图标,一个小图标、一个大图标,都是使用的R.mipmap.ic_launcher这张图,这在较低的编译版本上是没问题的,如果将targetSdkVersion指定成21或者更高的话,那么小图标则不可见(通知栏和大图的右下角有一个白白的圆),导致界面很不友好。

这到底是为什么呢?实际上,Android从5.0系统开始,对于通知栏图标的设计进行了修改。现在Google要求,所有应用程序的通知栏图标,应该只使用alpha图层来进行绘制,而不应该包括RGB图层(通俗点来讲,就是让我们的通知栏图标不要带颜色就可以了)。下边是支付宝和网易新闻的展示:


上图你会发现网易的图标更好看一些,因为系统给右下角的这个小圆圈默认是设置成灰色的,和我们的整体色调并不搭配,而网易则将这个小圆圈改成了红色,因此总体视觉效果更好。这种也很好处理,只需要在NotificationCompat.Builder中再多连缀一个setColor()方法就可以了:

Notification notification = builder.......setColor(Color.parseColor("#EAA935")).build();

自定义通知栏

自定义通知需要定义一个layout文件,使用RemoteViews加载它并设置一些点击事件,再设置到builder,如下:

public void showNotification(){NotificationCompat.Builder builder = new NotificationCompat.Builder(this);builder.setSmallIcon(R.mipmap.small_launch_ic);//自定义布局RemoteViews rv = new RemoteViews(getPackageName(),R.layout.message);rv.setTextViewText(R.id.tv,"有新通知了");builder.setContent(rv);//点击跳转Intent intent = new Intent(this, MainAct.class);PendingIntent pendingIntent = PendingIntent.getActivity(this, 1, intent, PendingIntent.FLAG_UPDATE_CURRENT);remoteViews.setOnClickPendingIntent(R.id.root, pendingIntent);Notification notification = builder.build();NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);notificationManager.notify(NOTIFICATION_ID,notification);
}

认识RemoteViews

RemoteViews主要用在通知栏和桌面小部件上,简单来说RemoteViews是一个可以跨进程显示view的类,显示的view是从布局文件inflate出来,且该类提供了一些基本的方法来修改这个view的内容。

RemoteViews并不是一个view, 但可以表示一个layout的布局;又因为是继承parcelable,所以可以跨进程使用,但因为是跨进程,所以没办法像我们之前通过findviewById方法来访问布局里的每个view,所以RemoteViews提供了一些set方法来更新view 的显示,RemoteViews可以支持大部分系统控件,但是不支持自定义控件。

原理

自定义通知栏和桌面小部件,是由NotificationManager和AppWidgetmanager管理,而NotificationManager和AppWidgetManager是通过Binder分别和SystemServer进程中的NotificationManagerServer以及AppWidgetService进行通信,他们是运行在系统进程中,即SystemServer进程, 而我们是要在自身的应用进程中来更新远程系统进程的UI。这样就构成来跨进程通信的场景。 最开始的一节我们知道RemoteViews 是实现了Parcelable接口的,这样就可以跨进程使用了。从构造方法开始,系统首先根据包名去得到该应用的资源,然后inflate出布局文件,在SystemServer进程中是一个普通的view,而在我们的进程看来这是一个RemoteViews,然后会通过一系列set方法来更新该RemoteViews。

认识PendingIntent

所谓的 PendingIntent 是区别于 Intent 而存在的。Intent(即意图)是立即发生的,而 PendingIntent 是在将来的某个时刻发生的。PendIntent其实是Intent的封装。

PendingIntent的使用场景主要用于闹钟、通知、桌面部件。

与Intent的区别

  • Intent 是意图的意思。Android 中的 Intent 正是取自这个意思,它是一个消息对象,通过它,Android 系统的四大组件能够方便的通信,并且保证解耦。Intent 可以说明某种意图,携带一种行为和相应的数据,发送到目标组件。
  • PendingIntent是对Intent的封装,但它不是立刻执行某个行为,而是满足某些条件或触发某些事件后才执行指定的行为。

我们的 Activity 如果设置了 exported = false,其他应用如果使用 Intent 就访问不到这个 Activity,但是使用 PendingIntent 是可以的。

即:PendingIntent将某个动作的触发时机交给其他应用;让那个应用代表自己去执行那个动作(权限都给他)

获取PendingIntent

关于PendingIntent的实例获取一般有以下五种方法,分别对应Activity、Broadcast、Service:

  • getActivity()
  • getActivities()
  • getBroadcast()
  • getService()
  • getForegroundService()

它们的参数都相同,都是四个:Context, requestCode, Intent, flags,分别对应上下文对象、请求码、请求意图用以指明启动类及数据传递、关键标志位。前面三个参数共同标志一个行为的唯一性。

PendingIntent的FLAG

  • FLAG_CANCEL_CURRENT:如果当前系统中已经存在一个相同的PendingIntent对象,那么就将先将已有的PendingIntent取消,然后重新生成一个PendingIntent对象。
  • FLAG_NO_CREATE:如果当前系统中不存在相同的PendingIntent对象,系统将不会创建该PendingIntent对象而是直接返回null,如果之前设置过,这次就能获取到。
  • FLAG_ONE_SHOT:该PendingIntent只作用一次。在该PendingIntent对象通过send()方法触发过后,PendingIntent将自动调用cancel()进行销毁,那么如果你再调用send()方法的话,系统将会返回一个SendIntentException。
  • FLAG_UPDATE_CURRENT:如果系统中有一个和你描述的PendingIntent对等的PendingInent,那么系统将使用该PendingIntent对象,但是会使用新的Intent来更新之前PendingIntent中的Intent对象数据,例如更新Intent中的Extras

8.0通知栏新增通知渠道

Android 8.0 系统,Google引入通知渠道,提高用户体验,方便用户管理通知信息,同时也提高了通知到达率

什么是通知渠道呢?顾名思义,就是每条通知都要属于一个对应的渠道。每个App都可以自由地创建当前App拥有哪些通知渠道,但是这些通知渠道的控制权都是掌握在用户手上的。用户可以自由地选择这些通知渠道的重要程度,是否响铃、是否振动、或者是否要关闭这个渠道的通知。

build.gradle中targetSdkVersion设置大于等于26。这时如果不对通知渠道适配,通知就无法显示。

所以我们要额外处理:

1.创建NotificationChannel对象,指定Channel的id、name和通知的重要程度

2.使用NotificationMannager的createNotificationChannel方法来添加Channel。

    private NotificationCompat.Builder getNotificationBuilder() {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {NotificationChannel channel = new NotificationChannel("channel_id", "channel_name",NotificationManager.IMPORTANCE_DEFAULT);//是否绕过请勿打扰模式channel.canBypassDnd();//闪光灯channel.enableLights(true);//锁屏显示通知channel.setLockscreenVisibility(VISIBILITY_SECRET);//闪关灯的灯光颜色channel.setLightColor(Color.RED);//桌面launcher的消息角标channel.canShowBadge();//是否允许震动channel.enableVibration(true);//获取系统通知响铃声音的配置channel.getAudioAttributes();//获取通知取到组channel.getGroup();//设置可绕过  请勿打扰模式channel.setBypassDnd(true);//设置震动模式channel.setVibrationPattern(new long[]{100, 100, 200});//是否会有灯光channel.shouldShowLights();getNotificationManager().createNotificationChannel(channel);}NotificationCompat.Builder notification = new NotificationCompat.Builder(this, "channel_id");notification.setContentTitle("新消息来了");notification.setContentText("周末到了,不用上班了");notification.setSmallIcon(R.mipmap.ic_launcher);notification.setAutoCancel(true);return notification;}

3.设置通知重要性级别

Android 8.0 及以上是使用NotificationManager.IMPORTANCE_,Android 7.1 及以下是使用NotificationCompat.PRIORITY_它们都是定义的常量:

总结

以上是我对通知栏相关使用或自定义方式的总结,这块也很简单,重点关注是RemoteViews和PendingIntent的知识点的认识和理解。

最后

我是i猩人,总结不易,转载注明出处,喜欢本篇文章的童鞋欢迎点赞、关注哦。

Android开发通知栏的那些事相关推荐

  1. [Android开发那点破事]解决android.os.NetworkOnMainThreadException

    昨天和女朋友换了手机,我的iPhone 4S 换了她得三星I9003.第一感觉就是好卡,果断刷机.以前是Android 2.3的系统.回来刷成了4.4. 好了,问题来了.在我用手机测试我们的APP的时 ...

  2. 【Android开发那点破事】打开APP加载页面实现

    今天的破事呢就说说APP加载页面的实现.一般情况下,当APP打开的时候,我们需要做很多事情,比如检查网络连接啊,初始化一些配置啊等等.我们可以让这些事情在APP完全打开之前做完,然后呢在打开的过程中显 ...

  3. 【Android开发那点破事】解决android.os.NetworkOnMainThreadException

    昨天和女朋友换了手机,我的iPhone 4S 换了她得三星I9003.第一感觉就是好卡,果断刷机.以前是Android 2.3的系统.回来刷成了4.4. 好了,问题来了.在我用手机测试我们的APP的时 ...

  4. 搭建android开发环境,android studio + Genymotion

    刚开始学习android,记录下自己的学习过程,期望和大家一起学习.进步 既然要学习android开发,首要之事就是搭建android开发环境,以前的android的开发环境都是eclipse+and ...

  5. android下载通知栏,Android开发中实现下载文件通知栏显示进度条

    android开发中实现下载文件通知栏显示进度条. 1.使用asynctask异步任务实现,调用publishprogress()方法刷新进度来实现(已优化) public class myasync ...

  6. android api版本 闪退_经验分享:从事 Android 开发六年,我学到的那些事

    你的代码质量应该随着经验的增加而提高,在本文作者基于 Android 开发者六年间,其都学到了什么? 以下为译文: 六年来,我为多家公司编写过各种应用程序.你编写代码或处理代码库的文化和方式会随着你的 ...

  7. 从事 Android 开发六年,我学到的那些事!

    你的代码质量应该随着经验的增加而提高,在本文作者基于 Android 开发者六年间,其都学到了什么? 作者 | Mrudula 译者 | 弯月,责编 | 屠敏 出品 | CSDN(ID:CSDNnew ...

  8. 分享一下身边朋友自学android开发及找工作的那些事!【不足勿喷】

    写在前面 前不久身边一个朋友突然告诉我他把原来的工作辞掉了,我问他最近在干嘛,他说他最近两个月学了java及android然后花了1周时间找工作,我问他现在怎么样了.他说比不上我们身边这些10K-20 ...

  9. 分享一下身边朋友自学android开发及找工作的那些事!【不足勿喷】 1

    写在前面 前不久身边一个朋友突然告诉我他把原来的工作辞掉了,我问他最近在干嘛,他说他最近两个月学了java及android然后花了1周时间找工作,我问他现在怎么样了.他说比不上我们身边这些10K-20 ...

最新文章

  1. 新地王的诞生终将付出惨痛的代价?
  2. NumPy学习笔记(一)
  3. java 映射类_将数据库类型映射到具体的Java类
  4. Java操作shell脚本
  5. CF1338D:Nested Rubber Bands(树形dp)
  6. 谷歌浏览器如何设置flash访问权限
  7. 计算机科学课程规范,计算机科学及技术学院《本科生课程设计规范化要求》.doc...
  8. Android 匿名共享内存驱动源码分析
  9. mac苹果电脑如何查看mac地址
  10. ios蓝牙开发学习笔记(一)蓝牙概述
  11. 左耳朵耗子:996不是福气,但努力就会成功么?
  12. 逻辑回归(LR) 算法模型简介
  13. 混合罚函数c语言程序,混合惩罚函数法.ppt
  14. 很多人生哲理好句子分享
  15. C语言中char和char *a[]和char (*a)[]
  16. python如何计算字典平均值_算出字典中数值的平均值
  17. 前台HTML现在预览附件
  18. 第2章 Python 数字图像处理(DIP) --数字图像基础2 - 图像感知要素 - 图像取样和量化 - 空间分辨率和灰度分辨率
  19. latex公式自动换行与不自动换行的实现
  20. 大一计算机策划案怎么做,计算机类大一社会实践活动策划书

热门文章

  1. JMeter参数大小写转换
  2. linux打开txt文件命令_「linux命令详解」lsof命令解析,教你一步打开所有文件
  3. 文本提取IP并批量自动化情报查询工具——getIpInfo
  4. 贪心算法《活动时间安排问题》
  5. 佳博80系列小票打印机 gp 80180安装驱动,显示打印错误
  6. PhoneGap 微信插件 for iOS
  7. (转)【mysql元数据库】使用information_schema.tables查询数据库和数据表信息 ---数据记录大小统计...
  8. 电脑锁屏 快捷方式设置
  9. 使用 Docker 运行微信 PC 客户端
  10. python背景色渐变_Python 生成纯色或渐变色图片