博主声明:
转载请在开头附加本文链接及作者信息,并标记为转载。本文由博主 威威喵 原创,请多支持与指教。
由于博主之前写过的通知代码,在 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样式的通知
自定义View样式的通知,需要根据自己的需求来决定,比如像音乐播放器那种样式的,就是一个自定义样式,下面是一个简单的布局文件:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/tv_notify_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:textColor="#000000"
android:textSize="16sp" />
<TextView
android:id="@+id/tv_notify_sub_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/tv_notify_text"
android:layout_marginLeft="16dp"
android:layout_marginTop="8dp"
android:textSize="14sp" />
<ImageView
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_below="@+id/tv_notify_sub_text"
android:layout_marginLeft="8dp"
android:layout_marginTop="8dp"
android:src="@mipmap/ic_launcher" />
<Button
android:id="@+id/btn_pending_intent"
android:layout_width="80dp"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginRight="8dp"
android:text="点击跳转" />
</RelativeLayout>
通知代码如下:
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 的通知方面的适配以及通知样式相关的案例,到此也基本满足我们日常开发中所需求的通知方式。