Notification(Notification的通知栏常驻、各种样式、点击⽆效、禁⽌滑。。。
Android的Notification是android系统中很重要的⼀个机制,
产品⼈员常常利⽤通知栏的⽅式,跟⽤户进⾏弱沟通。拥有推送通知的app要⽐没有此类功能的app活跃率要⾼很多。另外类似于墨迹天⽓,清理⼤师等app,也会将通知栏常驻,利⽤⾃定义的布局,⽅便⽤户及时快捷的查看所需的信息和使⽤快捷的功能。所以Notification的使⽤,也在开发当中,
使⽤的越来越频繁。今天我就来跟⼤家分享⼀下Notification的常⽤事项。
constant我不了解⼤家平时怎么使⽤Notification,我常常看到有些⼈的代码是这样写的:
Notification notification=new Notification(notificationIcon, notificationTitle, when);
notification.defaults=Notification.DEFAULT_ALL;
Intent intent=new Intent(MainActivity.this,SecondActivity.class);
PendingIntent Activity(MainActivity.this, 0, intent, 0);
notification.tLatestEventInfo(this,"测试展开title", "测试展开容",pendingIntent);
。。。。。。。。。。。。。
具体的代码我就不贴全了,因为⼤家如果注意IDE的提⽰的话,就会发现,其实这是⼀种不推荐的⽤法,API的⽀持已经过时了。最新的Notification的⽤法,是推荐使⽤V4包下的NotificationCompat.Builder, 利⽤它,进⾏各种设置,具体的⽤法先别着急,我们慢慢道来。
NotificationCompat.Builder notifyBuilder = new NotificationCompat.Builder(
this);
⾸先,我们需要先初始化⼀个notifyBuilder,然后利⽤它的各种t⽅法,进⾏相关设置,具体的设置,我们参考下图:图⽰中的序号1,叫做
notifyBuilder.tContentTitle("This is My Notification");
图⽰中的序号3,叫做
notifyBuilder.tContentText("Hello World");
图⽰中的需要5,叫做利⽤下⾯的⽅法来设置:
这三个参数的设定是必须的,每次调⽤Notification,必须得设定这三个参数。除去这三个以外,另外的2,4,6区域,分别是Large
Icon,Content Info,Time,设置⽅法如下所⽰:
Bitmap bitmap = BitmapFactory.decodeResource(getResources(),R.drawable.bigicon);
notifyBuilder.tLargeIcon(bitmap);
// 这⾥⽤来显⽰右下⾓的数字
notifyBuilder.tNumber(10);
notifyBuilder.tWhen(System.currentTimeMillis());
以上就是关于Notification的基本设置,下⾯,我们继续看看其它⽅⾯的设置,直接上代码:
// 将AutoCancel设为true后,当你点击通知栏的notification后,它会⾃动被取消消失
notifyBuilder.tAutoCancel(true);
// 将Ongoing设为true 那么notification将不能滑动删除
// notifyBuilder.tOngoing(true);
// 从Android4.1开始,可以通过以下⽅法,设置notification的优先级,优先级越⾼的,通知排的越靠前,优先级低的,不会在⼿机最顶部的状态栏显⽰图标notifyBuilder.tPriority(NotificationCompat.PRIORITY_MAX);
// notifyBuilder.tPriority(NotificationCompat.PRIORITY_MIN);
notifyBuilder.tTicker("Hi,Notification is here");
// Uri uri =
// Uri.par("source://"+getPackageName()+"/"+R.raw.cat);
// Uri uri = Uri.par("file:///mnt/sdcard/cat.mp3");
chingy// notifyBuilder.tSound(uri);
// Notification.DEFAULT_ALL:铃声、闪光、震动均系统默认。
// Notification.DEFAULT_SOUND:系统默认铃声。
// Notification.DEFAULT_VIBRATE:系统默认震动。
// Notification.DEFAULT_LIGHTS:系统默认闪光。
// notifyBuilder.tDefaults(Notification.DEFAULT_ALL);
NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
如上⾯的注释所⽰,如果你想点击完notification后,该通知⾃动消失,那么你就需要调⽤tAutoCancel(booleanb)这个⽅法,并且将其
设为true,如果你想让你的通知栏常驻,⽤户⽆法滑动删除,也不能通过⼿机的清除键删除,类似于墨迹天⽓等app的通知栏,那么你可以
设置tOngoing⽅法,也设为true,这样,通知栏只能通过代码调⽤cancel⽅法才能消失,很霸道地,有⽊有!另外,从Android4.1时
代开始,系统允许设置Notification的优先级,对于优先级⾼的通知,会排在通知栏的前⾯,并在会在⼿机最上端的Status Bar显⽰⼀个图标,如果优先级设定的较低,那么就会被系统显⽰在通知栏的后⾯,并且Status Bar不再显⽰相应的图标,设置优先级的⽅法,就是调⽤tPriority(intp)。另外,当启动通知栏的时候,我们常常可以在⼿机最上端的Status Bar上⾯,会闪现⼀段提⽰语,⽤来提醒⽤户,这段
提⽰语具体显⽰的⽂字,就是靠tTicker() 这个⽅法来实现的。除此之外,我们还可以设置,推送通知时的铃声、震动效果,闪光灯效果
等等,具体的我就不⼀⼀列举了,参考上⾯的⽰例代码即可,需要注意⼀点的是,设置通知的铃声,除去调⽤系统⾃带的外,还有两种⽅
式,分别是调⽤SD卡中的声⾳⽂件和项⽬⼯程⾃带的声⾳⽂件,这两种⽅式都需要⽤到Uri的 地址,具体如何获取这两种的Uri,我已经在
上⾯的代码中,写的很详细了,⼤家可以参考上⾯的代码,在⾃⼰的项⽬中实验⼀下。
说了这么多,还有最重要的⼀点没有讲,那就是在你设置完notification的各 种属性后,你需要启动这个notification,否则就前功尽弃
了,启动的⽅法,如上⾯的⽰例代码所⽰,你需要先获取⼀个 NotificationManager的实例,然后调⽤notify的⽅
法,notifyBuilder.build()这个⽅法,可以实例化⼀个notification的实例,另外,你还需要为这个notification分配⼀个独⼀⽆⼆的的id
号,将来notification的更新和删 除,都是依靠这个id号来做索引对应的。
有时候,我们会涉及到这么⼀个需求,那就是,产品设计,希望我们能够监听 notification的销毁,意思就是说,当⽤户⼿动滑动通知将其
删除或者通过⼿机的删除按钮将其清空时,我们希望可以捕获到这⼀信息,并作出相应的处理。⽐如说,我们在通知栏发送了⼀个通知,⽤
来更新⼀个资源的下载进度,当⽤户删除这个通知后,我们希望可以监听到这⼀变化,作出相应的处理,⽐如取消 下载,⽐如重新下载等
等,那么,应该如何监听取消的⾏为呢?请看代码:
Intent deleteIntent = new Intent(this, DeleteService.class);
int deleteCode = (int) SystemClock.uptimeMillis();
PendingIntent deletePendingIntent = Service(this,
deleteCode, deleteIntent, PendingIntent.FLAG_UPDATE_CURRENT);
notifyBuilder.tDeleteIntent(deletePendingIntent);
我 们给notifyBuilder设置⼀个DeleteIntent,这⾥指向了⼀个rvice,当删除的⾏为发⽣后,系统就会启动这个 rvice,我们就可以在
这个rvice中,做相应的逻辑处理了,当然,这⾥我只是举了⼀个例⼦,⽤来启动rvice,⼤家也可以将 Intent指向⼀个Activity或者⼀
个⼴播,不过Service()这个⽅法,就需要换成Activity()或者BroadCast()这两
个⽅法。
上⾯的内容,我们⼤概了解了如何给notification设定显⽰的内容,和如何监听销毁的⾏为。但是常常,我们会发现,除了以上功能外,我
们经常遇见的情形时,当我们点击了⼀个notification后,就会⾃动打开⼀个页⾯,展⽰出信息来源的具体页⾯,接下来,我们就针对这种
情况,来看看代码是如何控制的。
刚刚提到的⾃动跳转页⾯的功能,看似很简单的⼀个逻辑,其实也包含了各种逻辑处理情况,其中最主要的是有两种:
⼀:当我们处在⼿机桌⾯主屏的时候,突然来了⼀条邮箱的信息,来了⼀封新邮件,我们点击通知栏,系统会为我们打开最新收到的邮件,
当我们看完邮件后,按返回键,我们并不会马上回到⼿机桌⾯的主屏上,⽽是先返回到收件箱界 ⾯,然后再返回到邮件APP的主界⾯,然
后再返回到⼿机桌⾯的主屏上,它是按照邮件APP的页⾯队列返回的。
⼆:还是举刚才那个例⼦,当我们收到新邮件的通知后,我们点击打开新收到的邮件,当我们阅读完之后,我们想要点击返回键,⽴刻返回
到我们刚刚所处的界⾯,继续进⾏刚才还在进⾏的任务。
英语必修五单词录音
这两种情况,在产品设计中,常常出现,所以我们也要想办法去实现,那么如何去实现这两种情况呢,我们⼀个⼀个来看。
⾸先请看第⼀种情况的代码:
Intent notifyIntent = new Intent(this, NotifyRegularActivity.class);
TaskStackBuilder stackBuilder = ate(this);
stackBuilder.addParentStack(NotifyRegularActivity.class);
stackBuilder.addNextIntent(notifyIntent);
// 当设置下⾯PendingIntent.FLAG_UPDATE_CURRENT这个参数的时候,常常使得点击通知栏没效果,你需要给notification设置⼀个独⼀⽆⼆的requestCode int requestCode = (int) SystemClock.uptimeMillis();
PendingIntent resultPendingIntent = PendingIntent(
requestCode, PendingIntent.FLAG_UPDATE_CURRENT);
notifyBuilder.tContentIntent(resultPendingIntent);
我们继续贴上l的配置代码:
化妆品专业知识
<activity
android:name="ificationtest.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="ificationtest.OtherActivity"
android:label="OtherActivity"android:parentActivityName="ificationtest.MainActivity" >
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="ificationtest.MainActivity" />
</activity>
<activity
android:name="ificationtest.NotifyRegularActivity"
粒度
android:label="NotifyRegularActivity"
android:parentActivityName="ificationtest.OtherActivity" >
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="ificationtest.OtherActivity" />
</activity>
好,我们来分析⼀下上⾯的代码。⾸先我们设置了⼀个Intent,将其指向 NotifyRegularActivity,然后我们⽤到了TaskStackBuilder,它
可以⽤来控制界⾯返回的导航堆栈。
TaskStackBuilder stackBuilder = ate(this);
stackBuilder.addParentStack(NotifyRegularActivity.class);
stackBuilder.addNextIntent(notifyIntent);
我们利⽤这段代码,⾸先实例化了⼀个TaskStackBuilder,然后调⽤addParentStack()和addNextIntent(), 设置它的返回堆栈和跳转页⾯,跳转页⾯的Intent很好理解,跟⼤家平时的设置⽅式是⼀样的,那么它的返回堆栈是如何控制的呢?这就需要上⾯xml配置 ⽂件的配置了,⼤家请看,
在上⾯的配置⽂件中,⼀共有三个Activity,分别是MainActivity,OtherActivity,和 NotifyRegularActivity,其中NotifyRegularActivity就是我们点击通知栏后,要⾃动跳转的界⾯。在配置⽂件当中,
我们给后⾯两个Activity,设置了这么⼀个属性android:parentActivityName,它指的就是该activity的返回路径,因为刚刚我们在调⽤addParentStack()这个⽅法的时候,设置的参数是NotifyRegularActivity.class所以根据上⾯配置⽂件的配置内容,那么它的返回堆栈的顺序就是:
需要注意的是,为了向下兼容版本,我们在设置android:parentActivityName这个属性的时候,还需要在配置⽂件中,为每个Activity进⾏如下设置:
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="ificationtest.MainActivity" />
具体的value的指向,就需要你⾃⼰设定了,总之,它指向了该activity的返回页⾯。对TaskStackBuilder设置完成之后,我们再通过下⾯的代码获取PendingIntent,,然后赋值给notifyBuilder即可:
foe
fun学网
afternoon// 当设置下⾯PendingIntent.FLAG_UPDATE_CURRENT这个参数的时候,常常使得点击通知栏没效果,你需要给notification设置⼀个独⼀⽆⼆的requestCode
int requestCode = (int) SystemClock.uptimeMillis();
PendingIntent resultPendingIntent = PendingIntent(
requestCode, PendingIntent.FLAG_UPDATE_CURRENT);
notifyBuilder.tContentIntent(resultPendingIntent);
这⾥有两点需要注意⼀下:
1:PendingIntent.FLAG_UPDATE_CURRENT这个参数⼀般有四种选择分别是:
FLAG_CANCEL_CURRENT:如果构建的PendingIntent已经存在,则取消前⼀个,重新构建⼀个。
FLAG_NO_CREATE:如果前⼀个PendingIntent已经不存在了,将不再构建它。
FLAG_ONE_SHOT:表明这⾥构建的PendingIntent只能使⽤⼀次。
FLAG_UPDATE_CURRENT:如果构建的PendingIntent已经存在,那么系统将不会重复创建,只是把之前不同的传值替换掉。
如果没有特殊要求的话,我们常常会使⽤FLAG_UPDATE_CURRENT这个参数来构造PendingIntent,但是这样常常会引发第⼆个问题,什么问题呢?呵呵~
2:如上所述我们使⽤ FLAG_UPDATE_CURRENT这个参数后,常常会发现,我们点击通知栏后,系统没有响应,时灵时不灵的,很是忧郁,这是为什么呢?原来使⽤ FLAG_UPDATE_CURRENT这个参数后,系统不会重新创建新的PendingIntent,这样⼀来,如果你传递的Intent的 extra参数没有变化的话,那么系统就会认为你没有发送新的PendingIntent,这样就不会重新响应你的点击事件。⼀般情况下,为了能够区分每 次的PendingIntent不⼀样,我们常常会在构造Intent的时候,设置不同的Action或者Extra值,这样⼀来,及时是使⽤FLAG_UPDATE_CURRENT这个参数,系统也会因为传值参数的变化⽽去响应每次的点击跳转事件。不过这种解决⽅法还是有些⿇烦,有时候,我们根本不需要传递额外的Aciton或者参数值,这该怎么办呢?哈哈,解决代码已经在上⾯的代码中写出来了,在
int requestCode = (int) SystemClock.uptimeMillis();
获取发布通知时的时间,将它作为requestCode,这样就可以避免这些问题了。不过如果你要是使⽤FLAG_CANCEL_CURRENT这个参数的话,就会每次都创建⼀个新的,那么刚刚提到的这两个问题,也都不存在了,具体怎么⽤,看你实际的业务要求了。
上⾯的讲解,我们就可以解决刚刚讨论的第⼀种情形了,下⾯我们来说⼀下,第⼆种情形,也就是点击返回键后,直接返回刚刚任务所处的
界⾯,看看这个如何实现。来,看代码:
Intent notifyIntent = new Intent(this, NotifySpecialActivity.class);
notifyIntent.tFlags(Intent.FLAG_ACTIVITY_NEW_TASK
excl| Intent.FLAG_ACTIVITY_CLEAR_TASK);
// Creates the PendingIntent
// 当设置下⾯PendingIntent.FLAG_UPDATE_CURRENT这个参数的时候,常常使得点击通知栏没效
果,你需要给notification设置⼀个独⼀⽆⼆的requestCode int requestCode = (int) SystemClock.uptimeMillis();
PendingIntent pendIntent = Activity(this, requestCode,
notifyIntent, PendingIntent.FLAG_UPDATE_CURRENT);
notifyBuilder.tContentIntent(pendIntent);
继续看配置⽂件的设置:
<activity
广州拓展培训android:name="ificationtest.NotifySpecialActivity"
android:excludeFromRecents="true"
android:label="NotifySpecialActivity"
android:launchMode="singleTask"
android:taskAffinity="" >
</activity>
在代码中,我们设置NotifySpecialActivity为我们要跳转的界⾯,然后在xml的配置⽂件中,我们重点设置了这三个属性:
android:excludeFromRecents=”true”,android:launchMode=”singleTask”,android:taskAffinity=”“,第⼀个属性的设
置,是将该界⾯从最近任务栏当中移除,防⽌⽤户通过最近任务栏⽽进⼊到该界⾯,这样⼀来,只能通过通知来的点击来进⼊。第⼆种属性
的设置就很常见了,是为了防⽌该界⾯存在的情况下,重复创建该Activity,第三属性是为了配置代码中的这段来设置的:
notifyIntent.tFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_CLEAR_TASK);
这样的作⽤是为此次跳转界⾯的⾏为重新分配⼀个任务堆栈,⽽不从属于其它的任务堆栈,这样的话,当我们点击返回键后,就可以直接返
回到刚刚⽤户所处的任务界⾯了。由于这⾥我们不再使⽤TaskStackBuilder,所以最后需要调⽤
PendingIntent,然后赋值给notifyBuilder。这样,刚刚讨论过的第⼆种情形,我们就可以解决了,相⽐较第⼀种来说,这种解决⽅式更为
简洁,不过处理的业务逻辑也不⼀样,⼤家斟酌⽽定。
Notificaton在平时的产品设计中,常常⽤来显⽰跟⽹络交互的进度,我们常常的做法是在通知栏上⾯,显⽰⼀个进度条,⽤来更新交互的
进度,这个的实现⽅式很简单,主要依赖于mBuilder.tProgress()这个⽅法,具体的做法可以参考下⾯的代码: