概要
Notification通知,是一种具有全局效果的通知,它展示在屏幕的顶端,首先会表现为
一个图标的形式,当用户向下滑动的时候,展示出通知具体的内容。比较熟悉的通知有:短
信同事,文件下载通知,以及在音乐播放时,在通知栏有播放通知界面可以控制播放的暂停
播放。
有几点特性:
- 通知是运行在system server进程中的,由NotificationManagerService管理。
- Notification的布局并不是支持所有的View控件。
- 我们使用remoteViews,跨进程通讯更新Notification界面。
Notification的使用
通常的步骤:
- 创建一个通知栏的Builder构造类
- 定义通知栏的Action
- 设置通知栏点击事件
- NotificationManager 提交通知
1,一般形式的使用
- 创建通知,其中setContentIntent方法设置点击意图,在2.3及更低的版本
中如果未设置,会触发异常。 - 因为Android的快速发展,而Android的版本也快速的升级导致了一些兼容性
的问题。对于Notification而言,Android3.0是一个分水岭,在其之前构建
Notification推荐使用NotificationCompate.Builder,它位于android.support.
v4.app.NotificationCompat.Builder,是一个Android向下版本的兼容包。 - 使用闪光灯或者震动效果的通知时,需要添加相关的权限。
/**
* 创造默认形式的通知
* @return
*/
private Notification createDefault(int prog){
NotificationCompat.Builder mBuilder
= new NotificationCompat.Builder(this);
Notification n = mBuilder
.setContentTitle("测试标题")
//设置通知栏标题
.setContentText("测试内容")
//设置通知栏显示内容
.setLargeIcon(BitmapFactory.decodeResource(
getResources(),R.drawable.aa2))
//设置大图标
.setContentText("测试内容")
//设置通知栏显示内容
.setContentIntent(getDefalutIntent(
Notification.FLAG_AUTO_CANCEL))
//设置通知栏点击意图
// .setNumber(number) //设置通知集合的数量
.setTicker("测试通知来啦")
//通知首次出现在通知栏,带上升动画效果的
.setWhen(System.currentTimeMillis())
//通知产生的时间,会在通知信息里显示,一般是系统获
// 取到的时间
.setPriority(Notification.PRIORITY_DEFAULT)
//设置该通知优先级
.setAutoCancel(true)
//设置这个标志当用户单击面板就可以让通知将自动取消
// setOngoing(false)
// ture,设置他为一个正在进行的通知。他们通常是用来
// 表示一个后台任务,用户积极参与(如播放音乐)或以某种
// 方式正在等待,因此占用设备(如一个文件下载,同步操作
// ,主动网络连接)
.setDefaults(Notification.DEFAULT_VIBRATE)
//向通知添加声音、闪灯和振动效果的最简单、最一致的方
// 式是使用当前的用户默认设置,使用defaults属性,可以
// 组合
//Notification.DEFAULT_ALL Notification.DEFAULT_SOUND 添加声音
// requires VIBRATE permission
.setSmallIcon(R.drawable.ic_launcher)
//设置通知小ICON
.setProgress(100, prog, false)
//设置进度
.build();
return n;
}
private PendingIntent getDefalutIntent(int flags){
PendingIntent pIntent = PendingIntent.getActivity(this,
0, new Intent(this, NotificationActivity.class),
flags);
return pIntent;
}
相关权限:
<!-- 闪光灯权限 -->
<uses-permission android:name="android.permission.FLASHLIGHT"/>
<!-- 振动器权限 -->
<uses-permission android:name="android.permission.VIBRATE"/>
提交通知,(通知的更新,也就是重定义一个notification,以同一个ID提交
就是了)
Notification notification = createDefault(prog);
//Notification notification = createCustom();
NotificationManager nManager = (NotificationManager)
getSystemService(Context.NOTIFICATION_SERVICE);
nManager.notify(Notification_ID, notification);
效果如图:
2,自定义样式的使用
使用自定义样式,先看效果图。
分析:有个圆形进度条,实现方式:ImageView + ProgressDrawable(自定义)
接着直接上代码:
ProgressDrawable:
package com.example.songbinwang.littledemo.notification;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.drawable.Drawable;
/**
* Created by songbinwang on 2017/2/13.
*/
public class ProgressDrawable extends Drawable{
private Paint mPaint;
private RectF mRect;
private int progress = 90;
public ProgressDrawable(){
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(10);
mPaint.setColor(Color.YELLOW);
}
public void setProgress(int progress) {
this.progress = progress * 360 / 100;
}
@Override
public void draw(Canvas canvas) {
float cx = (mRect.right + mRect.left) / 2f;
float cy = (mRect.top + mRect.bottom) / 2f;
float radius = Math.min(mRect.width(), mRect.height())/2 -40;
canvas.drawArc(cx-radius, cy-radius, cx+ radius, cy+ radius, 0, progress, false, mPaint);
}
@Override
public void setBounds(int left, int top, int right, int bottom) {
super.setBounds(left, top, right, bottom);
mRect = new RectF(left, top, right, bottom);
}
@Override
public int getIntrinsicWidth() {
if(mRect != null){
return (int) mRect.width();
}
return 100;
}
@Override
public int getIntrinsicHeight() {
if(mRect != null){
return (int) mRect.height();
}
return 100;
}
@Override
public void setAlpha(int alpha) {
mPaint.setAlpha(alpha);
}
@Override
public void setColorFilter(ColorFilter colorFilter) {
mPaint.setColorFilter(colorFilter);
}
@Override
public int getOpacity() {
return PixelFormat.TRANSLUCENT;
}
}
创建notification(自定义RemoteViews)。
private Notification createCustom(boolean...b){
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this);
Notification n = mBuilder
.setContentIntent(getDefalutIntent(Notification.FLAG_AUTO_CANCEL))
//设置通知栏点击意图
// .setNumber(number)
// 设置通知集合的数量
.setTicker("测试通知来啦")
//通知首次出现在通知栏,带上升动画效果的
.setWhen(System.currentTimeMillis())
//通知产生的时间,会在通知信息里显示,一般是系统获取到的时间
.setPriority(Notification.PRIORITY_DEFAULT)
//设置该通知优先级
.setAutoCancel(true)
//设置这个标志当用户单击面板就可以让通知将自动取消
//.setOngoing(false)
// ture,设置他为一个正在进行的通知。他们通常是用来表示
// 一个后台任务,用户积极参与(如播放音乐)或以某种方式正
// 在等待,因此占用设备(如一个文件下载,同步操作,主动网络连接)
.setDefaults(Notification.DEFAULT_VIBRATE)
//向通知添加声音、闪灯和振动效果的最简单、最一致的方式是
// 使用当前的用户默认设置,使用defaults属性,可以组合
//Notification.DEFAULT_ALL Notification.DEFAULT_SOUND 添加声音
// requires VIBRATE permission
.setSmallIcon(R.drawable.ic_launcher)
//设置通知小ICON
.build();
RemoteViews remoteViews =
new RemoteViews(this.getPackageName(), R.layout.notification);
remoteViews.setImageViewResource(R.id.id_icon, R.drawable.aa2);
remoteViews.setTextViewText(R.id.id_title, "test title");
remoteViews.setTextViewText(R.id.id_content, "test content");
if(b == null){
mBitmap = Bitmap.createBitmap(50, 50, Bitmap.Config.RGB_565);
drawBitmap(mBitmap);
}
remoteViews.setImageViewBitmap(R.id.id_progress, mBitmap);
n.contentView = remoteViews;
return n;
}
更新样式:
private void updateN(){
new Thread(){
private boolean isContinue = true;
private int progress;
@Override
public void run() {
while(isContinue){
if(progress >= 100){
isContinue = false;
}
Message msg = handler.obtainMessage();
msg.what = MSG_UPDATE;
msg.obj = progress;
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
handler.sendMessage(msg);
progress += 5;
}
}
}.start();
}
Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch(msg.what){
case MSG_UPDATE:
int progress = (int) msg.obj;
//notifyN(progress);
updateProgressDrawable(progress);
break;
case MSG_FINISH:
break;
}
}
};
Notification_ID定义了唯一标示符,使用notify后旧通知被取代,起到
更新通知的效果。
private void updateProgressDrawable(int progress){
progressDrawable.setProgress(progress);
int w = dp2px(50);
int h = dp2px(50);
Bitmap.Config config = progressDrawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888
: Bitmap.Config.RGB_565;
Bitmap bitmap = Bitmap.createBitmap(w, h, config);
Canvas canvas = new Canvas(bitmap);
progressDrawable.setBounds(0, 0, w, h);
progressDrawable.draw(canvas);
mBitmap = bitmap;
Notification notification = createCustom(true);
NotificationManager nManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
nManager.notify(Notification_ID, notification);
mBitmap.recycle();
}
附上布局文件:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="64dp">
<ImageView
android:id="@+id/id_icon"
android:padding="6dp"
android:layout_marginLeft="10dp"
android:layout_width="64dp"
android:layout_height="64dp"
android:src="@android:color/holo_blue_bright"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="64dp"
android:layout_marginLeft="64dp"
android:layout_marginRight="64dp"
android:gravity="center_vertical"
android:paddingLeft="20dp"
android:orientation="vertical">
<TextView
android:id="@+id/id_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="24sp"
android:textColor="@android:color/black"
android:text="title"/>
<TextView
android:id="@+id/id_content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@android:color/black"
android:text="content"/>
</LinearLayout>
<ImageView
android:id="@+id/id_progress"
android:layout_width="64dp"
android:layout_height="64dp"
android:layout_gravity="center_vertical|right"/>
</FrameLayout>
开发中可能会碰到的问题:
低版本中的部分方法已经被弃用的
(1)Notification.Builder(this).getNotification()
(2)mNotification.setLatestEventInfo(this, “title”, “content”, null);
这些方法都已经被启用,虽然还有效果,可是不建议使用。所以开发过程中
尽量使用NotificationCompat.Builder(this)的构建方法去创建一个通知类。低版本中,自定义的通知栏中如果带有按钮,可能按钮点击事件会失灵
根据版本号,在低版本都会隐藏掉那些按钮低版本中mBuilder.setProgress(100, progress, false);没用,不显示进度条
此方法在4.0及以后版本才有用,如果为早期版本:需要自定义通知布局,其中包含ProgressBar视图自定义布局的时候,不同版本方法不一样
2.3之前(包括2.3)
Notification notify = mBuilder.build();
notify.contentView = view_custom;
mNotificationManager.notify(notifyId, notify)
2.3之后:
通过Builder以下方法赋于自定义布局。
mBuilder.setContent(view_custom)