Android通知Notification详解

来源:互联网 发布:java数组拼接成字符串 编辑:程序博客网 时间:2024/06/03 01:56

    • Notification的使用大体步骤
    • Notification简介
    • PendingIntent简介
    • 使用RemoteViews自定义Notification
    • 更新与移除通知
    • 设定提示响应
    • 附录

Notification的使用大体步骤:

1、 获取状态通知栏管理
2、 实例化通知栏构造器
3、 设置NotificationCompat.Builder
4、 设置PendingIntent
5、 显示

因为Android的快速发展,而Android的版本也快速的升级导致了一些兼容性的问题。对于Notification而言,Android3.0是一个分水岭,在其之前构建Notification推荐使用NotificationCompate.Builder,是一个Android向下版本的兼容包,而在Android3.0之后,一般推荐使用Notification.Builder构建。本博客主要介绍的是Android4.x的开发,所以在这里使用Notification.Builder进行讲解演示。

虽然通知中提供了各种属性的设置,但是一个通知对象,有几个属性是必须要设置的,其他的属性均是可选的,必须设置的属性如下:
1)、小图标,使用setSamllIcon()方法设置。
2)、标题,使用setContentTitle()方法设置。
3)、文本内容,使用setContentText()方法设置。

Notification简介

Notification有两种视觉风格,一种是标准视图(Normal View)、一种是大视图(Big view)。标准视图在Android中各版本是通用的,但是对于大视图而言,仅支持Android4.1+的版本。
Notification.flags属性参数:(是否可以设置多个):
从官方文档了解到,一个标准视图显示的大小保持在64dp高。如下图所示:
这里写图片描述
1、 通知标题
2、 大图标
3、 通知内容
4、 通知消息
5、 小图标
6、 通知时间,一般为系统时间,也可以使用setWhen()设置。

而对于大视图(Big View)而言,它的细节区域只能显示256dp高度的内容,并且只对Android4.1+之后的设备才支持,它比标准视图不一样的地方,均需要使用setStyle()方法设定,它大致的效果如下:
这里写图片描述
Android为我们提供了三个实现类,用于显示不同的场景。分别是:
Notification.BigPictureStyle, 在细节部分显示一个256dp高度的位图。
Notification.BigTextStyle,在细节部分显示一个大的文本块。
Notification.InboxStyle,在细节部分显示一段行文本

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 notification = builder.build();
notification.flags = Notification.FLAG_ONLY_ALERT_ONCE;

PendingIntent简介

对于一个通知而言,它显示的消息是有限的,一般仅用于提示一些概要信息。但是一般简短的消息,并不能表达需要告诉用户的全部内容,所以需要绑定一个意图,当用户点击通知的时候,调用一个意图展示出一个Activity用来显示详细的内容。而Notification中,并不使用常规的Intent去传递一个意图,而是使用PendingIntent。
先来说说Intent和PendingIntent的区别,PendingIntent可以看做是对Intent的包装,通过名称可以看出PendingIntent用于处理即将发生的意图,而Intent用来用来处理马上发生的意图。而对于通知来说,它是一系统级的全局通知,并不确定这个意图被执行的时间。当在应用外部执行PendingIntent时,因为它保存了触发应用的Context,使得外部应用可以如在当前应用中一样,执行PendingIntent里的Intent,就算执行的时候响应通知的应用已经被销毁了,也可以通过存在PendingIntent里的Context照常执行它,并且还可以处理Intent说带来的额外信息。
PendingInteng.getBroadcast(contex, requestCode, intent, flags)
PendingInteng.getService(contex, requestCode, intent, flags)
PendingInteng.getActivity(contex, requestCode, intent, flags)
PendingInteng.getActivities(contex, requestCode, intent, flags)
其中flags属性参数:
FLAG_ONE_SHOT 表示返回的PendingIntent仅能执行一次,执行完后自动消失
FLAG_NO_CREATE 表示如果描述的PendingIntent不存在,并不创建相应的PendingIntent,而是返回NULL
FLAG_CANCEL_CURRENT 表示相应的PendingIntent已经存在,则取消前者,然后创建新的PendingIntent
FLAG_UPDATE_CURRENT 表示更新的PendingIntent,如果构建的PendingIntent已经存在,则替换它,常用。

