Android Notification 食用指北

本文用的是

import android.support.v4.app.NotificationCompat;
下面的Notification.

Notification,是一种具有全局效果的通知,可以在系统的通知栏中显示。当 APP 向系统发出通知时,它将先以图标的形式显示在通知栏中。用户可以下拉通知栏查看通知的详细信息。通知栏和抽屉式通知栏均是由系统控制,用户可以随时查看。

通知的目的是告知用户 App 事件。在平时的使用中,通知主要有以下几个作用:

  1. 显示接收到短消息、及时消息等信息(如QQ、微信、新浪、短信)
  2. 显示客户端的推送消息,如广告、优惠、版本更新、推荐新闻等,常用的第三方 SDK 有: JPush 、 个推 、 信鸽 、 网易云信(偏重 IM ) 、 阿里云推送
  3. 显示正在进行的事物,例如:后台运行的程序,如音乐播放进度、下载进度等

其中,前两点可以归结为与用户交互,第三点是实时的任务提醒,同时第三点也会与用户交互。

Notification 的基本操作

Notification 的基本操作主要有创建、更新、取消这三种。一个 Notification 的必要属性有三项,如果不设置则在运行时会抛出异常:
1. 小图标,通过 setSmallIcon() 方法设置
2. 标题,通过 setContentTitle() 方法设置
3. 内容,通过 setContentText() 方法设置

除了以上三项,其它均为可选项。虽然如此,但还是应该给 Notification 设置一个 Action ,这样就可以直接跳转到 App 的某个 Activity 、启动一个 Service 或者发送一个 Broadcast。否则,Notification 仅仅只能起到通知的效果,而不能与用户交互。

当系统接收到通知时,可以通过震动、响铃、呼吸灯等多种方式进行提醒.

关于 setSmallIcon() 与 setLargeIcon()。在 NotificationCompat.Builder 中有设置通知的大小图标的两个方法。这两个方法有什么区别呢?当 setSmallIcon() 与 setLargeIcon() 同时存在时, smallIcon 显示在通知的右下角, largeIcon 显示在左侧;当只设置 setSmallIcon() 时, smallIcon 显示在左侧。

