日常生活中,相信很多人都会有这样的经历,每天手机都会收到一些来自不同来源app的一些消息,显示与状态栏,下拉即可查看,甚至可以点击进行调转到相应app界面,
鉴于这样的功能和效果非常常见,也非常适合推送用于显示,所以有必要对这个知识总结一下。实现起来其实也不复杂,联系实际生活,我们需要发布一个通知,首先需要发布者然后就是发布的内容,
跟Android中的api结合起来,通知消息的发布者就是 NotificationManager和 通知消息Notification .
NotificationManager : 是状态栏通知的管理类,负责发通知、清楚通知等。
Notification:状态栏通知对象,可以设置icon、文字、提示声音、振动等等参数。
通常发布一个通知包含四个步骤:
1.获取 NotificationManager 实例管理通知;
2.实例 Notification 对象; 创建一个消息对象
3.发送通知。
4.管理事件 Intent(额外)
—1.创建消息管理其
//创建一个通知管理器
NotificationManager notificationManager= (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
—2.获取Notification实例 获取Notification实例有很多方法处理 在此我只展示通用的方法(虽然这种方式是属于api16以上,但是已经可以了,毕竟16以下的Android机很少了。如果非要全面兼容可以用)
Notification notification = new Notification.Builder(context)
.setContentTitle("标题")
.setContentText("内容")
.setWhen(System.currentTimeMillis())
.setSmallIcon(R.mipmap.ic_small)
.setLargeIcon(BitmapFactory.decodeResource(context.getResources(), R.drawable.icon_notify))
.build();
如果非要全面兼容可以用,可以用以下代码
Notification notification=new NotificationCompat.Builder(context)
.setContentTitle("标题")
.setContentText("内容")
.setWhen(System.currentTimeMillis())
.setSmallIcon(R.mipmap.ic_small)
.setLargeIcon(BitmapFactory.decodeResource(context.getResources(), R.drawable.icon_notify))
.build();
—3. 发送通知
int notifiId=1;
notificationManager.notify(notifiId,notification);
以上代码非常简单,但是其实已经可以实现了消息通知栏了。可能有人不相信,拿我这里就贴图为证。
下图为状态栏显示结果:
下图为下拉之后的结果:
既然已经实现了消息通知栏,接着我们继续探究,以上结果是我运行在4.4系统上的结果,下面我相继对5.x系统,6.0系统,7.x系统分别做出测试。
5.1系统运行结果如下:
状态栏显示结果:
下拉后显示结果:
通过上图我们会发现在5.0手机上消息通知未下拉之前图标显示为白色,这个时候就很奇怪啦,明明设置了小图标,为什么会显示白色?经过查阅相关资料,是因为我们的图片资源的原因,我们小图标一定要是透明状态的.png格式图片,否则在状态栏显示成白色或者灰色。于是我就去找了一张透明背景的png图片,5.1运行结果如下;
此处我为了显示区别,设置小图标和大图标是两个不同的图片(正常情况下,我们应该要UI做两张不同大小的logo图片,分别用来显示状态栏图标和下拉之后的大图标),我们可以发现在大图片右下角有会自动多一个灰色背景的小图标,其实为了看着更和谐我们是可以设置右下角圆圈的背景色的。
Notification notification=new NotificationCompat.Builder(context)
.setContentTitle("通知栏标题")
.setContentText("这是消息通过通知栏的内容")
.setWhen(System.currentTimeMillis())
.setSmallIcon(R.drawable.ic_small)
.setColor(Color.parseColor("#8161F6"))
.setLargeIcon(BitmapFactory.decodeResource(context.getResources(), R.drawable.icon_notify))
.build();
运行再看拉下之后的结果:
是不是现在已经很好看啦。
6.0运行结果跟5.x类似,只需要注意的就是小图标一定要透明背景的png格式图片,大图标没有要求,下拉之后圆圈部分背景色直接设置跟大图标整体颜色相近即可。
接着在7.0手机上运行,跟之前的结果又会有点差别,这个差别是在从通知栏拉下来显示之后如下图:
这个其实就是我们的app_name,就是我们在清单文件中配置的app_name.
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".activity.MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".activity.WebViewActivity" />
<activity android:name=".activity.StatusBarActivity" />
<activity android:name=".activity.NotificationActivity"></activity>
</application>
到此可以说5.0至7.x的配置基本完成,再次总结一下,我们需要注意一下几个地方:
1.对于5.0以上的手机设置的小图标要求必须是透明背景的.png格式图片,大图标无要求 2.消息通知从状态栏下拉之后,大图标的右下角的圆圈部分是可以更改背景色的,我们可以将其设置成跟大图标本体色相近的颜色看着会比较和谐
3.对于7.0手机,从状态栏下拉之后,标题上方显示的是app_name是可以通过清单文件进行更改的。
接着就剩下8.0的适配,我们还是重新运行下以上代码,结果非常令人困扰,居然报错,报什么错列,请看下图:
错误原因其实就是:消息发布的时候 我们的通道是空的,经过相关资料查阅,发现8.0以上系统有一个消息通道的概念,在需要发布消息通知之前必须需要一个消息通道。接下来创建消息通道
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.O){
//创建 通知通道 channelid和channelname是必须的(自己命名就好)
NotificationChannel channel = new NotificationChannel(CHANNEL_ID, CHANEL_NAME, NotificationManager.IMPORTANCE_DEFAULT);
channel.enableLights(true);//是否在桌面icon右上角展示小红点
channel.setLightColor(Color.GREEN);//小红点颜色
channel.setShowBadge(false); //是否在久按桌面图标时显示此渠道的通知
}
通道对象创建之后,紧接着我们发送消息之前就必须先创建通道,即征对于8.0以上手机在发布消息前先创建好通道,代码如下:
//发送通知
int notifiId=1;
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.O){
notificationManager.createNotificationChannel(channel);
}
notificationManager.notify(notifiId,notification);
重写运行,我们发现仍然会提示之前的错误,之所以出现这个错误,其实是因为8.0以上手机要求,在构建消息对象时需要传入我们的通道渠道ID,所以我们构造消息对象的方法需要改变一下,代码如下:
Notification notification;
//获取Notification实例 获取Notification实例有很多方法处理 在此我只展示通用的方法(虽然这种方式是属于api16以上,但是已经可以了,毕竟16以下的Android机很少了,如果非要全面兼容可以用)
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.O){
//向上兼容 用Notification.Builder构造notification对象
notification = new Notification.Builder(context,CHANNEL_ID)
.setContentTitle("通知栏标题")
.setContentText("这是消息通过通知栏的内容")
.setWhen(System.currentTimeMillis())
.setSmallIcon(R.drawable.ic_small)
.setColor(Color.parseColor("#FEDA26"))
.setLargeIcon(BitmapFactory.decodeResource(context.getResources(),R.mipmap.ic_cpu))
.setTicker("巴士门")
.build();
}else {
//向下兼容 用NotificationCompat.Builder构造notification对象
notification = new NotificationCompat.Builder(context)
.setContentTitle("通知栏标题")
.setContentText("这是消息通过通知栏的内容")
.setWhen(System.currentTimeMillis())
.setSmallIcon(R.drawable.ic_small)
.setColor(Color.parseColor("#FEDA26"))
.setLargeIcon(BitmapFactory.decodeResource(context.getResources(),R.mipmap.ic_cpu))
.setTicker("巴士门")
.build();
}
其实就是在构造时多传一个通道ID;
到此我们的8.0适配也结束啦。
为了方便大家查看,我把自己写的demo也在此贴出来
public class NotificationHelper {
private static final String CHANNEL_ID="channel_id"; //通道渠道id
public static final String CHANEL_NAME="chanel_name"; //通道渠道名称
@TargetApi(Build.VERSION_CODES.O)
public static void show(Context context){
NotificationChannel channel = null;
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.O){
//创建 通知通道 channelid和channelname是必须的(自己命名就好)
channel = new NotificationChannel(CHANNEL_ID, CHANEL_NAME, NotificationManager.IMPORTANCE_DEFAULT);
channel.enableLights(true);//是否在桌面icon右上角展示小红点
channel.setLightColor(Color.GREEN);//小红点颜色
channel.setShowBadge(false); //是否在久按桌面图标时显示此渠道的通知
}
Notification notification;
//获取Notification实例 获取Notification实例有很多方法处理 在此我只展示通用的方法(虽然这种方式是属于api16以上,但是已经可以了,毕竟16以下的Android机很少了,如果非要全面兼容可以用)
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.O){
//向上兼容 用Notification.Builder构造notification对象
notification = new Notification.Builder(context,CHANNEL_ID)
.setContentTitle("通知栏标题")
.setContentText("这是消息通过通知栏的内容")
.setWhen(System.currentTimeMillis())
.setSmallIcon(R.drawable.ic_small)
.setColor(Color.parseColor("#FEDA26"))
.setLargeIcon(BitmapFactory.decodeResource(context.getResources(),R.mipmap.ic_cpu))
.setTicker("巴士门")
.build();
}else {
//向下兼容 用NotificationCompat.Builder构造notification对象
notification = new NotificationCompat.Builder(context)
.setContentTitle("通知栏标题")
.setContentText("这是消息通过通知栏的内容")
.setWhen(System.currentTimeMillis())
.setSmallIcon(R.drawable.ic_small)
.setColor(Color.parseColor("#FEDA26"))
.setLargeIcon(BitmapFactory.decodeResource(context.getResources(),R.mipmap.ic_cpu))
.setTicker("巴士门")
.build();
}
//发送通知
int notifiId=1;
//创建一个通知管理器
NotificationManager notificationManager= (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.O){
notificationManager.createNotificationChannel(channel);
}
notificationManager.notify(notifiId,notification);
}
}