Android(安卓)Notification 兼容3.0到8.0
Build.VERSION.SDK_INT<11
http://www.cnblogs.com/hasse/p/5164417.html
//Android 4.1之前 创建一个NotificationNotification notification = new Notification();//设置事件信息notification.setLatestEventInfo(context,title,content, pendingIntent);
Build.VERSION.SDK_INT >= 11 && Build.VERSION.SDK_INT < 22
//使用Notification.Builder创建一个NotificationNotification.Builder builder = new Notification.Builder(this);Notification notification= builder.getNotification();// 调用getNotification()来生成Notification //其实也可以这么写 Notification notification = builder.build();//将builder对象转换为普通的notification //实际上builder.getNotification();里面的实现就是builder.build()
Build.VERSION.SDK_INT >=22 && Build.VERSION.SDK_INT < 26
//使用NotificationCompat.Builder创建一个Notification Notification notification = new NotificationCompat.Builder(mContext).build();
https://www.jianshu.com/p/6187fe8a0704
Build.VERSION.SDK_INT>=26
Android系统在 8.0 以后增加了通知通道,要正确的在 8.0 系统上使用通知,
需要进行版本判定, 然后进行适配,创建出 Builder以后,其他操作不变。
如果不对其进行处理的话会出现:
Failed to post notification on channel "null"的错误提示。
https://blog.csdn.net/qq_39622065/article/details/83033167
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.O) { String channelId = "notification_simple"; NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); NotificationChannel channel = new NotificationChannel(channelId, "simple", NotificationManager.IMPORTANCE_DEFAULT); manager.createNotificationChannel(channel);}
参考文章
Notification、Notification.Builder 和NotificationCompat.Builder的区别 https://blog.csdn.net/weixin_43174412/article/details/82629985
Android-Notification通知的使用
https://blog.csdn.net/qq_41113081/article/details/86692761
https://developer.android.google.cn/guide/topics/ui/notifiers/notifications
googlesamples/android-Notifications
https://github.com/googlesamples/android-Notifications
NotificationCompatBuilder源码
/* * Copyright (C) 2017 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package androidx.core.app;import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP;import static androidx.core.app.NotificationCompat.DEFAULT_SOUND;import static androidx.core.app.NotificationCompat.DEFAULT_VIBRATE;import static androidx.core.app.NotificationCompat.FLAG_GROUP_SUMMARY;import static androidx.core.app.NotificationCompat.GROUP_ALERT_ALL;import static androidx.core.app.NotificationCompat.GROUP_ALERT_CHILDREN;import static androidx.core.app.NotificationCompat.GROUP_ALERT_SUMMARY;import android.app.Notification;import android.os.Build;import android.os.Bundle;import android.text.TextUtils;import android.util.SparseArray;import android.widget.RemoteViews;import androidx.annotation.RestrictTo;import java.util.ArrayList;import java.util.List;/** * Wrapper around {@link Notification.Builder} that works in a backwards compatible way. * * @hide */@RestrictTo(LIBRARY_GROUP)class NotificationCompatBuilder implements NotificationBuilderWithBuilderAccessor { private final Notification.Builder mBuilder; private final NotificationCompat.Builder mBuilderCompat; // @RequiresApi(16) - uncomment when lint bug is fixed. private RemoteViews mContentView; // @RequiresApi(16) - uncomment when lint bug is fixed. private RemoteViews mBigContentView; // @RequiresApi(16) - uncomment when lint bug is fixed. private final List mActionExtrasList = new ArrayList<>(); // @RequiresApi(16) - uncomment when lint bug is fixed. private final Bundle mExtras = new Bundle(); // @RequiresApi(20) - uncomment when lint bug is fixed. private int mGroupAlertBehavior; // @RequiresApi(21) - uncomment when lint bug is fixed. private RemoteViews mHeadsUpContentView; NotificationCompatBuilder(NotificationCompat.Builder b) { mBuilderCompat = b; if (Build.VERSION.SDK_INT >= 26) { mBuilder = new Notification.Builder(b.mContext, b.mChannelId); } else { mBuilder = new Notification.Builder(b.mContext); } Notification n = b.mNotification; mBuilder.setWhen(n.when) .setSmallIcon(n.icon, n.iconLevel) .setContent(n.contentView) .setTicker(n.tickerText, b.mTickerView) .setVibrate(n.vibrate) .setLights(n.ledARGB, n.ledOnMS, n.ledOffMS) .setOngoing((n.flags & Notification.FLAG_ONGOING_EVENT) != 0) .setOnlyAlertOnce((n.flags & Notification.FLAG_ONLY_ALERT_ONCE) != 0) .setAutoCancel((n.flags & Notification.FLAG_AUTO_CANCEL) != 0) .setDefaults(n.defaults) .setContentTitle(b.mContentTitle) .setContentText(b.mContentText) .setContentInfo(b.mContentInfo) .setContentIntent(b.mContentIntent) .setDeleteIntent(n.deleteIntent) .setFullScreenIntent(b.mFullScreenIntent, (n.flags & Notification.FLAG_HIGH_PRIORITY) != 0) .setLargeIcon(b.mLargeIcon) .setNumber(b.mNumber) .setProgress(b.mProgressMax, b.mProgress, b.mProgressIndeterminate); if (Build.VERSION.SDK_INT < 21) { mBuilder.setSound(n.sound, n.audioStreamType); } if (Build.VERSION.SDK_INT >= 16) { mBuilder.setSubText(b.mSubText) .setUsesChronometer(b.mUseChronometer) .setPriority(b.mPriority); for (NotificationCompat.Action action : b.mActions) { addAction(action); } if (b.mExtras != null) { mExtras.putAll(b.mExtras); } if (Build.VERSION.SDK_INT < 20) { if (b.mLocalOnly) { mExtras.putBoolean(NotificationCompatExtras.EXTRA_LOCAL_ONLY, true); } if (b.mGroupKey != null) { mExtras.putString(NotificationCompatExtras.EXTRA_GROUP_KEY, b.mGroupKey); if (b.mGroupSummary) { mExtras.putBoolean(NotificationCompatExtras.EXTRA_GROUP_SUMMARY, true); } else { mExtras.putBoolean( NotificationManagerCompat.EXTRA_USE_SIDE_CHANNEL, true); } } if (b.mSortKey != null) { mExtras.putString(NotificationCompatExtras.EXTRA_SORT_KEY, b.mSortKey); } } mContentView = b.mContentView; mBigContentView = b.mBigContentView; } if (Build.VERSION.SDK_INT >= 19) { mBuilder.setShowWhen(b.mShowWhen); if (Build.VERSION.SDK_INT < 21) { if (b.mPeople != null && !b.mPeople.isEmpty()) { mExtras.putStringArray(Notification.EXTRA_PEOPLE, b.mPeople.toArray(new String[b.mPeople.size()])); } } } if (Build.VERSION.SDK_INT >= 20) { mBuilder.setLocalOnly(b.mLocalOnly) .setGroup(b.mGroupKey) .setGroupSummary(b.mGroupSummary) .setSortKey(b.mSortKey); mGroupAlertBehavior = b.mGroupAlertBehavior; } if (Build.VERSION.SDK_INT >= 21) { mBuilder.setCategory(b.mCategory) .setColor(b.mColor) .setVisibility(b.mVisibility) .setPublicVersion(b.mPublicVersion) .setSound(n.sound, n.audioAttributes); for (String person: b.mPeople) { mBuilder.addPerson(person); } mHeadsUpContentView = b.mHeadsUpContentView; if (b.mInvisibleActions.size() > 0) { // Invisible actions should be stored in the extender so we need to check if one // exists already. Bundle carExtenderBundle = b.getExtras().getBundle(NotificationCompat.CarExtender.EXTRA_CAR_EXTENDER); if (carExtenderBundle == null) { carExtenderBundle = new Bundle(); } Bundle listBundle = new Bundle(); for (int i = 0; i < b.mInvisibleActions.size(); i++) { listBundle.putBundle( Integer.toString(i), NotificationCompatJellybean.getBundleForAction( b.mInvisibleActions.get(i))); } carExtenderBundle.putBundle( NotificationCompat.CarExtender.EXTRA_INVISIBLE_ACTIONS, listBundle); b.getExtras().putBundle( NotificationCompat.CarExtender.EXTRA_CAR_EXTENDER, carExtenderBundle); mExtras.putBundle( NotificationCompat.CarExtender.EXTRA_CAR_EXTENDER, carExtenderBundle); } } if (Build.VERSION.SDK_INT >= 24) { mBuilder.setExtras(b.mExtras) .setRemoteInputHistory(b.mRemoteInputHistory); if (b.mContentView != null) { mBuilder.setCustomContentView(b.mContentView); } if (b.mBigContentView != null) { mBuilder.setCustomBigContentView(b.mBigContentView); } if (b.mHeadsUpContentView != null) { mBuilder.setCustomHeadsUpContentView(b.mHeadsUpContentView); } } if (Build.VERSION.SDK_INT >= 26) { mBuilder.setBadgeIconType(b.mBadgeIcon) .setShortcutId(b.mShortcutId) .setTimeoutAfter(b.mTimeout) .setGroupAlertBehavior(b.mGroupAlertBehavior); if (b.mColorizedSet) { mBuilder.setColorized(b.mColorized); } if (!TextUtils.isEmpty(b.mChannelId)) { mBuilder.setSound(null) .setDefaults(0) .setLights(0, 0, 0) .setVibrate(null); } } } @Override public Notification.Builder getBuilder() { return mBuilder; } public Notification build() { final NotificationCompat.Style style = mBuilderCompat.mStyle; if (style != null) { style.apply(this); } RemoteViews styleContentView = style != null ? style.makeContentView(this) : null; Notification n = buildInternal(); if (styleContentView != null) { n.contentView = styleContentView; } else if (mBuilderCompat.mContentView != null) { n.contentView = mBuilderCompat.mContentView; } if (Build.VERSION.SDK_INT >= 16 && style != null) { RemoteViews styleBigContentView = style.makeBigContentView(this); if (styleBigContentView != null) { n.bigContentView = styleBigContentView; } } if (Build.VERSION.SDK_INT >= 21 && style != null) { RemoteViews styleHeadsUpContentView = mBuilderCompat.mStyle.makeHeadsUpContentView(this); if (styleHeadsUpContentView != null) { n.headsUpContentView = styleHeadsUpContentView; } } if (Build.VERSION.SDK_INT >= 16 && style != null) { Bundle extras = NotificationCompat.getExtras(n); if (extras != null) { style.addCompatExtras(extras); } } return n; } private void addAction(NotificationCompat.Action action) { if (Build.VERSION.SDK_INT >= 20) { Notification.Action.Builder actionBuilder = new Notification.Action.Builder( action.getIcon(), action.getTitle(), action.getActionIntent()); if (action.getRemoteInputs() != null) { for (android.app.RemoteInput remoteInput : RemoteInput.fromCompat( action.getRemoteInputs())) { actionBuilder.addRemoteInput(remoteInput); } } Bundle actionExtras; if (action.getExtras() != null) { actionExtras = new Bundle(action.getExtras()); } else { actionExtras = new Bundle(); } actionExtras.putBoolean(NotificationCompatJellybean.EXTRA_ALLOW_GENERATED_REPLIES, action.getAllowGeneratedReplies()); if (Build.VERSION.SDK_INT >= 24) { actionBuilder.setAllowGeneratedReplies(action.getAllowGeneratedReplies()); } actionExtras.putInt(NotificationCompat.Action.EXTRA_SEMANTIC_ACTION, action.getSemanticAction()); if (Build.VERSION.SDK_INT >= 28) { actionBuilder.setSemanticAction(action.getSemanticAction()); } actionExtras.putBoolean(NotificationCompat.Action.EXTRA_SHOWS_USER_INTERFACE, action.getShowsUserInterface()); actionBuilder.addExtras(actionExtras); mBuilder.addAction(actionBuilder.build()); } else if (Build.VERSION.SDK_INT >= 16) { mActionExtrasList.add( NotificationCompatJellybean.writeActionAndGetExtras(mBuilder, action)); } } protected Notification buildInternal() { if (Build.VERSION.SDK_INT >= 26) { return mBuilder.build(); } else if (Build.VERSION.SDK_INT >= 24) { Notification notification = mBuilder.build(); if (mGroupAlertBehavior != GROUP_ALERT_ALL) { // if is summary and only children should alert if (notification.getGroup() != null && (notification.flags & FLAG_GROUP_SUMMARY) != 0 && mGroupAlertBehavior == GROUP_ALERT_CHILDREN) { removeSoundAndVibration(notification); } // if is group child and only summary should alert if (notification.getGroup() != null && (notification.flags & FLAG_GROUP_SUMMARY) == 0 && mGroupAlertBehavior == GROUP_ALERT_SUMMARY) { removeSoundAndVibration(notification); } } return notification; } else if (Build.VERSION.SDK_INT >= 21) { mBuilder.setExtras(mExtras); Notification notification = mBuilder.build(); if (mContentView != null) { notification.contentView = mContentView; } if (mBigContentView != null) { notification.bigContentView = mBigContentView; } if (mHeadsUpContentView != null) { notification.headsUpContentView = mHeadsUpContentView; } if (mGroupAlertBehavior != GROUP_ALERT_ALL) { // if is summary and only children should alert if (notification.getGroup() != null && (notification.flags & FLAG_GROUP_SUMMARY) != 0 && mGroupAlertBehavior == GROUP_ALERT_CHILDREN) { removeSoundAndVibration(notification); } // if is group child and only summary should alert if (notification.getGroup() != null && (notification.flags & FLAG_GROUP_SUMMARY) == 0 && mGroupAlertBehavior == GROUP_ALERT_SUMMARY) { removeSoundAndVibration(notification); } } return notification; } else if (Build.VERSION.SDK_INT >= 20) { mBuilder.setExtras(mExtras); Notification notification = mBuilder.build(); if (mContentView != null) { notification.contentView = mContentView; } if (mBigContentView != null) { notification.bigContentView = mBigContentView; } if (mGroupAlertBehavior != GROUP_ALERT_ALL) { // if is summary and only children should alert if (notification.getGroup() != null && (notification.flags & FLAG_GROUP_SUMMARY) != 0 && mGroupAlertBehavior == GROUP_ALERT_CHILDREN) { removeSoundAndVibration(notification); } // if is group child and only summary should alert if (notification.getGroup() != null && (notification.flags & FLAG_GROUP_SUMMARY) == 0 && mGroupAlertBehavior == GROUP_ALERT_SUMMARY) { removeSoundAndVibration(notification); } } return notification; } else if (Build.VERSION.SDK_INT >= 19) { SparseArray actionExtrasMap = NotificationCompatJellybean.buildActionExtrasMap(mActionExtrasList); if (actionExtrasMap != null) { // Add the action extras sparse array if any action was added with extras. mExtras.putSparseParcelableArray( NotificationCompatExtras.EXTRA_ACTION_EXTRAS, actionExtrasMap); } mBuilder.setExtras(mExtras); Notification notification = mBuilder.build(); if (mContentView != null) { notification.contentView = mContentView; } if (mBigContentView != null) { notification.bigContentView = mBigContentView; } return notification; } else if (Build.VERSION.SDK_INT >= 16) { Notification notification = mBuilder.build(); // Merge in developer provided extras, but let the values already set // for keys take precedence. Bundle extras = NotificationCompat.getExtras(notification); Bundle mergeBundle = new Bundle(mExtras); for (String key : mExtras.keySet()) { if (extras.containsKey(key)) { mergeBundle.remove(key); } } extras.putAll(mergeBundle); SparseArray actionExtrasMap = NotificationCompatJellybean.buildActionExtrasMap(mActionExtrasList); if (actionExtrasMap != null) { // Add the action extras sparse array if any action was added with extras. NotificationCompat.getExtras(notification).putSparseParcelableArray( NotificationCompatExtras.EXTRA_ACTION_EXTRAS, actionExtrasMap); } if (mContentView != null) { notification.contentView = mContentView; } if (mBigContentView != null) { notification.bigContentView = mBigContentView; } return notification; } else { //noinspection deprecation return mBuilder.getNotification(); } } private void removeSoundAndVibration(Notification notification) { notification.sound = null; notification.vibrate = null; notification.defaults &= ~DEFAULT_SOUND; notification.defaults &= ~DEFAULT_VIBRATE; }}
其他问题
//我的代码Notification.Builder builder = new Notification.Builder(context);Bitmap largeIcon largeIcon = BitmapUtil.getLoacalBitmapFromUrl(imageUrl);//imageUrl是网络图片地址、先从网上下载图片到文件夹中、然后把它转为Bitmap builder.setLargeIcon(largeIcon);
// 6.0 报错 等待解决Caused by: java.lang.AbstractMethodError: abstract method "android.graphics.drawable.Drawable android.content.pm.PackageManager.getUserBadgeForDensity(android.os.UserHandle, int)"at android.app.Notification$Builder.getProfileBadgeDrawable(Notification.java:2890)at android.app.Notification$Builder.hasThreeLines(Notification.java:3105)at android.app.Notification$Builder.build(Notification.java:3660)```
更多相关文章
- 使用广播实现的Android关机及重启
- Android(安卓)获取系统或SDCARD剩余空间信息
- Android(安卓)4.4.2 禁用通知栏下拉
- Android中获取应用程序(包)的信息(launcher获取系统应用)
- 漫谈android系统(1)解析android编译
- android 让通知不被清除或者点击后不消失
- Android(安卓)UI之Notification
- Android简易实战教程--第十一话《获取手机所有应用信息Engine类
- unity项目中,需要将文本内容复制到系统剪切板(包含android,ios,u