使用RemoteViews自定义Notification

需要使用RemoteViews.RemoteViews描述了一个视图层次的结构,可以显示在另一个进程。RemoteViews提供了多个构造函数,一般使用RemoteViews(String packageName,int layoutId)。第一个参数为包的名称,第二个为layout资源的Id。当获取到RemoteViews对象之后,可以使用它的一系列setXxx()方法通过控件的Id设置控件的属性。最后使用NotificationCompat.Builder.setContent(RemoteViews)方法设置它到一个Notification中。
remoteViews.setOnClickPendingIntent(viewId, pendingIntent);可以进入不同的Activity。如:
remoteViews.setOnClickPendingIntent(R.id.titleTV, PendingIntent.getActivity(context, 0,
new Intent(context, ScrollingActivity.class), PendingIntent.FLAG_UPDATE_CURRENT));

更新与移除通知

在使用NotificationManager.notify()发送通知的时候,需要传递一个标识符,用于唯一标识这个通知。对于有些场景,并不是无限的添加新的通知,有时候需要更新原有通知的信息,这个时候可以重写构建Notification,而使用与之前通知相同标识符来发送通知,这个时候旧的通知就被被新的通知所取代,起到更新通知的效果。
对于一个通知,当展示在状态栏之后,但是使用过后,如何取消呢?Android为我们提供两种方式移除通知,一种是Notification自己维护,使用setAutoCancel()方法设置是否维护,传递一个boolean类型的数据。另外一种方式使用NotificationManager通知管理器对象来维护,它通过notify()发送通知的时候,指定的通知标识Id来操作通知,可以使用cancel(int)来移除一个指定的通知,也可以使用cancelAll()移除所有的通知。
使用NotificationManager移除指定通知示例:

NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);mNotificationManager.cancel(0);

设定提示响应

对于有些通知,需要调用一些设备的资源,使用户能更快的发现有新通知,一般可设定的响应有:铃声、闪光灯、震动。对于这三个属性,NotificationCompat.Builder提供了三个方法设定:
setSound(Uri sound):设定一个铃声,用于在通知的时候响应。传递一个Uri的参数,格式为“file:///mnt/sdcard/Xxx.mp3”。
setLights(int argb, int onMs, int offMs):设定前置LED灯的闪烁速率,持续毫秒数,停顿毫秒数。
setVibrate(long[] pattern):设定震动的模式,以一个long数组保存毫秒级间隔的震动。
大多数时候,我们并不需要设定一个特定的响应效果,只需要遵照用户设备上系统通知的效果即可,那么可以使用setDefaults(int)方法设定默认响应参数,在Notification中,对它的参数使用常量定义了,我们只需使用即可:
DEFAULT_ALL:铃声、闪光、震动均系统默认。
DEFAULT_SOUND:系统默认铃声。
DEFAULT_VIBRATE:系统默认震动。
DEFAULT_LIGHTS:系统默认闪光。
设置震动,需要权限:android.permission.VIBRATE
设置闪光灯,需要权限:android.permission.FLASHLIGHT

附录

下面是我封装的一个通知工具类:

