安卓通知与NotificationCompat.Builder

来源:互联网 发布:java写邮件qq邮箱 编辑:程序博客网 时间:2024/05/11 21:44

安卓更新挺快,以至于之前学的关于通知的使用方法都过时了

现在重新再写个文章记录一下


创建通知

Android 3.0 (API level 11)之前,使用new Notification()方式创建通知:

NotificationManager mNotifyMgr =       (NotificationManager) getSystemService(NOTIFICATION_SERVICE);PendingIntent contentIntent = PendingIntent.getActivity(      this, 0, new Intent(this, ResultActivity.class), 0);Notification notification = new Notification(icon, tickerText, when);notification.setLatestEventInfo(this, title, content, contentIntent);mNotifyMgr.notify(NOTIFICATIONS_ID, notification);

Android 3.0 (API level 11)及更高版本,改用Notification.Builder()来创建通知:

NotificationManager mNotifyMgr =       (NotificationManager) getSystemService(NOTIFICATION_SERVICE);PendingIntent contentIntent = PendingIntent.getActivity(      this, 0, new Intent(this, ResultActivity.class), 0);Notification notification = new Notification.Builder(this)            .setSmallIcon(R.drawable.notification_icon)            .setContentTitle("My notification")            .setContentText("Hello World!")            .setContentIntent(contentIntent)            .build();// getNotification()mNotifyMgr.notify(NOTIFICATIONS_ID, notification);

这里需要注意: "build()" 是Androdi 4.1(API level 16)加入的,用以替代
"getNotification()"。API level 16开始弃用"getNotification()"


通知基本用法

一个通知必须包含以下三项属性:

  • 小图标,对应 setSmallIcon()
  • 通知标题,对应 setContentTitle()
  • 详细信息,对应 setContentText()

其他属性均为可选项,更多属性方法请参考NotificationCompat.Builder。

尽管其他都是可选的,但一般都会为通知添加至少一个动作(Action),这个动作可以是跳转到Activity、启动一个Service或发送一个Broadcas等。 通过以下方式为通知添加动作:

  • 使用PendingIntent
  • 通过大视图通知的 Action Button //仅支持Android 4.1 (API level 16)及更高版本,稍后会介绍

创建通知

1、实例化一个NotificationCompat.Builder对象

NotificationCompat.Builder builder = new NotificationCompat.Builder(this)                .setSmallIcon(R.mipmap.ic_launcher)                .setContentTitle("我是头部")                .setContentText("内容内容内容内容内容内容内容内容");


NotificationCompat.Builder会自动设置默认值:

  • priority: PRIORITY_DEFAULT           --------优先级,有五个优先级别,范围从 PRIORITY_MIN (-2) 到 PRIORITY_MAX (2);默认为 PRIORITY_DEFAULT (0)。
  • when: System.currentTimeMillis()--------通知创建的时间,有的手机会显示,有的不会
  • audio stream: STREAM_DEFAULT--------当声音响起时,所用的音频流的类型
2、定义并设置一个通知动作(Action)


PendingIntent类封装了一个Intent和一个动作,当调用该类的send方法的时候,将会执行该动作。由于PendingIntent类是一个待处理的意图,这个动作通常是在将来的某个时刻要调用的一个操作,很可能是系统要调用的。
PendingIntent类中的动作是Context类中的几个方法之一,例如startActivity,startService,sendBroadcast
使用PendingIntent来启动一个Activity

Intent resultIntent = new Intent(this, ResultActivity.class);PendingIntent resultPendingIntent = PendingIntent.getActivity(            this, 0, resultIntent, PendingIntent.FLAG_UPDATE_CURRENT);mBuilder.setContentIntent(resultPendingIntent);

PendingIntent pi = PendingIntent.getActivity(Context context, int requestCode,Intent intent, int flags);

静态方法getActivity是返回PendingIntent类的一个实例的几个方法之一,其他的方法还有getActivities、getService和getBroadcast
这些方法决定了最终PendingIntent所能执行的动作,可以用来启动Activity,启动Service,发送广播等


3、NotificationManager

要发布一个通知,可以使用NotificationManager,这是Android系统中的内建服务之一,是一个已有的系统服务,可以通过如下代码来获取它
NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);


