转载请注明出处:http://blog.csdn.net/h_zhang/article/details/51114733
通知(Notification)是Android中一个比较有特色的功能,由于受到用户的认可和喜爱,IOS后来也加入了类似的功能。那么本篇文章就对Android Notification的使用方法做一个详细说明。Notification实际上是一则消息,不过这个消息显示在应用程序UI界面之外。也即是说,当你发出一条通知,它首先会在手机最上方的状态栏显示一个通知图标,下拉状态栏后可以看到通知详细内容。
创建一个最简单的通知
创建一个通知,你需要首先创建Notification.Builder对象,语法如下:
Notification.Builder builder = new Notification.Builder(this)
其中,this是Context实例。
然后使用builder开始构建通知的外观,有三个内容必须要进行设置的,缺一不可。
- 通知图标:由
builder.setSmallIcon()
设置 - 通知标题:由
builder.setContentTitle()
设置 - 通知内容:由
builder.setContentText()
设置
下表列出了Notification.Builder类中的其他一些常用方法:
方法定义 | 方法说明 |
---|---|
setAutoCancel(true) | 点击通知后,通知自动被销毁 |
setLargeIcon (Bitmap b) | 设置通知的大图标 |
setProgress (int max, int progress, boolean indeterminate) | 设置通知中显示进度条 |
setSound (Uri sound, AudioAttributes audioAttributes) | 设置通知发出后的音效 |
setVibrate (long[] pattern) | 设置通知发出后的震动效果 |
setLights (int argb, int onMs, int offMs) | 设置通知发出后的LED灯的闪烁效果 |
setContentIntent (PendingIntent intent) | 点击通知时触发的PendingIntent |
接着就调用NotificationCompat.Builder.build()
方法来创建出Notification实例。最后将创建出来的Notification实例传递给NotificationManager.notify()
方法就可以弹出一条通知。
下面代码创建并显示了一个最简单的通知:
布局文件,activity_main.xml :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:context="cn.hebut.notification.MainActivity"
tools:showIn="@layout/activity_main">
<Button
android:id="@+id/id_notification"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Notification"
android:onClick="notification"/>
</LinearLayout>
MainActivity.java :
public class MainActivity extends AppCompatActivity
{
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
public void notification(View view)
{
NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
Notification.Builder builder =
new Notification.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher)
.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher))
.setContentTitle("通知标题")
.setContentText("通知内容")
.setAutoCancel(true);
manager.notify(0, builder.build());
}
}
调用setAutoCancel(true)
方法,保证在点击通知之后,通知自动被销毁。最后一行manager.notify(0, builder.build());
用于发出一条通知。第一个参数是一个id,用于唯一标识一个通知;第二个参数就是一个Notificaton对象。下面贴一下程序运行效果:
当你去点击这条通知的时候不会有任何效果。不对啊,好像点击每条通知都会有反应的呀?其实,要想点击通知有反应,就得借助PendingIntent
来实现。那么什么是PendingIntent呢?PendintIntent和Intent又有什么区别呢?从字面上来看PendingIntent是一个挂起的Intent,PendingIntent本质上也是一个Intent,不同的是,Intent更倾向于立即执行某个动作,而PendingIntent更倾向于在某个合适的时机去执行某个动作。也可以把PendingIntent理解为某个延迟执行的Intent。下面代码实现点击通知时弹出一个新的Activity。
点击通知弹出的Activity布局文件, content_notification.xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="hello world"
android:textSize="22sp"/>
</LinearLayout>
对于MainActivity.java我就贴出有变化的代码,MainActivity.java:
public void notification(View view)
{
NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
Notification.Builder builder =
new Notification.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher)
.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher))
.setContentTitle("通知标题")
.setContentText("通知内容")
.setAutoCancel(true);
Intent intent = new Intent(this, NotificationActivity.class);
PendingIntent pi = PendingIntent.getActivity(this, 0, //
intent, PendingIntent.FLAG_UPDATE_CURRENT);
builder.setContentIntent(pi);
manager.notify(0, builder.build());
}
前面代码没有变化。第13行,创建了一个Intent实例,这个Intent用于启动NotificationActivity;第14行,使用PendingIntent.getActivity()
方法创建一个PendingIntent实例,第一个参数是Context对象;第二个参数是requestCode,一般传0就可以;第三个参数是一个Intent对象;第四个参数是flag,这里给PendingIntent.FLAG_UPDATE_CURRENT
,当然还有别的flag,大家可以查阅相关文档。第16行,调用builder.setContentIntent(pi)
方法将创建好的PendingIntent对象设置进去。下面是程序运行效果:
Activity from a notification
当用户点击通知启动一个Activity时,你就必须考虑到这个Activity用途是什么。根据需求的不同,Android给出了两种Activity:一种叫做Special Activity。由于本身的局限性,通知中无法展示大量的信息,所以需要借助Activity将信息进行显示。简单说,Special Activity仅仅是通知的延伸;令一种叫Regular Activity,将启动的Activity作为应用程序工作流中的一部分。这种Activity与应用程序是紧密耦合的,而不仅仅是通知的延伸。下面介绍这两种Activity的使用方法。
Special Activity
本文第一部分“创建一个最简单的通知”中,点击通知后弹出的Activity就是一个Special Activity。它的作用仅仅是通知的延伸,用于显示在通知中无法详细显示的信息。这种Activity在Manifest文件中注册的时候,一般需要做如下配置:
<activity
android:name=".NotificationActivity"
android:launchMode="singleTask"
android:excludeFromRecents="true">
</activity>
android:launchMode="singleTask"
表明该Activity在全局只有一个实例;android:excludeFromRecents="true"
表明在最近列表中不显示该Activity。
Regular Activity
对于Regular Activity,需要按如下步骤进行创建:
1. 创建一个Intent,用于启动点击通知后弹出的Activity
2. 通过调用TaskStackBuilder.create()
方法创建一个返回栈
3. 通过addParentStack()
将返回栈添加都栈构建器中
4. 调用addNextIntent()
并将第一步创建的Intent作为参数传入
最后在Manifest文件中注册该Activity时,需要指明Activity的层级关系:
<activity
android:name=".NotificationActivity"
android:parentActivityName=".MainActivity">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".MainActivity"/>
</activity>
下面我写了一个示例,用于展示Regular Activity的用法:
MainActivity.java:
public class MainActivity extends AppCompatActivity
{
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
public void notification(View view)
{
NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
Notification.Builder builder =
new Notification.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher)
.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher))
.setContentTitle("通知标题")
.setContentText("通知内容")
.setAutoCancel(true);
Intent intent = new Intent(this, NotificationActivity.class);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
stackBuilder.addParentStack(NotificationActivity.class);
stackBuilder.addNextIntent(intent);
PendingIntent pi = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
builder.setContentIntent(pi);
manager.notify(0, builder.build());
}
}
第25~27行,创建了一个返回栈,并把第24行创建的Intent对象添加到栈顶;第28行,利用stackBuilder.getPendingIntent()方法得到一个PendingIntent对象;第29行,将PendingIntent对象设置到builder中;最后调用manager.notify()发布该通知。
布局文件没有变,我就不贴了。
最后,在Manifest文件中注册该Activity:
<activity
android:name=".NotificationActivity"
android:parentActivityName=".MainActivity">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".MainActivity"/>
</activity>
下面是程序运行效果:
可以看到,当我们退出通过点击通知产生的Activity后,并没有返回到Android桌面,而是返回到了应用程序的Activity中。
动态更新通知内容
前面发布一个通知,最终调用了manager.notify(0, builder.build())
方法。这个方法第一个参数是通知ID。所以,你想更新通知内容,也是调用该方法,只要保证ID是你想要更新的通知即可。
下面代码片段展示了更新通知的用法:
public void notification(View view)
{
final NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
final Notification.Builder builder =
new Notification.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher)
.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher))
.setContentTitle("通知标题")
.setContentText("通知内容")
.setAutoCancel(true);
manager.notify(0, builder.build());
new Thread(new Runnable()
{
@Override
public void run()
{
int num = 10;
for(int i = 1; i <= num; i++)
{
builder.setContentText("通知内容" + i);
manager.notify(0, builder.build());
try
{
Thread.sleep(1 * 1000);
} catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
}).start();
}
当调用manager.notify(0, builder.build())
方法的时候,系统会先检查ID为0的通知是否存在。如果通知不存在就创建该通知,如果通知已经存在就对通知直接更新。
下图为程序运行效果:
在通知里显示进度条
现在很多APP都提供下载功能。比如常用的视频播放APP(优酷,土豆,爱奇艺),都支持视频下载功能。在视频下载的时候,这些APP也会发布一个通知,并在通知里显示当前视频下载的进度。下面就讲解一下如何在通知里显示进度条。
进度条分为两种,一种是确定性的,一种是不确定性的。当你能估计操作(比如,下载)的时长,你可以使用确定性进度条;当你无法估计操作的时长,就可以使用不确定性进行条。
在通知中显示进度条也非常方便,调用Notification.Builder类中的setProgress (int max, int progress, boolean indeterminate)
方法即可。第一个参数是进度最大值,一般给100;第二个参数是当前进度;第三个参数指明是确定性进度条还是不确定性进度条;
当下载操作完成后,你需要向用户提示操作完成并移除进度条。移除进度条调用setProgress(0, 0, false)
即可。下面给出示例:
MainActivity.java :
public class MainActivity extends AppCompatActivity
{
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
public void notification(View view)
{
final NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
final Notification.Builder builder =
new Notification.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher)
.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher))
.setContentTitle("下载视频")
.setContentText("视频正在下载...");
new Thread(new Runnable()
{
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
@Override
public void run()
{
int progress;
for (progress = 0; progress <= 100; progress += 10)
{
//确定性进度条
builder.setProgress(100, progress, false);
manager.notify(0, builder.build());
try
{
Thread.sleep(1 * 1000);
} catch (InterruptedException e)
{
e.printStackTrace();
}
}
//提示下载结束,并移除进度条
builder.setContentText("下载完成")
.setProgress(0, 0, false);
manager.notify(0, builder.build());
}
}).start();
}
}
代码也很简单。开了一个子线程用于模拟下载操作,在子线程中通过调用builder.setProgress(100, progress, false)
方法显示当前进度,然后调用manager.notify(0, builder.build())
方法来发布该通知。最后,当下载操作完成,给出提示并从通知中移除进度条。
下图是程序运行效果:
那么,如果想要显示不确定性进度条只需要将上面代码第34行builder.setProgress(100, progress, false)
修改为builder.setProgress(0, 0, true)
即可。然后继续调用manager.notify(0, builder.build())
方法来发布该通知。
程序运行效果如下所示:
OK,本篇文章到这就结束了。关于Android通知的用法,就先讲解这么多。通过对本文的学习,相信大家能够基本掌握通知的用法。谢谢大家观看~~~