美文网首页
android 扫盲 - Notification

android 扫盲 - Notification

作者: 前行的乌龟 | 来源:发表于2019-06-14 20:11 被阅读0次

    通知 Notification 我是好久没用过了,说实话都忘的一干二净了,记得前几次用的时候都是现 baidu 的,baidu 几次过后依然是没啥印象,如此和没学何异。所以这笔记该自己写就自己写,不是为了给别人看,而是给自己看,梳理脑中 Notification 的知识点以方便记忆,不梳理的记忆如同杂草,不但没好处还有害


    纵览 Notification API

    官方代码,无论如何代码结构分层总是做的很好的,抓住了业功能分层就能了解全貌了

    Notification 的核心 API:

    很简单,很经典的代码机构,不用多说大家都看得懂,都明白其中的意思,麻烦一些的是适配:

    • 4.1 - 4.1 之后 Notification 有些变化,官方提供了 NotificationCompat 兼容老版本
    • 8.0 - 同一个 app 的同送可能有很多,官方让加上渠道就是为了让用户不至于接受或者都不接受某个 app 的通知,而知你关心或者不关心的一些通知
    // 1. build 构造函数都要传渠道号
     var build = NotificationCompat.Builder(this, "7602")
    
    // 2. 在 application 中创建渠道,这个渠道是加入到系统设置中去的
    // 所以无法修改,只有 add 不能 updata,只有在 app 删除时系统才会删除通知渠道
    var notificationManager : NotificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
    
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        val channel = NotificationChannel("7602", "test 渠道",NotificationManager.IMPORTANCE_HIGH)
        // 可以添加多个渠道进去
        notificationManager.createNotificationChannel(channel)
      }
    

    Notification 发送步奏:

    // 1. 拿到远程系统服务
    var notificationManager : NotificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
    
    // 2. 在 8.0 上添加渠道
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        val channel = NotificationChannel("7602", "test 渠道",NotificationManager.IMPORTANCE_HIGH)
        notificationManager.createNotificationChannel(channel)
      }
    
    // 3. build 构建参数
    var build = NotificationCompat.Builder(this, "7602")
        .setContentTitle("Title...")
        .setContentText("text...")
        .setSmallIcon(R.mipmap.ic_launcher)
    
    // 4. 发送通知
    notificationManager.notify(1, build.build())
    

    build 中可配置参数

    • setContentTitle(CharSequence) - 设置标题
    • setContentText(CharSequence) - 设置内容
    • setSubText(CharSequence) - 设置内容下面一小行的文字
    • setTicker(CharSequence) - 设置收到通知时在顶部显示的文字信息
    • setSmallIcon(int) - 设置右下角的小图标,在接收到通知的时候顶部也会显示这个小图标
    • setLargeIcon(Bitmap) - 设置左边的大图标
    • setWhen(long) - 设置通知时间,一般设置的是收到通知时的System.currentTimeMillis()
    • setAutoCancel(boolean) - 用户点击Notification点击面板后是否让通知取消(默认不取消)
    • setDefaults(int) - 通知添加声音、闪灯和振动效果
      • Notification.DEFAULT_VIBRATE - 添加默认震动提醒
      • Notification.DEFAULT_SOUND - 添加默认声音提醒
      • Notification.DEFAULT_LIGHTS - 添加默认三色灯提醒
      • Notification.DEFAULT_ALL - 添加默认以上3种全部提醒
    • setVibrate(long[]) - 设置振动方式,比如:new long[] {0,300,500,700},延迟 0ms,振动300ms,在延迟 500ms, 接着再振动 700ms
    • setLights(int argb, int onMs, int offMs) - 设置三色灯,参数依次是:灯光颜色, 亮持续时间,暗的时间,不是所有颜色都可以,这跟设备有关,有些手机还不带三色灯; 另外,还需要为Notification设置flags为Notification.FLAG_SHOW_LIGHTS才支持三色灯提醒
    • setSound(Uri) - 设置接收到通知时的铃声
      • setDefaults(Notification.DEFAULT_SOUND) - 默认铃声
      • setSound(Uri.parse("file:///sdcard/xx/xx.mp3")) - 自定义铃声
      • setSound(Uri.withAppendedPath(Audio.Media.INTERNAL_CONTENT_URI, "5")) - Android多媒体库内的铃声
    • setOngoing(boolean) - 设置为 ture,表示它为一个正在进行的通知,他们通常是用来表示一个后台任务,如播放音乐,文件下载
    • setProgress(int,int,boolean) - 带进度条的通知,参数依次为:进度条最大数值,当前进度,setProgress(0, 0, false) 可以移除进度条,setProgress(0, 0, true) 可以一直显示进度条
    • setContentIntent(PendingIntent) - 通知的点击事件
    • setVisibility(int) - 锁屏时显示不显示
      • Notification.VISIBILITY_PUBLIC- 显示所有通知内容
      • Notification.VISIBILITY_PRIVATE - 只显示标题
      • Notification.VISIBILITY_SECRET - 不显示任何内容

    Notification 参数的说明

    1. Ticker 和 SubText 在哪显示


      SubText 挨着标题显示
    Ticker 在通知来的那一瞬间显示
    1. setProgress

    这里的 Progress 样式随着系统不同版本和手机厂商不同有所区别,样式不移动都一样,所以想要样式有没统一还是得采用自定义 Notification 的方式

    SmallIcon 是必须设置的,不设置报错,SmallIcon 在左,LargeIcon 在右


    注意点

    1. setSmallIcon
      setSmallIcon 必须设置的,要不然会直接报错

    2. 修改NotificationChannel
      NotificationChannel 之能往系统中添加,修改不存在的,相同 id 的 NotificationChannel 修改不生效,只有卸载 app 才会清除 NotificationChannel,替代方案是使用新 id 的 NotificationChannel


    富文本

    1. BigTextStyle

    一般要是文字多了的话,一行显示不下时就是下面这样



    这是我们可是使用 BigTextStyle 包裹文字


            var build = NotificationCompat.Builder(this, "7602")
                    .setStyle( NotificationCompat.BigTextStyle().bigText("AAAAA") )
    
    2. BigPictureStyle

    带大图的样式


    var bigPictureStyle = NotificationCompat.BigPictureStyle()
    bigPictureStyle.bigPicture(BitmapFactory.decodeResource(resources, R.drawable.ic_dog))
    bigPictureStyle.setSummaryText( "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" )
    
    var build = NotificationCompat.Builder(this, "7602")
        .setStyle(bigPictureStyle)
    
    3. InboxStyle

    列表


    val inboxStyle = NotificationCompat.InboxStyle()
    
    inboxStyle.addLine("AAA")
    inboxStyle.addLine("BBB")
    inboxStyle.addLine("CCC")
    
    build.setStyle(inboxStyle)
    
    4. MediaStyle

    其实还有这个的,但是我看大家都写的,没找到具体的资料


    通知的取消和更新

    1. 取消通知
      取消通知我想大家都踩的到,就是用 id 来取消呗,既然在发送时用了 id ,那么必然大概率是可以通过 id 来取消的
    1. 更新通知
      利用上次的 build ,使用相同的 id 直接 notify 就行了,相同 id 的通知只能存在一个

    优先级

    使用 setPriority 方法可以设置通知的优先级,有五个级别:

    • PRIORITY_DEFAULT - 默认
    • PRIORITY_MIN - 最低,系统只会在用户下拉状态栏的时候才会显示
    • PRIORITY_LOW - 较低,系统会将这类通知缩小,或者改变显示的顺序,将排在更重要的通知之后
    • PRIORITY_HIGH - 较高,系统可能会将这类通知方法,或改变显示顺序,比较靠前
    • PRIORITY_MAX - 最重要的程度, 会弹出一个单独消息框,让用户做出相应

    8.0 添加去到之后,不光 build 要设置,channel 一样在构造函数时要传优先级进去

            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                val channel = NotificationChannel("7602", "test 渠道", NotificationManager.IMPORTANCE_HIGH)
                notificationManager.createNotificationChannel(channel)
            }
    
            var build = NotificationCompat.Builder(this, "7602")
                    .setPriority(NotificationManager.IMPORTANCE_HIGH)
    

    PRIORITY_MAX 现在不好使了,channel 取值范围不支持这个参数了,最高到 PRIORITY_HIGH,另外手机厂商基本都懂通知这块了,随意这个优先级其实不怎惯用了,比如 8.0 之后你把 app 的通知标记为不重要了,这里你即便设置成 PRIORITY_HIGH 也不管用


    响应通知点击

    状态栏上的通知最最终是要用户来点击的,我们可以把 Notification 当做一个 Button 来处理,Button 可以设置 OnClickListener,Notification 因为是运行在系统进程上的,OnClickListener 对象传递过去也没有意思,这里借助的 intent,是把点击行为包装在 intent 中,没法做太多的花样,这个特殊的 intent 就是 PendingIntent

    PendingIntent 是一种特殊的 Intent, 作用和 Intent 一样是用于启动系统组件,可以是:

    当点击通知后,系统便会调用 PendingIntent,启动一个活动,服务或广播,这取决于你获取的是那种 PendingIntent。在 PendingIntent 中传入的 Context 销毁以后,PendingIntent 依旧有效,它一般使用在当 Context 销毁后需要执行 Intent的地方,一般不是用于立即执行的时候,比如在点击通知后唤醒一个 Activity。比如若是我们想要用 PendingIntent 大来一个页面,我们在后台 kill 该 app 进程,点击通知时依然会开发目标页面,和启动新的进程一样,该走的初始化都会走,比如 application onCreate 函数

    // 启动 Activity 的 PendingIntent
    var intent = Intent(this, NotificationReceiver::class.java)
    var pendingIntent = PendingIntent.getActivity(this, 0, intent, 0)
    var build = NotificationCompat.Builder(this, "7602")
        .setContentIntent(pendingIntent)
    
    // 发送 Broadcast 的 PendingIntent
    var intent2 = Intent("AAA")
    var pendingIntent2 = PendingIntent.getBroadcast(this, 0, intent2, 0)
    build.setContentIntent(pendingIntent2)
    
    
    // 启动服务 的 PendingIntent
    PendingIntent.getService(Context context, int requestCode, Intent intent, int flags);
    PendingIntent.getActivities(Context context, int reqeustCode, Intent[] intents, int flags);
    PendingIntent.getForgroundService(Context, int reqeustCode, Intent intent, int flags)
    

    注意自 8.0 禁止静态广播后,经测试静态广播的方式不好用了。广播,服务,页面的 intent 里可以传具体指令或是参数,已实现通知和其他组件的通信


    可以添加最多3个简单的按钮

    如图就是这3个按钮
    var actionBuilder1 = NotificationCompat.Action.Builder(R.drawable.ic_launcher_foreground, "Action1", pendingIntent)
    var actionBuilder2 = NotificationCompat.Action.Builder(R.drawable.ic_launcher_foreground, "Action2", pendingIntent)
    var actionBuilder3 = NotificationCompat.Action.Builder(R.drawable.ic_launcher_foreground, "Action3", pendingIntent)
    
    build.addAction( actionBuilder1.build() )
    build.addAction( actionBuilder2.build() )
    build.addAction( actionBuilder3.build() )
    

    自定义通知样式 RemoteViews

    RemoteViews 是远程 view,我们通过系统 API 把 layoutID,复制操作发送到远程去显示


    这个就是,使用自己的 layout xml 布局,但是有个坑,通知能支持的 RemoteViews 的高度是固定的,比如官方原话:

    普通视图布局限制为 64 dp,扩展视图布局限制为 256 dp

    但是国内的厂商啊基本都自己改改的,我手里这台魅族 16 th,估计能支持 80dp 高了,所以这里大家注意一下

    另外 RemoteViews 能支持的布局类型和 view 不多,不支持的会直接报错,下面的是能支持的:

    • Layout
      • FrameLayout
      • LinearLayout
      • RelativeLayout
      • GridLayout
    • view
      • View Button
      • ImageView
      • ImageButton
      • TextView
      • ProgressBar
      • ListView
      • GridView
      • StackView
      • ViewStub
      • AdapterViewFlipper
      • ViewFlipper
      • AnalogClock
      • Chronometer

    RemoteViews 不能 findViewById 来赋值,只能把 id 和值一起发给远程,包括点击也是这样的

    RemoteViews remoteViews = new RemoteViews(getPackageName(),R.layout.notification_mobile_play);
    remoteViews.setOnClickPendingIntent(R.id.btn_pre, getActivityPendingIntent(11));
    remoteViews.setOnClickPendingIntent(R.id.btn_next, getActivityPendingIntent(12));
    remoteViews.setOnClickPendingIntent(R.id.btn_start, getActivityPendingIntent(13));
    remoteViews.setOnClickPendingIntent(R.id.ll_root, getActivityPendingIntent(14));
    remoteViews.setTextViewText(R.id.tv_title, "标题");   
    remoteViews.setTextViewText(R.id.tv_artist, "艺术家");  
    

    自定义通知应用很多的,比如音视频操作,下载,app 辅助等,通知和 app 组件之间的交互都是通过服务或是广播来接收通知相关的点击事件


    NotificationChannel 通知渠道

    8.0 要大家添加这个通知渠道,然后渠道内也是可以设置一些参数的

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        //android 8.0以上需要特殊处理,也就是targetSDKVersion为26以上
        createNotificationChannel();
    }
    
    @TargetApi(Build.VERSION_CODES.O)
    private void createNotificationChannel() {
        NotificationChannel channel = new NotificationChannel(CHANNEL_ID, CHANNEL_NAME, NotificationManager.IMPORTANCE_DEFAULT);
        channel.canBypassDnd();//是否绕过请勿打扰模式
        channel.enableLights(true);//闪光灯
        channel.setLockscreenVisibility(VISIBILITY_SECRET);//锁屏显示通知
        channel.setLightColor(Color.RED);//闪关灯的灯光颜色
        channel.canShowBadge();//桌面launcher的消息角标
        channel.enableVibration(true);//是否允许震动
        channel.getAudioAttributes();//获取系统通知响铃声音的配置
        channel.getGroup();//获取通知取到组
        channel.setBypassDnd(true);//设置可绕过 请勿打扰模式
        channel.setVibrationPattern(new long[]{100, 100, 200});//设置震动模式
        channel.shouldShowLights();//是否会有灯光
        getManager().createNotificationChannel(channel);
    }
    

    相关文章

      网友评论

          本文标题:android 扫盲 - Notification

          本文链接:https://www.haomeiwen.com/subject/lnxhfctx.html