安卓更新挺快,以至于之前学的关于通知的使用方法都过时了
现在重新再写个文章记录一下
创建通知
Android 3.0 (API level 11)之前,使用new Notification()方式创建通知:
NotificationManager mNotifyMgr =
(NotificationManager) getSystemService(NOTIFICATION_SERVICE);
PendingIntent contentIntent = PendingIntent.getActivity(
this, 0, new Intent(this, ResultActivity.class), 0);
Notification notification = new Notification(icon, tickerText, when);
notification.setLatestEventInfo(this, title, content, contentIntent);
mNotifyMgr.notify(NOTIFICATIONS_ID, notification);
Android 3.0 (API level 11)及更高版本,改用Notification.Builder()来创建通知:
NotificationManager mNotifyMgr =
(NotificationManager) getSystemService(NOTIFICATION_SERVICE);
PendingIntent contentIntent = PendingIntent.getActivity(
this, 0, new Intent(this, ResultActivity.class), 0);
Notification notification = new Notification.Builder(this)
.setSmallIcon(R.drawable.notification_icon)
.setContentTitle("My notification")
.setContentText("Hello World!")
.setContentIntent(contentIntent)
.build();// getNotification()
mNotifyMgr.notify(NOTIFICATIONS_ID, notification);
这里需要注意: "build()" 是Androdi 4.1(API level 16)加入的,用以替代
"getNotification()"。API level 16开始弃用"getNotification()"
通知基本用法
一个通知必须包含以下三项属性:
- 小图标,对应 setSmallIcon()
- 通知标题,对应 setContentTitle()
- 详细信息,对应 setContentText()
其他属性均为可选项,更多属性方法请参考NotificationCompat.Builder。
尽管其他都是可选的,但一般都会为通知添加至少一个动作(Action),这个动作可以是跳转到Activity、启动一个Service或发送一个Broadcas等。 通过以下方式为通知添加动作:
- 使用PendingIntent
- 通过大视图通知的 Action Button //仅支持Android 4.1 (API level 16)及更高版本,稍后会介绍
创建通知
1、实例化一个NotificationCompat.Builder对象
NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle("我是头部")
.setContentText("内容内容内容内容内容内容内容内容");
NotificationCompat.Builder会自动设置默认值:
- priority: PRIORITY_DEFAULT --------优先级,有五个优先级别,范围从
PRIORITY_MIN(-2) 到PRIORITY_MAX(2);默认为PRIORITY_DEFAULT(0)。 - when: System.currentTimeMillis()--------通知创建的时间,有的手机会显示,有的不会
- audio stream: STREAM_DEFAULT--------当声音响起时,所用的音频流的类型
PendingIntent类中的动作是Context类中的几个方法之一,例如startActivity,startService,sendBroadcast
使用PendingIntent来启动一个Activity
Intent resultIntent = new Intent(this, ResultActivity.class);
PendingIntent resultPendingIntent = PendingIntent.getActivity(
this, 0, resultIntent, PendingIntent.FLAG_UPDATE_CURRENT);
mBuilder.setContentIntent(resultPendingIntent);
PendingIntent pi = PendingIntent.getActivity(Context context, int requestCode,Intent intent, int flags);
这些方法决定了最终PendingIntent所能执行的动作,可以用来启动Activity,启动Service,发送广播等
3、NotificationManager
NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(int id, notification);
Notification对象
Notificatioin notification = Builder.build();
通知ID用于标识该通知,在想要取消特定Notification的时候,就需要使用到它
mNotificationManager.cancel(int id);
此外,除非发生以下情况之一,否则通知会一直可见:
- 用户单独或通过使用“全部清除”清除了该通知(如果通知可以清除)
- 用户点击通知,且在创建通知时调用了 setAutoCancel(true)
- 针对特定的通知 ID 调用了 cancel(int id)
- 调用了 cancelAll() 方法,该方法将删除之前发出的所有通知
更新通知
更新通知很简单,只需再次发送相同ID的通知即可,如果之前的通知依然存在则会更新通知属性,如果之前通知不存在则重新创建。
取消通知
取消通知有如下4种方式:
- 点击通知栏的清除按钮,会清除所有可清除的通知
- 设置了 setAutoCancel() 或 FLAG_AUTO_CANCEL的通知,点击该通知时会清除它
- 通过 NotificationManager 调用 cancel() 方法清除指定ID的通知
- 通过 NotificationManager 调用 cancelAll() 方法清除所有该应用之前发送的通知
创建简单通知
private int id = 1;
public void notification(View view) {
Drawable drawable = ContextCompat.getDrawable(this, R.drawable.ic_submit);
Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap();
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this);
//设置小图标
mBuilder.setSmallIcon(R.mipmap.ic_launcher);
//设置大图标
mBuilder.setLargeIcon(bitmap);
//设置标题
mBuilder.setContentTitle("这是标题");
//设置通知正文
mBuilder.setContentText("这是正文,当前ID是:" + id);
//设置摘要
mBuilder.setSubText("这是摘要");
//设置是否点击消息后自动clean
mBuilder.setAutoCancel(true);
//在通知的右边设置大的文本。
mBuilder.setContentInfo("右侧文本");
//与setContentInfo类似,但如果设置了setContentInfo则无效果
//用于当显示了多个相同ID的Notification时,显示消息总数
mBuilder.setNumber(2);
//通知在状态栏显示时的文本
mBuilder.setTicker("在状态栏上显示的文本");
//设置优先级
mBuilder.setPriority(NotificationCompat.PRIORITY_MAX);
//自定义消息时间,以毫秒为单位,当前设置为比系统时间少一小时
mBuilder.setWhen(System.currentTimeMillis() - 3600000);
//设置为一个正在进行的通知,此时用户无法清除通知
mBuilder.setOngoing(true);
//设置消息的提醒方式,震动提醒:DEFAULT_VIBRATE 声音提醒:NotificationCompat.DEFAULT_SOUND
//三色灯提醒NotificationCompat.DEFAULT_LIGHTS 以上三种方式一起:DEFAULT_ALL
mBuilder.setDefaults(NotificationCompat.DEFAULT_SOUND);
//设置震动方式,延迟零秒,震动一秒,延迟一秒、震动一秒
mBuilder.setVibrate(new long[]{0, 1000, 1000, 1000});
Intent intent = new Intent(this, ShadowTextViewActivity.class);
PendingIntent pIntent = PendingIntent.getActivity(this, 0, intent, 0);
mBuilder.setContentIntent(pIntent);
NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(id++, mBuilder.build());
}
public void cleanNotification(View view) {
NotificationManager mNotificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.cancelAll();
mNotificationManager.cancel(1);
}
通知类型
大视图通知
通知有两种视图:普通视图和大视图。
普通视图:
大视图:
默认情况下为普通视图,可通过NotificationCompat.Builder.setStyle()设置大视图。
注: 大视图(Big Views)由Android 4.1(API level 16)开始引入,且仅支持Android 4.1及更高版本。
构建大视图通知
Drawable drawable = ContextCompat.getDrawable(this, R.drawable.ic_submit);
Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap();
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this);
//设置小图标
mBuilder.setSmallIcon(R.mipmap.ic_launcher);
//设置大图标
mBuilder.setLargeIcon(bitmap);
//设置标题
mBuilder.setContentTitle("这是标题");
//设置通知正文
mBuilder.setContentText("这是正文,当前ID是:" + id);
//设置优先级
mBuilder.setPriority(NotificationCompat.PRIORITY_MAX);
//设置为一个正在进行的通知,此时用户无法清除通知
mBuilder.setOngoing(true);
mBuilder.setDefaults(NotificationCompat.DEFAULT_SOUND);
Intent intent = new Intent(this, ShadowTextViewActivity.class);
PendingIntent pIntent = PendingIntent.getActivity(this, 0, intent, 0);
mBuilder.setContentIntent(pIntent);
// 该方法在Android 4.1之前会被忽略
mBuilder.setStyle(new NotificationCompat.BigTextStyle()
.bigText("这里可以显示一大串文字,你可以试试\n这里可以显示一大串文字,你可以试试\n这里可以显示一大串文字,你可以试试\n这里可以显示一大串文字,你可以试试"))
//添加Action Button
.addAction (R.mipmap.ic_launcher,
"取消", pIntent)
.addAction (R.mipmap.ic_launcher,
"确定", pIntent);
NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(id, mBuilder.build());
效果图如下
Drawable drawable = ContextCompat.getDrawable(this, R.drawable.ic_loading_fail);
Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap();
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
builder.setContentTitle("这是标题");
builder.setContentText("这是正文");
builder.setSmallIcon(R.drawable.ic_circulation);
builder.setLargeIcon(BitmapFactory.decodeResource(getResources(),R.drawable.ic_submit));
builder.setDefaults(NotificationCompat.DEFAULT_ALL);
builder.setAutoCancel(true);
NotificationCompat.BigPictureStyle style = new NotificationCompat.BigPictureStyle();
style.setBigContentTitle("展开后的标题");
style.setSummaryText("这是摘要");
style.bigPicture(bitmap);
builder.setStyle(style);
Intent intent = new Intent(this, ShadowTextViewActivity.class);
PendingIntent pIntent = PendingIntent.getActivity(this, 0, intent, 0);
builder.setContentIntent(pIntent);
NotificationManager mNotificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(id, builder.build());
效果图如下
进度条通知
-
明确进度的进度条
使用setProgress(max, progress, false)来更新进度。
max: 最大进度值
progress: 当前进度
false: 是否是不明确的进度条模拟下载过程,示例如下:
int id = 1;
...
mNotifyManager = (NotificationManager)
getSystemService(Context.NOTIFICATION_SERVICE);
mBuilder = new NotificationCompat.Builder(this);
mBuilder.setContentTitle("Picture Download")
.setContentText("Download in progress")
.setSmallIcon(R.drawable.ic_notification);
// Start a lengthy operation in a background thread
new Thread(
new Runnable() {
@Override
public void run() {
int incr;
for (incr = 0; incr <= 100; incr+=5) {
mBuilder.setProgress(100, incr, false);
mNotifyManager.notify(id, mBuilder.build());
try {
// Sleep for 5 seconds
Thread.sleep(5*1000);
} catch (InterruptedException e) {
Log.d(TAG, "sleep failure");
}
}
mBuilder.setContentText("Download complete")//下载完成
.setProgress(0,0,false); //移除进度条
mNotifyManager.notify(id, mBuilder.build());
}
}
).start();
-
上图,分别为下载过程中进度条通知 和 下载完成移除进度条后的通知。 -
不确定进度的进度条
使用setProgress(0, 0, true)来表示进度不明确的进度条mBuilder.setProgress(0, 0, true); mNotifyManager.notify(id, mBuilder.build());
启动 Activity 时保留导航
从通知中启动 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 及更低版本的支持。为此,请通过添加
<meta-data>元素作为<activity>的子项来指定正在启动的Activity的父项。对于此元素,请设置
android:name="android.support.PARENT_ACTIVITY"。 设置android:value="<parent_activity_name>",其中,<parent_activity_name>是父<activity>元素的android:name值。请参阅下面的 XML 示例。 - 同样添加对 Android 4.1 及更高版本的支持。为此,请将
android:parentActivityName属性添加到正在启动的Activity的<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>
- 添加对 Android 4.0.3 及更低版本的支持。为此,请通过添加
- 根据可启动
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());
设置特殊 Activity PendingIntent
下文介绍如何设置特殊 Activity PendingIntent。
特殊 Activity 无需返回栈,因此您不必在清单文件中定义其 Activity 层次结构,也不必调用 addParentStack() 来构建返回栈。取而代之的是,您可使用清单文件设置 Activity 任务选项,并通过调用 getActivity() 创建 PendingIntent:
- 在清单文件中,将以下属性添加到
Activity的<activity>元素- Activity 的完全限定类名。
-
与您在代码中设置的
FLAG_ACTIVITY_NEW_TASK标志相结合,这可确保此Activity不会进入应用的默认任务。任何具有应用默认关联的现有任务均不受影响。 - 将新任务从“最新动态”中排除,这样用户就不会在无意中导航回它。
android:name="activityclass"android:taskAffinity=""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());
- 创建可启动
自定义通知布局
您可以利用通知框架定义自定义通知布局,由该布局定义通知在 RemoteViews 对象中的外观。 自定义布局通知类似于常规通知,但是它们是基于 XML 布局文件中所定义的 RemoteViews。
自定义通知布局的可用高度取决于通知视图。普通视图布局限制为 64 dp,扩展视图布局限制为 256 dp。
要定义自定义通知布局,请首先实例化 RemoteViews 对象来扩充 XML 布局文件。然后,调用 setContent(),而不是调用 setContentTitle() 等方法。要在自定义通知中设置内容详细信息,请使用 RemoteViews 中的方法设置视图子项的值:
- 在单独的文件中为通知创建 XML 布局。您可以根据需要使用任何文件名,但必须使用扩展名
.xml。 - 在您的应用中,使用
RemoteViews方法定义通知的图标和文本。通过调用setContent()将此RemoteViews对象放入NotificationCompat.Builder中。避免在RemoteViews对象上设置背景Drawable,因为文本颜色可能使文本变得难以阅读。
此外,RemoteViews 类中还有一些方法可供您轻松将 Chronometer 或 ProgressBar 添加到通知布局。如需了解有关为通知创建自定义布局的详细信息,请参阅 RemoteViews 参考文档。
注意:使用自定义通知布局时,要特别注意确保自定义布局适用于不同的设备方向和分辨率。 尽管这条建议适用于所有“视图”布局,但对通知尤为重要,因为抽屉式通知栏中的空间非常有限。 不要让自定义布局过于复杂,同时确保在各种配置中对其进行测试。
本文介绍了Android 3.0及以上版本创建通知的方法,包括使用NotificationCompat.Builder的基本用法,如何更新和取消通知,创建大视图和进度条通知,以及在启动Activity时保留导航的实现。此外,还讲解了如何设置自定义通知布局和理解Android通知的使用要点。
515

被折叠的 条评论
为什么被折叠?