package com.test.testandroid;import android.app.Notification;import android.app.NotificationManager;import android.app.PendingIntent;import android.content.Context;import android.content.Intent;import android.graphics.BitmapFactory;import android.widget.RemoteViews;/** * Created by Administrator on 2016-6-19. * notification builder android */public class NotificationUtil {    private Context context;    private NotificationManager notificationManager;    public NotificationUtil(Context context) {        this.context = context;        notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);    }    /**     * 普通的Notification     */    public void postNotification() {        Notification.Builder builder = new Notification.Builder(context);        Intent intent = new Intent(context, MainActivity.class);  //需要跳转指定的页面        PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);        builder.setContentIntent(pendingIntent);        builder.setSmallIcon(R.mipmap.ic_launcher);// 设置图标        builder.setContentTitle("标题");// 设置通知的标题        builder.setContentText("内容");// 设置通知的内容        builder.setWhen(System.currentTimeMillis());// 设置通知来到的时间        builder.setAutoCancel(true); //自己维护通知的消失        builder.setTicker("new message");// 第一次提示消失的时候显示在通知栏上的        builder.setOngoing(true);        builder.setNumber(20);        Notification notification = builder.build();        notification.flags = Notification.FLAG_NO_CLEAR;  //只有全部清除时,Notification才会清除        notificationManager.notify(0,notification);    }    /**     * 使用下载的Notification,在4.0以后才能使用<p></p>     * Notification.Builder类中提供一个setProgress(int max,int progress,boolean indeterminate)方法用于设置进度条,     * max用于设定进度的最大数,progress用于设定当前的进度,indeterminate用于设定是否是一个确定进度的进度条。     * 通过indeterminate的设置,可以实现两种不同样式的进度条,一种是有进度刻度的(true),一种是循环流动的(false)。     */    public void postDownloadNotification() {        final Notification.Builder builder = new Notification.Builder(context);        builder.setSmallIcon(R.mipmap.ic_launcher)                .setTicker("showProgressBar").setContentInfo("contentInfo")                .setOngoing(true).setContentTitle("ContentTitle")                .setContentText("ContentText");        // 模拟下载过程        new Thread(new Runnable() {            @Override            public void run() {                int progress ;                for (progress = 0; progress < 100; progress += 5) {                    // 将setProgress的第三个参数设为true即可显示为无明确进度的进度条样式                    builder.setProgress(100, progress, false);                    notificationManager.notify(0, builder.build());                    try {                        Thread.sleep(1 * 1000);                    } catch (InterruptedException e) {                        System.out.println("sleep failure");                    }                }                builder.setContentTitle("Download complete")                        .setProgress(0, 0, false).setOngoing(false);                notificationManager.notify(0, builder.build());            }        }).start();    }    /**     * 大视图通知在4.1以后才能使用,BigTextStyle<p></p>     * ****************************************************<p></p>     * Helper class for generating large-format notifications that include a lot of text.     *     * Here's how you'd set the <code>BigTextStyle</code> on a notification:     * <pre class="prettyprint">     * Notification notif = new Notification.Builder(mContext)     *     .setContentTitle(&quot;New mail from &quot; + sender.toString())     *     .setContentText(subject)     *     .setSmallIcon(R.drawable.new_mail)     *     .setLargeIcon(aBitmap)     *     .setStyle(new Notification.BigTextStyle()     *         .bigText(aVeryLongString))     *     .build();     * </pre>     *     * @see Notification#bigContentView     */    public void postBigTextNotification() {        Notification.BigTextStyle textStyle = new Notification.BigTextStyle();        textStyle.setBigContentTitle("大标题")                // 标题                .setSummaryText("SummaryText")                .bigText("Helper class for generating large-format notifications" +                        " that include a lot of text;  !!!!!!!!!!!" +                        "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");        Notification.Builder builder2 = new Notification.Builder(                context);        builder2.setSmallIcon(R.mipmap.ic_launcher);// 小图标        // 大图标        builder2.setLargeIcon(BitmapFactory.decodeResource(                context.getResources(), R.mipmap.ic_launcher));  //R.mipmap.close        builder2.setTicker("showBigView_Text")                .setContentInfo("contentInfo");        builder2.setStyle(textStyle);        builder2.setAutoCancel(true);        notificationManager.notify(0, builder2.build());    }    /**     * 大布局通知在4.1以后才能使用,大布局图片     */    public void postBigPictureNotification() {        Notification.BigPictureStyle bigPictureStyle = new Notification.BigPictureStyle();        bigPictureStyle.bigPicture(BitmapFactory.decodeResource(context.getResources(),                R.mipmap.ic_launcher));  //R.drawable.back        Notification.Builder builder = new Notification.Builder(                context);        builder.setSmallIcon(R.mipmap.ic_launcher);// 小图标        // 大图标        builder.setLargeIcon(BitmapFactory.decodeResource(                context.getResources(), R.drawable.ic_stop));        builder.setTicker("showBigView_Picture")                .setContentInfo("contentInfo");        builder.setStyle(bigPictureStyle);        builder.setAutoCancel(true);        notificationManager.notify(0, builder.build());    }    /**     * 大布局通知在4.1以后才能使用,InboxStyle     */    public void postInboxNotification() {        Notification.InboxStyle inboxStyle = new Notification.InboxStyle();        inboxStyle.setBigContentTitle("InboxStyle");        inboxStyle.setSummaryText("Test");        for(int i = 0 ; i < 10; i++){            inboxStyle.addLine("new:" + i);        }        Notification.Builder builder5 = new Notification.Builder(                context);        builder5.setSmallIcon(R.mipmap.ic_launcher);// 小图标        // 大图标        builder5.setLargeIcon(BitmapFactory.decodeResource(                context.getResources(), R.drawable.ic_stop));        builder5.setTicker("showBigView_InboxStyle")                .setContentInfo("contentInfo");        builder5.setStyle(inboxStyle);        builder5.setAutoCancel(true);        notificationManager.notify(0, builder5.build());    }    /**     * 自定义通知<p></p>     *     * 不设置notification.contentIntent = pendingIntent;则报如下异常:     * android.app.RemoteServiceException:     * Bad notification posted from package com.test.testandroid: Couldn't expand RemoteViews for: StatusBarNotification(     * pkg=com.test.testandroid user=UserHandle{0} id=0 tag=null score=0 key=0|com.test.testandroid|0|null|10168|0: Notification     * (pri=0 contentView=com.test.testandroid/0x7f040038 vibrate=null sound=null defaults=0x0 flags=0x10 color=0xff00aeff vis=PRIVATE))     */    public void postCustomNotification() {        RemoteViews contentViews = new RemoteViews(context.getPackageName(),                R.layout.mynotification);        contentViews.setImageViewResource(R.id.imageNotifi,R.mipmap.ic_launcher);        contentViews.setTextViewText(R.id.titleTV,"自定义通知标题");        contentViews.setTextViewText(R.id.textTV,"自定义通知内容");        Intent intent = new Intent(context, MainActivity.class);        PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);        contentViews.setOnClickPendingIntent(R.id.titleTV, pendingIntent);        contentViews.setOnClickPendingIntent(R.id.textTV, PendingIntent.getActivity(context, 0,                new Intent(context, ScrollingActivity.class), PendingIntent.FLAG_UPDATE_CURRENT);        Notification.Builder builder = new Notification.Builder(context);        builder.setSmallIcon(R.mipmap.ic_launcher);        builder.setContentTitle("custom notification");        builder.setContentText("custom test");        builder.setTicker("custom ticker");        builder.setAutoCancel(true);        builder.setContent(contentViews);        notificationManager.notify(0,builder.build());    }    public void cancelById() {        notificationManager.cancel(0);  //对应NotificationManager.notify(id,notification);第一个参数    }    public void cancelAllNotification() {        notificationManager.cancelAll();    }}

使用方法:

NotificationUtil notiUtil = new NotificationUtil(this);//        notiUtil .postNotification();//        notiUtil .postDownloadNotification();//        notiUtil .postBigTextNotification();//        notiUtil .postBigPictureNotification();//        notiUtil .postCustomNotification();        notiUtil .postInboxNotification();

其中自定义的postCustomNotification()运行结果如下图:

布局怎么都不能居中,后来使用了如下的方法:

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="wrap_content"    android:layout_height="match_parent"    android:layout_gravity="center"    android:gravity="center_vertical">    <RelativeLayout        android:layout_width="wrap_content"        android:layout_height="36dp"        android:gravity="center"        android:layout_gravity="center"        android:background="@drawable/bg">        <ImageView            android:id="@+id/imageNotifi"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_centerVertical="true"            android:gravity="center_vertical" />            。。。。。

不知是否还有更好的办法。

参考:
(1)Android-通知之Notification;
(2)Android通知栏Notification整合;

1 0