然后,在该NotificationManager上调用notify方法来发布一个通知,需要传入唯一的ID和Notification对象
mNotificationManager.notify(int id, notification);

注意这里要求传入的是notification,但是我们创建的是NotificationCompat.Builder,这时候你需要生成Notification对象
Notificatioin notification = Builder.build();

通知ID用于标识该通知,在想要取消特定Notification的时候,就需要使用到它

mNotificationManager.cancel(int id);


此外,除非发生以下情况之一,否则通知会一直可见:

  • 用户单独或通过使用“全部清除”清除了该通知(如果通知可以清除)
  • 用户点击通知,且在创建通知时调用了 setAutoCancel(true)
  • 针对特定的通知 ID 调用了 cancel(int id)
  • 调用了 cancelAll() 方法,该方法将删除之前发出的所有通知

更新通知

更新通知很简单,只需再次发送相同ID的通知即可,如果之前的通知依然存在则会更新通知属性,如果之前通知不存在则重新创建。

取消通知

取消通知有如下4种方式:

  • 点击通知栏的清除按钮,会清除所有可清除的通知
  • 设置了 setAutoCancel() 或 FLAG_AUTO_CANCEL的通知,点击该通知时会清除它
  • 通过 NotificationManager 调用 cancel() 方法清除指定ID的通知
  • 通过 NotificationManager 调用 cancelAll() 方法清除所有该应用之前发送的通知


创建简单通知


private int id = 1;    public void notification(View view) {        Drawable drawable = ContextCompat.getDrawable(this, R.drawable.ic_submit);        Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap();        NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this);        //设置小图标        mBuilder.setSmallIcon(R.mipmap.ic_launcher);        //设置大图标        mBuilder.setLargeIcon(bitmap);        //设置标题        mBuilder.setContentTitle("这是标题");        //设置通知正文        mBuilder.setContentText("这是正文,当前ID是:" + id);        //设置摘要        mBuilder.setSubText("这是摘要");        //设置是否点击消息后自动clean        mBuilder.setAutoCancel(true);        //在通知的右边设置大的文本。        mBuilder.setContentInfo("右侧文本");        //与setContentInfo类似,但如果设置了setContentInfo则无效果        //用于当显示了多个相同ID的Notification时,显示消息总数        mBuilder.setNumber(2);        //通知在状态栏显示时的文本        mBuilder.setTicker("在状态栏上显示的文本");        //设置优先级        mBuilder.setPriority(NotificationCompat.PRIORITY_MAX);        //自定义消息时间,以毫秒为单位,当前设置为比系统时间少一小时        mBuilder.setWhen(System.currentTimeMillis() - 3600000);        //设置为一个正在进行的通知,此时用户无法清除通知        mBuilder.setOngoing(true);        //设置消息的提醒方式,震动提醒:DEFAULT_VIBRATE     声音提醒:NotificationCompat.DEFAULT_SOUND        //三色灯提醒NotificationCompat.DEFAULT_LIGHTS     以上三种方式一起:DEFAULT_ALL        mBuilder.setDefaults(NotificationCompat.DEFAULT_SOUND);        //设置震动方式,延迟零秒,震动一秒,延迟一秒、震动一秒        mBuilder.setVibrate(new long[]{0, 1000, 1000, 1000});        Intent intent = new Intent(this, ShadowTextViewActivity.class);        PendingIntent pIntent = PendingIntent.getActivity(this, 0, intent, 0);        mBuilder.setContentIntent(pIntent);        NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);        mNotificationManager.notify(id++, mBuilder.build());    }    public void cleanNotification(View view) {        NotificationManager mNotificationManager =                (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);        mNotificationManager.cancelAll();        mNotificationManager.cancel(1);    }


效果如下

通知类型

大视图通知

通知有两种视图:普通视图和大视图。
普通视图:



大视图:


默认情况下为普通视图,可通过NotificationCompat.Builder.setStyle()设置大视图。

注: 大视图(Big Views)由Android 4.1(API level 16)开始引入,且仅支持Android 4.1及更高版本。