代码:

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    public static final String NOTIFICATION_TAG = "littlejie";

    private int updataIndex = 0;
    private int clearIndex = 0;

    private Button ClickMe1;
    private Button ClickMe2;
    private Button ClickMe3;
    private Button ClickMe4;
    private Button ClickMe5;
    private Button ClickMe6;
    private Button ClickMe7;
    private Button ClickMe8;
    private Button ClickMe9;
    private Button ClickMe10;
    private Button ClickMe11;

    //获取 NotificationManager 实例
    private NotificationManager mNotificationManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
        //NotificationManager 实例不能创建在onCreate之前
        mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
    }

    private void initView() {
        ClickMe1 = (Button) findViewById(R.id.ClickMe1);
        ClickMe1.setOnClickListener(this);
        ClickMe2 = (Button) findViewById(R.id.ClickMe2);
        ClickMe2.setOnClickListener(this);
        ClickMe3 = (Button) findViewById(R.id.ClickMe3);
        ClickMe3.setOnClickListener(this);
        ClickMe4 = (Button) findViewById(R.id.ClickMe4);
        ClickMe4.setOnClickListener(this);
        ClickMe5 = (Button) findViewById(R.id.ClickMe5);
        ClickMe5.setOnClickListener(this);
        ClickMe6 = (Button) findViewById(R.id.ClickMe6);
        ClickMe6.setOnClickListener(this);
        ClickMe7 = (Button) findViewById(R.id.ClickMe7);
        ClickMe7.setOnClickListener(this);
        ClickMe8 = (Button) findViewById(R.id.ClickMe8);
        ClickMe8.setOnClickListener(this);
        ClickMe9 = (Button) findViewById(R.id.ClickMe9);
        ClickMe9.setOnClickListener(this);
        ClickMe10 = (Button) findViewById(R.id.ClickMe10);
        ClickMe10.setOnClickListener(this);
        ClickMe11 = (Button) findViewById(R.id.ClickMe11);
        ClickMe11.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.ClickMe1:
                ShowNotification();
                break;
            case R.id.ClickMe2:
                ShowLargeIconNotification();
                break;
            case R.id.ClickMe3:
                ShowNotificationWithTag();
                break;
            case R.id.ClickMe4:
                ShowIntentNotification();
                break;
            case R.id.ClickMe5:
                ShowUpdata1Notification();
                break;
            case R.id.ClickMe6:
                ShowTenNotifications();
                break;
            case R.id.ClickMe7:
                ShowFlagNoClearNotification();
                break;
            case R.id.ClickMe8:
                ShowFlagAutoCancelNotification();
                break;
            case R.id.ClickMe9:
                ShowFlagOngoingEventNotification();
                break;

            /**
             * 取消 Notification
             * 取消通知有如下 5 种方式:
             * 点击通知栏的清除按钮,会清除所有可清除的通知
             *      设置了 setAutoCancel() 或 FLAG_AUTO_CANCEL 的通知,点击该通知时会清除它
             *      通过 NotificationManager 调用 cancel(int id) 方法清除指定 ID 的通知
             *      通过 NotificationManager 调用 cancel(String tag, int id) 方法清除指定 TAG 和 ID 的通知
             *      通过 NotificationManager 调用 cancelAll() 方法清除所有该应用之前发送的通知
             *
             * 如果你是通过 NotificationManager.notify(String tag, int id, Notification notify) 方法创建的通知,
             * 那么只能通过 NotificationManager.cancel(String tag, int id) 方法才能清除对应的通知,
             * 调用NotificationManager.cancel(int id) 无效。
             * */
            case R.id.ClickMe10:
                clearIndex += 1;
                if (clearIndex == 5) {
                    clearIndex = 10;
                }
                if (clearIndex == 20) {
                    clearIndex = 1;
                }
                mNotificationManager.cancel(clearIndex);
                break;
            case R.id.ClickMe11:

                mNotificationManager.cancel(NOTIFICATION_TAG, 3);
                break;
        }
    }

    /**
     * 最简单的Notification
     * Notification 的创建主要涉及到 Notification.Builder,Notification,NotificationManager.
     * Notification.Builer : 使用建造者模式构建 Notification 对象。
     * Notification : 通知对应类,保存通知相关的数据。NotificationManager 向系统发送通知时会用到。
     * NotificationManager : NotificationManager 是通知管理类,它是一个系统服务。调用 NotificationManager 的 notify() 方法可以向系统发送通知。
     */
    private void ShowNotification() {
/*
        创建一个Notification主要有一下三个步骤
        1.获取 NotificationManager 实例
        2.实例化 NotificationCompat.Builder 并设置相关属性
        3.通过 builder.build() 方法生成 Notification 对象,并发送通知
*/

        //实例化NotificationCompat.Builde并设置相关属性
        NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
                .setSmallIcon(R.drawable.box)
                .setContentTitle("Title is a test")
                .setContentText("Text is a test");
        //通过builder.build()方法生成Notification对象,并发送通知,第一个参数:id=1
        mNotificationManager.notify(1, builder.build());
    }

    /**
     * 设置大图标
     */
    private void ShowLargeIconNotification() {

        Resources res = MainActivity.this.getResources();
        NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
                .setSmallIcon(R.drawable.book_open)
                //设置大图标
                .setLargeIcon(BitmapFactory.decodeResource(res, R.drawable.bank))
                .setContentTitle("Title is a LargeIcon test")
                .setContentText("Text is a LargeIcon test");
        mNotificationManager.notify(2, builder.build());
    }

    /**
     * 使用notify(String tag, int id, Notification notification)方法发送通知
     * 移除对应通知需使用 cancel(String tag, int id)
     */
    private void ShowNotificationWithTag() {
        NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
                .setSmallIcon(R.mipmap.ic_launcher)
                .setContentTitle("Send Notification With Tag")
                .setContentText("Hi,My id is 1,tag is " + NOTIFICATION_TAG);
        mNotificationManager.notify(NOTIFICATION_TAG, 3, builder.build());
    }

    /**
     * 给 Notification 设置 Action,让Notification可以跳转,点击可清除
     */
    private void ShowIntentNotification() {

        //获取PendingIntent
        Intent mainIntent = new Intent(this, MainActivity.class);

        //四个参数分别是:context,requestCode,intent,flag
/*
        PendingIntent 是一种特殊的 Intent ,字面意思可以解释为延迟的 Intent ,用于在某个事件结束后执行特定的 Action 。
        从上面带 Action 的通知也能验证这一点,当用户点击通知时,才会执行。
        PendingIntent 是 Android 系统管理并持有的用于描述和获取原始数据的对象的标志(引用)。
        也就是说,即便创建该PendingIntent对象的进程被杀死了,这个PendingItent对象在其他进程中还是可用的。
        PendingIntent 主要可以通过以下三种方式获取:
            //获取一个用于启动 Activity 的 PendingIntent 对象
            public static PendingIntent getActivity(Context context, int requestCode, Intent intent, int flags);

            //获取一个用于启动 Service 的 PendingIntent 对象
            public static PendingIntent getService(Context context, int requestCode, Intent intent, int flags);

            //获取一个用于向 BroadcastReceiver 广播的 PendingIntent 对象
            public static PendingIntent getBroadcast(Context context, int requestCode, Intent intent, int flags)

        PendingIntent 的第四个参数flag的种类:

            FLAG_CANCEL_CURRENT:如果当前系统中已经存在一个相同的 PendingIntent 对象,
            那么就将先将已有的 PendingIntent 取消,然后重新生成一个 PendingIntent 对象。

            FLAG_NO_CREATE:如果当前系统中不存在相同的 PendingIntent 对象,系统将不会创建该 PendingIntent 对象
            而是直接返回 null 。

            FLAG_ONE_SHOT:该 PendingIntent 只作用一次。

            FLAG_UPDATE_CURRENT:如果系统中已存在该 PendingIntent 对象,那么系统将保留该 PendingIntent 对象,
            但是会使用新的 Intent 来更新之前 PendingIntent 中的 Intent 对象数据,例如更新 Intent 中的 Extras 。

 */
        PendingIntent mainPendingIntent = PendingIntent.getActivity(this, 0, mainIntent, PendingIntent.FLAG_UPDATE_CURRENT);

        Resources res = MainActivity.this.getResources();
        NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
                .setSmallIcon(R.drawable.battery)
                //设置大图标
                .setLargeIcon(BitmapFactory.decodeResource(res, R.drawable.button_add))
                .setContentTitle("Title is a can Intent test")
                .setContentText("Text is a can Intent test")
                //点击通知后自动清除
                .setAutoCancel(true)
                //设置跳转
                .setContentIntent(mainPendingIntent);
        mNotificationManager.notify(4, builder.build());
    }

    /**
     * 更新 Notification
     * 更新通知很简单,只需要再次发送相同 ID 的通知即可,如果之前的通知还未被取消,则会直接更新该通知相关的属性;
     * 如果之前的通知已经被取消,则会重新创建一个新通知。
     */
    private void ShowUpdata1Notification() {

        updataIndex += 1;

        NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
                .setSmallIcon(R.drawable.box)
                .setContentTitle("Title Have Updata : " + updataIndex)
                .setContentText("Text Have Updata : " + updataIndex);
        //更新的时候,这里要传相应的ID
        mNotificationManager.notify(1, builder.build());
    }

    /**
     * 循环发送十个通知
     */
    private void ShowTenNotifications() {
        for (int i = 10; i < 20; i++) {
            NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
                    .setSmallIcon(R.mipmap.ic_launcher)
                    .setContentTitle("Send Notification Batch")
                    .setContentText("Hi,My id is " + i);
            mNotificationManager.notify(i, builder.build());
        }
    }

    /**
     * 设置FLAG_NO_CLEAR
     * 该 flag 表示该通知不能被状态栏的清除按钮给清除掉,也不能被手动清除,但能通过 cancel() 方法清除
     * Notification.flags属性可以通过 |= 运算叠加效果
     */
    private void ShowFlagNoClearNotification() {
        NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

        NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
                .setSmallIcon(R.mipmap.ic_launcher)
                .setContentTitle("Send Notification Use FLAG_NO_CLEAR")
                .setContentText("Hi,My id is 1,i can't be clear.");
        Notification notification = builder.build();
        //设置 Notification 的 flags = FLAG_NO_CLEAR
        //FLAG_NO_CLEAR 表示该通知不能被状态栏的清除按钮给清除掉,也不能被手动清除,但能通过 cancel() 方法清除
        //flags 可以通过 |= 运算叠加效果
        notification.flags |= Notification.FLAG_NO_CLEAR;
        mNotificationManager.notify(5, notification);
    }

    /**
     * 设置FLAG_AUTO_CANCEL
     * 该 flag 表示用户单击通知后自动消失
     */
    private void ShowFlagAutoCancelNotification() {
        NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

        //设置一个Intent,不然点击通知不会自动消失
        Intent resultIntent = new Intent(this, MainActivity.class);
        PendingIntent resultPendingIntent = PendingIntent.getActivity(this, 0, resultIntent, PendingIntent.FLAG_UPDATE_CURRENT);
        NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
                .setSmallIcon(R.mipmap.ic_launcher)
                .setContentTitle("Send Notification Use FLAG_AUTO_CLEAR")
                .setContentText("Hi,My id is 1,i can be clear.")
                .setContentIntent(resultPendingIntent);
        Notification notification = builder.build();
        //设置 Notification 的 flags = FLAG_NO_CLEAR
        //FLAG_AUTO_CANCEL 表示该通知能被状态栏的清除按钮给清除掉
        //等价于 builder.setAutoCancel(true);
        notification.flags |= Notification.FLAG_AUTO_CANCEL;
        mNotificationManager.notify(6, notification);
    }

    /**
     * 设置FLAG_ONGOING_EVENT
     * 该 flag 表示发起正在运行事件(活动中)
     */
    private void ShowFlagOngoingEventNotification() {

        NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
                .setSmallIcon(R.mipmap.ic_launcher)
                .setContentTitle("Send Notification Use FLAG_ONGOING_EVENT")
                .setContentText("Hi,My id is 1,i can't be clear.");
        Notification notification = builder.build();
        //设置 Notification 的 flags = FLAG_NO_CLEAR
        //FLAG_ONGOING_EVENT 表示该通知通知放置在正在运行,不能被手动清除,但能通过 cancel() 方法清除
        //等价于 builder.setOngoing(true);
        notification.flags |= Notification.FLAG_ONGOING_EVENT;
        mNotificationManager.notify(7, notification);
    }
}


