对于想了解Android中Notification用法实例总结的读者,本文将是一篇不可错过的文章,我们将详细介绍android的notification,并且为您提供关于androidnotifica
对于想了解Android中Notification用法实例总结的读者,本文将是一篇不可错过的文章,我们将详细介绍android的notification,并且为您提供关于android notification、Android Notification 从 notify 到添加 view 的处理流程、android Notification 的一个简单应用(在 Notification 中嵌入一个进度条,并且这个 Notification 点击消失但不会跳转)、android notification 的总结分析的有价值信息。
本文目录一览:- Android中Notification用法实例总结(android的notification)
- android notification
- Android Notification 从 notify 到添加 view 的处理流程
- android Notification 的一个简单应用(在 Notification 中嵌入一个进度条,并且这个 Notification 点击消失但不会跳转)
- android notification 的总结分析
Android中Notification用法实例总结(android的notification)
本文实例总结了 Android中Notification用法。分享给大家供大家参考,具体如下:
我们在用手机的时候,如果来了短信,而我们没有点击查看的话,是不是在手机的最上边的状态栏里有一个短信的小图标提示啊?你是不是也想实现这种功能呢?今天的Notification就是解决这个问题的。
我们也知道Android系统也是在不断升级的,有关Notification的用法也就有很多种,有的方法已经被android抛弃了,现在我实现了三种不同的方法,并适应不同的android版本。现在我就把代码公布出来,我喜欢把解释写在代码中,在这里我就不多说了,先看效果图:
再看代码,主要的代码如下:
package net.loonggg.notification; 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.widget.RemoteViews; public class MainActivity extends Activity { private static final int NOTIFICATION_FLAG = 1; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } public void notificationMethod(View view) { // 在Android进行通知处理,首先需要重系统哪里获得通知管理器notificationmanager,它是一个系统Service。 notificationmanager manager = (notificationmanager) getSystemService(Context.NOTIFICATION_SERVICE); switch (view.getId()) { // 默认通知 case R.id.btn1: // 创建一个PendingIntent,和Intent类似,不同的是由于不是马上调用,需要在下拉状态条出发的activity,所以采用的是PendingIntent,即点击Notification跳转启动到哪个Activity PendingIntent pendingIntent = PendingIntent.getActivity(this,new Intent(this,MainActivity.class),0); // 下面需兼容Android 2.x版本是的处理方式 // Notification notify1 = new Notification(R.drawable.message,// "TickerText:" + "您有新短消息,请注意查收!",System.currentTimeMillis()); Notification notify1 = new Notification(); notify1.icon = R.drawable.message; notify1.tickerText = "TickerText:您有新短消息,请注意查收!"; notify1.when = System.currentTimeMillis(); notify1.setLatestEventInfo(this,"Notification Title","This is the notification message",pendingIntent); notify1.number = 1; notify1.flags |= Notification.FLAG_AUTO_CANCEL; // FLAG_AUTO_CANCEL表明当通知被用户点击时,通知将被清除。 // 通过通知管理器来发起通知。如果id不同,则每click,在statu那里增加一个提示 manager.notify(NOTIFICATION_FLAG,notify1); break; // 默认通知 API11及之后可用 case R.id.btn2: PendingIntent pendingIntent2 = PendingIntent.getActivity(this,0); // 通过Notification.Builder来创建通知,注意API Level // API11之后才支持 Notification notify2 = new Notification.Builder(this) .setSmallIcon(R.drawable.message) // 设置状态栏中的小图片,尺寸一般建议在24×24,这个图片同样也是在下拉状态栏中所显示,如果在那里需要更换更大的图片,可以使用setLargeIcon(Bitmap // icon) .setTicker("TickerText:" + "您有新短消息,请注意查收!")// 设置在status // bar上显示的提示文字 .setContentTitle("Notification Title")// 设置在下拉status // bar后Activity,本例子中的NotififyMessage的TextView中显示的标题 .setContentText("This is the notification message")// TextView中显示的详细内容 .setContentIntent(pendingIntent2) // 关联PendingIntent .setNumber(1) // 在TextView的右方显示的数字,可放大图片看,在最右侧。这个number同时也起到一个序列号的左右,如果多个触发多个通知(同一ID),可以指定显示哪一个。 .getNotification(); // 需要注意build()是在API level // 16及之后增加的,在API11中可以使用getNotificatin()来代替 notify2.flags |= Notification.FLAG_AUTO_CANCEL; manager.notify(NOTIFICATION_FLAG,notify2); break; // 默认通知 API16及之后可用 case R.id.btn3: PendingIntent pendingIntent3 = PendingIntent.getActivity(this,0); // 通过Notification.Builder来创建通知,注意API Level // API16之后才支持 Notification notify3 = new Notification.Builder(this) .setSmallIcon(R.drawable.message) .setTicker("TickerText:" + "您有新短消息,请注意查收!") .setContentTitle("Notification Title") .setContentText("This is the notification message") .setContentIntent(pendingIntent3).setNumber(1).build(); // 需要注意build()是在API // level16及之后增加的,API11可以使用getNotificatin()来替代 notify3.flags |= Notification.FLAG_AUTO_CANCEL; // FLAG_AUTO_CANCEL表明当通知被用户点击时,通知将被清除。 manager.notify(NOTIFICATION_FLAG,notify3);// 步骤4:通过通知管理器来发起通知。如果id不同,则每click,在status哪里增加一个提示 break; // 自定义通知 case R.id.btn4: // Notification myNotify = new Notification(R.drawable.message,// "自定义通知:您有新短信息了,请注意查收!",System.currentTimeMillis()); Notification myNotify = new Notification(); myNotify.icon = R.drawable.message; myNotify.tickerText = "TickerText:您有新短消息,请注意查收!"; myNotify.when = System.currentTimeMillis(); myNotify.flags = Notification.FLAG_NO_CLEAR;// 不能够自动清除 RemoteViews rv = new RemoteViews(getPackageName(),R.layout.my_notification); rv.setTextViewText(R.id.text_content,"hello wrold!"); myNotify.contentView = rv; Intent intent = new Intent(Intent.ACTION_MAIN); PendingIntent contentIntent = PendingIntent.getActivity(this,1,intent,1); myNotify.contentIntent = contentIntent; manager.notify(NOTIFICATION_FLAG,myNotify); break; case R.id.btn5: // 清除id为NOTIFICATION_FLAG的通知 manager.cancel(NOTIFICATION_FLAG); // 清除所有的通知 // manager.cancelAll(); break; default: break; } } }
再看主布局文件:
还有一个是:自定义通知的布局文件my_notification.xml,代码如下:
希望本文所述对大家Android程序设计有所帮助。
android notification
现在需要做一个notification的功能,要求12小时没有点击应用,就会给你发送一个notification。点击后进入应用,又重新计时,保证关机的情况下,一直在计时,有做过的给点提示啊Android Notification 从 notify 到添加 view 的处理流程
创建 Notification 是很容易的,android8.0 以后开始加入通知渠道 NotificationChannel,然后在构造 NotificationCompat.Builder 的时候,指定要发送的渠道,最后调用 NotificationManager.notify (id,notification) 发送通知。
public void notify(int id, Notification notification)
{
notify(null, id, notification);
}
---------------
public void notify(String tag, int id, Notification notification)
{
notifyAsUser(tag, id, notification, new UserHandle(UserHandle.myUserId()));
}
---------------
public void notifyAsUser(String tag, int id, Notification notification, UserHandle user)
{
INotificationManager service = getService();
final Notification copy = Builder.maybeCloneStrippedForDelivery(notification, isLowRam);
...
try {
service.enqueueNotificationWithTag(pkg, mContext.getOpPackageName(), tag, id,
copy, user.getIdentifier());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
-------------------
static public INotificationManager getService()
{
if (sService != null) {
return sService;
}
IBinder b = ServiceManager.getService("notification");
sService = INotificationManager.Stub.asInterface(b);
return sService;
}
获取了 INotificationManager 远程接口对象,把 Notification 给加入到队列中,
INotificationManager 的远程对象是 NotificationManagerService 里的 mservice,NotificationManagerService 是系统服务。在开机启动的时候,Systemserver 里和其他系统服务一起启动,最后注册到 ServiceManager 里。
publishBinderService (Context.NOTIFICATION_SERVICE, mService); // 把 service 注册到 Servicemanager 里
----
private final IBinder mService = new INotificationManager.Stub(){
...
}
接着前面的,找到了 enqueueNotificationWithTag
@Override
public void enqueueNotificationWithTag(String pkg, String opPkg, String tag, int id,
Notification notification, int userId) throws RemoteException {
enqueueNotificationInternal(pkg, opPkg, Binder.getCallingUid(),
Binder.getCallingPid(), tag, id, notification, userId);
}
------------
void enqueueNotificationInternal(final String pkg, final String opPkg, final int callingUid,
final int callingPid, final String tag, final int id, final Notification notification,
int incomingUserId) {
.... 处理 notification 包含的信息,通知渠道,优先级。。
mHandler.post(new EnqueueNotificationRunnable(userId, r));
}
把 notification 转换为 NotificationRecord,并 post 给 EnqueueNotificationRunnable,
EnqueueNotificationRunnable 的 run 方法里。
@Override
public void run() {
synchronized (mNotificationLock) {
mEnqueuedNotifications.add(r);
scheduleTimeoutLocked(r);
...
mHandler.post(new PostNotificationRunnable(r.getKey()));
}
------------
@Override
public void run() {
synchronized (mNotificationLock) {
try {
NotificationRecord r = null;
int N = mEnqueuedNotifications.size();
NotificationRecord old = mNotificationsByKey.get(key);
final StatusBarNotification n = r.sbn;
final Notification notification = n.getNotification();
...
if (notification.getSmallIcon() != null) {
StatusBarNotification oldSbn = (old != null) ? old.sbn : null;
mListeners.notifyPostedLocked(n, oldSbn);
if (oldSbn == null || !Objects.equals(oldSbn.getGroup(), n.getGroup())) {
mHandler.post(new Runnable() {
@Override
public void run() {
mGroupHelper.onNotificationPosted(
n, hasAutoGroupSummaryLocked(n));
}
});
}
}
...
buzzBeepBlinkLocked(r);
}
------------
void buzzBeepBlinkLocked(NotificationRecord record) {
处理 notification 的 声音 震动和灯光闪烁
}
------------
public void notifyPostedLocked(StatusBarNotification sbn, StatusBarNotification oldSbn) {
发送给状态栏
mHandler.post(new Runnable() {
@Override
public void run() {
notifyPosted(info, sbnToPost, update);
}
});
}
↓
private void notifyPosted(final ManagedServiceInfo info,
final StatusBarNotification sbn, NotificationRankingUpdate rankingUpdate) {
final INotificationListener listener = (INotificationListener) info.service;
StatusBarNotificationHolder sbnHolder = new StatusBarNotificationHolder(sbn);
try {
listener.onNotificationPosted(sbnHolder, rankingUpdate);
} catch (RemoteException ex) {
Log.e(TAG, "unable to notify listener (posted): " + listener, ex);
}
}
INotificationListener 是另一个远程接口对象
protected class NotificationListenerWrapper extends INotificationListener.Stub
------------
@Override
public void onNotificationPosted(IStatusBarNotificationHolder sbnHolder,
NotificationRankingUpdate update) {
SomeArgs args = SomeArgs.obtain();
args.arg1 = sbn;
args.arg2 = mRankingMap;
mHandler.obtainMessage(MyHandler.MSG_ON_NOTIFICATION_POSTED,
args).sendToTarget();
}
case MSG_ON_NOTIFICATION_POSTED: {
SomeArgs args = (SomeArgs) msg.obj;
StatusBarNotification sbn = (StatusBarNotification) args.arg1;
RankingMap rankingMap = (RankingMap) args.arg2;
args.recycle();
onNotificationPosted(sbn, rankingMap);
------------
public void onNotificationPosted(StatusBarNotification sbn, RankingMap rankingMap) {
onNotificationPosted(sbn);
}
public void onNotificationPosted(StatusBarNotification sbn) {
// optional
}
很意外,发现方法是空的,那调这么多有什么用? 研究了一下发现,onNotificationPosted 的这个方法属于的是
public abstract class NotificationListenerService extends Service {
1
NotificationListenerService 是个抽象方法,那很自然调用的时候会调用它的子类,
然后
public class NotificationListenerWithPlugins extends NotificationListenerService
1
但是找了一圈 NotificationListenerWithPlugins ,没有 onNotificationPosted,那只有继续找它的子类了,
后来发现,在 Statusbar 里有个匿名内部类实现了 NotificationListenerService 的方法。
private final NotificationListenerWithPlugins mNotificationListener =
new NotificationListenerWithPlugins() {
...
@Override
public void onNotificationPosted(final StatusBarNotification sbn,
final RankingMap rankingMap) {
mHandler.post(new Runnable() {
@Override
public void run() {
...
if (isUpdate) {
updateNotification(sbn, rankingMap);
} else {
addNotification(sbn, rankingMap);
}
...
}
}
...
}
------------
public void addNotification(StatusBarNotification notification, RankingMap ranking)
throws InflationException {
Entry shadeEntry = createNotificationViews(notification);
boolean isHeadsUped = shouldPeek(shadeEntry);.
...
}
------------
protected NotificationData.Entry createNotificationViews(StatusBarNotification sbn)
throws InflationException {
NotificationData.Entry entry = new NotificationData.Entry(sbn);
Dependency.get(LeakDetector.class).trackInstance(entry);
entry.createIcons(mContext, sbn);
// Construct the expanded view.
inflateViews(entry, mStackScroller);
}
------------
protected void inflateViews(Entry entry, ViewGroup parent) {
new RowInflaterTask().inflate(mContext, parent, entry,
row -> {
bindRow(entry, pmUser, sbn, row);
updateNotification(entry, pmUser, sbn, row);
});
}
最后 bindRow 就是去构造通知栏的通知 View,然后 updateNotification 就是去显示到状态栏。
private void updateNotification(Entry entry, PackageManager pmUser,
StatusBarNotification sbn, ExpandableNotificationRow row) {
...
row.updateNotification(entry);
}
------------
public void updateNotification(NotificationData.Entry entry) {
mEntry = entry;
mStatusBarNotification = entry.notification;
mNotificationInflater.inflateNotificationViews();
}
------------
public void inflateNotificationViews() {
inflateNotificationViews(FLAG_REINFLATE_ALL);
}
------------
void inflateNotificationViews(int reInflateFlags) {
...
StatusBarNotification sbn = mRow.getEntry().notification;
new AsyncInflationTask(sbn, reInflateFlags, mRow, mIsLowPriority,
mIsChildInGroup, mUsesIncreasedHeight, mUsesIncreasedHeadsUpHeight, mRedactAmbient,
mCallback, mRemoteViewClickHandler).execute();
}
使用了异步任务 AsyncTask 去完成布局
AsyncInflationTask
@Override
protected InflationProgress doInBackground(Void... params) {
return createRemoteViews(mReInflateFlags,
recoveredBuilder, mIsLowPriority, mIsChildInGroup,
mUsesIncreasedHeight, mUsesIncreasedHeadsUpHeight, mRedactAmbient,
packageContext);
}
------------
private static InflationProgress createRemoteViews(int reInflateFlags,
Notification.Builder builder, boolean isLowPriority, boolean isChildInGroup,
boolean usesIncreasedHeight, boolean usesIncreasedHeadsUpHeight, boolean redactAmbient,
Context packageContext) {
InflationProgress result = new InflationProgress();
isLowPriority = isLowPriority && !isChildInGroup;
if ((reInflateFlags & FLAG_REINFLATE_CONTENT_VIEW) != 0) {
result.newContentView = createContentView(builder, isLowPriority, usesIncreasedHeight);
}
if ((reInflateFlags & FLAG_REINFLATE_EXPANDED_VIEW) != 0) {
result.newExpandedView = createExpandedView(builder, isLowPriority);
}
if ((reInflateFlags & FLAG_REINFLATE_HEADS_UP_VIEW) != 0) {
result.newHeadsUpView = builder.createHeadsUpContentView(usesIncreasedHeadsUpHeight);
}
if ((reInflateFlags & FLAG_REINFLATE_PUBLIC_VIEW) != 0) {
result.newPublicView = builder.makePublicContentView();
}
if ((reInflateFlags & FLAG_REINFLATE_AMBIENT_VIEW) != 0) {
result.newAmbientView = redactAmbient ? builder.makePublicAmbientNotification()
: builder.makeAmbientNotification();
}
result.packageContext = packageContext;
return result;
}
到了这里,都是创建各种布局
比如 createContentView
public RemoteViews createContentView() {
return createContentView(false /* increasedheight */ );
}
------------
public RemoteViews createContentView(boolean increasedHeight) {
if (mN.contentView != null && useExistingRemoteView()) {
return mN.contentView;
} else if (mStyle != null) {
final RemoteViews styleView = mStyle.makeContentView(increasedHeight);
if (styleView != null) {
return styleView;
}
}
return applyStandardTemplate(getBaseLayoutResource());
}
这里会去判断我们是否有在 notification 里添加 style, 如果有不同的 style,比如音乐播放器那种 notification,就是自定义 style,如果没有,那就用默认的 layout。
private int getBaseLayoutResource() {
return R.layout.notification_template_material_base;
}
------------
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/status_bar_latest_event_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:tag="base" >
<include layout="@layout/notification_template_header" />
<LinearLayout
android:id="@+id/notification_main_column"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="top"
android:layout_marginStart="@dimen/notification_content_margin_start"
android:layout_marginEnd="@dimen/notification_content_margin_end"
android:layout_marginTop="@dimen/notification_content_margin_top"
android:layout_marginBottom="@dimen/notification_content_margin_bottom"
android:orientation="vertical" >
<include layout="@layout/notification_template_part_line1" />
<include layout="@layout/notification_template_text" />
<include
android:layout_width="match_parent"
android:layout_height="@dimen/notification_progress_bar_height"
android:layout_marginTop="@dimen/notification_progress_margin_top"
layout="@layout/notification_template_progress" />
</LinearLayout>
<include layout="@layout/notification_template_right_icon" />
</FrameLayout>
原来这就是我们用的 notification 的布局内容。
private RemoteViews applyStandardTemplate(int resId) {
return applyStandardTemplate(resId, mParams.reset().fillTextsFrom(this));
}
private RemoteViews applyStandardTemplate(int resId, boolean hasProgress) {
return applyStandardTemplate(resId, mParams.reset().hasProgress(hasProgress)
.fillTextsFrom(this));
}
private RemoteViews applyStandardTemplate(int resId, StandardTemplateParams p) {
updateBackgroundColor(contentView);
bindNotificationHeader(contentView, p.ambient);
bindLargeIcon(contentView);
}
android Notification 的一个简单应用(在 Notification 中嵌入一个进度条,并且这个 Notification 点击消失但不会跳转)
网上很多的例子都是直接获取 Notification 对象来设置一个通知,其实 Notification 跟 Dialog 一样,也有自己的 Builder,可以用 builder 对象来设置一个 Notification
这个例子是在 Notification 中嵌入一个进度条,并且这个 Notification 点击消失但不会跳转(跟 android 的 vcard 文件导入时弹出的 Notification 一样)
NotificationManager mNotificationManager = (NotificationManager)
context.getSystemService(Context.NOTIFICATION_SERVICE);
Notification.Builder builder = new Notification.Builder(context);
builder.setOngoing(true);
builder.setProgress (total, current, false);// 设置进度条,false 表示是进度条,true 表示是个走马灯
builder.setTicker (title);// 设置 title
builder.setWhen(System.currentTimeMillis());
builder.setContentTitle (content);// 设置内容
builder.setAutoCancel (true);// 点击消失
builder.setSmallIcon(R.drawable.upload);
builder.setContentIntent (PendingIntent.getActivity (context, 0, new Intent (), 0));// 这句和点击消失那句是 “Notification 点击消失但不会跳转” 的必须条件,如果只有点击消失那句,这个功能是不能实现的
Notification noti = builder.getNotification();
mNotificationManager.notify(id,noti);
希望这个例子对其他人有点用,因为我特曾为这个功能苦恼过,呵呵!
android notification 的总结分析
分类
notification有以下几种:
1>普通notification
1.内容标题
2.大图标
3.内容
4.内容附加信息
5.小图标
6.时间
2>大布局Notification
图1
大布局notification是在android4.1以后才增加的,大布局notification与小布局notification只在‘7'部分有区别,其它部分都一致。大布局notification只有在所有notification的最上 面时才会显示大布局,其它情况下显示小布局。你也可以用手指将其扩展为大布局(前提是它是大布局)。如下图:
图2
大布局notification有三种类型:如图1为NotificationCompat.InBoxStyle 类型。图2左部为NotificationCompat.BigTextStyle。图2右部 为:NotificationCompat.BigPictureStyle
3>自定义布局notification
除了系统提供的notification,我们也可以自定义notification。如下图所示的一个音乐播放器控制notification:
图3
如何创建notification
1>实例化一个NotificationCompat.Builder对象;如builder
2>调用builder的相关方法对notification进行上面提到的各种设置
3>调用builder.build()方法此方法返回一个notification对象。
4>实例化一个notificationmanager对象;如:manager
5>调用manager的notify方法。
注:
一个notification不必对上面所有的选项都进行设置,但有3项是必须的:
小图标,set by setSmallIcon()
内容标题,set by setContentTitle()
内容,set by setContentText()
示例代码
示例程序截图:
0>初始化部分代码
View Code
public class MainActivity extends Activity implements OnClickListener {
private static final int NOTIFICATION_ID_1 = 0;
private static final int NOTIFICATION_ID_2 = 1;
private static final int NOTIFICATION_ID_3 = 2;
private static final int NOTIFICATION_ID_4 = 3;
private static final int NOTIFICATION_ID_5 = 4;
private static final int NOTIFICATION_ID_6 = 5;
private static final int NOTIFICATION_ID_7 = 6;
private static final int NOTIFICATION_ID_8 = 7;
private static int messageNum = 0;
private Context context = this;
private notificationmanager manager;
private Bitmap icon;
private static final int[] btns = new int[] { R.id.btn1,R.id.btn2,
R.id.btn3,R.id.btn4,R.id.btn5,R.id.btn6,R.id.btn7,R.id.btn8,
R.id.btn9 };
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
}
private void init() {
// 获取通知服务
manager = (notificationmanager) getSystemService(Context.NOTIFICATION_SERVICE);
// 注册监听器
for (int btn : btns) {
findViewById(btn).setonClickListener(this);
}
icon = BitmapFactory.decodeResource(getResources(),
R.drawable.ic_launcher);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn1:
shownormal();
break;
case R.id.btn2:
showBigView_Text();
break;
case R.id.btn3:
showBigView_Pic();
break;
case R.id.btn4:
showBigView_InBox();
break;
case R.id.btn5:
showCustomView();
break;
case R.id.btn6:
backApp();
break;
case R.id.btn7:
backScreen();
break;
case R.id.btn8:
showProgressBar();
break;
case R.id.btn9:
dismiss();
break;
default:
Toast.makeText(context,"error",Toast.LENGTH_SHORT).show();
break;
}
}
private void dismiss() {
manager.cancelAll();
}
1>普通notification
View Code
private void shownormal() {
Notification notification = new NotificationCompat.Builder(context)
.setLargeIcon(icon).setSmallIcon(R.drawable.ic_launcher)
.setTicker("shownormal").setContentInfo("contentInfo")
.setContentTitle("ContentTitle").setContentText("ContentText")
.setNumber(++messageNum)
.setAutoCancel(true).setDefaults(Notification.DEFAULT_ALL)
.build();
manager.notify(NOTIFICATION_ID_1,notification);
}