文章目录

  • 前言
  • 一、安卓8.0以下用法讲解
  • 使用步骤
  • 通知栏属性设置
  • 二、安卓8.0及以上版本用法讲解
  • 使用步骤
  • 问题解析
  • 运行报错:Fail to post notification on channel "null"
  • 三、实例代码
  • 定义一个简单的通知
  • 模拟下载进度条通知
  • 自定义通知模拟酷狗音乐
  • 总结



前言

关于Notification的用法,主要是要区分安卓版本,安卓8.0以下直接设置Builder就可以了,,安卓8.0及以上版本需要设置NotificationChannel管道


一、安卓8.0以下用法讲解

使用步骤

1. 获得NotificationManager对象: NotificationManager mNManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
2. 创建一个通知栏的Builder构造类: Notification.Builder mBuilder = new Notification.Builder(this);
3. 对Builder进行相关的设置,比如标题,内容,图标,动作等
4.调用Builder的build()方法为notification赋值
5.调用NotificationManager的notify()方法发送通知
6.另外我们还可以调用NotificationManager的cancel()方法取消通知

通知栏属性设置

1.设置通知标题

builder.setContentTitle("通知标题");

2.设置通知内容

builder.setContentText("我是通知类容");

3.设置通知内容下面的文字

builder.setSubText("内容下面的文字");

4.设置收到通知时在顶部显示的文字信息

builder.setTicker("来通知啦");

5.设置通知时间,System.currentTimeMillis()表示收到通知时的时间

builder.setWhen(System.currentTimeMillis());

6.设置通知左边的大图标

builder.setLargeIcon(Bitmap);

7.设置通知右边的小图标

builder.setSmallIcon(int);

8.设置通知声音

//设置通知声音并设置默认铃声
builder.setDefaults(Notification.DEFAULT_SOUND);
//获取自定义铃声
builder.setSound(Uri.parse("file:///sdcard/xx/xx.mp3")) 
//获取Android多媒体库内的铃声
builder.setSound(Uri.withAppendedPath(Audio.Media.INTERNAL_CONTENT_URI, "5"))

9.设置通知闪灯

//设置通知闪灯并设置默认闪灯方式
builder.setDefaults(Notification.DEFAULT_LIGHTS);
//设置三色灯(需要设备支持),参数依次是:灯光颜色, 亮持续时间,暗的时间
builder.setLights();

10.设置通知振动

//设置通知振动并设置默认振动方式
builder.setDefaults(Notification.DEFAULT_VIBRATE);
//设置自定义振动方式:延迟0ms,然后振动300ms,在延迟500ms, 接着再振动700ms
builder.setVibrate(new long[] {0,300,500,700});

11.设置通知闪灯+振动+声音

builder.setDefaults(Notification.DEFAULT_ALL);

12.设置带进度条的通知
参数依次为:进度条最大数值,当前进度,进度是否不确定

如果为确定的进度条:调用setProgress(max, progress, false)来设置通知, 在更新进度的时候在此发起通知更新progress,并且在下载完成后要移除进度条 ,通过调用setProgress(0, 0, false)既可。如果为不确定(持续活动)的进度条, 这是在处理进度无法准确获知时显示活动正在持续,所以调用setProgress(0, 0, true) ,操作结束时,调用setProgress(0, 0, false)并更新通知以移除指示条
builder.setProgress(int,int,boolean)

13.设置通知优先级

MAX:重要而紧急的通知,通知用户这个事件是时间上紧迫的或者需要立即处理的。
HIGH:高优先级用于重要的通信内容,例如短消息或者聊天,这些都是对用户来说比较有兴趣的。
DEFAULT:默认优先级用于没有特殊优先级分类的通知。
LOW:低优先级可以通知用户但又不是很紧急的事件。
MIN:用于后台消息 (例如天气或者位置信息)。最低优先级通知将只在状态栏显示图标,只有用户下拉通知抽屉才能看到内容。
builder.setPriority(Notification.PRIORITY_MAX);

14.设置点击通知栏的回调
主要应用于点击通知后打开activity,service,或者其他操作
PendingIntent的第四个参数有4个值:

