segmentfault 对 mackdown 语法的支持不是很好,有些图片都显示不出来,大家可以去我的掘金查看这篇文章。

一、Notification 概述

Notification,俗称通知,是一种具有全局效果的通知,它展示在屏幕的顶端,首先会表现为一个图标的形式,当用户向下滑动的时候,展示出通知具体的内容。系统为开发者提供了不同种类的通知样式模板可以使用,开发者也可以根据自己需要自定义通知样式。

二、通知渠道(NotificationChannel)

通知渠道是 Google 在 Android O 中新增加的功能,新的版本中把振动、音效和灯效等相关效果放在了通知渠道中控制,这样用户就可以有选择的控制应用的某一类通知的通知效果,而不像之前版本中应用所有通知都受控于一种设置。需要注意的是,在 Android O 版本中,发送通知的时候必须要为通知设置通知渠道,否则通知不会被发送

public void addNotificationChannel() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        //创建通知渠道
        CharSequence name = "渠道名称1";
        String description = "渠道描述1";
        int importance = NotificationManager.IMPORTANCE_DEFAULT;//重要性级别 这里用默认的
        NotificationChannel mChannel = new NotificationChannel(channelId, name, importance);

        mChannel.setDescription(description);//渠道描述
        mChannel.enableLights(true);//是否显示通知指示灯
        mChannel.enableVibration(true);//是否振动

        mNotificationManager.createNotificationChannel(mChannel);//创建通知渠道
    }
}

三、发送通知

1、简单通知

效果图如下所示:

<img src = "https://img-blog.csdnimg.cn/20200902092733164.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl8zODQ3ODc4MA==,size_16,color_FFFFFF,t_70#pic_center" width="180" height="360"></img>
具体代码如下:

NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this, channelId)
        .setSmallIcon(R.mipmap.ic_launcher)//小图标
        .setContentTitle("我是标题")
        .setContentText("我是内容内容");

mNotificationManager.notify(id, mBuilder.build());

2、大文本通知

效果图如下所示:

<img src = "https://img-blog.csdnimg.cn/20200902093724237.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl8zODQ3ODc4MA==,size_16,color_FFFFFF,t_70#pic_center" width="180" height="360"></img>
具体代码如下:

NotificationCompat.Builder mBuilder2 = new NotificationCompat.Builder(this, channelId)
        .setSmallIcon(R.mipmap.ic_launcher)//小图标
        .setStyle(new NotificationCompat.BigTextStyle().bigText("通知渠道是 Google 在 Android O 中新增加的功能," +
                "新的版本中把振动、音效和灯效等相关效果放在了通知渠道中控制," +
                "这样用户就可以有选择的控制应用的某一类通知的通知效果," +
                "而不像之前版本中应用所有通知都受控于一种设置。需要注意的是," +
                "在 Android O 版本中,发送通知的时候必须要为通知设置通知渠道,否则通知不会被发送"))
        .setContentTitle("我是标题");

mNotificationManager.notify(id, mBuilder2.build());

3、通知可点击

效果图如下所示:
gif展示
具体代码如下:

NotificationCompat.Builder mBuilder2 = new NotificationCompat.Builder(this, channelId)
        .setSmallIcon(R.mipmap.ic_launcher)//小图标
        .setStyle(new NotificationCompat.BigTextStyle().bigText("通知渠道是 Google 在 Android O 中新增加的功能," +
                "新的版本中把振动、音效和灯效等相关效果放在了通知渠道中控制," +
                "这样用户就可以有选择的控制应用的某一类通知的通知效果," +
                "而不像之前版本中应用所有通知都受控于一种设置。需要注意的是," +
                "在 Android O 版本中,发送通知的时候必须要为通知设置通知渠道,否则通知不会被发送"))
        .setContentTitle("我是标题");

Intent intent = new Intent(this, NotificationActivity.class);
PendingIntent ClickPending = PendingIntent.getActivity(this, 0, intent, 0);

mBuilder2.setContentIntent(ClickPending);
mBuilder2.setAutoCancel(true);//点击这条通知自动从通知栏中取消

mNotificationManager.notify(id, mBuilder2.build());

4、点击事件监听

我们都知道系统并未提供相应的 API 去监听通知点击事件。那么如果要捕获通知的点击,要怎么办呢。在 PendingIntent 中提供了一个方法 getBroadcast( ),我们可以通过广播的方式进行处理:当用户点击通知时,发送一个广播,我们可以在这个广播接收者中做需要的操作。

具体代码如下:

NotificationCompat.Builder mBuilder3 = new NotificationCompat.Builder(this, channelId)
        .setSmallIcon(R.mipmap.ic_launcher)//小图标
        .setStyle(new NotificationCompat.BigTextStyle().bigText("通知渠道是 Google 在 Android O 中新增加的功能," +
                "新的版本中把振动、音效和灯效等相关效果放在了通知渠道中控制," +
                "这样用户就可以有选择的控制应用的某一类通知的通知效果," +
                "而不像之前版本中应用所有通知都受控于一种设置。需要注意的是," +
                "在 Android O 版本中,发送通知的时候必须要为通知设置通知渠道,否则通知不会被发送"))
        .setContentTitle("我是标题");

Intent intent3 = new Intent(BROADCAST_ACTION);
intent3.putExtra("data","12345");//带上参数
PendingIntent pendingIntent = PendingIntent.getBroadcast(this,id,intent3, PendingIntent.FLAG_UPDATE_CURRENT);

mBuilder3.setContentIntent(pendingIntent);
mBuilder3.setAutoCancel(true);//点击这条通知自动从通知栏中取消

