博主声明:
转载请在开头附加本文链接及作者信息,并标记为转载。本文由博主 威威喵 原创,请多支持与指教。
本文首发于此 博主:威威喵 | 博客主页:https://blog.csdn.net/smile_running
由于博主之前写过的通知代码,在 Android 8.0 以上跑的时候,却怎么也通知不出来。本来之前在其它模拟器(android 5.x)上进行测试的时候,还是好好的。突然在 8.0 上跑的时候,就不行了,这很明显就是版本适配出现了问题。
于是呢,博主就去看了一些相关的资料,原来在 8.0 版本,谷歌就为每一个通知设定了一个 NotificationChannel,如果在通知代码里没有加这个 Channel 的话,在 8.0 及以上都无法显示通知出来的。
好了,接下来通过一个简单的 Demo 去适配 Android 8.0 及以上的通知,案例中包含了普通样式的通知、自定义View样式的通知、带进度条的通知、以及悬浮式通知。
首先,我们要解决的一个问题,如何进行适配,既适配 8.0 及以上,和 8.0 以下。
先获取 NotificationManager 的实例,用于管理通知:
private NotificationManager mNotificationManager;
mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
接着是创建 Notification 代码,这里就要对 Android 版本进行适配工作
private Notification.Builder getNotificationBuilder() {
checkOpenNotification(this);
Notification.Builder builder;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { // if android version >= 8.0
builder = new Notification.Builder(this, "channel_id");
@SuppressLint("WrongConstant")
NotificationChannel channel = new NotificationChannel("channel_id", "channel_name",
NotificationManager.IMPORTANCE_DEFAULT);
channel.setLockscreenVisibility(NotificationCompat.VISIBILITY_PUBLIC);
mNotificationManager.createNotificationChannel(channel);
} else {
builder = new Notification.Builder(this);
}
builder.setContentTitle("content-title");
builder.setContentText("content-text");
builder.setSubText("sub-text");
builder.setShowWhen(true);
builder.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher));
builder.setSmallIcon(R.mipmap.ic_launcher_round);
return builder;
}
如果在 sdk 大于 8.0 及以上的时候,就要创建一个 NotificationChannel 的实例,小于 8.0 那就不需要了,并且可以在 Channel 中设置铃声、震动、呼吸灯、优先级等等。
接下来也是非常重要的一步,就是去系统设置里面,将本应用的通知功能给打开,由于一些手机自己定制的系统,会默认将这项通知功能给关闭,如果不打开的话,也照样显示不了通知信息的。
由于用户可以并不知道如何进行设置,我们可以用代码来先检测该功能是否被打开了,代码如下:
private void checkOpenNotification(Context context) {
boolean notify = NotificationManagerCompat.from(context).areNotificationsEnabled();
if (!notify) {
Intent intent = new Intent();
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && Build.VERSION.SDK_INT < Build.VERSION_CODES.P) { // android 5.x - 9.x
intent.setAction("android.settings.APP_NOTIFICATION_SETTINGS");
intent.putExtra("app_package", context.getPackageName());
intent.putExtra("app_uid", context.getApplicationInfo().uid);
} else if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { // android 4.x
intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
intent.addCategory(Intent.CATEGORY_DEFAULT);
intent.setData(Uri.parse("package:" + context.getPackageName()));
} else {
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setAction("android.settings.APPLICATION_DETAILS_SETTINGS");
intent.setData(Uri.fromParts("package", context.getPackageName(), null));
}
context.startActivity(intent);
}
}
这里设计到了不同版本系统的区别,以及跳转到通知设置的方法,如果用户没有打开该权限,就会引导跳转到设置页面,将下面的通知功能打开即可。
普通样式的通知,就设置了通知内容、标题、副标题等信息,代码很简单,如下:
private void showNormalNotification() {
mNotificationManager.notify(1, getNotificationBuilder().build());
}
效果图如下:
自定义View样式的通知,需要根据自己的需求来决定,比如像音乐播放器那种样式的,就是一个自定义样式,下面是一个简单的布局文件:
通知代码如下:
private void showCustomNotification() {
Notification.Builder builder = getNotificationBuilder();
RemoteViews contentView = new RemoteViews(getPackageName(), R.layout.notify_content_view);
contentView.setTextViewText(R.id.tv_notify_text, "Text");
contentView.setTextViewText(R.id.tv_notify_sub_text, "SubText");
Intent intent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
contentView.setOnClickPendingIntent(R.id.btn_pending_intent, pendingIntent);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
builder.setCustomContentView(contentView);
}
mNotificationManager.notify(2, builder.build());
}
效果图:
带进度样式的通知,可以用于系统更新、下载服务上,给用户通知一下下载进度,代码如下:
private void showProgressNotification() {
final Notification.Builder builder = getNotificationBuilder();
builder.setOnlyAlertOnce(true);//设置震动、铃声等只提醒一次
mNotificationManager.notify(3, builder.build());
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i <= 100; i++) {
try {
Thread.sleep(100);
builder.setProgress(100, i, false);
mNotificationManager.notify(3, builder.build());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
这里仅做了一个线程模拟下载的例子,效果如下:
悬浮式样式的通知场景也很多,比如现在的 App 一般都是用这种方式,但是博主发现,在我现在这个模拟器,Android 9.0 上始终无法悬浮出来,目前也没有成功。但是,在 5.x 的系统上,是可以实现悬浮效果的。就如下面显示的这样:
其代码如下:
private void showSuspendNotification() {
Notification.Builder builder = getNotificationBuilder();
Intent intent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
builder.setContentText("SuspendNotification")
.setFullScreenIntent(pendingIntent, true);
mNotificationManager.notify(4, builder.build());
}
最后,这就是关于 Android 的通知方面的适配以及通知样式相关的案例,到此也基本满足我们日常开发中所需求的通知方式。