带进度条的Notification

    private void ShowProgressBarNotification() {

        count++;

        NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
                .setSmallIcon(R.mipmap.ic_launcher)
                .setContentTitle("带进度条的")
                .setContentText("神奇吧.")
                .setProgress(100, count, false);
        mNotification = builder.build();

        mNotificationManager.notify(8, mNotification);
    }

    Runnable run = new Runnable() {
        @Override
        public void run() {
            Log.e("11111", "run");
            ShowProgressBarNotification();
            if (count < 100) {
                handler.postDelayed(run, 200);
            }
        }
    };
需要在上面添加:

private Notification mNotification;
private int count = 0;
private Handler handler = new Handler();
在点击的时候:

ShowProgressBarNotification();
handler.post(run);

设置 Notification 的通知效果

前面讲了 Notification 的创建、更新和取消,以及给 Notification 设置 Action 等基本操作。那么,我怎么给 Notification 设置诸如震动、铃声、呼吸灯等效果呢?别急,接下来马上就会告诉你怎么给 Notification 添加效果。

Notification 有震动、响铃、呼吸灯三种响铃效果,可以通过 setDefaults(int defualts) 方法来设置。 Default 属性有以下四种,一旦设置了 Default 效果,自定义的效果就会失效

设置系统默认提醒效果,一旦设置默认提醒效果,则自定义的提醒效果会全部失效。具体可看源码
添加默认震动效果,需要申请震动权限
<uses-permission android:name="android.permission.VIBRATE" />
Notification . DEFAULT_VIBRATE
 
