日常生活中,相信很多人都会有这样的经历,每天手机都会收到一些来自不同来源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); } }