Android Notification 的使用

最近一直在研究 android ,并一边研究一边做应用。其中遇到了把程序通知常驻在 Notification 栏,并且不能被 clear 掉(就像android QQ一样)的问题。经过研究实现了其功能,现把 Notification 的使用总结如下:

Notification 的使用需要导入 3 个类

1 2 3 importandroid.app.PendingIntent; importandroid.app.NotificationManager; importandroid.app.Notification;

代码示例及说明

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 NotificationManager nm = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE); Notification n = newNotification(R.drawable.chat,"Hello,there!", System.currentTimeMillis()); n.flags = Notification.FLAG_AUTO_CANCEL; Intent i = newIntent(arg0.getContext(), NotificationShow.class); i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_ACTIVITY_NEW_TASK); //PendingIntent PendingIntent contentIntent = PendingIntent.getActivity( arg0.getContext(), R.string.app_name, i, PendingIntent.FLAG_UPDATE_CURRENT); n.setLatestEventInfo( arg0.getContext(), "Hello,there!", "Hello,there,I'm john.", contentIntent); nm.notify(R.string.app_name, n);

下面依次对每一段代码进行分析:

1 NotificationManager nm = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);

创建 NotificationManager,其中创建的 nm 对象负责“发出”与“取消” Notification。

1 2 Notification n = newNotification(R.drawable.chat,"Hello,there!", System.currentTimeMillis()); n.flags = Notification.FLAG_ONGOING_EVENT;

创建 Notification ,参数依次为:icon的资源id,在状态栏上展示的滚动信息,时间。其中创建的 n 对象用来描述出现在系统通知栏的信息,之后我们将会看到会在 n 对象上设置点击此条通知发出的Intent。

1 n.flags = Notification.FLAG_AUTO_CANCEL;

设置 n.flags 为 Notification.FLAG_AUTO_CANCEL ,该标志表示当用户点击 Clear 之后,能够清除该通知。

1 2 Intent i = newIntent(arg0.getContext(), NotificationShow.class); i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_ACTIVITY_NEW_TASK);

创建一个Intent,该Intent使得当用户点击该通知后发出这个Intent

请注意,如果要以该Intent启动一个Activity,一定要设置 Intent.FLAG_ACTIVITY_NEW_TASK 标记。

Intent.FLAG_ACTIVITY_CLEAR_TOP :如果在当前Task中,有要启动的Activity,那么把该Acitivity之前的所有Activity都关掉,并把此Activity置前以避免创建Activity的实例

Intent.FLAG_ACTIVITY_NEW_TASK :系统会检查当前所有已创建的Task中是否有该要启动的Activity的Task,若有,则在该Task上创建Activity,若没有则新建具有该Activity属性的Task,并在该新建的Task上创建Activity。更多请参见 “(转载)Android下Affinities和Task”

1 2 3 4 5 6 //PendingIntent PendingIntent contentIntent = PendingIntent.getActivity( arg0.getContext(), R.string.app_name, i, PendingIntent.FLAG_UPDATE_CURRENT);

PendingIntent 为Intent的包装,这里是启动Intent的描述,PendingIntent.getActivity 返回的PendingIntent表示,此PendingIntent实例中的Intent是用于启动 Activity 的Intent。PendingIntent.getActivity的参数依次为:Context,发送者的请求码(可以填0),用于系统发送的Intent,标志位。

其中 PendingIntent.FLAG_UPDATE_CURRENT 表示如果该描述的PendingIntent已存在,则改变已存在的PendingIntent的Extra数据为新的PendingIntent的Extra数据。

PendingIntent :包装Intent,Intent 是我们直接使用 startActivity , startService 或 sendBroadcast 启动某项工作的意图。而某些时候,我们并不能直接调用startActivity , startServide 或 sendBroadcast ,而是当程序或系统达到某一条件才发送Intent。如这里的Notification,当用户点击Notification之后,由系统发出一条Activity 的 Intent 。因此如果我们不用某种方法来告诉系统的话,系统是不知道是使用 startActivity ,startService 还是 sendBroadcast 来启动Intent 的(当然还有其他的“描述”),因此这里便需要PendingIntent。

1 2 3 4 5 n.setLatestEventInfo( arg0.getContext(), "Hello,there!", "Hello,there,I'm john.", contentIntent);

设置显示在通知下拉框中的信息,参数依次为:Context,标题,内容,PendingIntent。

1 nm.notify(R.string.app_name, n);

启动Notification,参数依次为:在你的程序中标识Notification的id值(用来区分同一程序中的不同Notifycation,如果程序中只有一个Notification那么这里随便你填什么都可以,不过类型必须要为int),要通知的Notification。

如何使自己的Notification像Android QQ一样能出现在 “正在运行的”栏目下面

其实很简单,只需设置Notification.flags = Notification.FLAG_ONGOING_EVENT;便可以了。

如何改变 Notification 在“正在运行的”栏目下面的布局

创建 RemoteViews 并赋给 Notification.contentView ,再把 PendingIntent 赋给 Notification.contentIntent 便可以了,如:

