Notification是通知单的意思,在windows中任务栏右边的系统状态栏就经常会弹出一个”气泡”,这个气泡就和android中Notification中是一样的概念。这种Notification 模式经常被应用在系统运行一些后台程序,当需要通知或提示前台一些信息的场景。比如在windows中,开机时如果防火墙是关闭状态,系统会在任务栏右边弹出一个“气泡”提示用户:防火墙未开启,如果点击那个气泡则会弹出防火墙设置菜单。在Android中也差不多是这样处理的,不过它有个更好的功能就是:将所有的Notification保存在列表中,当你点击列表中的条目时,系统就会启用这个条目相关的Notification中的Intent,然后切换Intent定义的Activity。而且Android中的Notification还允许用户可以定义它出现时伴随着手机闪烁、震动或铃声。
Notification的主要用途是给后台程序通知前台一些信息,或者要求前台做一些选择响应。使用Notification系统会在屏幕的上方的状态栏上显示提示信息,就在这里:
当系统有出现Notification时,用户可以通过将屏幕上方的状态栏往下拉的方式看到所有的Notification信息:
我们看看如何使用Notification。首先由上面的图我们可以发现,Notification只是整个NotificationManger的一部分,一个NotificationManager里可以有多个Notification,所以先要获取NotificationManager对象,使用它来管理Notification。
NotificationManager跟LayoutInflater一样是系统的service,所以你不需要创建它,而是调用Activity.getSystemService来获取:
1
2
|
String ns = Context.NOTIFICATION_SERVICE;
NotificationManager mNotificationManager = (NotificationManager) getSystemService(ns);
|
获取之后就需要创建Notification了,并配置它的属性:
1
2
3
4
5
|
int
icon = R.drawable.notification_icon;
CharSequence tickerText =
"Hello"
;
long
when = System.currentTimeMillis();
Notification notification =
new
Notification(icon, tickerText, when);
|
上面创建一个Notification,配置它的icon,显示内容和弹出Notification的时间。接着你需要定义一个当你点击Notification时需要启用的intent:
1
2
|
Intent notificationIntent =
new
Intent(
this
, MyClass.
class
);
PendingIntent contentIntent = PendingIntent.getActivity(
this
,
0
, notificationIntent,
0
);
|
配置完Intent后,就将这个配置完的Intent与Notification关联,然后将Notification提交给NotificationManager,让其弹出Notification:
1
|
notification.setLatestEventInfo(context, contentTitle, contentText, contentIntent);
|
综上代码我们总结出创建Notification需要下面几个步骤:
- 获取NotificationManager,这个对象不是创建的,而是由Activity.getSystemService获取。
- 创建Notification对象
- 配置Notification对象的icon,内容和时间。
- 创建一个PendingIntent,这个Intent就是当用户点击Notification时用来启用Activity的。
- 将上一步创建的PendingIntent与Notification关联,(点击Notification时启用该Intent)。
- 调用NotificationManger的notify方法将Notification显示到系统的状态栏。
现在我们写一个测试例子,测试弹出Notification,因为它需要intent来弹出一个Activity,所以我们先定义一个Activity:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
package
com.android777.demo.uicontroller;
import
android.app.Activity;
import
android.os.Bundle;
import
android.view.View;
import
android.widget.Button;
import
android.widget.CheckBox;
import
android.widget.ImageButton;
import
android.widget.RadioButton;
import
android.widget.Toast;
import
android.widget.ToggleButton;
public
class
ButtonActivity
extends
Activity {
@Override
protected
void
onCreate(Bundle savedInstanceState) {
super
.onCreate(savedInstanceState);
setContentView(R.layout.button);
Button btn = (Button) findViewById(R.id.button1);
btn.setOnClickListener(
new
View.OnClickListener() {
@Override
public
void
onClick(View v) {
Toast.makeText(ButtonActivity.
this
,
"Button点击事件"
, Toast.LENGTH_LONG).show();
}
});
}
}
|
然后在AndroidMenifest.xml文件中声明这个Activity:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
<?
xml
version
=
"1.0"
encoding
=
"utf-8"
?>
<
manifest
xmlns:android
=
"http://schemas.android.com/apk/res/android"
package
=
"com.android777.demo.uicontroller"
android:versionCode
=
"1"
android:versionName
=
"1.0"
>
<
application
android:icon
=
"@drawable/icon"
android:label
=
"@string/app_name"
>
<
activity
android:name
=
".notification.NotificationDemoActivity"
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
=
".ButtonActivity"
/>
</
application
>
</
manifest
>
|
NotificationDemoActivity.java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
|
package
com.android777.demo.uicontroller.notification;
import
com.android777.demo.uicontroller.ButtonActivity;
import
com.android777.demo.uicontroller.R;
import
android.app.Activity;
import
android.app.Notification;
import
android.app.NotificationManager;
import
android.app.PendingIntent;
import
android.content.Context;
import
android.content.Intent;
import
android.os.Bundle;
import
android.view.View;
import
android.view.View.OnClickListener;
import
android.view.ViewGroup.LayoutParams;
import
android.widget.Button;
import
android.widget.TextView;
public
class
NotificationDemoActivity
extends
Activity
implements
OnClickListener{
private
final
int
NOTIFY_ID =
1
;
@Override
protected
void
onCreate(Bundle savedInstanceState) {
super
.onCreate(savedInstanceState);
TextView btn =
new
TextView(
this
);
btn.setText(
"点击我显示Notification"
);
btn.setLayoutParams(
new
LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
setContentView(btn);
btn.setOnClickListener(
this
);
}
@Override
public
void
onClick(View v) {
//1.获取NotificationManager对象
NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
//2.创建Notification,配置它的属性
Notification n =
new
Notification();
n.icon = R.drawable.icon ;
//配置icon
n.tickerText =
"这是显示在状态的信息"
;
n.when = System.currentTimeMillis() ;
//创建点击Notification时 启用的intent
Intent intent =
new
Intent(
this
, ButtonActivity.
class
);
PendingIntent pendingIntent = PendingIntent.getActivity(
this
,
0
,
//requestCode
intent,
0
);
//flags
//将创建的PendingIntent 配置到Notification中
n.setLatestEventInfo(
this
,
"这个是标题"
,
"这是显示的内容"
, pendingIntent);
//将之前配置的Notification提交给NotificationManager,显示出来
nm.notify(NOTIFY_ID, n);
}
}
|
当点击TextView时:
我们可以看到在系统的状态栏上显示了一条信息,将状态栏往下拉动时可以看到:
当系统接收到多个Notification时,在状态栏上会上下滚动的显示这些Notification。NotificationManager为每个Notification赋上一个id值:
1
|
nm.notify(NOTIFY_ID, n);
|
所以每个Notification都是独立的。你还可以更新Notification在状态栏的显示信息和它本身的信息,因为它们都有一个唯一的id值,只要你notifiy一个存在的id值,那么原来的Notification就被修改成新的Notification,达到了更新的效果。 这样做总比添加一个新的Notification好,节省了内容空间和NotificationManager的显示空间。
你可以修改Notification的很多配置如控制它的提示音、震动频率和显示效果。
1. 修改提示音:
1
|
notification.sound = Uri.parse(
"file:///sdcard/notification/ringer.mp3"
);
|
2. 修改震动频率:
1
2
|
long
[] vibrate = {
0
,
100
,
200
,
300
};
notification.vibrate = vibrate;
|
上面的vibrate中的数值是ms值,数组表示的是震动和等待时间的交替间隔,如上面数组的意思是:等待0ms,震动100ms,等待200ms,震动300ms。
3. LED屏 闪光效果:
1
2
3
4
|
notification.ledARGB =
0xff00ff00
;
notification.ledOnMS =
300
;
notification.ledOffMS =
1000
;
notification.flags |= Notification.FLAG_SHOW_LIGHTS;
|
上面代码中的ledARGB是指LED闪的光的颜色,用ARGB表示,ledOnMS是指闪光持续多少ms,上面为例是持续300ms,同理ledOffMS是指关掉闪光的时间,最后那行是开启闪光效果。上面三种控制效果都可以使用默认值:
1
2
3
|
notification.defaults |= Notification.DEFAULT_LIGHTS;
notification.defaults |= Notification.DEFAULT_VIBRATE;
notification.defaults |= Notification.DEFAULT_SOUND;
|
Notification中的flags还提供了其他有用的功能:
1
|
notification.flags |= Notification.FLAG_AUTO_CANCEL;
|
Notification被选中(点击)就消失,即一点击执行内部的PendingIntent后就从NotificationManager中移除。
1
|
notification.flags |= Notification.FLAG_INSISTENT;
|
Notification持续重复提示音,直到用户做出响应。(除非情况紧急,否则别用这个吧,都烦死用户了。)
1
|
notification.flags |= Notification.FLAG_ONGOING_EVENT;
|
提示用户这个Notification的应用正在运行,比如后台音乐播放。
1
|
notification.flags |= Notification.FLAG_NO_CLEAR;
|
指示这个Notification不能被clear,这个一般用在“FLAG_ONGOING_EVENT”,因为“FLAG_ONGOING_EVENT”持续运行在后台,所以不能被clear掉。
在Notification中创建自定义的View视图
默认Notification由一个icon、一个title和contentText三个区域组成,但是它支持自定义布局,在这边它使用的是RemoteView。我们创建一个RemoteView对象,然后将它赋给Notification.contentView,然后配置它的Intent,最后由NotificationManager通过notify将其显示出来。
custom_notification_layout.xml:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
<
LinearLayout
xmlns:android
=
"http://schemas.android.com/apk/res/android"
android:orientation
=
"horizontal"
android:layout_width
=
"fill_parent"
android:layout_height
=
"fill_parent"
android:padding
=
"3dp"
>
<
ImageView
android:id
=
"@+id/image"
android:layout_width
=
"wrap_content"
android:layout_height
=
"fill_parent"
android:layout_marginRight
=
"10dp"
/>
<
TextView
android:id
=
"@+id/text"
android:layout_width
=
"wrap_content"
android:layout_height
=
"fill_parent"
android:textColor
=
"#000"
/>
</
LinearLayout
>
|
1
2
3
4
5
6
7
8
9
10
11
|
//设置View
RemoteViews contentView =
new
RemoteViews(getPackageName(), R.layout.custom_notification_layout);
contentView.setImageViewResource(R.id.image, R.drawable.notification_image);
contentView.setTextViewText(R.id.text,
"Hello, this message is in a custom expanded view"
);
notification.contentView = contentView;
//设置Intent
Intent notificationIntent =
new
Intent(
this
, MyClass.
class
);
PendingIntent contentIntent = PendingIntent.getActivity(
this
,
0
, notificationIntent,
0
);
notification.contentIntent = contentIntent;
//弹出Notification
mNotificationManager.notify(CUSTOM_VIEW_ID, notification);
|