我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Android开发通知栏的那些事

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Android开发通知栏的那些事

对于通知栏的使用,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)
            
            .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;
        @Override
        public void run() {
            Log.i("progress", progress + "");
            while (progress <= 100) {
                progress++;
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.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) {
    //先设定RemoteViews
    RemoteViews 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_它们都是定义的常量:
android8.0通知渠道级别

总结

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


作者:Toper-C


免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Android开发通知栏的那些事

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Android开发通知栏的那些事

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

Android之开发消息通知栏

一:先来效果图二:实现步骤 1.xml布局实现 2022-06-06

不可不知的Android strings.xml那些事

strings.xml 有很多需要注意的地方和一些小技巧,知道了这些可以让你的 Android 应用更加规范易用,感兴趣的小伙伴们可以参考一下 不要复用 这一条可能很多人会有不同的意见,因为广为流行的编程理念就在教导我们要复用代码,当然
2022-06-06

Android开机启动的那些事

以前知道AMS、PMS这些概念及其功能,开发的过程中也会用到,就是不知道其来源,好奇心害死猫,扒着扒着扒到系统开机启动这个知识层面上来了,好吧,那今天就说说这个吧! 系统开机启动过程 Android系统的启动,主要是指Android手机关机
2022-06-06

Android开发 -- 状态栏通知Notification、NotificationManager详解

本想自己写一个的,但是看到这篇之后,我想还是转过来吧,实在是非常的详细: 在Android系统中,发一个状态栏通知还是很方便的。下面我们就来看一下,怎么发送状态栏通知,状态栏通知又有哪些参数可以设置? 首先,发送一个状态栏通知必须用到两个类
2022-06-06

【UI篇】Android 沉浸式状态栏的那些事

目录 window.decorView.systemUiVisibility 的参数常量1.View.SYSTEM_UI_FLAG_HIDE_NAVIGATION:(>=api16)2.View.SYSTEM_UI_FLAG_FUL
2023-08-17

Android开发之禁止下拉通知栏的方法

本文实例讲述了Android开发之禁止下拉通知栏的方法。分享给大家供大家参考,具体如下: 1.在AndroidManifest.xml中添加权限2022-06-06

Android开发中怎么实现一个沉浸式通知栏

Android开发中怎么实现一个沉浸式通知栏?相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。①DrawerLayout+Toolbar添加依赖库(谷歌提供)compile com
2023-05-31

Android开发之使用通知栏显示提醒信息的方法

本文实例讲述了Android开发之使用通知栏显示提醒信息的方法。分享给大家供大家参考,具体如下: 用通知栏来提醒public void notifyKJ() {//获得通知管理器,通知是一项系统服务NotificationManager m
2022-06-06

Android开发中那些需要注意的坑

这个是看知乎的时候发现的一个问题,感觉挺有意思,就将自己遇到的坑记录下来。 1、Andorid L theme colorPrimary 不能使用带有alpha的颜色值,否则会有异常抛出, 直接判断了是否alpha是否等于0或者255,其他
2022-06-06

Android通知栏增加快捷开关的功能实现教程

对于Android来说其中一项很方便的操作便是下拉菜单,下拉菜单栏可以快捷打开某项设置,这篇文章主要给大家介绍了关于Android通知栏增加快捷开关的功能实现,需要的朋友可以参考下
2023-01-30

优秀Web开发者提升开发能力必知的事有哪些

这篇文章主要介绍了优秀Web开发者提升开发能力必知的事有哪些,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。  1. 不要只盯着代码  如今人人都会写代码。很多业余爱好者也可以
2023-06-08

Android 移动应用开发 使用Notification通知 及NotificationChannel的使用

首先需要一个NotificationManager对象来对通知进行管理。代码如下 NotificationManager manager = (NotificationManager)getSystemService(NOTIFICATIO
2022-06-06

编程热搜

  • Android:VolumeShaper
    VolumeShaper(支持版本改一下,minsdkversion:26,android8.0(api26)进一步学习对声音的编辑,可以让音频的声音有变化的播放 VolumeShaper.Configuration的三个参数 durati
    Android:VolumeShaper
  • Android崩溃异常捕获方法
    开发中最让人头疼的是应用突然爆炸,然后跳回到桌面。而且我们常常不知道这种状况会何时出现,在应用调试阶段还好,还可以通过调试工具的日志查看错误出现在哪里。但平时使用的时候给你闹崩溃,那你就欲哭无泪了。 那么今天主要讲一下如何去捕捉系统出现的U
    Android崩溃异常捕获方法
  • android开发教程之获取power_profile.xml文件的方法(android运行时能耗值)
    系统的设置–>电池–>使用情况中,统计的能耗的使用情况也是以power_profile.xml的value作为基础参数的1、我的手机中power_profile.xml的内容: HTC t328w代码如下:
    android开发教程之获取power_profile.xml文件的方法(android运行时能耗值)
  • Android SQLite数据库基本操作方法
    程序的最主要的功能在于对数据进行操作,通过对数据进行操作来实现某个功能。而数据库就是很重要的一个方面的,Android中内置了小巧轻便,功能却很强的一个数据库–SQLite数据库。那么就来看一下在Android程序中怎么去操作SQLite数
    Android SQLite数据库基本操作方法
  • ubuntu21.04怎么创建桌面快捷图标?ubuntu软件放到桌面的技巧
    工作的时候为了方便直接打开编辑文件,一些常用的软件或者文件我们会放在桌面,但是在ubuntu20.04下直接直接拖拽文件到桌面根本没有效果,在进入桌面后发现软件列表中的软件只能收藏到面板,无法复制到桌面使用,不知道为什么会这样,似乎并不是很
    ubuntu21.04怎么创建桌面快捷图标?ubuntu软件放到桌面的技巧
  • android获取当前手机号示例程序
    代码如下: public String getLocalNumber() { TelephonyManager tManager =
    android获取当前手机号示例程序
  • Android音视频开发(三)TextureView
    简介 TextureView与SurfaceView类似,可用于显示视频或OpenGL场景。 与SurfaceView的区别 SurfaceView不能使用变换和缩放等操作,不能叠加(Overlay)两个SurfaceView。 Textu
    Android音视频开发(三)TextureView
  • android获取屏幕高度和宽度的实现方法
    本文实例讲述了android获取屏幕高度和宽度的实现方法。分享给大家供大家参考。具体分析如下: 我们需要获取Android手机或Pad的屏幕的物理尺寸,以便于界面的设计或是其他功能的实现。下面就介绍讲一讲如何获取屏幕的物理尺寸 下面的代码即
    android获取屏幕高度和宽度的实现方法
  • Android自定义popupwindow实例代码
    先来看看效果图:一、布局
  • Android第一次实验
    一、实验原理 1.1实验目标 编程实现用户名与密码的存储与调用。 1.2实验要求 设计用户登录界面、登录成功界面、用户注册界面,用户注册时,将其用户名、密码保存到SharedPreference中,登录时输入用户名、密码,读取SharedP
    Android第一次实验

目录