关于Android 通知

1,712 阅读4分钟

什么是通知渠道

每条通知都要属于一个对应的渠道。每个App都可以自由地创建当前App拥有哪些通知渠道,但是这些通知渠道的控制权都是掌握在用户手上的。用户可以自由地选择这些通知渠道的重要程度,是否响铃、是否振动、或者是否要关闭这个渠道的通知。Google这次对于8.0系统通知渠道的推广态度还是比较强硬的,targetSdkVersion在26以上如果不使用通知渠道的话,那么App的通知将完全无法弹出。

创建通知渠道

上代码

  	String channelId = "message";
    	String channelName = "消息提示";
        int importance = NotificationManager.IMPORTANCE_HIGH;

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {

            NotificationChannel channel = new NotificationChannel(channelId, channelName, importance);
            NotificationManager notificationManager = (NotificationManager) getSystemService(
                    NOTIFICATION_SERVICE);
            notificationManager.createNotificationChannel(channel);
        }

这里创建了一个叫消息提示的的通知渠道,重要程度为NotificationManager.IMPORTANCE_HIGH 紧急。

创建通知渠道的这部分代码,你可以写在Activity中,也可以写在Application中,实际上可以写在程序的任何位置,只需要保证在通知弹出之前调用就可以了。并且创建通知渠道的代码只在第一次执行的时候才会创建,以后每次执行创建代码系统会检测到该通知渠道已经存在了,因此不会重复创建,也并不会影响任何效率。

显示通知

    NotificationManager notificationManager =
                (NotificationManager) getContext().getSystemService(Context.NOTIFICATION_SERVICE);

        Intent intent = new Intent(getContext(), NotificationActivity.class);
        PendingIntent pi = PendingIntent.getService(getContext(), 0, intent, 0);

        Notification notification = new NotificationCompat.Builder(this, channelId)
                //标题
                .setContentTitle("收到一条聊天消息")
                //内容
                .setContentText("今天中午吃什么")
                //设置发送的时间
                .setWhen(System.currentTimeMillis())
                //设置小图标(通知栏没有下拉的图标)
                .setSmallIcon(R.drawable.icon_done)
                //设置右侧大图标
                .setLargeIcon(BitmapFactory.decodeResource(getResources(),
                        R.drawable.icon_head_hydra_2))
                //设置点击通知后自动删除通知
                .setAutoCancel(true)
                .setContentIntent(pi)
                .build();
        notificationManager.notify(1, notification);


        //似乎只有设置了setContentIntent,AutoCancel才能生效

image.png

多行文字通知

  
        NotificationManager notificationManager =
                (NotificationManager) getContext().getSystemService(Context.NOTIFICATION_SERVICE);

        Intent intent = new Intent(getContext(), NotificationActivity.class);
        PendingIntent pi = PendingIntent.getService(getContext(), 0, intent, 0);

        String title = "多行文字标题";
        String content =
                "多行文字内容,多行文字内容,多行文字内容,多行文字内容,多行文字内容,多行文字内容,多行文字内容,多行文字内容,多行文字内容,多行文字内容,多行文字内容";


        //创建多文字样式
        NotificationCompat.BigTextStyle bigTextStyle = new NotificationCompat.BigTextStyle()
                .setBigContentTitle(title)
                .bigText(content);
        Notification notification = new NotificationCompat.Builder(this, channelId)
                //标题
                .setContentTitle("你有一条新消息")
                //设置小图标(通知栏没有下拉的图标)
                .setSmallIcon(R.drawable.icon_done)
                //设置右侧大图标
                .setLargeIcon(BitmapFactory.decodeResource(getResources(),
                        R.drawable.icon_head_hydra_2))
                //设置发送的时间
                .setWhen(System.currentTimeMillis())
                //设置点击通知后自动删除通知
                .setAutoCancel(true)
                .setContentIntent(pi)
                .setStyle(bigTextStyle)
                .build();
        notificationManager.notify(1, notification);

        //这里设置setContentText 也不会生效,会直接显示bigTextStyle里的内容,下拉之后不会显示setContentTitle,直接显示bigText

弹出样式

image.png

微信消息样式

NotificationManager notificationManager =
                (NotificationManager) getContext().getSystemService(Context.NOTIFICATION_SERVICE);

        Intent intent = new Intent(getContext(), NotificationActivity.class);
        PendingIntent pi = PendingIntent.getService(getContext(), 0, intent, 0);

        String title = "冰冰";
        ArrayList<String> messageList = new ArrayList<String>();
        messageList.add("今晚有空吗?");
        messageList.add("晚上跟我一起去玩吧?");
        messageList.add("怎么不回复我??我生气了!!");
        messageList.add("我真生气了!!!!!你听见了吗!");
        messageList.add("别不理我!!!");
        String content = "[" + messageList.size() + "条]" + title + ": " + messageList.get(0);


        NotificationCompat.InboxStyle inboxStyle = new NotificationCompat.InboxStyle();
        for (String msg : messageList) {
            inboxStyle.addLine(msg);
        }
        inboxStyle.setSummaryText("[" + messageList.size() + "条]" + title);


        Notification notification = new NotificationCompat.Builder(this, channelId)
                //标题
                .setContentTitle(title)
                //内容
                .setContentText(content)
                //设置小图标(通知栏没有下拉的图标)
                .setSmallIcon(R.drawable.icon_done)
                //设置右侧大图标
                .setLargeIcon(BitmapFactory.decodeResource(getResources(),
                        R.drawable.icon_head_hydra_2))
                //设置发送的时间
                .setWhen(System.currentTimeMillis())
                //设置点击通知后自动删除通知
                .setAutoCancel(true)
                .setContentIntent(pi)
                .setStyle(inboxStyle)
                .build();
        notificationManager.notify(1, notification);

