Android之Notification通知详解

(一)、简介:
显示在手机状态栏的通知。Notification所代表的是一种具有全局效果的通知,程序一般通过NotificationManager服务来发送Notification。Android3.0增加了Notification.Builder类,该类可以轻松地创建Notification对象。

Notification,俗称通知,是一种具有全局效果的通知,它展示在屏幕的顶端,首先会表现为一个图标的形式,当用户向下滑动的时候,展示出通知具体的内容。

  【注意:】因为一些Android版本的兼容性问题,对于Notification而言,Android3.0是一个分水岭,如果不考虑向下兼容的问题,构建Notification使用Notification.Builder构建,如果考虑到向下兼容性的问题,一般推荐使用 NotificationCompat.Builder构建( NotificationCompat类在v4包中:android.support.v4.app.NotificationCompat)。


通知一般通过NotificationManager服务来发送一个Notification对象来完成,NotificationManager是一个重要的系统级服务,该对象位于应用程序的框架层中,应用程序可以通过它像系统发送全局的通知。这个时候需要创建一个Notification对象,用于承载通知的内容。但是一般在实际使用过程中,一般不会直接构建Notification对象,而是使用它的一个内部类NotificationCompat.Builder来实例化一个对象(Android3.0之下使用Notification.Builder),并设置通知的各种属性,最后通过NotificationCompat.Builder.build()方法得到一个Notification对象。当获得这个对象之后,可以使用NotificationManager.notify()方法发送通知。

  NotificationManager类是一个通知管理器类,这个对象是由系统维护的服务,是以单例模式获得,所以一般并不直接实例化这个对象。在Activity中,可以使用Activity.getSystemService(String)方法获取NotificationManager对象,Activity.getSystemService(String)方法可以通过Android系统级服务的句柄,返回对应的对象。在这里需要返回NotificationManager,所以直接传递Context.NOTIFICATION_SERVICE即可。

  虽然通知中提供了各种属性的设置,但是一个通知对象,有几个属性是必须要设置的,其他的属性均是可选的,必须设置的属性如下:

  • 小图标,使用setSamllIcon()方法设置。
  • 标题,使用setContentTitle()方法设置。
  • 文本内容,使用setContentText()方法设置。 

(二)、Notification.Builder类中提供的方法:
builder.setAutoCancel();   设置点击通知后,状态栏自动删除通知。
builder.setSmallIcon(R.drawable.alert);   设置通知小图标
builder.setLargeIcon(R.drawable.alert2);   设置通知大图标
builder.setContentTitle("标题");   设置通知标题
builder.setContentText("文本");   设置通知内容
builder.setDefaults(Notification.DEFAULT_SOUND
| Notification.DEFAULT_VIBRATE);   设置通知的音乐、振动、LED等。
builder.setSound();   设置通知的音乐
builder.setTicker();  设置通知在状态栏的提示文本。第一次提示消息的时候显示在通知栏上。
builder.setContentIntent();   设置点击通知后将要启动的程序组件对应的PendingIntent。

(三)、发送Notification的步骤:(四部曲)
1、调用getSystemService(NOTIFICATION_SERVICE)方法获取系统的NotificationManager服务,它是一个重要的系统服务。应用程序可以通过NotificationManager 向系统发送全局通知;
2、构造Notification.Builder对象;
3、设置Notification.Builder对象的各种属性;
4、通过NotificationManager notify()方法发送Notification。