mNotificationManager.notify(id, mBuilder3.build());
break;

接受的代码如下所示:

public class DynamicBroadcast extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent){
        String data = intent.getStringExtra("data");
        Log.i("dataTag","点击通知事件发过来的数据为: " + data);
    }
}

运行结果如下所示:
数据
可以看到我们已经成功的监测到了点击事件并接收到了传过来的数据。

四、完整代码

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private Button btn_send;
    private Button btn_send_big_text;
    private Button btn_broadcast;

    // 通知相关
    private int id = 1111;
    private String channelId = "channelId1";//渠道id
    private NotificationManager mNotificationManager;

    private String BROADCAST_ACTION="android.intent.action.BROADCAST_ACTION";
    private DynamicBroadcast dynamicBroadcast;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        btn_send = findViewById(R.id.btn_send);
        btn_send_big_text = findViewById(R.id.btn_send_big_text);
        btn_broadcast = findViewById(R.id.btn_broadcast);
        btn_send.setOnClickListener(this);
        btn_send_big_text.setOnClickListener(this);
        btn_broadcast.setOnClickListener(this);

        mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        addNotificationChannel();


        //动态注册广播
        dynamicBroadcast=new DynamicBroadcast();
        IntentFilter intentFilter=new IntentFilter(BROADCAST_ACTION);
        registerReceiver(dynamicBroadcast,intentFilter);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();

        if(dynamicBroadcast!=null){
            unregisterReceiver(dynamicBroadcast);
        }
    }

    public void addNotificationChannel() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            //创建通知渠道
            CharSequence name = "渠道名称1";
            String description = "渠道描述1";
            int importance = NotificationManager.IMPORTANCE_DEFAULT;//重要性级别 这里用默认的
            NotificationChannel mChannel = new NotificationChannel(channelId, name, importance);

            mChannel.setDescription(description);//渠道描述
            mChannel.enableLights(true);//是否显示通知指示灯
            mChannel.enableVibration(true);//是否振动

            mNotificationManager.createNotificationChannel(mChannel);//创建通知渠道
        }
    }


    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.btn_send:
                NotificationCompat.Builder mBuilder1 = new NotificationCompat.Builder(this, channelId)
                        .setSmallIcon(R.mipmap.ic_launcher)//小图标
                        .setContentTitle("我是标题")
                        .setContentText("我是内容内容");

                mNotificationManager.notify(id, mBuilder1.build());
                break;
            case R.id.btn_send_big_text:
                NotificationCompat.Builder mBuilder2 = new NotificationCompat.Builder(this, channelId)
                        .setSmallIcon(R.mipmap.ic_launcher)//小图标
                        .setStyle(new NotificationCompat.BigTextStyle().bigText("通知渠道是 Google 在 Android O 中新增加的功能," +
                                "新的版本中把振动、音效和灯效等相关效果放在了通知渠道中控制," +
                                "这样用户就可以有选择的控制应用的某一类通知的通知效果," +
                                "而不像之前版本中应用所有通知都受控于一种设置。需要注意的是," +
                                "在 Android O 版本中,发送通知的时候必须要为通知设置通知渠道,否则通知不会被发送"))
                        .setContentTitle("我是标题");

                Intent intent = new Intent(this, NotificationActivity.class);
                PendingIntent ClickPending = PendingIntent.getActivity(this, 0, intent, 0);

                mBuilder2.setContentIntent(ClickPending);
                mBuilder2.setAutoCancel(true);//点击这条通知自动从通知栏中取消

                mNotificationManager.notify(id, mBuilder2.build());

                break;
            case R.id.btn_broadcast:
                NotificationCompat.Builder mBuilder3 = new NotificationCompat.Builder(this, channelId)
                        .setSmallIcon(R.mipmap.ic_launcher)//小图标
                        .setStyle(new NotificationCompat.BigTextStyle().bigText("通知渠道是 Google 在 Android O 中新增加的功能," +
                                "新的版本中把振动、音效和灯效等相关效果放在了通知渠道中控制," +
                                "这样用户就可以有选择的控制应用的某一类通知的通知效果," +
                                "而不像之前版本中应用所有通知都受控于一种设置。需要注意的是," +
                                "在 Android O 版本中,发送通知的时候必须要为通知设置通知渠道,否则通知不会被发送"))
                        .setContentTitle("我是标题");

                Intent intent3 = new Intent(BROADCAST_ACTION);
                intent3.putExtra("data","12345");//带上参数
                PendingIntent pendingIntent = PendingIntent.getBroadcast(this,id,intent3, PendingIntent.FLAG_UPDATE_CURRENT);

                mBuilder3.setContentIntent(pendingIntent);
                mBuilder3.setAutoCancel(true);//点击这条通知自动从通知栏中取消

                mNotificationManager.notify(id, mBuilder3.build());
                break;
        }
    }
}

五、备注

测试的时候发现,在 Google 的 Pixel 手机上,当通知显示出来时,对应小图标的icon的样式是一个纯白的小方块或者小圆块。如下图所示:


<img src = "https://img-blog.csdnimg.cn/20200914155303239.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl8zODQ3ODc4MA==,size_16,color_FFFFFF,t_70#pic_center" width="250" height="260"></img>


出现这个问题的原因就是 google 原生的手机通过 setSmallIcon() 方法设置的图片必须是<font color=red>背景透明的</font>,所有不透明的点最终都会显示为白色。详情请看这篇博客。


Maenj_Ba_lah
28 声望7 粉丝

真正的大师,永远怀着一颗学徒的心。