android 扫盲 - Notification

2019-06-14  本文已影响0人  前行的乌龟

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


纵览 Notification API

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

Notification 的核心 API:

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

// 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 中可配置参数


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 方法可以设置通知的优先级,有五个级别:

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 不多,不支持的会直接报错,下面的是能支持的:

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);
}
上一篇下一篇

猜你喜欢

热点阅读