添加系统默认声音效果,设置此值后,调用setSound()设置自定义声音无效
Notification . DEFAULT_SOUND
 
添加默认呼吸灯效果,使用时须与 Notification.FLAG_SHOW_LIGHTS 结合使用,否则无效
Notification . DEFAULT_LIGHTS
 
添加上述三种默认提醒效果
Notification . DEFAULT_ALL

除了以上几种设置 Notification 默认通知效果,还可以通过以下几种 FLAG 设置通知效果。

//提醒效果常用 Flag
//三色灯提醒,在使用三色灯提醒时候必须加该标志符
Notification . FLAG_SHOW_LIGHTS
 
//发起正在运行事件(活动中)
Notification . FLAG_ONGOING_EVENT
 
//让声音、振动无限循环,直到用户响应 (取消或者打开)
Notification . FLAG_INSISTENT
 
//发起Notification后,铃声和震动均只执行一次
Notification . FLAG_ONLY_ALERT_ONCE
 
//用户单击通知后自动消失
Notification . FLAG_AUTO_CANCEL
 
//只有调用NotificationManager.cancel()时才会清除
Notification . FLAG_NO_CLEAR
 
//表示正在运行的服务
Notification . FLAG_FOREGROUND_SERVICE

三种特效:

    /**
     * 铃声效果的通知
     * 补充:使用系统自带的铃声效果:Uri.withAppendedPath(Audio.Media.INTERNAL_CONTENT_URI, "6");
     */
    private void showRingNotifyWith() {
        NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
                .setSmallIcon(R.mipmap.ic_launcher)
                .setContentTitle("我是伴有铃声效果的通知")
                .setContentText("美妙么?安静听~")
                //调用系统默认响铃,设置此属性后setSound()会无效
                .setDefaults(Notification.DEFAULT_SOUND);
        //调用系统多媒体裤内的铃声
        //.setSound(Uri.withAppendedPath(MediaStore.Audio.Media.INTERNAL_CONTENT_URI,"2"));
        //调用自己提供的铃声,位于 /res/values/raw 目录下
        //.setSound(Uri.parse("android.resource://com.littlejie.notification/" + R.raw.sound));
        //另一种设置铃声的方法
        //Notification notify = builder.build();
        //调用系统默认铃声
        //notify.defaults = Notification.DEFAULT_SOUND;
        //调用自己提供的铃声
        //notify.sound = Uri.parse("android.resource://com.littlejie.notification/"+R.raw.sound);
        //调用系统自带的铃声
        //notify.sound = Uri.withAppendedPath(MediaStore.Audio.Media.INTERNAL_CONTENT_URI,"2");
        //mManager.notify(2,notify);
        Notification notify = builder.build();
        //无限循环
        //notify.flags |= Notification.FLAG_INSISTENT;
        mNotificationManager.notify(9, notify);
    }

    /**
     * 展示有震动效果的通知,需要在AndroidManifest.xml中申请震动权限
     * <uses-permission android:name="android.permission.VIBRATE" />
     * 补充:测试震动的时候,手机的模式一定要调成铃声+震动模式,否则你是感受不到震动的
     */
    private void showNotifyWithVibrate() {
        //震动也有两种设置方法,与设置铃声一样,在此不再赘述
        long[] vibrate = new long[]{0, 500, 1000, 1500};
        NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
                .setSmallIcon(R.mipmap.ic_launcher)
                .setContentTitle("我是伴有震动效果的通知")
                .setContentText("颤抖吧,凡人~")
                //使用系统默认的震动参数,会与自定义的冲突
                //.setDefaults(Notification.DEFAULT_VIBRATE)
                //自定义震动效果
                .setVibrate(vibrate);
        //另一种设置震动的方法
        //Notification notify = builder.build();
        //调用系统默认震动
        //notify.defaults = Notification.DEFAULT_VIBRATE;
        //调用自己设置的震动
        //notify.vibrate = vibrate;
        //mNotificationManager.notify(9,notify);
        mNotificationManager.notify(9, builder.build());
    }

    /**
     * 通知无限循环,直到用户取消或者打开通知栏(其实触摸就可以了),效果与FLAG_ONLY_ALERT_ONCE相反
     * 注:这里没有给Notification设置PendingIntent,也就是说该通知无法响应,所以只能手动取消
     */
    private void showInsistentNotify() {
        NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
                .setSmallIcon(R.mipmap.ic_launcher)
                .setContentTitle("我是一个死循环,除非你取消或者响应")
                .setContentText("啦啦啦~")
                .setDefaults(Notification.DEFAULT_ALL);
        Notification notify = builder.build();
        notify.flags |= Notification.FLAG_INSISTENT;
        mNotificationManager.notify(6, notify);
    }


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值