FLAG_ONE_SHOT:表示返回的PendingIntent仅能执行一次,执行完后自动取消
FLAG_NO_CREATE:表示如果描述的PendingIntent不存在,并不创建相应的PendingIntent,而是返回NULL
FLAG_CANCEL_CURRENT:表示相应的PendingIntent已经存在,则取消前者,然后创建新的	PendingIntent, 这个有利于数据保持为最新的,可以用于即时通信的通信场景
FLAG_UPDATE_CURRENT:表示更新的PendingIntent
Intent intent = new Intent(context,MainActivity.class);  
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);  
builder.setContentIntent(pendingIntent)

15.设置通知是否正在进行,用于后台任务,如下载,网络连接等后台任务,设置为true表示正在执行后台任务

builder.setOngoing(true)

16.设置是否可以清除

builder.setAutoCancel(true);

二、安卓8.0及以上版本用法讲解

使用步骤

1.第一步仍然时获得NotificationManager对象: NotificationManager mNManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
2.创建NotificationChannel 
3.添加NotificationChannel 
4.创建一个通知栏的Builder构造类: Notification.Builder mBuilder = new Notification.Builder(this,id);要注意比安卓8.0以下的多一个参数:NotificationChannel 的id
5.仍然要对Builder进行相关的设置,比如标题,内容,图标,动作等
6.调用Builder的build()方法为notification赋值
7.调用NotificationManager的notify()方法发送通知
8.另外我们还可以调用NotificationManager的cancel()方法取消通知

问题解析

运行报错:Fail to post notification on channel “null”

问题出现原因:
在安卓8.0以上的设备上使用安卓8.0以下的方法发送的通知就会出现上述报错

三、实例代码

定义一个简单的通知

import androidx.appcompat.app.AppCompatActivity;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Intent;
import android.graphics.BitmapFactory;
import android.os.Build;
import android.os.Bundle;

public class MainActivity extends AppCompatActivity {
    private NotificationManager mNManager;
    private Notification.Builder builder;
    private int Notification_id = 1;

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

        mNManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);

        //判断安卓版本
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            String id ="channel_1";//channel的id
            String description = "123";//channel的描述信息
            int importance = NotificationManager.IMPORTANCE_LOW;//channel的重要性
            NotificationChannel channel = new NotificationChannel(id, description, importance);//生成channel
            //为channel添加属性
            //channel.enableVibration(true); 震动
            //channel.enableLights(true);提示灯
            mNManager.createNotificationChannel(channel);//添加channel
            builder = new Notification.Builder(this,id);
        }else{
            builder = new Notification.Builder(this);
        }

        //设置通知标题
        builder.setContentTitle("通知标题");
        //设置通知类容
        builder.setContentText("我是通知类容");
        //设置通知类容下面的文字
        builder.setSubText("内容下面的文字");
        //设置收到通知时在顶部显示的文字信息
        builder.setTicker("来通知啦");
        //设置通知时间,System.currentTimeMillis()表示收到通知时的时间
        builder.setWhen(System.currentTimeMillis());
        //设置左边的大图标
        builder.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.jsrrr));
        //设置通知右下角显示的小图标
        builder.setSmallIcon(R.drawable.conn);
        /*
        向通知添加声音、闪灯和振动效果
            Notification.DEFAULT_VIBRATE(添加默认震动提醒);
            Notification.DEFAULT_SOUND(添加默认声音提醒);
            Notification.DEFAULT_LIGHTS(添加默认三色灯提醒)
            Notification.DEFAULT_ALL(添加默认以上3种全部提醒)
         */
        builder.setDefaults(Notification.DEFAULT_VIBRATE);

        //设置振动方式:延迟0ms,然后振动300ms,在延迟500ms, 接着再振动700ms
        builder.setVibrate(new long[] {0,300,500,700});

        builder.setPriority(Notification.PRIORITY_MAX);

        builder.setAutoCancel(true);    //设置可以清除

        Intent intent = new Intent(MainActivity.this,MainActivity.class);
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
        builder.setContentIntent(pendingIntent);

        Notification notification = builder.build();
        mNManager.notify(Notification_id, notification);
    }


    @Override
    protected void onDestroy() {
        super.onDestroy();
        mNManager.cancel(Notification_id);
    }
}

模拟下载进度条通知

public class MainActivity extends AppCompatActivity {
    private NotificationManager mNManager;
    private Notification.Builder builder;
    private int Notification_id = 1;
    private Notification notification;
    