1 2 3 4 5 6 7 8 9 10 11 12 13 PendingIntent contentIntent = PendingIntent.getActivity( arg0.getContext(), R.string.app_name, i, PendingIntent.FLAG_UPDATE_CURRENT); RemoteViews rv = newRemoteViews(Main.this.getPackageName(), R.layout.notification_view); rv.setImageViewResource(R.id.image, R.drawable.chat); rv.setTextViewText(R.id.text,"Hello,there,I'm john."); n.contentView = rv; n.contentIntent = contentIntent; nm.notify(R.string.app_name, n);

注意,如果使用了contentView,那么便不要使用Notification.setLatestEventInfo。如果setLatestEventInfo在赋给 Notification.contentView 的代码之后,那么contentView的效果将被覆盖,显示的便是 setLatestEventInfo 的效果;如果 setLatestEventInfo 在 Notification.contentView 的代码之前,那么显示的便是 Notification.contentView 的效果,也就是说不管你想要setLatestEventInfo 或 contentView 的自定义效果,请保证始终只有一句设置代码,因为在最后一句绑定的时候,之前的设置contentView或setLatestEventInfo的代码都是完全没有必要的。

PendingIntent字面意义:等待的,未决定的Intent。
要得到一个pendingIntent对象,使用方法类的静态方法getActivity(Context, int, Intent, int),getBroadcast(Context, int, Intent, int),
getService(Context, int, Intent, int) 分别对应着Intent的3个行为,跳转到一个activity组件、打开一个广播组件和打开一个服务组件。
参数有4个,比较重要的事第三个和第一个,其次是第四个和第二个。可以看到,要得到这个对象,必须传入一个Intent作为参数,必须有context作为参数。

<wbr style="line-height:26px; text-align:left"><span style="line-height:26px; text-align:left">pendingIntent是一种特殊的Intent。主要的区别在于Intent的执行立刻的,而<wbr>pendingIntent的执行不是立刻的。<wbr>pendingIntent执行的操作实质上是参数传进来的Intent的操作,但是使用<wbr>pendingIntent的目的在于它所包含的Intent的操作的执行是需要满足某些条件的。<br> 主要的使用的地方和例子:通知<span lang="EN-US">Notificatio的发送,短消息</span><span lang="EN-US">SmsManager</span></wbr></wbr></wbr></span><span lang="EN-US" style="line-height:26px; text-align:left">的发送和警报器AlarmManager的执行等等。<br></span><span style="line-height:26px; text-align:left"></span></wbr>

Android的状态栏通知(Notification)

如果需要查看消息,可以拖动状态栏到屏幕下方即可查看消息。

步骤:

1获取通知管理器NotificationManager,它也是一个系统服务

2建立通知Notification notification = new Notification(icon, null, when);

3为新通知设置参数(比如声音,震动,灯光闪烁)

4把新通知添加到通知管理器

发送消息的代码如下:

//获取通知管理器

NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE)

int icon = android.R.drawable.stat_notify_chat;

long when = System.currentTimeMillis();//通知发生的时间为系统当前时间

//新建一个通知,指定其图标和标题

Notification notification = new Notification(icon, null, when);//第一个参数为图标,第二个参数为短暂提示标题,第三个为通知时间

notification.defaults = Notification.DEFAULT_SOUND;//发出默认声音

notification.flags |= Notification.FLAG_AUTO_CANCEL;//点击通知后自动清除通知

Intent openintent = new Intent(this, OtherActivity.class);

PendingIntent contentIntent = PendingIntent.getActivity(this, 0, openintent, 0);//当点击消息时就会向系统发送openintent意图

