关于Notification通知的一点愚见(自定义通知栏)
来源:互联网 发布:语文试卷编制软件 编辑:程序博客网 时间:2024/06/05 16:08
今天在复习Notification通知栏的时候,好奇翻了一下源码,终于弄懂了PendingIntent在Notification中的机制以及工作流程,这对我研究Activity的启动流程有了一定的帮助。
通知的实现
我们复习一下常规的通知栏是怎么样实现的:
//声明一个新的Notification,在里面设置参数 Notification notification = new Notification(); notification.icon = R.drawable.ic_launcher; notification.tickerText = "hello world"; notification.when = System.currentTimeMillis(); notification.flags = Notification.FLAG_AUTO_CANCEL; Intent intent = new Intent(this, DemoActivity_2.class); //PendingIntent是延时Intent是指当点击通知栏之后弹出intent指向activity PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); //这里是指给予通知栏一个标准布局 notification.setLatestEventInfo(this, "chapter_5", "this is notification.", pendingIntent); //声明一个NotificationManager NotificationManager manager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE); //根据ID发送 manager.notify(sId, notification);
第一步:声明好Notification之后,我们要在notification中设置好参数,比如图标,text,时间,flag等等。
第二步:声明一个Intent,接着将Intent放入PendingIntent中。这个时候PendingIntent中我们要将Intent封装如PendingIntent中。
第三步:声明一个NotificationManager之后,调用notify(int id,Notification n)来发送通知请求。
在这里我们可以清晰的知道NotificationManager其实就是发送notification通知相关的参数出发送端的进程之外,那么这里一定用到了进程间的通讯Binder,而发送的数据notification一定是序列化。
public class Notification implements Parcelable
下面是部分参数源码:
/** * A timestamp related to this notification, in milliseconds since the epoch. * * Default value: {@link System#currentTimeMillis() Now}. * * Choose a timestamp that will be most relevant to the user. For most finite events, this * corresponds to the time the event happened (or will happen, in the case of events that have * yet to occur but about which the user is being informed). Indefinite events should be * timestamped according to when the activity began. * * Some examples: * * <ul> * <li>Notification of a new chat message should be stamped when the message was received.</li> * <li>Notification of an ongoing file download (with a progress bar, for example) should be stamped when the download started.</li> * <li>Notification of a completed file download should be stamped when the download finished.</li> * <li>Notification of an upcoming meeting should be stamped with the time the meeting will begin (that is, in the future).</li> * <li>Notification of an ongoing stopwatch (increasing timer) should be stamped with the watch's start time. * <li>Notification of an ongoing countdown timer should be stamped with the timer's end time. * </ul> * */ public long when; /** * The resource id of a drawable to use as the icon in the status bar. * This is required; notifications with an invalid icon resource will not be shown. */ public int icon; /** * If the icon in the status bar is to have more than one level, you can set this. Otherwise, * leave it at its default value of 0. * * @see android.widget.ImageView#setImageLevel * @see android.graphics.drawable.Drawable#setLevel */ public int iconLevel; /** * The number of events that this notification represents. For example, in a new mail * notification, this could be the number of unread messages. * * The system may or may not use this field to modify the appearance of the notification. For * example, before {@link android.os.Build.VERSION_CODES#HONEYCOMB}, this number was * superimposed over the icon in the status bar. Starting with * {@link android.os.Build.VERSION_CODES#HONEYCOMB}, the template used by * {@link Notification.Builder} has displayed the number in the expanded notification view. * * If the number is 0 or negative, it is never shown. */ public int number; /** * The intent to execute when the expanded status entry is clicked. If * this is an activity, it must include the * {@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK} flag, which requires * that you take care of task management as described in the * <a href="{@docRoot}guide/topics/fundamentals/tasks-and-back-stack.html">Tasks and Back * Stack</a> document. In particular, make sure to read the notification section * <a href="{@docRoot}guide/topics/ui/notifiers/notifications.html#HandlingNotifications">Handling * Notifications</a> for the correct ways to launch an application from a * notification. */ public PendingIntent contentIntent; /** * The intent to execute when the notification is explicitly dismissed by the user, either with * the "Clear All" button or by swiping it away individually. * * This probably shouldn't be launching an activity since several of those will be sent * at the same time. */ public PendingIntent deleteIntent; /** * The view that will represent this notification in the expanded status bar. */ public RemoteViews contentView;...
上面这些就是notification要通过Binder传输到AMS的数据。那么对应的,如果我们想要自定义一个通知栏的话,其实就是将相关的View数据通过RemoteView的contentView(上面的注释明确的写出了这个View将代表了通知在状态栏上)通信到AMS中。这样子就可以办到自定义的通知栏了。
相对应的setLastEventInfo是设置默认模板的通知样式,下面是源码:
public void setLatestEventInfo(Context context, CharSequence contentTitle, CharSequence contentText, PendingIntent contentIntent) { Notification.Builder builder = new Notification.Builder(context); // First, ensure that key pieces of information that may have been set directly // are preserved builder.setWhen(this.when); builder.setSmallIcon(this.icon); builder.setPriority(this.priority); builder.setTicker(this.tickerText); builder.setNumber(this.number); builder.setColor(this.color); builder.mFlags = this.flags; builder.setSound(this.sound, this.audioStreamType); builder.setDefaults(this.defaults); builder.setVibrate(this.vibrate); // now apply the latestEventInfo fields if (contentTitle != null) { builder.setContentTitle(contentTitle); } if (contentText != null) { builder.setContentText(contentText); } builder.setContentIntent(contentIntent); builder.buildInto(this); }
在Notification的Builder内部类中已经将通知的默认模板给设定好了。
自定义通知栏
所谓自定义通知栏知道原理之后,我们就很好的实现这个自定义的通知栏了。我们先自定义一个布局文件出来。
下面是布局文件xml的配置:
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/light_green" android:padding="10dp" android:gravity="center" android:orientation="horizontal" > <ImageView android:id="@+id/icon" android:background="#000000" android:layout_width="40dp" android:scaleType="centerInside" android:layout_height="40dp" /> <LinearLayout android:id="@+id/layout" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="right" android:orientation="vertical" > <TextView android:id="@+id/msg" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="5dp" android:textColor="@android:color/white" android:visibility="visible" android:text="TextView" /> <TextView android:id="@+id/open_activity2" android:padding="2dp" android:background="@drawable/common_bkg" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="@android:color/white" android:text="open DemoActivity_2" /> </LinearLayout></LinearLayout>
配置好了之后,我们来实现notification中的参数:
//声明一个新的Notification,在里面设置参数 Notification notification = new Notification(); notification.icon = R.drawable.ic_launcher; notification.tickerText = "hello world"; notification.when = System.currentTimeMillis(); notification.flags = Notification.FLAG_AUTO_CANCEL; Intent intent = new Intent(this, DemoActivity_1.class); intent.putExtra("sid", "" + sId); //PendingIntent是延时Intent是指当点击通知栏之后启动intent指向activity PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
这里和前面相似,接下来我们要透过RemoteView来重新设置整个通知的View:
RemoteViews remoteViews = new RemoteViews(getPackageName(), R.layout.layout_notification); remoteViews.setTextViewText(R.id.msg, "chapter_5: " + sId); remoteViews.setImageViewResource(R.id.icon, R.drawable.icon1); //PendingIntent是延时Intent是指当点击通知栏之后启动intent指向activity PendingIntent openActivity2PendingIntent = PendingIntent.getActivity(this, 0, new Intent(this, DemoActivity_2.class), PendingIntent.FLAG_UPDATE_CURRENT); remoteViews.setOnClickPendingIntent(R.id.open_activity2, openActivity2PendingIntent); //设置contentview notification.contentView = remoteViews; //设置pendingItent notification.contentIntent = pendingIntent; NotificationManager manager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE); manager.notify(sId, notification);
这样子就完成了自定义通知栏的实现了,而RemoteView的工作原理之后再另外说一下吧。
下一章将总结一下,之前明白的PendingIntent在Notification中工作原理。
感谢郭霖大神和任玉刚大神的博客和书籍。
- 关于Notification通知的一点愚见(自定义通知栏)
- adroid自定义notification通知栏
- 通知栏通知Notification
- Notification 通知栏通知
- Notification通知栏通知
- 关于通知Notification的基础知识
- 关于Notification的一点愚见(PendingIntent工作流程)
- 通知栏通知:Notification的实现
- Notification消息通知 通知栏的实现
- android通知栏的消息通知(Notification)
- 自定义通知(notification)
- Android自定义Notification通知
- 关于通知Notification
- Notification通知栏的使用
- Notification通知栏的使用
- 通知栏Notification的整合
- Notification 通知栏的使用
- Notification通知栏的用法
- IMS----IP Multimedia Subsystem
- 最佳实践之JS-状态模式
- 【Leetcode】Two Sum II - Input array is sorted
- oracle中层次查询start by ... connect by....详解
- 每天一条liunux--touch命令
- 关于Notification通知的一点愚见(自定义通知栏)
- 便捷提醒小插件之gritter
- mybatis传List
- Synchronized常见用法
- Netty使用MessagePack首先自定义编解码器
- Android 系统签名
- ListView去掉分割线
- CSS :hover和:active区别
- iOS SQLCipher SQLite加密 详解