全面解析Notification
Jina75J
8年前
<p>Notification在Android中使用的频率可以说是非常高的,本文我将围绕着Notification的各方面进行解析,使大家对Notification有更好的认识。</p> <p><strong>Notification的使用步骤</strong></p> <p><strong>1.获取NotificationManager</strong></p> <pre> <code class="language-java">NotificationManager mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); </code></pre> <p><strong>2.创建NotificationCompat.Builder</strong></p> <pre> <code class="language-java">NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this); </code></pre> <p><strong>3.对Builder设置一些Notification相关属性:</strong></p> <pre> <code class="language-java">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 </code></pre> <p><strong>4.使用Builder创建通知</strong></p> <pre> <code class="language-java">Notification notification = mBuilder.build(); </code></pre> <p><strong>5.使用NotificationManager将通知推送出去</strong></p> <pre> <code class="language-java">int id = 199; LogUtils.d(TAG, "创建通知"); mNotificationManager.notify(id, notification); </code></pre> <p><strong>Notification重要方法解析</strong></p> <p>Notification 的基本操作主要有创建、更新、取消这三种。一个 Notification 的必要属性有三项,如果不设置则在运行时会抛出异常:</p> <ol> <li>小图标,通过 setSmallIcon() 方法设置</li> <li>标题,通过 setContentTitle() 方法设置</li> <li>内容,通过 setContentText() 方法设置</li> </ol> <p>除了以上三项,其它均为可选项。虽然如此,但还是应该给 Notification 设置一个 Action ,这样就可以直接跳转到 App 的某个 Activity 、启动一个 Service 或者发送一个 Broadcast。否则,Notification 仅仅只能起到通知的效果,而不能与用户交互。</p> <p>当系统接收到通知时,可以通过震动、响铃、呼吸灯等多种方式进行提醒。</p> <p><strong>1) setSmallIcon() 与 setLargeIcon()</strong></p> <p>在 NotificationCompat.Builder 中有设置通知的大小图标的两个方法。这两个方法有什么区别呢?当 setSmallIcon() 与 setLargeIcon() 同时存在时, smallIcon 显示在largeIcon的右下角;当只设置 setSmallIcon() 时, smallIcon 显示在左侧。看下图你就明白了。对于部分 ROM ,可能修改过源码,如 MIUI 上通知的大图标和小图标是没有区别的。</p> <p style="text-align:center"><img src="https://simg.open-open.com/show/a194f6b22507749e0ce7a69189bf7cbb.jpg"></p> <p>Google 官方是这么解释 setSmallIcon() 这个方法的:</p> <pre> <code class="language-java">Set the small icon resource, which will be used to represent the notification in the status bar. The platform template for the expanded view will draw this icon in the left, unless a large icon has also been specified, in which case the small icon will be moved to the right-hand side. </code></pre> <p><strong>2) 设置提醒标志符Flags</strong></p> <p>方法解释:提醒标志符,向通知添加声音、闪灯和振动效果等设置达到通知提醒效果,可以组合多个属性</p> <p>a) 创建通知栏之后通过给他添加.flags属性赋值。</p> <pre> <code class="language-java">Notification notification = mBuilder.build(); notification.flags = Notification.FLAG_AUTO_CANCEL; </code></pre> <p>b) 通过setContentIntent(PendingIntent intent)方法中的意图设置对应的flags</p> <pre> <code class="language-java">public PendingIntent getDefalutIntent(int flags){ PendingIntent pendingIntent= PendingIntent.getActivity(this, 1, new Intent(), flags); return pendingIntent; } </code></pre> <p><strong>各标志符介绍</strong></p> <pre> <code class="language-java">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 //表示正在运行的服务 </code></pre> <p><strong>3) .setDefaults(int defaults)(NotificationCompat.Builder中的方法,用于设置通知到来时,通过什么方式进行提示)</strong></p> <p>方法解释:向通知添加声音、闪灯和振动效果的最简单、使用默认(defaults)属性,可以组合多个属性(和方法1中提示效果一样的)</p> <p>对应属性:</p> <p>Notification.DEFAULT_VIBRATE //添加默认震动提醒 需要 VIBRATE permission</p> <p>Notification.DEFAULT_SOUND // 添加默认声音提醒</p> <p>Notification.DEFAULT_LIGHTS// 添加默认三色灯提醒</p> <p>Notification.DEFAULT_ALL// 添加默认以上3种全部提醒</p> <pre> <code class="language-java">/** * 显示带有默认铃声、震动、呼吸灯效果的通知 * 如需实现自定义效果,请参考后面三个例子 */ private void showNotifyWithMixed() { NotificationCompat.Builder builder = new NotificationCompat.Builder(this) .setSmallIcon(R.mipmap.ic_launcher) .setContentTitle("我是有铃声+震动+呼吸灯效果的通知") .setContentText("库里就是叼~") //等价于setDefaults(Notification.DEFAULT_SOUND | Notification.DEFAULT_LIGHTS | Notification.DEFAULT_VIBRATE); .setDefaults(Notification.DEFAULT_ALL); mManager.notify(5, builder.build()); } </code></pre> <p><strong>4) setVibrate(long[] pattern)</strong></p> <p>方法解释:设置震动的时间</p> <pre> <code class="language-java">.setVibrate(new long[] {0,300,500,700}); </code></pre> <p>实现效果:延迟0ms,然后振动300ms,在延迟500ms,接着在振动700ms。</p> <p>还有另外一种写法:</p> <pre> <code class="language-java">mBuilder.build().vibrate = new long[] {0,300,500,700}; </code></pre> <p>如果希望设置默认振动方式,设置了方法(2)中默认为DEFAULT_VIBRATE 即可。</p> <p>例子:</p> <pre> <code class="language-java">/** * 展示有震动效果的通知,需要在AndroidManifest.xml中申请震动权限 * <uses-permission android:name="android.permission.VIBRATE" /> * 补充:测试震动的时候,手机的模式一定要调成铃声+震动模式,否则你是感受不到震动的 */ private void showNotifyWithVibrate() { //震动也有两种设置方法,与设置铃声一样,在此不再赘述 long[] vibrate = new long[]{0, 500, 1000, 1500}; NotificationCompat.Builder builder = new NotificationCompat.Builder(this) .setSmallIcon(R.mipmap.ic_launcher) .setContentTitle("我是伴有震动效果的通知") .setContentText("颤抖吧,凡人~") //使用系统默认的震动参数,会与自定义的冲突 //.setDefaults(Notification.DEFAULT_VIBRATE) //自定义震动效果 .setVibrate(vibrate); //另一种设置震动的方法 //Notification notify = builder.build(); //调用系统默认震动 //notify.defaults = Notification.DEFAULT_VIBRATE; //调用自己设置的震动 //notify.vibrate = vibrate; //mManager.notify(3,notify); mManager.notify(3, builder.build()); } </code></pre> <p><strong>4)方法:.setLights(intledARGB ,intledOnMS ,intledOffMS )</strong></p> <p>方法解释:android支持三色灯提醒,这个方法就是设置不同场景下的不同颜色的灯。</p> <p>描述:其中ledARGB 表示灯光颜色、 ledOnMS 亮持续时间、ledOffMS 暗的时间。</p> <p>注意:</p> <p>1)只有在设置了标志符Flags为Notification.FLAG_SHOW_LIGHTS的时候,才支持三色灯提醒。</p> <p>2)这边的颜色跟设备有关,不是所有的颜色都可以,要看具体设备。</p> <pre> <code class="language-java">Notification notify = mBuilder.build(); notify .setLights(0xff00eeff, 500, 200) </code></pre> <p>同理,以下方法也可以设置同样效果:</p> <pre> <code class="language-java">Notification notify = mBuilder.build(); notify.flags = Notification.FLAG_SHOW_LIGHTS; notify.ledARGB = 0xff00eeff; notify.ledOnMS = 500; notify.ledOffMS = 400; </code></pre> <p>如果希望使用默认的三色灯提醒,设置了方法(2)中默认为DEFAULT_LIGHTS即可。</p> <p>例子:</p> <pre> <code class="language-java">/** * 显示带有呼吸灯效果的通知,但是不知道为什么,自己这里测试没成功 */ private void showNotifyWithLights() { final NotificationCompat.Builder builder = new NotificationCompat.Builder(this) .setSmallIcon(R.mipmap.ic_launcher) .setContentTitle("我是带有呼吸灯效果的通知") .setContentText("一闪一闪亮晶晶~") //ledARGB 表示灯光颜色、 ledOnMS 亮持续时间、ledOffMS 暗的时间 .setLights(0xFF0000, 3000, 3000); Notification notify = builder.build(); //只有在设置了标志符Flags为Notification.FLAG_SHOW_LIGHTS的时候,才支持呼吸灯提醒。 notify.flags = Notification.FLAG_SHOW_LIGHTS; //设置lights参数的另一种方式 //notify.ledARGB = 0xFF0000; //notify.ledOnMS = 500; //notify.ledOffMS = 5000; //使用handler延迟发送通知,因为连接usb时,呼吸灯一直会亮着 Handler handler = new Handler(); handler.postDelayed(new Runnable() { @Override public void run() { mManager.notify(4, builder.build()); } }, 10000); } </code></pre> <p><strong>5)方法:.setSound(Uri sound)</strong></p> <p>方法解释:设置默认或则自定义的铃声,来提醒。</p> <pre> <code class="language-java">//获取默认铃声 .setDefaults(Notification.DEFAULT_SOUND) //获取自定义铃声 .setSound(Uri.parse("file:///sdcard/dance.mp3")) //获取Android多媒体库内的铃声 .setSound(Uri.withAppendedPath(Audio.Media.INTERNAL_CONTENT_URI, "5")) </code></pre> <p>同理相同效果的另一种设置方法这边就不讲, 和上面的都是一样的。</p> <p>例子:</p> <pre> <code class="language-java">/** * 展示有自定义铃声效果的通知 * 补充:使用系统自带的铃声效果:Uri.withAppendedPath(Audio.Media.INTERNAL_CONTENT_URI, "6"); */ private void showNotifyWithRing() { NotificationCompat.Builder builder = new NotificationCompat.Builder(this) .setSmallIcon(R.mipmap.ic_launcher) .setContentTitle("我是伴有铃声效果的通知") .setContentText("美妙么?安静听~") //调用系统默认响铃,设置此属性后setSound()会无效 //.setDefaults(Notification.DEFAULT_SOUND) //调用系统多媒体裤内的铃声 //.setSound(Uri.withAppendedPath(MediaStore.Audio.Media.INTERNAL_CONTENT_URI,"2")); //调用自己提供的铃声,位于 /res/values/raw 目录下 .setSound(Uri.parse("android.resource://com.littlejie.notification/" + R.raw.sound)); //另一种设置铃声的方法 //Notification notify = builder.build(); //调用系统默认铃声 //notify.defaults = Notification.DEFAULT_SOUND; //调用自己提供的铃声 //notify.sound = Uri.parse("android.resource://com.littlejie.notification/"+R.raw.sound); //调用系统自带的铃声 //notify.sound = Uri.withAppendedPath(MediaStore.Audio.Media.INTERNAL_CONTENT_URI,"2"); //mManager.notify(2,notify); mManager.notify(2, builder.build()); } </code></pre> <p><strong>6)方法:.setPriority(int pri)</strong></p> <p>方法解释:设置优先级(实际项目中并无大用,设置最高级也不会使得你的通知栏出现在第一位)</p> <p style="text-align:center"><img src="https://simg.open-open.com/show/49cb61284949626eb7dbf90d4e7f7c84.jpg"></p> <p>对应属性:</p> <ol> <li>Notification.PRIORITY_DEFAULT(优先级为0)</li> <li>Notification.PRIORITY_HIGH</li> <li>Notification.PRIORITY_LOW</li> <li>Notification.PRIORITY_MAX(优先级为2)</li> <li>Notification.PRIORITY_MIN(优先级为-2)</li> </ol> <p>Notification.PRIORITY_MAX是优先级最高,Notification.PRIORITY_MIN优先级最低</p> <p><strong>7)方法:setOngoing(boolean ongoing)</strong></p> <p>方法解释:设置为ture,表示它为一个正在进行的通知。他们通常是用来表示一个后台任务,用户积极参与(如播放音乐)或以某种方式正在等待,因此占用设备(如一个文件下载,同步操作,主动网络连接)</p> <p>PS:我们看到360手机卫士的通知栏一直固定在手机中,就是通过设置这个标记,使用该标记后你的通知栏无法被用户手动进行删除,只能通过代码进行删除,慎用</p> <p><strong>8)setProgress(int max, int progress,boolean indeterminate)</strong></p> <p>属性:max:进度条最大数值 、progress:当前进度、indeterminate:表示进度是否不确定,true为不确定,false为确定</p> <p>功能:设置带进度条的通知,可以在下载中使用</p> <p>注意:此方法在4.0及以后版本才有用,如果为早期版本:需要自定义通知布局,其中包含ProgressBar视图</p> <p>使用:如果为确定的进度条:调用setProgress(max, progress, false)来设置通知,在更新进度的时候在此发起通知更新progress,并且在下载完成后要移除进度条,通过调用setProgress(0, 0, false)既可。</p> <p>如果为不确定(持续活动)的进度条,这是在处理进度无法准确获知时显示活动正在持续,所以调用setProgress(0, 0, true) ,操作结束时,调用setProgress(0, 0, false)并更新通知以移除指示条</p> <p><strong>9)如何更新 Notification</strong></p> <p>更新通知很简单,只需要再次发送相同 ID 的通知即可,如果之前的通知还未被取消,则会直接更新该通知相关的属性;如果之前的通知已经被取消,则会重新创建一个新通知。</p> <p>更新通知跟发送通知使用相同的方式。</p> <pre> <code class="language-java">private void refreshNotification() { //获取NotificationManager实例 NotificationManager notifyManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); //实例化NotificationCompat.Builde并设置相关属性 NotificationCompat.Builder builder = new NotificationCompat.Builder(this) //设置小图标 .setSmallIcon(R.mipmap.icon_fab_repair) //设置通知标题 .setContentTitle("最简单的Notification") //设置通知内容 .setContentText("只有小图标、标题、内容") //设置通知时间,默认为系统发出通知的时间,通常不用设置 //.setWhen(System.currentTimeMillis()); //通过builder.build()方法生成Notification对象,并发送通知,id=1 notifyManager.notify(1, builder.build()); } </code></pre> <p><strong>10)如何取消 Notification?</strong></p> <p>取消通知有如下 5 种方式:</p> <p>1. 点击通知栏的清除按钮,会清除所有可清除的通知</p> <p>2. 设置了 setAutoCancel() 或 FLAG_AUTO_CANCEL 的通知,点击该通知时会清除它</p> <p>3. 通过 NotificationManager 调用 cancel(int id) 方法清除指定 ID 的通知</p> <p>4. 通过 NotificationManager 调用 cancel(String tag, int id) 方法清除指定 TAG 和 ID 的通知</p> <p>5. 通过 NotificationManager 调用 cancelAll() 方法清除所有该应用之前发送的通知</p> <p>如果你是通过 NotificationManager.notify(String tag, int id, Notification notify) 方法创建的通知,那么只能通过 NotificationManager.cancel(String tag, int id) 方法才能清除对应的通知,调用NotificationManager.cancel(int id) 无效。</p> <p>例子:</p> <pre> <code class="language-java">public class DemoActivity extends Activity implements View.OnClickListener { //Notification.FLAG_FOREGROUND_SERVICE //表示正在运行的服务 public static final String NOTIFICATION_TAG = "test"; public static final int DEFAULT_NOTIFICATION_ID = 1; private NotificationManager mNotificationManager; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_simple_notification); findViewById(R.id.btn_remove_all_notification).setOnClickListener(this); findViewById(R.id.btn_send_notification).setOnClickListener(this); findViewById(R.id.btn_remove_notification).setOnClickListener(this); findViewById(R.id.btn_send_notification_with_tag).setOnClickListener(this); findViewById(R.id.btn_remove_notification_with_tag).setOnClickListener(this); findViewById(R.id.btn_send_ten_notification).setOnClickListener(this); findViewById(R.id.btn_send_flag_no_clear_notification).setOnClickListener(this); findViewById(R.id.btn_send_flag_ongoing_event_notification).setOnClickListener(this); findViewById(R.id.btn_send_flag_auto_cancecl_notification).setOnClickListener(this); mNotificationManager = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.btn_remove_all_notification: //移除当前 Context 下所有 Notification,包括 FLAG_NO_CLEAR 和 FLAG_ONGOING_EVENT mNotificationManager.cancelAll(); break; case R.id.btn_send_notification: //发送一个 Notification,此处 ID = 1 sendNotification(); break; case R.id.btn_remove_notification: //移除 ID = 1 的 Notification,注意:该方法只针对当前 Context。 mNotificationManager.cancel(DEFAULT_NOTIFICATION_ID); break; case R.id.btn_send_notification_with_tag: //发送一个 ID = 1 并且 TAG = littlejie 的 Notification //注意:此处发送的通知与 sendNotification() 发送的通知并不冲突 //因为此处的 Notification 带有 TAG sendNotificationWithTag(); break; case R.id.btn_remove_notification_with_tag: //移除一个 ID = 1 并且 TAG = littlejie 的 Notification //注意:此处移除的通知与 NotificationManager.cancel(int id) 移除通知并不冲突 //因为此处的 Notification 带有 TAG mNotificationManager.cancel(NOTIFICATION_TAG, DEFAULT_NOTIFICATION_ID); break; case R.id.btn_send_ten_notification: //连续发十条 Notification sendTenNotifications(); break; case R.id.btn_send_flag_no_clear_notification: //发送 ID = 1, flag = FLAG_NO_CLEAR 的 Notification //下面两个 Notification 的 ID 都为 1,会发现 ID 相等的 Notification 会被最新的替换掉 sendFlagNoClearNotification(); break; case R.id.btn_send_flag_auto_cancecl_notification: sendFlagOngoingEventNotification(); break; case R.id.btn_send_flag_ongoing_event_notification: sendFlagAutoCancelNotification(); break; } } /** * 发送最简单的通知,该通知的ID = 1 */ private void sendNotification() { //这里使用 NotificationCompat 而不是 Notification ,因为 Notification 需要 API 16 才能使用 //NotificationCompat 存在于 V4 Support Library NotificationCompat.Builder builder = new NotificationCompat.Builder(this) .setSmallIcon(R.mipmap.ic_launcher) .setContentTitle("Send Notification") .setContentText("Hi,My id is 1"); mNotificationManager.notify(DEFAULT_NOTIFICATION_ID, builder.build()); } /** * 使用notify(String tag, int id, Notification notification)方法发送通知 * 移除对应通知需使用 cancel(String tag, int id) */ private void sendNotificationWithTag() { NotificationCompat.Builder builder = new NotificationCompat.Builder(this) .setSmallIcon(R.mipmap.ic_launcher) .setContentTitle("Send Notification With Tag") .setContentText("Hi,My id is 1,tag is " + NOTIFICATION_TAG); mNotificationManager.notify(NOTIFICATION_TAG, DEFAULT_NOTIFICATION_ID, builder.build()); } /** * 循环发送十个通知 */ private void sendTenNotifications() { for (int i = 0; i < 10; i++) { NotificationCompat.Builder builder = new NotificationCompat.Builder(this) .setSmallIcon(R.mipmap.ic_launcher) .setContentTitle("Send Notification Batch") .setContentText("Hi,My id is " + i); mNotificationManager.notify(i, builder.build()); } } /** * 设置FLAG_NO_CLEAR * 该 flag 表示该通知不能被状态栏的清除按钮给清除掉,也不能被手动清除,但能通过 cancel() 方法清除 * Notification.flags属性可以通过 |= 运算叠加效果 */ private void sendFlagNoClearNotification() { NotificationCompat.Builder builder = new NotificationCompat.Builder(this) .setSmallIcon(R.mipmap.ic_launcher) .setContentTitle("Send Notification Use FLAG_NO_CLEAR") .setContentText("Hi,My id is 1,i can't be clear."); Notification notification = builder.build(); //设置 Notification 的 flags = FLAG_NO_CLEAR //FLAG_NO_CLEAR 表示该通知不能被状态栏的清除按钮给清除掉,也不能被手动清除,但能通过 cancel() 方法清除 //flags 可以通过 |= 运算叠加效果 notification.flags |= Notification.FLAG_NO_CLEAR; mNotificationManager.notify(DEFAULT_NOTIFICATION_ID, notification); } /** * 设置FLAG_AUTO_CANCEL * 该 flag 表示用户单击通知后自动消失 */ private void sendFlagAutoCancelNotification() { //设置一个Intent,不然点击通知不会自动消失 Intent resultIntent = new Intent(this, MainActivity.class); PendingIntent resultPendingIntent = PendingIntent.getActivity( this, 0, resultIntent, PendingIntent.FLAG_UPDATE_CURRENT); NotificationCompat.Builder builder = new NotificationCompat.Builder(this) .setSmallIcon(R.mipmap.ic_launcher) .setContentTitle("Send Notification Use FLAG_AUTO_CLEAR") .setContentText("Hi,My id is 1,i can be clear.") .setContentIntent(resultPendingIntent); Notification notification = builder.build(); //设置 Notification 的 flags = FLAG_NO_CLEAR //FLAG_AUTO_CANCEL 表示该通知能被状态栏的清除按钮给清除掉 //等价于 builder.setAutoCancel(true); notification.flags |= Notification.FLAG_AUTO_CANCEL; mNotificationManager.notify(DEFAULT_NOTIFICATION_ID, notification); } /** * 设置FLAG_ONGOING_EVENT * 该 flag 表示发起正在运行事件(活动中) */ private void sendFlagOngoingEventNotification() { NotificationCompat.Builder builder = new NotificationCompat.Builder(this) .setSmallIcon(R.mipmap.ic_launcher) .setContentTitle("Send Notification Use FLAG_ONGOING_EVENT") .setContentText("Hi,My id is 1,i can't be clear."); Notification notification = builder.build(); //设置 Notification 的 flags = FLAG_NO_CLEAR //FLAG_ONGOING_EVENT 表示该通知通知放置在正在运行,不能被手动清除,但能通过 cancel() 方法清除 //等价于 builder.setOngoing(true); notification.flags |= Notification.FLAG_ONGOING_EVENT; mNotificationManager.notify(DEFAULT_NOTIFICATION_ID, notification); } } </code></pre> <p><strong>给Notification设置PendingIntent</strong></p> <p>PendingIntent可以通过setContentIntent(PendingIntent intent)这个方法进行设置</p> <p>当我们点击通知栏时想跳转一个Activity或者开启一个service时,就可以通过设置PendingIntent达成</p> <p>PendingIntent 是 Android 系统管理并持有的用于描述和获取原始数据的对象的标志(引用)。也就是说,即便创建该PendingIntent对象的进程被杀死了,这个PendingItent对象在其他进程中还是可用的。</p> <p>日常使用中的短信、闹钟等都用到了 PendingIntent。</p> <p>PendingIntent 主要可以通过以下三种方式获取:</p> <pre> <code class="language-java">//获取一个用于启动 Activity 的 PendingIntent 对象 public static PendingIntent getActivity(Context context, int requestCode, Intent intent, int flags); //获取一个用于启动 Service 的 PendingIntent 对象 public static PendingIntent getService(Context context, int requestCode, Intent intent, int flags); //获取一个用于向 BroadcastReceiver 广播的 PendingIntent 对象 public static PendingIntent getBroadcast(Context context, int requestCode, Intent intent, int flags) </code></pre> <p>PendingIntent 具有以下几种 flag:</p> <p>FLAG_CANCEL_CURRENT:如果当前系统中已经存在一个相同的 PendingIntent 对象,那么就将先将已有的 PendingIntent 取消,然后重新生成一个 PendingIntent 对象。</p> <p>FLAG_NO_CREATE:如果当前系统中不存在相同的 PendingIntent 对象,系统将不会创建该 PendingIntent 对象而是直接返回 null 。</p> <p>FLAG_ONE_SHOT:该 PendingIntent 只作用一次。</p> <p>FLAG_UPDATE_CURRENT:如果系统中已存在该 PendingIntent 对象,那么系统将保留该 PendingIntent 对象,但是会使用新的 Intent 来更新之前 PendingIntent 中的 Intent 对象数据,例如更新 Intent 中的 Extras 。</p> <p><strong>自定义Notification</strong></p> <p>Android系统允许使用RemoteViews来自定义通知。自定义普通视图通知高度限制为64dp,大视图通知高度限制为256dp。同时,建议自定义通知尽量简单,以提高兼容性。</p> <p>自定义通知需要做如下操作:1、创建自定义通知布局2、使用RemoteViews定义通知组件,如图标、文字等3、调用setContent()将RemoteViews对象绑定到NotificationCompat.Builder4、同正常发送通知流程</p> <p>注意: 避免为通知设置背景,因为兼容性原因,有些文字可能看不清。</p> <p>关于自定义Notification兼容问题,请阅读我的另一篇博客 Android通知栏版本兼容解决方案</p> <p>例子:</p> <pre> <code class="language-java">RemoteViews notifactionView = new RemoteViews(mContext.getPackageName(), R.layout.cl_screen_notification); mBuilder.setContent(notifactionView); notifactionView.setOnClickPendingIntent(R.id.cl_screen_notification, pendingIntent); Bitmap pluginIcon = drawableToBitmap(pluginDrawable); LogUtils.d("myl", "获得icon" + pluginIcon); notifactionView.setImageViewBitmap(R.id.cl_plugin_icon, pluginIcon); notifactionView.setTextViewText(R.id.dl_plugin_msg, pluginContent); Notification notification = mBuilder.build(); int id = 199; LogUtils.d(TAG, "创建通知"); mNotificationManager.notify(id, notification); </code></pre> <p><strong>Notification的各种样式</strong></p> <p>1) BigText样式(Android 4.1以上)</p> <p>a) 最大高度一般为256dp</p> <p>b) 不是最新的通知时默认为折叠状态</p> <p>c) 不设置SummaryText的话,展开后最下面一行的内容会消失</p> <p>例子:</p> <pre> <code class="language-java">private void showBigViewText() { NotificationCompat.BigTextStyle textStyle = new BigTextStyle(); textStyle .setBigContentTitle("BigContentTitle") .setSummaryText("SummaryText") .bigText( "I am Big Text"); Notification notification = new NotificationCompat.Builder(context) .setLargeIcon(icon).setSmallIcon(R.drawable.ic_launcher) .setTicker("showBigView_Text").setContentInfo("contentInfo") .setContentTitle("ContentTitle").setContentText("ContentText") .setStyle(textStyle) .setAutoCancel(true).setDefaults(Notification.DEFAULT_ALL) .build(); manager.notify(NOTIFICATION_ID_2, notification); } </code></pre> <p>2) Inbox样式</p> <p>a) 高度一般为256dp</p> <p>b) 不是最新的通知时默认为折叠状态</p> <p>c) 不设置SummaryText的话,展开后最下面一行的内容会消失</p> <p>例子:</p> <pre> <code class="language-java">private void showBigViewInbox() { NotificationCompat.InboxStyle inboxStyle = new NotificationCompat.InboxStyle(); inboxStyle.setBigContentTitle("BigContentTitle").setSummaryText( "SummaryText"); for (int i = 0; i < 5; i++) inboxStyle.addLine("news:" + i); Notification notification = new NotificationCompat.Builder(context) .setLargeIcon(icon).setSmallIcon(R.drawable.ic_launcher) .setTicker("showBigView_Inbox").setContentInfo("contentInfo") .setContentTitle("ContentTitle").setContentText("ContentText") .setStyle(inboxStyle) .setAutoCancel(true).setDefaults(Notification.DEFAULT_ALL) .build(); manager.notify(NOTIFICATION_ID_4, notification); } </code></pre> <p>3) BigPicture样式</p> <p>a) 高度一般为256dp</p> <p>b) 不是最新的通知时为默认折叠状态</p> <p>c) 不设置SummaryText的话,展开后第二行字的内容会消失</p> <p>例子:</p> <pre> <code class="language-java">private void showBigViewPic() { NotificationCompat.BigPictureStyle pictureStyle = new BigPictureStyle(); pictureStyle.setBigContentTitle("BigContentTitle") .setSummaryText("SummaryText").bigPicture(icon); Notification notification = new NotificationCompat.Builder(context) .setLargeIcon(icon).setSmallIcon(R.drawable.ic_launcher) .setTicker("showBigView_Pic").setContentInfo("contentInfo") .setContentTitle("ContentTitle").setContentText("ContentText") .setStyle(pictureStyle) .setAutoCancel(true).setDefaults(Notification.DEFAULT_ALL) .build(); manager.notify(NOTIFICATION_ID_3, notification); } </code></pre> <p>4) 折叠式Notification</p> <p>折叠式Notification是一种自定义视图的Notification,用来显示长文本和一些自定义的布局的场景。它有两种状态,一种是普通状态下的视图,一种是展开状态下的视图。和普通Notification不同的是,我们需要自定义的视图,而这个视图显示的进程和我们创建视图的进程不再一个进程,所以我们需要使用RemoteViews,首先要使用RemoteViews来创建我们的自定义视图:</p> <pre> <code class="language-java">//用RemoteViews来创建自定义Notification视图 RemoteViews remoteViews = new RemoteViews(getPackageName(), R.layout.view); </code></pre> <p>视图的布局文件:</p> <pre> <code class="language-java"><?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="100dp" android:background="@drawable/fold" android:orientation="horizontal"> <ImageView android:id="@+id/iv_image" android:layout_width="100dp" android:layout_height="100dp" android:src="@drawable/fold" /> <TextView android:id="@+id/tv_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="30dp" android:layout_marginLeft="150dp" android:text="展开后的视图" android:textColor="@color/colorPrimaryDark"/> </LinearLayout> </code></pre> <p>把自定义视图赋值给Notification展开时的视图</p> <pre> <code class="language-java">//指定展开时的视图 notification.bigContentView = remoteViews; </code></pre> <p>也可以把自定义视图赋值给Notification普通状态时的视图</p> <pre> <code class="language-java">//指定普通状态时的视图 notification.contentView = remoteViews; </code></pre> <p>折叠式Notification完整代码:</p> <pre> <code class="language-java">Notification.Builder builder = new Notification.Builder(this); Intent mIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://blog.csdn.net/itachi85/")); PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, mIntent, 0); builder.setContentIntent(pendingIntent); builder.setSmallIcon(R.drawable.foldleft); builder.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.lanucher)); builder.setAutoCancel(true); builder.setContentTitle("折叠式通知"); //用RemoteViews来创建自定义Notification视图 RemoteViews remoteViews = new RemoteViews(getPackageName(), R.layout.view_fold); Notification notification = builder.build(); //指定展开时的视图 notification.bigContentView = remoteViews; notificationManager.notify(1, notification); </code></pre> <p>5) 悬挂式Notification (5.0新增)</p> <p>悬挂式Notification是android5.0新增加的方式,悬挂式Notification不需要下拉通知栏就直接显示出来悬挂在屏幕上方并且焦点不变仍在用户操作的界面因此不会打断用户的操作,过几秒就会自动消失。他需要调用setFullScreenIntent来将Notification变为悬挂式Notification</p> <pre> <code class="language-java">//如果描述的PendingIntent已经存在,则在产生新的Intent之前会先取消掉当前的 PendingIntent hangPendingIntent = PendingIntent.getActivity(this, 0, hangIntent, PendingIntent.FLAG_CANCEL_CURRENT); builder.setFullScreenIntent(hangPendingIntent, true); </code></pre> <p>悬挂式Notification完整代码:</p> <pre> <code class="language-java">Notification.Builder builder = new Notification.Builder(this); Intent mIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://blog.csdn.net/itachi85/")); PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, mIntent, 0); builder.setContentIntent(pendingIntent); builder.setSmallIcon(R.drawable.foldleft); builder.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.lanucher)); builder.setAutoCancel(true); builder.setContentTitle("悬挂式通知"); //设置点击跳转 Intent hangIntent = new Intent(); hangIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); hangIntent.setClass(this, MyNotificationActivity.class); //如果描述的PendingIntent已经存在,则在产生新的Intent之前会先取消掉当前的 PendingIntent hangPendingIntent = PendingIntent.getActivity(this, 0, hangIntent, PendingIntent.FLAG_CANCEL_CURRENT); builder.setFullScreenIntent(hangPendingIntent, true); notificationManager.notify(2, builder.build()); </code></pre> <p style="text-align:center"><img src="https://simg.open-open.com/show/cfae35310f55fe6e43fe11643b2c0763.png"></p> <p>6) 锁屏通知</p> <p>Android 5.0(API level 21)开始,通知可以显示在锁屏上。用户可以通过设置选择是否允许敏感的通知内容显示在安全的锁屏上。你的应用可以通过setVisibility()控制通知的显示等级:</p> <p>VISIBILITY_PRIVATE : 显示基本信息,如通知的图标,但隐藏通知的全部内容</p> <p>VISIBILITY_PUBLIC : 显示通知的全部内容</p> <p>VISIBILITY_SECRET : 不显示任何内容,包括图标</p> <pre> <code class="language-java">builder.setVisibility(Notification.VISIBILITY_PUBLIC); </code></pre> <p> </p> <p>来自:http://mobile.51cto.com/android-536672.htm</p> <p> </p>