android通知有很多种,现在来粗略的列举一下。
一般使用Notification类创建通知,然后用NotificationManager来管理它,由于Notification在3.0以上才有,这里使用了v4包的NotificationCompat。
Notification种类
一般种
首先是一般的通知
代码如下,点击通知跳转到MainActivity
if(v.getId() == R.id.notify){
Intent intent = new Intent(getActivity(), MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(getActivity(),0,intent,PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder testBuild = new NotificationCompat.Builder(getActivity());
testBuild.setContentIntent(pendingIntent);
testBuild = new NotificationCompat.Builder(getActivity());
testBuild.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle("title")
.setContentText("text")
.setContentIntent(pendingIntent)
.setLargeIcon(BitmapFactory.decodeResource(getResources(),R.mipmap.big))//当设置的时候,通知图标显示这个,而setSmallIcon显示在大图标的右下角,没设置的时候通知栏显示SmallIcon
.setAutoCancel(true);//点击通知之后通知会消失
// .setSubText("SubText")//显示ContentText下面,
// .setContentInfo("ContentInfo")//设置之后会占用setNumber的位置
testBuild.setNumber(++number);//标示当前有多少条通知,多条通知应该整合成一条,不然通知栏就泛滥了
notificationManager.notify(COM_ID, testBuild.build());//发送通知COM_ID为标示当前通知的id
}
NotificationManager用来管理通知,那么就可以发送和取消了
notificationManager.cancel(COM_ID);//取消指定id的通知
notificationManager.cancelAll();//取消所有
带选项的通知
代码和上面差不多,加多了两个Action
Intent intent = new Intent(getActivity(), MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(getActivity(),0,intent,PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder testBuild = new NotificationCompat.Builder(getActivity());
testBuild.setContentIntent(pendingIntent);
testBuild = new NotificationCompat.Builder(getActivity());
testBuild.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle("title") .setContentText("texttexttexttexttexttexttexttexttexttexttexttexttexttexttexttexttexttexttexttexttexttexttexttexttexttexttexttexttexttexttexttexttexttexttexttext")
.setContentIntent(pendingIntent)
.setLargeIcon(BitmapFactory.decodeResource(getResources(),R.mipmap.big))//当设置的时候,通知图标显示这个,而setSmallIcon显示在大图标的右下角,没设置的时候通知栏显示SmallIcon
.setAutoCancel(true);//点击通知之后通知会消失
testBuild.addAction(android.R.drawable.ic_menu_close_clear_cancel,"取消",pendingIntent);
testBuild.addAction(android.R.drawable.ic_delete,"删除",pendingIntent);
notificationManager.notify(2, testBuild.build());
进度条通知
testBuild = new NotificationCompat.Builder(getActivity());
testBuild.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle("title")
.setContentText("teexttexttext")
.setLargeIcon(BitmapFactory.decodeResource(getResources(),R.mipmap.big))
.setAutoCancel(true);
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
testBuild.setProgress(100,i,false);
notificationManager.notify(3, testBuild.build());
SystemClock.sleep(100);
}
testBuild.setContentText("下载完成").setProgress(0, 0, false);
notificationManager.notify(3, testBuild.build());
}
}).start();
这里开启线程模拟下载文件,一直notificationManager.notify指定id就可以实现进度条更新,注意下载完成后要调用setProgress(0, 0, false)关掉进度条。
要在 Android 4.0 及更高版本的平台上使用进度指示器,需调用 setProgress()。对于早期版本,您必须创建包括 ProgressBar 视图的自定义通知布局。
奇行种,通过builder.setStyle修改通知布局
BigTextStyle的长文本通知
一般通知的ContentText只有一行,过长的话就用”…”代替,使用BigTextStyle可以实现多行ContentText,不过也只有ContentText多行,title,SummaryText也还是只有一行
Intent intent = new Intent(getActivity(), MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(getActivity(),0,intent,PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder testBuild = new NotificationCompat.Builder(getActivity());
testBuild.setContentIntent(pendingIntent);
testBuild = new NotificationCompat.Builder(getActivity());
testBuild.setStyle(new NotificationCompat.BigTextStyle().bigText("12bigTextbigTextbigTextbigTextbigTextbigTextbigTextbigTextbigTextbigTextbigTextbigTextbigTextbigTextbigText")
.setSummaryText("setSummaryTextsetSummaryTextsetSummaryTextsetSummaryTextsetSummaryTextsetSummaryTextsetSummaryTextsetSummaryTextsetSummaryTextsetSummaryTextsetSummaryTextsetSummaryTextsetSummaryTextsetSummaryTextsetSummaryTextsetSummaryText"));
testBuild.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle("title")
.setContentText("text")
.setContentIntent(pendingIntent)
.setLargeIcon(BitmapFactory.decodeResource(getResources(),R.mipmap.big))//当设置的时候,通知图标显示这个,而setSmallIcon显示在大图标的右下角,没设置的时候通知栏显示SmallIcon
.setAutoCancel(true);//点击通知之后通知会消失
testBuild.setNumber(++number);//标示当前有多少条通知,多条通知应该整合成一条,不然通知栏就泛滥了
notificationManager.notify(COM_ID, testBuild.build());//发送通知COM_ID为标示当前通知的id
当在BigTextStyle设置了bigText之后,下拉的过程中调用的是BigTextStyle的text,setContentTitle里面的内容就失效了。完全下拉的时候才生效,调用setContentTitle。
InboxStyle的多行文本通知
NotificationCompat.Builder builder = new NotificationCompat.Builder(getActivity());
builder.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle("title")
.setContentText("text");
NotificationCompat.InboxStyle inboxStyle = new NotificationCompat.InboxStyle();
inboxStyle.setSummaryText("setSummaryText");
inboxStyle.setBigContentTitle("setBigContentTitle");
inboxStyle.addLine("hello").addLine("==world").addLine("fuck");
builder.setStyle(inboxStyle);
builder.setSubText("subtext");
notificationManager.notify(6,builder.build());
addLine方法感觉类似StringBuilder,实现跨行追加,他也会占用setContentText,setSubText。完全下拉的时候不会占用
BigPictureStyle 带大图的通知
android5的截图通知就是用着叼方法。
Intent intent = new Intent(Intent.ACTION_VIEW);
PendingIntent pendingIntent = PendingIntent.getActivity(getActivity(),0,intent,PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder builder = new NotificationCompat.Builder(getActivity());
builder.setStyle(new NotificationCompat.BigPictureStyle().setSummaryText("setSummaryText").setBigContentTitle("setBigContentTitle").bigLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher)).bigPicture(BitmapFactory.decodeResource(getResources(), R.mipmap.tes1024)));
builder.setContentTitle("title")
.setContentText("text")
.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.big))
.setSmallIcon(R.mipmap.ic_launcher);
builder.addAction(android.R.drawable.ic_menu_close_clear_cancel,"取消",pendingIntent);
notificationManager.notify(5, builder.build());
下拉的时候调用的是BigPictureStyle里面的setSummaryText,setBigContentTitle等等,
下拉到底部就调用Builder的setContentText,setLargeIcon,setContentTitle了
MediaStyle 的媒体通知
这样子的,不说了,试不成功,不想去研究它了
自定义界面通知
Intent intent1 = new Intent(Intent.ACTION_VIEW,Uri.parse("http://www.baidu.com"));
PendingIntent pendingIntent1 = PendingIntent.getActivity(getActivity(),0,intent1,0);
NotificationCompat.Builder builder = new NotificationCompat.Builder(getActivity());
builder.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle("title")
.setContentText("text").setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.big));
RemoteViews remoteViews = new RemoteViews(getActivity().getPackageName(),R.layout.item);
remoteViews.setOnClickPendingIntent(R.id.image2, pendingIntent1);
builder.setContent(remoteViews);
Notification build = builder.build();
notificationManager.notify(8,build);
这里为第二个image设置了一个点击事件
RemoteViews中不能添加EditText。
基于前台服务的通知
只要服务运行,通知就关不了,比较常见,很多程序都使用
public class MyService extends Service {
public MyService() {
}
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
@Override
public void onCreate() {
super.onCreate();
Intent intent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this,0,intent,PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder testBuild = new NotificationCompat.Builder(this);
testBuild.setContentIntent(pendingIntent);
testBuild = new NotificationCompat.Builder(this);
testBuild.setVisibility(Notification.VISIBILITY_PRIVATE);
testBuild.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle("title")
.setContentText("text")
.setContentIntent(pendingIntent)
.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.big))//当设置的时候,通知图标显示这个,而setSmallIcon显示在大图标的右下角,没设置的时候通知栏显示SmallIcon
startForeground(1,testBuild.build());
}
}
Notification其他东西
启动 Activity 时保留导航
以下内容来自google官方文档:
从通知中启动 Activity 时,您必须保留用户的预期导航体验。 点击“返回”应该使用户将应用的正常工作流回退到主屏幕,而点击“最新动态”则应将 Activity 显示为单独的任务。 要保留导航体验,您应该在全新任务中启动 Activity。如何设置 PendingIntent 以获得全新任务取决于正在启动的 Activity 的性质。一般有两种情况:
常规 Activity
您要启动的 Activity 是应用的正常工作流的一部分。在这种情况下,请设置 PendingIntent 以启动全新任务并为 PendingIntent提供返回栈,这将重现应用的正常“返回”行为。
Gmail 应用中的通知演示了这一点。点击一封电子邮件消息的通知时,您将看到消息具体内容。 触摸返回将使您从 Gmail 回退到主屏幕,就好像您是从主屏幕(而不是通知)进入 Gmail 一样。
无论您触摸通知时处于哪个应用,都会发生这种情况。 例如,如果您在 Gmail 中撰写消息时点击了一封电子邮件的通知,则会立即转到该电子邮件。 触摸“返回”会依次转到收件箱和主屏幕,而不是转到您在撰写的邮件。
特殊 Activity
仅当从通知中启动时,用户才会看到此 Activity。 从某种意义上说,Activity 是通过提供很难显示在通知本身中的信息来扩展通知。对于这种情况,请将 PendingIntent 设置为在全新任务中启动。但是,由于启动的 Activity 不是应用 Activity 流程的一部分,因此无需创建返回栈。点击“返回”仍会将用户带到主屏幕。
设置常规 Activity PendingIntent
要设置可启动直接进入 Activity 的 PendingIntent,请执行以下步骤:
- 在清单文件中定义应用的 Activity 层次结构。
添加对 Android 4.0.3 及更低版本的支持。为此,请通过添加 元素作为 的子项来指定正在启动的 Activity 的父项。
对于此元素,请设置 android:name=”android.support.PARENT_ACTIVITY”。 设置 android:value=””,其中, 是父 元素的 android:name 值。请参阅下面的 XML 示例。
同样添加对 Android 4.1 及更高版本的支持。为此,请将 android:parentActivityName 属性添加到正在启动的 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>
- 根据可启动 Activity 的 Intent 创建返回栈:
创建 Intent 以启动 Activity。
通过调用 TaskStackBuilder.create() 创建堆栈生成器。
通过调用 addParentStack() 将返回栈添加到堆栈生成器。 对于在清单文件中所定义层次结构内的每个 Activity,返回栈均包含可启动 Activity 的 Intent 对象。此方法还会添加一些可在全新任务中启动堆栈的标志。
注:尽管 addParentStack() 的参数是对已启动 Activity 的引用,但是方法调用不会添加可启动 Activity 的 Intent,而是留待下一步进行处理。
通过调用 addNextIntent(),添加可从通知中启动 Activity 的 Intent。 将在第一步中创建的 Intent 作为 addNextIntent() 的参数传递。
如需,请通过调用 TaskStackBuilder.editIntentAt() 向堆栈中的 Intent 对象添加参数。有时,需要确保目标 Activity 在用户使用“返回”导航回它时会显示有意义的数据。
通过调用 getPendingIntent() 获得此返回栈的 PendingIntent。 然后,您可以使用此 PendingIntent 作为 setContentIntent() 的参数。
以下代码段演示了该流程:
Intent resultIntent = new Intent(this, ResultActivity.class);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
// Adds the back stack
stackBuilder.addParentStack(ResultActivity.class);
// Adds the Intent to the top of the stack
stackBuilder.addNextIntent(resultIntent);
// Gets a PendingIntent containing the entire back stack
PendingIntent 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());
addParentStack addNextIntent 的调用顺序觉得两个activity在栈的位置,
addNextIntent:Add a new Intent to the task stack. The most recently added Intent will invoke
the Activity at the top of the final task stack.最新添加的intent执行的时候放到栈顶,方法里面调用mIntents.add(nextIntent);
addParentStack:add the activity parent chain as specified by manifest <meta-data> elements to the task stack builder. 添加在meta-data中声明的父activity,最终也调用了mIntents.add(insertAt, parent);因此这两个谁最后添加,点击通知之后谁就显示在栈顶
设置特殊 Activity PendingIntent
下文介绍如何设置特殊 Activity PendingIntent。
特殊 Activity 无需返回栈,因此您不必在清单文件中定义其 Activity 层次结构,也不必调用 addParentStack() 来构建返回栈。取而代之的是,您可使用清单文件设置 Activity 任务选项,并通过调用 getActivity() 创建 PendingIntent:
- 在清单文件中,将以下属性添加到 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>
- 构建并发出通知:
创建可启动 Activity的 Intent。
通过使用 FLAG_ACTIVITY_NEW_TASK 和 FLAG_ACTIVITY_CLEAR_TASK 标志调用 setFlags(),将 Activity 设置为在新的空任务中启动。
为 Intent 设置所需的任何其他选项。
通过调用 getActivity() 从 Intent 中创建 PendingIntent。 然后,您可以使用此 PendingIntent 作为 setContentIntent() 的参数。
以下代码段演示了该流程:
// Instantiate a Builder object.
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
// Creates an Intent for the Activity
Intent notifyIntent =
new Intent(this, ResultActivity.class);
// Sets the Activity to start in a new, empty task
notifyIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_CLEAR_TASK);
// Creates the PendingIntent
PendingIntent notifyPendingIntent =
PendingIntent.getActivity(
this,
0,
notifyIntent,
PendingIntent.FLAG_UPDATE_CURRENT
);
// Puts the PendingIntent into the notification builder
builder.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 NotificationManager
mNotificationManager.notify(id, builder.build());
优先级-决定显示位置
您可以根据需要设置通知的优先级。优先级充当一个提示,提醒设备 UI 应该如何显示通知。 要设置通知的优先级,请调用 NotificationCompat.Builder.setPriority() 并传入一个 NotificationCompat 优先级常量。有五个优先级别,范围从 PRIORITY_MIN (-2) 到 PRIORITY_MAX (2);如果未设置,则优先级默认为 PRIORITY_DEFAULT (0)。
如何选择合适的优先级
DEFAULT、HIGH 和 MAX 是中断优先级别,在活动过程中有中断用户的风险。 为了避免打扰应用的用户,中断优先级仅保留用于以下通知 :
- 涉及另一个用户
- 时间敏感
可能会立即改变用户在现实世界中的行为
设置为 LOW 和 MIN 的通知可能仍然对用户很重要: 很多通知(如果不是绝大多数)不需要用户立即注意,也不需要振动,但仍然包含用户选择查看通知时将会觉得重要的信息。 LOW 和 MIN优先级通知的条件包括:
不涉及其他用户
- 不属于时间敏感型
- 包含用户可能感兴趣但可选择在空闲时浏览的内容
可见性
您的应用可以控制在安全锁定屏幕上显示的通知中可见的详细级别。 调用 setVisibility() 并指定以下值之一:
- VISIBILITY_PUBLIC 显示通知的完整内容。
- VISIBILITY_SECRET 不会在锁定屏幕上显示此通知的任何部分。
- VISIBILITY_PRIVATE 显示通知图标和内容标题等基本信息,但是隐藏通知的完整内容。
设置 VISIBILITY_PRIVATE 后,您还可以提供其中隐藏了某些详细信息的替换版本通知内容。例如,短信 应用可能会显示一条通知,指出“您有 3 条新短信”,但是隐藏了短信内容和发件人。要提供此替换版本的通知,请先使用 NotificationCompat.Builder 创建替换通知。创建专用通知对象时,请通过 setPublicVersion() 方法为其附加替换通知。
锁屏状态下才有效
浮动通知
对于 Android 5.0(API 级别 21),当设备处于活动状态时(即,设备未锁定且其屏幕已打开),通知可以显示在小型浮动窗口中(也称为“浮动通知”)。 这些通知看上去类似于精简版的通知,只是浮动通知还显示操作按钮。 用户可以在不离开当前应用的情况下处理或清除浮动通知。
可能触发浮动通知的条件示例包括:
- 用户的 Activity 处于全屏模式中(应用使用 fullScreenIntent),或者通知具有较高的优先级并使用铃声或振动
//或者
testBuild.setFullScreenIntent(pendingIntent,true);
//或者
testBuild.setPriority(Notification.PRIORITY_HIGH);
testBuild.setDefaults(Notification.DEFAULT_SOUND);
通知元数据
通知可根据您使用以下 NotificationCompat.Builder 方法分配的元数据进行排序:
- 当设备处于“优先”模式时,setCategory() 会告知系统如何处理应用通知(例如,通知代表传入呼叫、即时消息还是闹铃)。
- 如果优先级字段设置为 PRIORITY_MAX 或 PRIORITY_HIGH 的通知还有声音或振动,则 setPriority() 会将其显示在小型浮动窗口中。
- addPerson() 允许您向通知添加人员名单。您的应用可以使用此名单指示系统将指定人员发出的通知归成一组,或者将这些人员发出的通知视为更重要的通知。