(四)、示例代码:
核心代码如下:
 @Override
    public void onClick(View v) {
        if (v.getId() == R.id.btn1){ //普通的Notification
             //1.通过系统服务获取NotificationManager对象
             NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);

            //2.获取建造者对象,通过建造者对象来设置Notification的属性
            NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
            //前三个必须设置
            builder.setContentTitle("提示:");
            builder.setSmallIcon(R.mipmap.ic_launcher);
            builder.setContentText("ContentText");
            builder.setContentInfo("天气转凉,注意保暖");
            builder.setSubText("SubText");
            //设置大图标,如果大图标和小图标同时存在,则大图标在最左边,小图标在右下方
            builder.setLargeIcon(BitmapFactory.decodeResource(getResources(),android.R.drawable.star_on));
            //收到通知,有三种用户提示方式:声音,震动,呼吸灯
            builder.setDefaults(Notification.DEFAULT_ALL);
            //第一次收到消息时的提示信息
            builder.setTicker("来消息了");

            /**
             * 3.设置跳转
             * 通过PendingIntent.getActivity获得一个PendingIntent对象,
             * PendingIntent对intent进行了封装,在达到某个要求后跳转。
             * 这里不能用intent进行跳转,因为intent必须在页面启动之后才能初始化,实现跳转,
             * 而通知没有页面,或者在某个组件没有初始化之前就执行了
             */
            Intent intent = new Intent(this,Main2Activity.class);
            PendingIntent activity = PendingIntent.getActivity(this, 1, intent, PendingIntent.FLAG_ONE_SHOT);
            builder.setContentIntent(activity);
            //点击通知后进行跳转,会自动取消(这一步不要忘记)
            builder.setAutoCancel(true);

            //4.commit,确认刚才的设置,调用NotificationManager的notify方法后便可生效
            Notification notification = builder.build();
            notificationManager.notify(1,notification);
        }else if(v.getId() == R.id.btn2){ //显示大图的Notification
            NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
            NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
            //这三个基础的设置必须有
            builder.setSmallIcon(android.R.drawable.ic_media_play);
            builder.setContentTitle("优酷");
            builder.setContentText("最新视频");

            //装饰者模式,BigPictureStyle:大图模式
            //BigPictureStyle对象初始化的时候要把builder传进去,在builder的基础上继续做高级的设置
            NotificationCompat.BigPictureStyle bigPictureStyle = new NotificationCompat.BigPictureStyle(builder);
            bigPictureStyle.bigPicture(BitmapFactory.decodeResource(getResources(),android.R.drawable.star_on));
            //bigPictureStyle必须要build
            bigPictureStyle.build();
            notificationManager.notify(2,builder.build());

        }else if(v.getId() == R.id.btn3){ //显示进度的Notification
            NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);

            NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
            builder.setSmallIcon(R.mipmap.ic_launcher);
            builder.setContentText("正在下载");
            builder.setContentTitle("提示");
            int index = 0;
            for (int i = 0; i < 5; i++) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                index += 200;
                //设置进度,第三个参数表示是否模糊,如果为true的话,就不会显示详细进度
                builder.setProgress(1000,index,false);

                Notification build = builder.build();
                notificationManager.notify(3, build);
            }
            //下载完成后,从通知栏移除指定id的通知
            notificationManager.cancel(3);
        }else if(v.getId() == R.id.btn4){ //下载网络图片
            //使用HttpUtils之前需要先导包
            HttpUtils utils = new HttpUtils();
            String url = "http://p3.so.qhmsg.com/t014a6628f309b37a93.jpg"; //图片地址
            String path = Environment.getExternalStorageDirectory().getAbsolutePath()+"/1607.jpg"; //保存路径
            //为什么使用抽象类而不是接口?
            //抽象类可以有抽象方法,也可以有非抽象方法,实例化抽象类时对应他的非抽象方法可以选择性的去实现
            utils.download(url, path, new RequestCallBack<File>() {
                //当前我们要下载,需要知道进度,所以要选择一个非抽象的方法,即onLoading
                //此方法在下载完成之前会一直执行
                @Override
                public void onLoading(long total, long current, boolean isUploading) {
                    super.onLoading(total, current, isUploading);
                    //拿到NotificationManager对象
                    NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);

                    //拿到Builder对象
                    NotificationCompat.Builder builder = new NotificationCompat.Builder(MainActivity.this);

                    //设置Builder的属性
                    builder.setSmallIcon(android.R.drawable.stat_sys_download);
                    builder.setContentTitle("提示");
                    //把下载的进度显示在通知栏上
                    builder.setContentText((current/(float)total)*100 + "%");
                    builder.setProgress((int)total,(int)current,false);

                    Notification build = builder.build();
                    notificationManager.notify(4,build);
                }

                //下载成功后,注意实现用户点击后跳转到查看页面
                @Override
                public void onSuccess(ResponseInfo<File> responseInfo) {
                    NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
                    notificationManager.cancel(4);
                    //下载成功后,提示用户“点击查看”,点击后跳转到另外一个页面
                    NotificationCompat.Builder builder = new NotificationCompat.Builder(MainActivity.this);
                    builder.setSmallIcon(android.R.drawable.stat_sys_download);
                    builder.setContentTitle("提示");
                    builder.setContentText("点击查看");
                    Intent intent = new Intent(MainActivity.this,Main2Activity.class);
                    PendingIntent pendingIntent = PendingIntent.getActivity(MainActivity.this,6,intent,0);
                    builder.setContentIntent(pendingIntent);
                    builder.setAutoCancel(true);

                    Notification build = builder.build();
                    notificationManager.notify(1,build);
                }

                //下载失败,要打印出错误信息
                @Override
                public void onFailure(HttpException error, String msg) {
                    Log.e("error",msg);
                }
            });
        }