notification.setLatestEventInfo(this, “标题”, “我是内容", contentIntent);

mNotificationManager.notify(0, notification);//第一个参数为自定义的通知唯一标识

重点是setLatestEventInfo( )方法的最后一个参数!!!!它是一个PendingIntent!!!!!!!!!

这里使用到了PendingIntent(pend本意是待定,不确定的意思)

PendingIntent可以看作是对Intent的包装。PendingIntent主要持有的信息是它所包装的Intent和当前ApplicationContext。正由于PendingIntent中保存有当前ApplicationContext,使它赋予带他程序一种执行的Intent的能力,就算在执行时当前Application已经不存在了,也能通过存在PendingIntent里的Context照样执行Intent


Intent和PendingIntent的区别(总结)

a. Intent是立即使用的,而PendingIntent可以等到事件发生后触发,PendingIntent可以cancel
b. Intent在程序结束后即终止,而PendingIntent在程序结束后依然有效
c. PendingIntent自带Context,而Intent需要在某个Context内运行
d. Intent在原task中运行,PendingIntent在新的task中运行


PendingIntent用于描述Intent及其最终的行为
你可以通过getActivity(Context context, int requestCode, Intent intent, int flags)系列方法从系统取得一个用于启动一个Activity的PendingIntent对象,
可以通过getService(Context context, int requestCode, Intent intent, int flags)方法从系统取得一个用于启动一个Service的PendingIntent对象
可以通过getBroadcast(Context context, int requestCode, Intent intent, int flags)方法从系统取得一个用于向BroadcastReceiver的Intent广播的PendingIntent对象
返回的PendingIntent可以递交给别的应用程序,然后继续处理。这里的话你可以稍后才处理PendingIntent中描述的Intent及其最终行为。
当你把PendingIntent递交给别的程序进行处理时,PendingIntent仍然拥有PendingIntent原程序所拥有的权限(with the same permissions and identity).当你从系统取得一个PendingIntent时,一定要非常小心才行。比如,通常,如果Intent目的地是你自己的component(Activity/Service/BroadcastReceiver)的话,你最好采用在Intent中显示指定目的component名字的方式,以确保Intent最终能发到目的,否则Intent最后可能不知道发到哪里了。一个PendingIntent就是Android系统中的一个token(节点,这个应该是Linux或C\C++用语)的一个对象引用,它描述了一些将用于retrieve的数据(这里,这些数据描述了Intent及其最终的行为)。
这就意味着即使PendingIntent原进程结束了的话, PendingIntent本身仍然还存在,可在其他进程(PendingIntent被递交到的其他程序)中继续使用.如果我在从系统中提取一个PendingIntent的,而系统中有一个和你描述的PendingIntent对等的PendingInent, 那么系统会直接返回和该PendingIntent其实是同一token的PendingIntent,而不是一个新的token和PendingIntent。然而你在从提取PendingIntent时,通过FLAG_CANCEL_CURRENT参数,让这个老PendingIntent的先cancel()掉,这样得到的pendingInten和其token的就是新的了。
通过FLAG_UPDATE_CURRENT参数的话,可以让新的Intent会更新之前PendingIntent中的Intent对象数据,例如更新Intent中的Extras。另外,我们也可以在PendingIntent的原进程中调用PendingIntent的cancel ()把其从系统中移除掉。


创建一个通知的示例代码:


int icon = MyAdUtil.getCompentID(packageName, "drawable", "myad_download");//获取icon资源
CharSequence tickerText = "开始下载";
mNotification = new Notification(icon, tickerText, System.currentTimeMillis());
mNotification.flags = Notification.FLAG_ONGOING_EVENT;// 放置在"正在运行"栏目中
int layout = MyAdUtil.getCompentID(packageName, "layout","download_notification_layout");//内容布局
int id_filename = MyAdUtil.getCompentID(packageName, "id", "fileName");//内容布局中的TextView
RemoteViews contentView = new RemoteViews(mContext.getPackageName(),layout);
contentView.setTextViewText(id_filename, "正在下载:" + appName);
mNotification.contentView = contentView;
Intent intent = new Intent("Action");
PendingIntent contentIntent = PendingIntent.getActivity(mContext, 0,intent,PendingIntent.FLAG_UPDATE_CURRENT);
mNotification.contentIntent = contentIntent;
mNotificationManager.notify(notifyId, mNotification);


注意:Notification点击可以跳转到一个Activity,BroadCast,Service,但是它没有点击事件的从写(onClick),所以比如你想实现点击通知栏可以弹出一个对话框,这时候你就可以将弹出对话框这个逻辑功能写到activity,broadcase,service中,实现这样的功能,在通知栏中实现下载进度条,点击实现暂停和开始,这时候可以定义一个广播:代码如下:


Intent intents = new Intent(mContext,HandlerDownload.class);//其中HandlerDownload是逻辑功能的广播
intents.setAction("Actions");
intents.putExtra("adID", msg.what);
contentIntent = PendingIntent.getBroadcast(mContext, 0,intents, PendingIntent.FLAG_UPDATE_CURRENT);
mNotification.deleteIntent = contentIntent;
mNotificationManager.notify(msg.what, mNotification);


处理逻辑的广播:

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
public class HandlerDownload extends BroadcastReceiver{
private static String ACTION = "Action";//Intent名称
@Override
public void onReceive(Context context, Intent intent) {
if (ACTION.equals(intent.getAction())) {
//实现暂停和开始的逻辑功能
}
}
}

这样就可以实现类似点击后的逻辑效果了.


更多相关文章

  1. Android 应用程序获得系统权限
  2. iOS vs Android 系统架构
  3. Android 如何在App中启动系统闹钟
  4. linux内核启动android文件系统过程分析
  5. 《Android系统级深入开发—移植与调试 》china-pub新书上架
  6. Android Activity 界面跳转动画(系统、自定义)
  7. 第2课第1节_Android灯光系统_led_class驱动
  8. Android 振动器(Vibrator)系统

随机推荐

  1. android gravity和layout_gravity区别
  2. Android使用JDBC连接mysql数据库
  3. 《精通Android 2》书评
  4. Android音频底层调试-基于tinyalsa
  5. android selector的用法解析
  6. Android 超级用户工具箱
  7. 10个很棒的学习Android 开发的网站
  8. Android应用开发工程师项目实战 共18章(
  9. android基础控件学习学习(1)【入门篇】
  10. android里面EditTex多行输入及输入置顶问