Android Notification 详解

xiexiang 7年前
   <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>