    int a;     //事务执行的总进度
    int b = 0;     //事务执行的初始进度
    int c = 100;     //进度条的总进度
    
    Handler myHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            if (msg.what == 111) {
                //计算当前实际进度
                double e = (double) b / a;
                double f = c * e;
                int g = (int) f;     
                if (g <= c) {
                    //下载过程中实时更新进度条和百分比显示
                    builder.setProgress(c, g, false);
                    builder.setContentText(g + "%");
                }else{
                    //下载完成后不在显示进度条
                    builder.setProgress(0, 0, false);
                    builder.setContentText("下载完成!");
                }
                mNManager.notify(Notification_id, notification);
            }
        }
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mNManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);

        //判断安卓版本
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            String id = "channel_1";//channel的id
            String description = "123";//channel的描述信息
            int importance = NotificationManager.IMPORTANCE_LOW;//channel的重要性
            NotificationChannel channel = new NotificationChannel(id, description, importance);//生成channel
            //为channel添加属性
            //channel.enableVibration(true); 震动
            //channel.enableLights(true);提示灯
            mNManager.createNotificationChannel(channel);//添加channel
            builder = new Notification.Builder(this, id);
        } else {
            builder = new Notification.Builder(this);
        }

        //设置通知标题
        builder.setContentTitle("下载通知");
        //设置通知类容
        builder.setContentText("0%");
        //设置通知类容下面的文字
        builder.setSubText("正在下载");
        //设置收到通知时在顶部显示的文字信息
        builder.setTicker("来通知啦");
        //设置通知时间,System.currentTimeMillis()表示收到通知时的时间
        builder.setWhen(System.currentTimeMillis());
        //设置左边的大图标
        builder.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.jsrrr));
        //设置通知右下角显示的小图标
        builder.setSmallIcon(R.drawable.conn);

        builder.setProgress(0, 0, true);

        builder.setAutoCancel(true);    //设置可以清除

        notification = builder.build();
        mNManager.notify(Notification_id, notification);

        //模拟下载,每秒输出一个进度值
        new Timer().schedule(new TimerTask() {
            @Override
            public void run() {
                a = 10;
                b++;
                if (b > a) {
                    cancel();
                }
            }
        }, 0, 1000);

        //每秒通过hander更新一次进度值
        new Timer().schedule(new TimerTask() {
            @Override
            public void run() {
                if (b > a) {
                    cancel();
                } else {
                    //定时循环执行的内容
                    myHandler.sendEmptyMessage(111);
                }
            }
        }, 0, 1000);
    }
    @Override
    protected void onDestroy() {
        super.onDestroy();
        mNManager.cancel(Notification_id);
    }

自定义通知模拟酷狗音乐

代码讲解:
1.首先自定义一个布局添加到Notification中,布局中设置按钮和监听事件
2.监听事件中发送指定action的广播,广播也可以根据需求携带其他参数
3.建立一个广播接收器,定义接收到广播后的操作

自定义布局:layout.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <TextView
                android:id="@+id/name"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginLeft="20dp"
                android:text="爱是你我"
                android:textSize="32dp"
                android:textStyle="bold" />

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_below="@+id/name"
                android:layout_marginLeft="10dp"
                android:layout_marginTop="10dp"
                android:orientation="horizontal">

                <RelativeLayout
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_weight="1">

                    <ImageButton
                        android:id="@+id/upper"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_centerInParent="true"
                        android:src="@android:drawable/ic_media_rew" />
                </RelativeLayout>

                <RelativeLayout
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_weight="1">

                    <ImageButton
                        android:id="@+id/onoff"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_centerInParent="true" />
                </RelativeLayout>

                <RelativeLayout
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_weight="1">

                    <ImageButton
                        android:id="@+id/below"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_centerInParent="true"
                        android:src="@android:drawable/ic_media_ff" />
                </RelativeLayout>
            </LinearLayout>
        </RelativeLayout>
    </RelativeLayout>
</LinearLayout>

广播接收器
MyReceiver.java

public class MyReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        switch (intent.getAction()) {
            case "upper":
                Toast.makeText(context, "切换为上一首", Toast.LENGTH_SHORT).show();
                break;
            case "onoff":

                Toast.makeText(context, "播放暂停切换", Toast.LENGTH_SHORT).show();

                break;
            case "below":
                Toast.makeText(context, "切换为下一首", Toast.LENGTH_SHORT).show();
                break;
        }

    }
}