构建大视图通知
Drawable drawable = ContextCompat.getDrawable(this, R.drawable.ic_submit);        Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap();        NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this);        //设置小图标        mBuilder.setSmallIcon(R.mipmap.ic_launcher);        //设置大图标        mBuilder.setLargeIcon(bitmap);        //设置标题        mBuilder.setContentTitle("这是标题");        //设置通知正文        mBuilder.setContentText("这是正文,当前ID是:" + id);        //设置优先级        mBuilder.setPriority(NotificationCompat.PRIORITY_MAX);        //设置为一个正在进行的通知,此时用户无法清除通知        mBuilder.setOngoing(true);        mBuilder.setDefaults(NotificationCompat.DEFAULT_SOUND);        Intent intent = new Intent(this, ShadowTextViewActivity.class);        PendingIntent pIntent = PendingIntent.getActivity(this, 0, intent, 0);        mBuilder.setContentIntent(pIntent);        // 该方法在Android 4.1之前会被忽略        mBuilder.setStyle(new NotificationCompat.BigTextStyle()                .bigText("这里可以显示一大串文字,你可以试试\n这里可以显示一大串文字,你可以试试\n这里可以显示一大串文字,你可以试试\n这里可以显示一大串文字,你可以试试"))                //添加Action Button                .addAction (R.mipmap.ic_launcher,                        "取消", pIntent)                .addAction (R.mipmap.ic_launcher,                        "确定", pIntent);        NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);        mNotificationManager.notify(id, mBuilder.build());



效果图如下


不仅可以放一大段文字,还能放一张大图哦!
Drawable drawable = ContextCompat.getDrawable(this, R.drawable.ic_loading_fail);        Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap();        NotificationCompat.Builder builder = new NotificationCompat.Builder(this);        builder.setContentTitle("这是标题");        builder.setContentText("这是正文");        builder.setSmallIcon(R.drawable.ic_circulation);        builder.setLargeIcon(BitmapFactory.decodeResource(getResources(),R.drawable.ic_submit));        builder.setDefaults(NotificationCompat.DEFAULT_ALL);        builder.setAutoCancel(true);        NotificationCompat.BigPictureStyle style = new NotificationCompat.BigPictureStyle();        style.setBigContentTitle("展开后的标题");        style.setSummaryText("这是摘要");        style.bigPicture(bitmap);        builder.setStyle(style);        Intent intent = new Intent(this, ShadowTextViewActivity.class);        PendingIntent pIntent = PendingIntent.getActivity(this, 0, intent, 0);        builder.setContentIntent(pIntent);        NotificationManager mNotificationManager =                (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);        mNotificationManager.notify(id, builder.build());

效果图如下


进度条通知

  • 明确进度的进度条
    使用setProgress(max, progress, false)来更新进度。
    max: 最大进度值
    progress: 当前进度
    false: 是否是不明确的进度条

    模拟下载过程,示例如下:

