第十九章 Android中的通知Notification

作者: 忆念成风 | 来源:发表于2017-09-26 17:34 被阅读239次

    通知(Notification)这个功能对于我们来说非常的常见。打开手机的时候,各种软件的推送消息蜂拥而至,然后我们的通知栏被挤得满满的。你看到的消息提示框就是通知。

    1. Notification 状态栏通知的作用

    从JellyBean 以来,通知系统做了一次被引入Android 以来最重大的结构性和功能性的变动。

    • 通知可以包含操作,用户可以在通知抽屉中直接做出回应
    • 通知在大小和布局方面更加灵活,可以展开显示更多的信息
    • 通知有了优先级高低的排列方式,而不仅仅是时间的排列

    1.1 通知状态栏的作用

    1.显示接收短消息以及即时信息等(短信 ,QQ,微信等)
    2.显示客户端的推送消息 (广告,推荐消息等)
    3.显示正在进行的事务 (播放器的显示,版本更新等)

    2. Notification的基本用法

    通知的基本用法还是很灵活的,可以在活动中创建,也可以在广播接收器中创建,还可以在服务中创建。一般在广播和服务中用的比较多,因为只有在程序进入后台的时候,我们才需要使用通知,活动中使用的比较少。

    2.1 通知的基本布局

    通知的基本布局包括:

    • 发送通知的应用图标或者发送人的头像
    • 通知标题和消息
    • 时间戳
    • 当主图标显示发送人头像时,在副图标位置显示应用图标
    通知的基本布局

    2.2 通知的扩展布局

    通知的扩展布局显示消息的前面几行或者图片的预览,后面的信息折叠起来,这样用户就可以看到更多的信息。用户可以通过 pinch-zoom 或者双手指滑动来打开扩展布局。Android 为单条消息提供了两种扩展布局 (文字和图像) 供你开发应用时使用。

    通知的扩展布局

    从 Jelly Bean 开始,Android 支持在通知底部显示附加操作。通过这些操作,用户可以对通知直接执行常见的任务,而不用打开应用。这样可以加快操作,配合上滑出消失操作,使用户的通知抽屉体验更加顺滑。
    可以放入通知中的操作有以下特点:

    • 对于该通知重要、常用和典型的操作
    • 时间紧迫的
    • 不会与相邻的操作重复的

    不要放置:

    • 模糊的
    • 和点击通知得到的效果一样的操作,例如阅读或者打开

    2.3 通知的优先级

    从 Jelly Bean 开始,Android 为通知增加了优先级标志。这样你可以使重要的通知相对于其他通知,总是显示在第一个。请通过以下的表格仔细选择通知的优先级

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

    2.4 创建通知的步骤

    1. 创建一个通知管理类NotificationManager,通过调用 getSystemService()的方法获得。getSystemService方法接收一个字符串参数用于确定获取系统的哪个服务,传入Context.NOTIFICATION_SERVICE
    NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);  
    
    1. 使用Builder构造器创建Notification对象。这里使用 support-v4库中提供的NotificationCompat
    NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(context);  
    或者这样写:
    Notification notification = NotificationCompat.Builder(context).builder();  
    
    1. 对Builder进行配置(写法和dialog差不多)
        mBuilder.setContentTitle("测试标题")//设置通知栏标题  
        .setContentText("测试内容") //设置通知栏显示内容
        .setContentIntent(getDefalutIntent(Notification.FLAG_AUTO_CANCEL)) //设置通知栏点击意图  
    //  .setNumber(number) //设置通知集合的数量  
        .setTicker("测试通知来啦") //通知首次出现在通知栏,带上升动画效果的  
        .setWhen(System.currentTimeMillis())//通知产生的时间,会在通知信息里显示,一般是系统获取到的时间  
        .setPriority(Notification.PRIORITY_DEFAULT) //设置该通知优先级  
    //  .setAutoCancel(true)//设置这个标志当用户单击面板就可以让通知将自动取消    
        .setOngoing(false)//ture,设置他为一个正在进行的通知。他们通常是用来表示一个后台任务,用户积极参与(如播放音乐)或以某种方式正在等待,因此占用设备(如一个文件下载,同步操作,主动网络连接)  
        .setDefaults(Notification.DEFAULT_VIBRATE)//向通知添加声音、闪灯和振动效果的最简单、最一致的方式是使用当前的用户默认设置,使用defaults属性,可以组合  
        //Notification.DEFAULT_ALL  Notification.DEFAULT_SOUND 添加声音 // requires VIBRATE permission  
        .setSmallIcon(R.drawable.ic_launcher);//设置通知小ICON  
     
    
    1. 设置通知栏PendingIntent(点击动作事件等都包含在这里)。PendingIntent 从名字上看和Intent 很像,它们都指明一个意图,都可以开启活动,开启服务和发送广播。但是Intent 倾向于立即执行某个动作,而PendingIntent 倾向于某个时机执行动作。

    2. 最后一步,发送通知请求

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

    notify()方法有两个参数,一个参数是id,要保证每个通知所指定的id都是不同的,第二个参数则是Notification对象。
    显示一个通知:

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

    2.5 通知的方法

    1. 设置提醒的标志符号flags,添加声音,设置闪灯,震动等效果。
    两种设置方法:
    1). 实例化之后,在设置flags

    Notification notification = mBuilder.build();  
    notification.flags = Notification.FLAG_AUTO_CANCEL;  
    

    2). 通过setContentIntent(PendingIntent intent)方法中的意图设置对应的flags

    public PendingIntent getDefalutIntent(int flags){  
        PendingIntent pendingIntent= PendingIntent.getActivity(this, 1, new Intent(), flags);  
        return pendingIntent;  
    } 
    

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

    2. setDefaults(int defaults) (NotificationCompat.Builder中的方法,用于提示)
    功能:向通知添加声音、闪灯和振动效果的最简单、使用默认(defaults)属性,可以组合多个属性(和方法1中提示效果一样的)
    对应属性:
    Notification.DEFAULT_VIBRATE //添加默认震动提醒 需要 VIBRATE permission
    Notification.DEFAULT_SOUND // 添加默认声音提醒
    Notification.DEFAULT_LIGHTS// 添加默认三色灯提醒
    Notification.DEFAULT_ALL// 添加默认以上3种全部提醒
    3. setVibrate(long[] pattern)
    功能:设置震动方式

    .setVibrate(new long[] {0,300,500,700});  
    

    实现效果:延迟0ms,然后振动300ms,在延迟500ms,接着在振动700ms。
    写法二:

    mBuilder.build().vibrate = new long[] {0,300,500,700};  
    

    4. setLights(intledARGB ,intledOnMS ,intledOffMS )
    功能:android支持三色灯提醒,这个方法就是设置不同场景下的不同颜色的灯。
    描述:其中ledARGB 表示灯光颜色、 ledOnMS 亮持续时间、ledOffMS 暗的时间。
    注意:1)只有在设置了标志符Flags为Notification.FLAG_SHOW_LIGHTS的时候,才支持三色灯提醒。
    2)这边的颜色跟设备有关,不是所有的颜色都可以,要看具体设备。

    .setLights(0xff0000ff, 300, 0)  
    

    同理,实现同样的效果:

    Notification notify = mBuilder.build();  
    notify.flags = Notification.FLAG_SHOW_LIGHTS;  
    notify.ledARGB = 0xff0000ff;  
    notify.ledOnMS = 300;  
    notify.ledOffMS = 300;  
    

    如果希望使用默认的三色灯提醒,设置了方法(2)中默认为DEFAULT_LIGHTS即可。
    5. setSound(Uri sound)
    功能:设置默认或则自定义的铃声,来提醒。

    //获取默认铃声  
    .setDefaults(Notification.DEFAULT_SOUND)  
    //获取自定义铃声  
    .setSound(Uri.fromFile(new File("file:///sdcard/xx/xx.mp3")))  
    //获取Android多媒体库内的铃声  
    .setSound(Uri.withAppendedPath(Audio.Media.INTERNAL_CONTENT_URI, "5"))  
    

    6. setPriority(int pri)
    对应属性(作用看上图就可知道):
    Notification.PRIORITY_DEFAULT
    Notification.PRIORITY_HIGH
    Notification.PRIORITY_LOW
    Notification.PRIORITY_MAX
    Notification.PRIORITY_MIN
    7. setOngoing(boolean ongoing)
    功能:设置为ture,表示它为一个正在进行的通知。他们通常是用来表示一个后台任务,用户积极参与(如播放音乐)或以某种方式正在等待,因此占用设备(如一个文件下载,同步操作,主动网络连接)
    8. setProgress(int max, int progress,boolean indeterminate)
    属性:max:进度条最大数值 、progress:当前进度、indeterminate:表示进度是否不确定,true为不确定,如下第3幅图所示 ,false为确定下第1幅图所示
    功能:设置带进度条的通知,可以在下载中使用

    带进度条的通知

    9. 设置点击取消
    点击通知消息之后,上面的图标还是没有消掉
    1)在buider配置的方法中添加

    .setAutoCancel(true)
    

    2 ) 在创建管理通知类NotificationManager的时候,调用cancel()方法

    NotificationManager manager= (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);  
    manager.cancel(1);
    

    这里的这个1 ,是在创建通知的时候给每条通知指定的notifyId 。因此如果你想取消哪条id就传哪个值。

    2.6 PendingIntent 的用法

    PendingIntent的用法很简单。它主要提供了几个静态方法用于获取PendingIntent的实现,可以根据需求使用getActivity()方法,getBroadcast()方法,getService()方法,这几个方法里面的参数都是一样的。第一个参数是Context ,第二个参数一般用不到传个0就好,第三个参数是一个Intent的对象,通过它来构建PendingIntent的“意图”,第四个用于确定PendingIntent的行为.
    2.6.1 PendingIntent的位标识符:
    FLAG_ONE_SHOT 表示返回的PendingIntent仅能执行一次,执行完后自动取消
    FLAG_NO_CREATE 表示如果描述的PendingIntent不存在,并不创建相应的PendingIntent,而是返回NULL
    FLAG_CANCEL_CURRENT 表示相应的PendingIntent已经存在,则取消前者,然后创建新的PendingIntent,这个有利于数据保持为最新的,可以用于即时通信的通信场景
    FLAG_UPDATE_CURRENT 表示更新的PendingIntent

    2.6.2 在各种情况下情况下它还会根据各种情况触发效果:
    contentIntent:在通知窗口区域,Notification被单击时的响应事件由该intent触发;
    deleteIntent:当用户点击全部清除按钮时,响应该清除事件的Intent;
    fullScreenIntent:响应紧急状态的全屏事件(例如来电事件),也就是说通知来的时候,跳过在通知区域点击通知这一步,直接执行fullScreenIntent代表的事件。
    1). 点击通知栏跳转到指定的XXActivity中

    Intent intent = new Intent(context,XXX.class);  
    PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);  
    mBuilder.setContentIntent(pendingIntent)
    

    2). 在执行了清空全部的通知操作时候,可以设置以下方法来相应这个事件

    Intent deleteIntent = new Intent();  
    deleteIntent.setClass(context, XXXReceiver.class);  
    deleteIntent.setAction(DELETE_ACTION);  
    notification.deleteIntent = PendingIntent.getBroadcast(context, 0, deleteIntent, 0);  
    

    3). 在响应紧急事件(如来电)时候,可以设置以下方法来相应这个事件

    setFullScreenIntent(PendingIntent intent, boolean highPriority)
    

    3. 创建自定义的通知栏

    Notification的自定义布局是RemoteViews,和其他RemoteViews一样,在自定义视图布局文件中,仅支持FrameLayout、LinearLayout、RelativeLayout三种布局控件和AnalogClock、Chronometer、Button、ImageButton、ImageView、ProgressBar、TextView、ViewFlipper、ListView、GridView、StackView和AdapterViewFlipper这些显示控件,不支持这些类的子类或Android提供的其他控件。否则会引起ClassNotFoundException异常

    3.1 创建自定义的步骤

    1). 创建自定义的视图
    2). 获取远程视图对象
    3). 设置PendingIntent(来响应各种事件)
    4). 发起Notification

    1.创建自定义的视图

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="100dp">
    <ImageView
        android:id="@+id/iv_not_head_image"
        android:layout_width="0dp"
        android:layout_weight="1"
        android:layout_height="match_parent"
        android:src="@mipmap/youname"
        android:scaleType="centerCrop"
        />
        <LinearLayout
            android:layout_width="0dp"
            android:layout_weight="3"
            android:layout_height="match_parent"
            android:orientation="vertical"
            android:background="#0093fe">
            <TextView
                android:id="@+id/tv_not_head_title"
                android:layout_width="match_parent"
                android:layout_height="0dp"
                android:layout_weight="1"
                android:text="歌名"
                android:gravity="center"
                android:textColor="#fff"
                android:textSize="18sp"/>
            <TextView
                android:id="@+id/tv_not_head_content"
                android:layout_width="match_parent"
                android:layout_height="0dp"
                android:layout_weight="1"
                android:text="歌手"
                android:gravity="center"
                android:textColor="#fff"
                android:textSize="15sp"/>
    
        </LinearLayout>
    <LinearLayout
        android:id="@+id/ll_custom_button"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:orientation="horizontal"
        android:layout_weight="2"
        android:background="#334455">
        <ImageView
            android:id="@+id/iv_not_up"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="match_parent"
            android:src="@drawable/btn_prev"
            android:scaleType="centerInside"
           />
        <ImageView
            android:id="@+id/iv_not_play"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="match_parent"
            android:src="@drawable/btn_play"
            android:scaleType="centerInside"/>
        <ImageView
            android:id="@+id/iv_not_next"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="match_parent"
            android:src="@drawable/btn_next"
            android:scaleType="centerInside"/>
    
    </LinearLayout>
    
    
    </LinearLayout>
    

    2.获取视图对象

     RemoteViews mRemoteViews= new RemoteViews(getPackageName(),R.layout.notification_my_style);
            mRemoteViews.setImageViewResource(R.id.iv_not_head_image,R.mipmap.youname);
    
            mRemoteViews.setTextViewText(R.id.tv_not_head_title,"应思量");
            mRemoteViews.setTextViewText(R.id.tv_not_head_content,"五色石");
            if( Build.VERSION.SDK_INT <= 9){
                mRemoteViews.setViewVisibility(R.id.ll_custom_button, View.GONE);
            }else{
                mRemoteViews.setViewVisibility(R.id.ll_custom_button, View.VISIBLE);
                if(isPlay){
                    mRemoteViews.setImageViewResource(R.id.iv_not_play,R.drawable.btn_pause);
                }else{
                    mRemoteViews.setImageViewResource(R.id.iv_not_play,R.drawable.btn_play);
                }
            }
    

    3.设置响应事件 ,这里设置广播来处理点击事件。

     //点击事件处理
            Intent buttonIntent=new Intent(ACTION_BUTTON);
             //头像点击
            buttonIntent.putExtra(INTENT_BUTTONID_TAG,BUTTON_PREV_ID);
            //这里加了广播,所及INTENT的必须用getBroadcast方法
            PendingIntent intent_head_image = PendingIntent.getBroadcast(this, 1, buttonIntent, PendingIntent.FLAG_UPDATE_CURRENT);
            mRemoteViews.setOnClickPendingIntent(R.id.iv_not_head_image, intent_head_image);
            //歌名
            buttonIntent.putExtra(INTENT_BUTTONID_TAG,TEXTVIEW_TITLE_ID);
            PendingIntent intent_title = PendingIntent.getBroadcast(this,2,buttonIntent,PendingIntent.FLAG_UPDATE_CURRENT);
            mRemoteViews.setOnClickPendingIntent(R.id.tv_not_head_title,intent_title);
            //歌手
            buttonIntent.putExtra(INTENT_BUTTONID_TAG,TEXTVIEW_CONTENT_ID);
            PendingIntent intent_content = PendingIntent.getBroadcast(this,3,buttonIntent,PendingIntent.FLAG_UPDATE_CURRENT);
            mRemoteViews.setOnClickPendingIntent(R.id.tv_not_head_content,intent_content);
    
            //上一曲
            buttonIntent.putExtra(INTENT_BUTTONID_TAG,IMAGEVIEW_LEFT_ID);
            PendingIntent intent_left = PendingIntent.getBroadcast(this,4,buttonIntent,PendingIntent.FLAG_UPDATE_CURRENT);
            mRemoteViews.setOnClickPendingIntent(R.id.iv_not_up,intent_left);
            //播放、暂停按钮
            buttonIntent.putExtra(INTENT_BUTTONID_TAG,IMAGEVIEW_CONTENT_ID);
            PendingIntent intent_play= PendingIntent.getBroadcast(this,5,buttonIntent,PendingIntent.FLAG_UPDATE_CURRENT);
            mRemoteViews.setOnClickPendingIntent(R.id.iv_not_play, intent_play);
            //下一曲
            buttonIntent.putExtra(INTENT_BUTTONID_TAG,IMAGEVIEW_RIGHT_ID);
            PendingIntent intent_right= PendingIntent.getBroadcast(this,6,buttonIntent,PendingIntent.FLAG_UPDATE_CURRENT);
            mRemoteViews.setOnClickPendingIntent(R.id.iv_not_next, intent_right);
    

    4.发起Notification

     NotificationManager manager= (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
       NotificationCompat.Builder  builder= new NotificationCompat.Builder(this);
            builder.setContent(mRemoteViews);
            builder.setWhen(System.currentTimeMillis());
            builder.setPriority(NotificationCompat.PRIORITY_DEFAULT);
            builder.setOngoing(true);
            builder.setSmallIcon(R.drawable.a2);
            builder.setAutoCancel(true);
            manager.notify(1, builder.build());
    
    自定义通知

    github地址:https://github.com/wangxin3119/MyNotificationDemo

    相关文章

      网友评论

      本文标题:第十九章 Android中的通知Notification

      本文链接:https://www.haomeiwen.com/subject/mlajextx.html