(五)、PendingIntent:
1、PendingIntent字面意义:等待的,悬而未决的Intent;Intent一般是用作Activity、Sercvice、BroadcastReceiver之间传递数据,而Pendingintent,一般用在 Notification上,可以理解为延迟执行的intent,PendingIntent是对Intent一个包装;
2、得到一个 PendingIntent 对象,使用方法类的静态方法 getActivity(Context, int, Intent, int);
3、PendingIntent是一种特殊的Intent。主要的区别在于Intent是立刻执行,而 PendingIntent 的执行不是立刻,而是当条件满足后才发送企图,而且PendingIntent 可以取消
4、PendingIntent执行的操作实质上是参数传进来的Intent的操作,使用 PendingIntent 的目的在于它所包含的Intent的操作的执行是需要满足某些条件的。
5、主要的使用的地方和例子:通知Notificatio的发送,短消息SmsManager的发送和警报器AlarmManager的执行等。
总而言之,PendingIntent就是一个可以在满足一定条件下执行的Intent,它相比于Intent的优势在于自己携带有Context对象,这样他就不必依赖于某个activity才可以存在。


(六)、Intent和PendingIntent的区别:掌握,以备面试之需】
  1. Intent是立即使用的,而PendingIntent可以等到事件发生后触发,PendingIntent可以cancel
  2. Intent在程序结束后即终止,而PendingIntent在程序结束后依然有效
  3. PendingIntent自带Context,而Intent需要在某个Context内运行;
  4. Intent在原task中运行,PendingIntent在新的task中运行。
(七)、PendingIntent的几个常量:(getActivity(Context, int, Intent, int)方法中的第四个参数
  1. FLAG_ONE_SHOT : 这个PendingIntent只能使用一次。
  2. FLAG_NO_CREATE : 如果被描述的PendingIntent不存在,那么简单地返回null,而不是创建它。
  3. FLAG_CANCEL_CURRENT : 如果被描述的PendingIntent已经存在,在即将生成一个新的PendingIntent前,当前的一个要被取消。
  4. FLAG_UPDATE_CURRENT :如果被描述的PendingIntent已经存在,那么继续保持它,但它其中的数据会因为新Intent而更新。
【注解】

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

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

FLAG_ONE_SHOT:该 PendingIntent只作用一次。在该PendingIntent对象通过send()方法触发过后,PendingIntent将自动调用 cancel()进行销毁,那么如果你再调用send()方法的话,系统将会返回一个SendIntentException。

FLAG_UPDATE_CURRENT: 如果系统中有一个和你描述的PendingIntent对等的PendingInent,那么系统将使用该PendingIntent对象,但是会使用新的Intent来更新之前PendingIntent中的Intent对象数据,例如更新Intent中的Extras。


(八)实现效果如下:



  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值