int id = 1;...mNotifyManager = (NotificationManager)     getSystemService(Context.NOTIFICATION_SERVICE);mBuilder = new NotificationCompat.Builder(this);mBuilder.setContentTitle("Picture Download")    .setContentText("Download in progress")    .setSmallIcon(R.drawable.ic_notification);// Start a lengthy operation in a background threadnew Thread(    new Runnable() {        @Override        public void run() {            int incr;            for (incr = 0; incr <= 100; incr+=5) {                mBuilder.setProgress(100, incr, false);                mNotifyManager.notify(id, mBuilder.build());                try {                    // Sleep for 5 seconds                    Thread.sleep(5*1000);                } catch (InterruptedException e) {                    Log.d(TAG, "sleep failure");                }            }            mBuilder.setContentText("Download complete")//下载完成                               .setProgress(0,0,false);    //移除进度条            mNotifyManager.notify(id, mBuilder.build());        }    }).start();



  • 上图,分别为下载过程中进度条通知 和 下载完成移除进度条后的通知。

  • 不确定进度的进度条
    使用setProgress(0, 0, true)来表示进度不明确的进度条

    mBuilder.setProgress(0, 0, true); mNotifyManager.notify(id, mBuilder.build());



  • 启动 Activity 时保留导航


    从通知中启动 Activity 时,您必须保留用户的预期导航体验。 点击“返回”应该使用户将应用的正常工作流回退到主屏幕,而点击“最新动态”则应将Activity 显示为单独的任务。 要保留导航体验,您应该在全新任务中启动 Activity。如何设置 PendingIntent 以获得全新任务取决于正在启动的Activity 的性质。一般有两种情况:

    常规 Activity
    您要启动的 Activity 是应用的正常工作流的一部分。在这种情况下,请设置 PendingIntent 以启动全新任务并为 PendingIntent提供返回栈,这将重现应用的正常“返回”行为。

    Gmail 应用中的通知演示了这一点。点击一封电子邮件消息的通知时,您将看到消息具体内容。 触摸返回将使您从 Gmail 回退到主屏幕,就好像您是从主屏幕(而不是通知)进入 Gmail 一样。

    无论您触摸通知时处于哪个应用,都会发生这种情况。 例如,如果您在 Gmail 中撰写消息时点击了一封电子邮件的通知,则会立即转到该电子邮件。 触摸“返回”会依次转到收件箱和主屏幕,而不是转到您在撰写的邮件。

    特殊 Activity
    仅当从通知中启动时,用户才会看到此 Activity。 从某种意义上说,Activity 是通过提供很难显示在通知本身中的信息来扩展通知。对于这种情况,请将 PendingIntent 设置为在全新任务中启动。但是,由于启动的 Activity 不是应用 Activity 流程的一部分,因此无需创建返回栈。点击“返回”仍会将用户带到主屏幕。

    设置常规 Activity PendingIntent

    要设置可启动直接进入 Activity 的 PendingIntent,请执行以下步骤:

    1. 在清单文件中定义应用的 Activity 层次结构。
      1. 添加对 Android 4.0.3 及更低版本的支持。为此,请通过添加 <meta-data> 元素作为 <activity>的子项来指定正在启动的 Activity 的父项。

        对于此元素,请设置 android:name="android.support.PARENT_ACTIVITY"。 设置 android:value="<parent_activity_name>",其中,<parent_activity_name> 是父 <activity> 元素的 android:name 值。请参阅下面的 XML 示例。

      2. 同样添加对 Android 4.1 及更高版本的支持。为此,请将 android:parentActivityName 属性添加到正在启动的 Activity 的 <activity> 元素中。

      最终的 XML 应如下所示:

      <activity    android:name=".MainActivity"    android:label="@string/app_name" >    <intent-filter>        <action android:name="android.intent.action.MAIN" />        <category android:name="android.intent.category.LAUNCHER" />    </intent-filter></activity><activity    android:name=".ResultActivity"    android:parentActivityName=".MainActivity">    <meta-data        android:name="android.support.PARENT_ACTIVITY"        android:value=".MainActivity"/></activity>
    2. 根据可启动 Activity 的 Intent 创建返回栈:
      1. 创建 Intent 以启动 Activity
      2. 通过调用 TaskStackBuilder.create() 创建堆栈生成器。
      3. 通过调用 addParentStack() 将返回栈添加到堆栈生成器。 对于在清单文件中所定义层次结构内的每个 Activity,返回栈均包含可启动 Activity的 Intent 对象。此方法还会添加一些可在全新任务中启动堆栈的标志。

        注:尽管 addParentStack() 的参数是对已启动 Activity 的引用,但是方法调用不会添加可启动 Activity 的 Intent,而是留待下一步进行处理。

      4. 通过调用 addNextIntent(),添加可从通知中启动 Activity 的 Intent。 将在第一步中创建的 Intent 作为 addNextIntent() 的参数传递。
      5. 如需,请通过调用 TaskStackBuilder.editIntentAt() 向堆栈中的 Intent 对象添加参数。有时,需要确保目标 Activity 在用户使用“返回”导航回它时会显示有意义的数据。
      6. 通过调用 getPendingIntent() 获得此返回栈的 PendingIntent。 然后,您可以使用此 PendingIntent 作为 setContentIntent() 的参数。

    以下代码段演示了该流程:

    ...Intent resultIntent = new Intent(this, ResultActivity.class);TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);// Adds the back stackstackBuilder.addParentStack(ResultActivity.class);// Adds the Intent to the top of the stackstackBuilder.addNextIntent(resultIntent);// Gets a PendingIntent containing the entire back stackPendingIntent resultPendingIntent =        stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);...NotificationCompat.Builder builder = new NotificationCompat.Builder(this);builder.setContentIntent(resultPendingIntent);NotificationManager mNotificationManager =    (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);mNotificationManager.notify(id, builder.build());

    设置特殊 Activity PendingIntent

    下文介绍如何设置特殊 Activity PendingIntent

    特殊 Activity 无需返回栈,因此您不必在清单文件中定义其 Activity 层次结构,也不必调用 addParentStack() 来构建返回栈。取而代之的是,您可使用清单文件设置 Activity 任务选项,并通过调用 getActivity() 创建 PendingIntent

    1. 在清单文件中,将以下属性添加到 Activity 的 <activity> 元素
      android:name="activityclass"
      Activity 的完全限定类名。
      android:taskAffinity=""
      与您在代码中设置的 FLAG_ACTIVITY_NEW_TASK 标志相结合,这可确保此 Activity 不会进入应用的默认任务。任何具有应用默认关联的现有任务均不受影响。
      android:excludeFromRecents="true"
      将新任务从“最新动态”中排除,这样用户就不会在无意中导航回它。

      以下代码段显示了该元素:

      <activity    android:name=".ResultActivity"...    android:launchMode="singleTask"    android:taskAffinity=""    android:excludeFromRecents="true"></activity>...
    2. 构建并发出通知:
      1. 创建可启动 Activity的 Intent
      2. 通过使用 FLAG_ACTIVITY_NEW_TASK 和 FLAG_ACTIVITY_CLEAR_TASK 标志调用 setFlags(),将 Activity 设置为在新的空任务中启动。
      3. 为 Intent 设置所需的任何其他选项。
      4. 通过调用 getActivity() 从 Intent 中创建 PendingIntent。 然后,您可以使用此 PendingIntent 作为 setContentIntent() 的参数。

      以下代码段演示了该流程:

      // Instantiate a Builder object.NotificationCompat.Builder builder = new NotificationCompat.Builder(this);// Creates an Intent for the ActivityIntent notifyIntent =        new Intent(this, ResultActivity.class);// Sets the Activity to start in a new, empty tasknotifyIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK                        | Intent.FLAG_ACTIVITY_CLEAR_TASK);// Creates the PendingIntentPendingIntent notifyPendingIntent =        PendingIntent.getActivity(        this,        0,        notifyIntent,        PendingIntent.FLAG_UPDATE_CURRENT);// Puts the PendingIntent into the notification builderbuilder.setContentIntent(notifyPendingIntent);// Notifications are issued by sending them to the// NotificationManager system service.NotificationManager mNotificationManager =    (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);// Builds an anonymous Notification object from the builder, and// passes it to the NotificationManagermNotificationManager.notify(id, builder.build());

    自定义通知布局


    您可以利用通知框架定义自定义通知布局,由该布局定义通知在 RemoteViews 对象中的外观。 自定义布局通知类似于常规通知,但是它们是基于 XML 布局文件中所定义的 RemoteViews

    自定义通知布局的可用高度取决于通知视图。普通视图布局限制为 64 dp,扩展视图布局限制为 256 dp。

    要定义自定义通知布局,请首先实例化 RemoteViews 对象来扩充 XML 布局文件。然后,调用 setContent(),而不是调用 setContentTitle() 等方法。要在自定义通知中设置内容详细信息,请使用 RemoteViews 中的方法设置视图子项的值:

    1. 在单独的文件中为通知创建 XML 布局。您可以根据需要使用任何文件名,但必须使用扩展名 .xml
    2. 在您的应用中,使用 RemoteViews 方法定义通知的图标和文本。通过调用 setContent() 将此 RemoteViews 对象放入 NotificationCompat.Builder中。避免在 RemoteViews 对象上设置背景 Drawable,因为文本颜色可能使文本变得难以阅读。

    此外,RemoteViews 类中还有一些方法可供您轻松将 Chronometer 或 ProgressBar 添加到通知布局。如需了解有关为通知创建自定义布局的详细信息,请参阅 RemoteViews 参考文档。

    注意:使用自定义通知布局时,要特别注意确保自定义布局适用于不同的设备方向和分辨率。 尽管这条建议适用于所有“视图”布局,但对通知尤为重要,因为抽屉式通知栏中的空间非常有限。 不要让自定义布局过于复杂,同时确保在各种配置中对其进行测试。


    本文参考文章

    全面了解Android Notification

    Android Notification的使用


    https://developer.android.com/guide/topics/ui/notifiers/notifications.html#Updating


    原创粉丝点击