Android Notification 详解
xiexiang
8年前
<h2>1. 简单用法</h2> <p>创建通知</p> <p>创建通知至少包含 <strong>小图标、标题、内容</strong> 才能显示</p> <pre> <code class="language-java">NotificationCompat.Builder builder = new NotificationCompat.Builder(this) .setSmallIcon(R.drawable.notification_icon) .setContentTitle("My notification") .setContentText("Hello World!");</code></pre> <p>发送通知</p> <pre> <code class="language-java">NotificationManager manager = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE); manager.notify(notifyId, builder.build());</code></pre> <p>取消通知</p> <pre> <code class="language-java">NotificationManager manager = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE); // 取消notifyId关联的通知 manager.cancel(notifyId); // 取消所有通知 manager.cancelAll();</code></pre> <h2>2. 基本信息</h2> <p>标题/内容/小图标</p> <p>必要信息</p> <pre> <code class="language-java">// 标题 builder.setContentTitle("这是通知标题"); // 内容 builder.setContentText("这是通知内容"); // 小图标 builder.setSmallIcon(R.mipmap.ic_small_icon);</code></pre> <p>大图标</p> <p>大图标,未设置时使用小图标代替</p> <pre> <code class="language-java">// 大图标 Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), R.mipmap.ic_large_icon); builder.setLargeIcon(bitmap);</code></pre> <p>次要内容</p> <p>setContentInfo 在 api 24 被废弃,不再显示,用 setSubText 代替</p> <p>setNumber 在 api 24 被废弃,不再显示</p> <pre> <code class="language-java">// 次要内容 builder.setSubText("这是通知的次要内容"); // 附加文本 builder.setContentInfo("INFO"); // 附加数字,等价于 setContentInfo, 为了显示效果用一个不同的字体尺寸显示数字 builder.setNumber(123);</code></pre> <p>时间</p> <p>setShowWhen 在 api 17 被添加</p> <p>setChronometerCountDown 在 api 24 添加</p> <pre> <code class="language-java">// 设置时间 builder.setWhen(System.currentTimeMillis()) // 设置是否显示时间 builder.setShowWhen(false); // 设置是否显示时钟表示时间(count up) builder.setUsesChronometer(false);); // 设置时钟是否为倒计时(count down) builder.setChronometerCountDown(false);</code></pre> <p>进度条</p> <p>当使用了 setSubText() 后,进度条将不显示</p> <p>api 24 之后,setSubText() 不再影响进度条</p> <pre> <code class="language-java">int max = 100; // 进度最大值 int progress = 50; // 当前进度 int indeterminate = false; // 是否是不明确的进度条 builder.setProgress(max, progress, indeterminate);</code></pre> <p>状态栏摘要(ticker)</p> <p>在 api 21 后不再显示,仅用于辅助服务。</p> <pre> <code class="language-java">builder.setTicker("this is ticker");</code></pre> <h2>3. 标志符(Flags)</h2> <table> <thead> <tr> <th>Flag</th> <th>描述</th> </tr> </thead> <tbody> <tr> <td>Notification.FLAG_SHOW_LIGHTS</td> <td>是否使用呼吸灯提醒</td> </tr> <tr> <td>Notification.FLAG_INSISTENT</td> <td>持续提醒(声音/振动)直到用户响应(点击/取消)</td> </tr> <tr> <td>Notification.FLAG_ONLY_ALERT_ONCE</td> <td>提醒(铃声/震动/滚动通知摘要)只执行一次</td> </tr> <tr> <td>Notification.FLAG_ONGOING_EVENT</td> <td>正在进行中通知</td> </tr> <tr> <td>Notification.FLAG_AUTO_CANCEL</td> <td>用户点击通知后自动取消</td> </tr> <tr> <td>Notification.FLAG_NO_CLEAR</td> <td>用户无法取消</td> </tr> <tr> <td>Notification.FLAG_FOREGROUND_SERVICE</td> <td>表示正在运行的服务</td> </tr> </tbody> </table> <p>设置是否使用呼吸灯提醒(FLAG_SHOW_LIGHTS)</p> <p>通过 builder.setLights 或 builder.setDefaults 设置使用呼吸灯时会自动添加 FLAG_SHOW_LIGHTS</p> <p>设置提醒只执行一次(FLAG_ONLY_ALERT_ONCE)</p> <p>设置提醒只执行一次</p> <pre> <code class="language-java">builder.setOnlyAlertOnce(true);</code></pre> <p>设置自动取消(FLAG_AUTO_CANCEL)</p> <p>需要同时设置了 setContentIntent() 才有效</p> <pre> <code class="language-java">builder.setAutoCancel(true); builder.setContentIntent(pendingIntent);</code></pre> <p>设置通知为进行中(FLAG_ONGOING_EVENT)</p> <p>通常表示一个用户积极参与的后台任务,比如电话,下载,播放音乐等</p> <p>用户不能取消,效果类似 FLAG_NO_CLEAR<br> 用户点击通知且设置了自动取消时会被删除</p> <pre> <code class="language-java">builder.setOngoing(true);</code></pre> <p>设置 FLAG_INSISTENT/FLAG_NO_CLEAR</p> <p>NotificationCompat.Builder 未提供设置方法,只能通过 Notification</p> <pre> <code class="language-java">Notification n = builder.build(); // 持续提醒直到用户响应 n.flags |= Notification.FLAG_INSISTENT; // 用户无法取消 n.flags |= Notification.FLAG_NO_CLEAR; manager.notify(notifyId, n);</code></pre> <h2>4. 优先级</h2> <table> <thead> <tr> <th>优先级</th> <th>描述</th> </tr> </thead> <tbody> <tr> <td>Notification.PRIORITY_MAX</td> <td>重要而紧急的通知,通知用户这个事件是时间上紧迫的或者需要立即处理的。</td> </tr> <tr> <td>Notification.PRIORITY_HIGH</td> <td>高优先级用于重要的通信内容,例如短消息或者聊天,这些都是对用户来说比较有兴趣的</td> </tr> <tr> <td>Notification.PRIORITY_DEFAULT</td> <td>默认优先级用于没有特殊优先级分类的通知</td> </tr> <tr> <td>Notification.PRIORITY_LOW</td> <td>低优先级可以通知用户但又不是很紧急的事件。只显示状态栏图标</td> </tr> <tr> <td>Notification.PRIORITY_MIN</td> <td>用于后台消息 (例如天气或者位置信息)。只有用户下拉通知抽屉才能看到内容</td> </tr> </tbody> </table> <p>设置优先级</p> <pre> <code class="language-java">builder.setPriority(Notification.PRIORITY_HIGH);</code></pre> <h2>5. 提醒通知到达</h2> <p>提供了 <strong>铃声/振动/呼吸灯</strong> 三种提醒方式,可以使用一种或同时使用多种</p> <p>使用默认提醒</p> <table> <thead> <tr> <th>FLAG</th> <th>描述</th> </tr> </thead> <tbody> <tr> <td>Notification.DEFAULT_SOUND</td> <td>添加默认声音提醒</td> </tr> <tr> <td>Notification.DEFAULT_VIBRATE</td> <td>添加默认震动提醒</td> </tr> <tr> <td>Notification.DEFAULT_LIGHTS</td> <td>添加默认呼吸灯提醒</td> </tr> <tr> <td>Notification.DEFAULT_ALL</td> <td>同时添加以上三种默认提醒</td> </tr> </tbody> </table> <pre> <code class="language-java">// 添加默认声音提醒 builder.setDefaults(Notification.DEFAULT_SOUND); // 添加默认呼吸灯提醒,自动添加FLAG_SHOW_LIGHTS builder.setDefaults(Notification.DEFAULT_LIGHTS);</code></pre> <p>添加自定义提醒</p> <pre> <code class="language-java">// 添加自定义声音提醒 builder.setSound(Uri.parse("path/to/sound")); // 添加自定义震动提醒 // 延迟200ms后震动300ms,再延迟400ms后震动500ms long[] pattern = new long[]{200,300,400,500}; builder.setVibrate(pattern); // 添加自定义呼吸灯提醒,自动添加FLAG_SHOW_LIGHTS int argb = 0xffff0000; // led灯光颜色 int onMs = 300; // led亮灯持续时间 int offMs = 100; // led熄灯持续时间 builder.setLights(argb, onMs, offMs);</code></pre> <h2>6. 事件</h2> <p>点击内容事件</p> <pre> <code class="language-java">int flags = PendingIntent.FLAG_UPDATE_CURRENT; Intent intent = new Intent(this, ResultActivity.class); PendingIntent pi = PendingIntent.getActivity(this, 0, intent, flags); builder.setContentIntent(pi);</code></pre> <p>取消通知事件</p> <p>通知被用户取消时发送(清除所有,右滑删除)</p> <p>“自动取消( FLAG_AUTO_CANCEL )”不会产生该事件</p> <pre> <code class="language-java">Intent intent = new Intent(ACTION); intent.putExtra("op", op); PendingIntent pi = PendingIntent.getBroadcast(this, 0, intent, 0); builder.setDeleteIntent(pi);</code></pre> <p>全屏通知事件</p> <p>响应紧急事件(比如来电)</p> <pre> <code class="language-java">Intent intent = new Intent(ACTION); intent.putExtra("op", op); PendingIntent pi = PendingIntent.getBroadcast(this, 0, intent, 0); builder.setFullScreenIntent(pi, true);</code></pre> <h2>7. 浮动通知</h2> <p>Android 5.0(API 21)开始支持浮动通知</p> <p>设备处于 <strong>活动状态(设备未锁定且其屏幕已打开)</strong> 时,可显示浮动通知</p> <p>满足下列条件之一可触发浮动通知:</p> <ul> <li>用户的 Activity 处于全屏模式中(应用使用 fullScreenIntent)</li> <li>通知具有 <strong>较高的优先级</strong> (PRIORITY_MAX 或 PRIORITY_HIGH)并 <strong>使用铃声或振动</strong></li> </ul> <p>注:国内各种ROM可能由于各种原因导致浮动通知不能显示</p> <h2>8. 锁定屏幕通知</h2> <p>Android 5.0(API 21)开始,通知可显示在锁定屏幕上。</p> <p>可使用此功能提供媒体播放控件以及其他常用操作。</p> <p>用户可以通过“设置”选择是否将通知显示在锁定屏幕上。</p> <p>设置可见性</p> <ul> <li>VISIBILITY_PUBLIC 显示通知的完整内容。</li> <li>VISIBILITY_SECRET 不会在锁定屏幕上显示此通知的任何部分。</li> <li>VISIBILITY_PRIVATE 显示通知图标和内容标题等基本信息,但是隐藏通知的完整内容。</li> </ul> <p>设置 VISIBILITY_PRIVATE 后,还可以通过 setPublicVersion() 提供其中隐藏了某些详细信息的替换版本通知内容。</p> <h2>9. 扩展布局</h2> <p>Android 4.1(API 16) 开始支持扩展布局,下拉抽屉中最顶部的一条通知的扩展布局自动展开</p> <p>Android 7.0(API 24) 开始每条通知都可以单独展开</p> <h3>操作按钮</h3> <p>api 19 开始支持添加操作按钮,每个展开的通知可包含最多3个操作按钮</p> <pre> <code class="language-java">// 添加操作按钮 builder.addAction(icon1, title1, pendingIntent1); builder.addAction(icon2, title2, pendingIntent2);</code></pre> <h3>样式</h3> <p>使用 Builder.setStyle() 设置扩展布局样式</p> <p>多行文本通知</p> <pre> <code class="language-java">Notification notif = new Notification.Builder(mContext) .setContentTitle("New mail from " + sender.toString()) .setContentText(subject) .setSmallIcon(R.drawable.new_mail) .setLargeIcon(aBitmap) .setStyle(new Notification.BigTextStyle().bigText(aVeryLongString)) .build();</code></pre> <p>大图通知</p> <pre> <code class="language-java">Notification notif = new Notification.Builder(mContext) .setContentTitle("New photo from " + sender.toString()) .setContentText(subject) .setSmallIcon(R.drawable.new_post) .setLargeIcon(aBitmap) .setStyle(new Notification.BigPictureStyle().bigPicture(aBigBitmap)) .build();</code></pre> <p>收件箱通知</p> <p>最多显示5行消息</p> <pre> <code class="language-java">Notification notif = new Notification.Builder(mContext) .setContentTitle("5 New mails from " + sender.toString()) .setContentText(subject) .setSmallIcon(R.drawable.new_mail) .setLargeIcon(aBitmap) .setStyle(new Notification.InboxStyle() .addLine(str1) .addLine(str2) .setContentTitle("") .setSummaryText("+3 more")) .build();</code></pre> <h2>10. 保留 Activity 返回栈</h2> <h3>常规 Activity</h3> <p>默认情况下,从通知启动一个Activity,按返回键会回到主屏幕。</p> <p>但某些时候有按返回键仍然留在当前应用的需求,这就要用到TaskStackBuilder了。</p> <p>1、在manifest中定义Activity的关系</p> <pre> <code class="language-java"><activity android:name=".ResultActivity" android:parentActivityName=".MainActivity"> </activity></code></pre> <p>2、构建带返回栈的PendingIntent并发送通知</p> <pre> <code class="language-java">// 构建返回栈 TaskStackBuilder tsb = TaskStackBuilder.create(this); tsb.addParentStack(ResultActivity.class); tsb.addNextIntent(new Intent(this, ResultActivity.class)); // 构建包含返回栈的 PendingIntent PendingIntent pi = tsb.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT); // 构建通知 NotificationCompat.Builder builder = new NotificationCompat.Builder(this); ... builder.setContentIntent(pi); // 发送通知 NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); manager.notify(notifyId, builder.build());</code></pre> <h3>特殊Activity</h3> <p>默认情况下,从通知启动的Activity会在近期任务列表里出现。</p> <p>如果不需要在近期任务里显示,则需要做以下操作:</p> <p>1、在manifest中定义Activity</p> <pre> <code class="language-java"><activity android:name=".ResultActivity" android:launchMode="singleTask" android:taskAffinity="" android:excludeFromRecents="true"> </activity></code></pre> <p>2、构建PendingIntent并发送通知</p> <pre> <code class="language-java">// 创建 Intent Intent intent = new Intent(this, ResultActivity.class); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); // 创建 PendingIntent PendingIntent pi = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); // 构建通知 NotificationCompat.Builder builder = new NotificationCompat.Builder(this); ... builder.setContentIntent(pi); // 发送通知 NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); manager.notify(notifyId, builder.build());</code></pre> <h2>Demo</h2> <p><a href="/misc/goto?guid=4959731800439115467" rel="nofollow,noindex">https://github.com/czy1121/NotificationDemo</a></p> <p style="text-align:center"><img src="https://simg.open-open.com/show/bcf434586f9dd74b21f76de7479b27a4.png"></p> <p style="text-align:center">notify</p> <p>api 19 (android 4.4)</p> <p style="text-align:center"><img src="https://simg.open-open.com/show/7650713910b6c7fd1643c3d6cb0050e5.png"></p> <p style="text-align:center">api19_big_text</p> <p style="text-align:center"><img src="https://simg.open-open.com/show/2795c39286907512db6ff0281e2b3618.png"></p> <p style="text-align:center">api19_big_picture</p> <p>api 21 (android 5.0)</p> <p style="text-align:center"><img src="https://simg.open-open.com/show/fdd141ed53103986b20a93acf5dc52d0.png"></p> <p style="text-align:center">api21_big_text</p> <p style="text-align:center"><img src="https://simg.open-open.com/show/dc4dd3c63c269700b91667bfaba65d16.png"></p> <p style="text-align:center">api19_big_picture</p> <p style="text-align:center"><img src="https://simg.open-open.com/show/badb4dad49c876538519337283894229.png"></p> <p style="text-align:center">api21_progress_bar</p> <p style="text-align:center"><img src="https://simg.open-open.com/show/260488ed6f9a234ef26c2087ea2c06a2.png"></p> <p style="text-align:center">api21_heads_up</p> <p>api 24 (android 7.0)</p> <p style="text-align:center"><img src="https://simg.open-open.com/show/8f52c2127e6a3caa56c3d661ff08de5f.png"></p> <p style="text-align:center">api24_basic</p> <p style="text-align:center"><img src="https://simg.open-open.com/show/5163027c2404907d0f3329a66d14e8f7.png"></p> <p style="text-align:center">api24_progress_bar</p> <p style="text-align:center"><img src="https://simg.open-open.com/show/417745b82521e406f829d77071d3e3f7.png"></p> <p style="text-align:center">api24_heads_up</p> <h2>参考</h2> <p><a href="/misc/goto?guid=4959731800531455337" rel="nofollow,noindex">https://developer.android.com/reference/android/app/Notification.Builder.html</a></p> <p><a href="/misc/goto?guid=4959731800616786803" rel="nofollow,noindex">https://developer.android.com/reference/android/support/v4/app/NotificationCompat.Builder.html</a></p> <p><a href="/misc/goto?guid=4959731800699078639" rel="nofollow,noindex">https://developer.android.com/guide/topics/ui/notifiers/notifications.html</a></p> <p>全面了解Android Notification</p> <p><a href="/misc/goto?guid=4959731800780387602" rel="nofollow,noindex">http://www.jianshu.com/p/22e27a639787</a></p> <p> </p> <p>来自:http://www.jianshu.com/p/d2051a785309</p> <p> </p>