image.png

image.png

进度条样式

NotificationManager notificationManager =
        (NotificationManager) getContext().getSystemService(Context.NOTIFICATION_SERVICE);

Intent intent = new Intent(getContext(), NotificationActivity.class);
PendingIntent pi = PendingIntent.getService(getContext(), 0, intent, 0);

Notification notification = new NotificationCompat.Builder(this, channelId)
        //标题
        .setContentTitle("正在下载")
        //内容
        .setContentText("50%")
        //设置发送的时间
        .setWhen(System.currentTimeMillis())
        //设置小图标(通知栏没有下拉的图标)
        .setSmallIcon(R.drawable.icon_done)
        //设置右侧大图标
        .setLargeIcon(BitmapFactory.decodeResource(getResources(),
                R.drawable.icon_head_hydra_2))
        //设置点击通知后自动删除通知
        .setAutoCancel(true)
        .setContentIntent(pi)
        //主要是这句
        .setProgress(100, 50, false)
        .build();
notificationManager.notify(1, notification);

//setProgress(100, 50, false)

image.png

大图样式

NotificationManager notificationManager =
        (NotificationManager) getContext().getSystemService(Context.NOTIFICATION_SERVICE);

Intent intent = new Intent(getContext(), NotificationActivity.class);
PendingIntent pi = PendingIntent.getService(getContext(), 0, intent, 0);


NotificationCompat.BigPictureStyle bigPictureStyle =
        new NotificationCompat.BigPictureStyle()
        .bigPicture(BitmapFactory.decodeResource(getResources(),
                R.drawable.icon_head_hydra_5))
        .setBigContentTitle("图片标题");


Notification notification = new NotificationCompat.Builder(this, channelId)
        //标题
        .setContentTitle("你有一条新消息")
        .setContentText("图片")
        //设置小图标(通知栏没有下拉的图标)
        .setSmallIcon(R.drawable.icon_done)
        //设置右侧大图标
        .setLargeIcon(BitmapFactory.decodeResource(getResources(),
                R.drawable.icon_head_hydra_2))
        //设置发送的时间
        .setWhen(System.currentTimeMillis())
        //设置点击通知后自动删除通知
        .setAutoCancel(true)
        .setContentIntent(pi)
        .setStyle(bigPictureStyle)
        .build();
notificationManager.notify(1, notification);

image.png

image.png

自定义通知栏view

RemoteViews remoteViews = new RemoteViews(getPackageName(), R.layout.custom_view_layout);
        // 设置点击事件
        remoteViews.setOnClickPendingIntent(R.id.iv_play_or_pause, getActivityPendingIntent(1));
        remoteViews.setOnClickPendingIntent(R.id.iv_next, getActivityPendingIntent(2));
        remoteViews.setOnClickPendingIntent(R.id.iv_cancel, getActivityPendingIntent(3));

        remoteViews.setTextViewText(R.id.tv_title, "标题");
        remoteViews.setTextViewText(R.id.tv_summery, "艺术家");

NotificationManager notificationManager =
                (NotificationManager) getContext().getSystemService(Context.NOTIFICATION_SERVICE);

        Intent intent = new Intent(getContext(), NotificationActivity.class);
        PendingIntent pi = PendingIntent.getService(getContext(), 0, intent, 0);

        Notification notification = new NotificationCompat.Builder(this, channelId)
                //设置发送的时间
                .setWhen(System.currentTimeMillis())
                //设置小图标(通知栏没有下拉的图标)
                .setSmallIcon(R.drawable.icon_done)
                //设置右侧大图标
                .setLargeIcon(BitmapFactory.decodeResource(getResources(),
                        R.drawable.icon_head_hydra_2))
                //设置点击通知后自动删除通知
                .setAutoCancel(true)
                .setContentIntent(pi)
                .setContent(remoteViews)
                .build();
        notificationManager.notify(1, notification);

image.png

关于通知栏块是很混乱的,Android系统大版本更新的时候经常有变动。国内厂商修改很严重,我手上有小米和vivo的测试机,以上的代码在不同的手机上表现也各不相同。如果有用到复杂视图的通知栏,最好是自定义通知栏view。

传送门

资料

Android通知栏微技巧,8.0系统中通知栏的适配 NotifyUtil NotificationDemo