MainActivity.java

import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Build;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.RemoteViews;

import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    private NotificationManager mNManager;
    private Notification.Builder builder;
    private int Notification_id = 1;
    private Notification notification;
    private RemoteViews ntView;
    private Button front;
    private Button bt;
    private Button rear;
    private boolean of = false;     //播放状态


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

    public void createReceiver() {
        //注册广播接收器
        MyReceiver bt = new MyReceiver();
        IntentFilter itFilter = new IntentFilter();
        itFilter.addAction("upper");
        itFilter.addAction("onoff");
        itFilter.addAction("below");
        registerReceiver(bt, itFilter);

    }

    //创建通知
    public void createNotification() {
        mNManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
        //判断安卓版本
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            String id = "channel_1";//channel的id
            String description = "123";//channel的描述信息
            int importance = NotificationManager.IMPORTANCE_LOW;//channel的重要性
            NotificationChannel channel = new NotificationChannel(id, description, importance);//生成channel
            mNManager.createNotificationChannel(channel);//添加channel
            builder = new Notification.Builder(this, id);
        } else {
            builder = new Notification.Builder(this);
        }

        //通过RemoteViews来创建自定义的Notification视图
        ntView = new RemoteViews(getPackageName(), R.layout.layout);

        ntView.setImageViewResource(R.id.onoff, android.R.drawable.ic_media_pause);

        //上一首按钮设置监听,点击按钮后发送一个广播
        //创建一个Intent
        Intent upper_intent = new Intent("upper");
        //设置点击通知后发送一个广播
        PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, upper_intent, PendingIntent.FLAG_UPDATE_CURRENT);
        //将点击后发送的广播与自定义view中的控件绑定
        ntView.setOnClickPendingIntent(R.id.upper, pendingIntent);

        //给播放暂停按钮设置监听,点击按钮后发送一个广播
        Intent onoff_intent = new Intent("onoff");
        PendingIntent pendingIntent2 = PendingIntent.getBroadcast(this, 0, onoff_intent, PendingIntent.FLAG_UPDATE_CURRENT);
        ntView.setOnClickPendingIntent(R.id.onoff, pendingIntent2);


        //下一首按钮设置监听,点击按钮后发送一个广播
        Intent below_intent = new Intent("below");
        PendingIntent pendingIntent3 = PendingIntent.getBroadcast(this, 0, below_intent, PendingIntent.FLAG_UPDATE_CURRENT);
        ntView.setOnClickPendingIntent(R.id.below, pendingIntent3);


        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            builder.setCustomContentView(ntView);
        }

        //设置通知右下角显示的小图标
        builder.setSmallIcon(R.drawable.ic_launcher_foreground);
        builder.setAutoCancel(false);

        notification = builder.build();
        mNManager.notify(Notification_id, notification);
    }


    @Override
    protected void onDestroy() {
        super.onDestroy();
        mNManager.cancel(Notification_id);
    }

    private void initView() {
        front = (Button) findViewById(R.id.front);
        bt = (Button) findViewById(R.id.bt);
        rear = (Button) findViewById(R.id.rear);

        front.setOnClickListener(this);
        bt.setOnClickListener(this);
        rear.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            //切换上一首,修改通知上显示的歌名
            case R.id.front:
                ntView.setTextViewText(R.id.name, "万里长城永不倒");
                mNManager.notify(Notification_id, notification);
                break;
            case R.id.bt:
                //默认设置了通知为暂停状态,点击按钮后,修改按钮图片为播放状态,再次点击修改图片为暂停状态
                if (of) {
                    of = false;
                    ntView.setImageViewResource(R.id.onoff, android.R.drawable.ic_media_pause);
                    mNManager.notify(Notification_id, notification);
                } else {
                    of = true;
                    ntView.setImageViewResource(R.id.onoff, android.R.drawable.ic_media_play);
                    mNManager.notify(Notification_id, notification);
                }
                break;
            //切换下一首,修改通知上显示的歌名
            case R.id.rear:
                ntView.setTextViewText(R.id.name, "等一分钟");
                mNManager.notify(Notification_id, notification);
                break;
        }
    }
}

总结

上面写了常见的关于Notification几个应用代码都可以直接复制使用,关于Notification还有其他几种应用以后再研究。