Notification的几种基本使用方法,大家肯定都已经烂熟于心,我也不必多说.
接下来我想说的是android5.0 后的弹出通知,
网上的方法是:
//第一步:实例化通知栏构造器Notification.Builder:
Notification.Builder builder =new Notification.Builder(MainActivity.this);//实例化通知栏构造器Notification.Builder,参数必填(Context类型),为创建实例的上下文
//第二步:获取状态通知栏管理:
NotificationManager mNotifyMgr = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);//获取状态栏通知的管理类(负责发通知、清除通知等操作)
//第三步:设置通知栏PendingIntent(点击动作事件等都包含在这里):
Intent push =new Intent(MainActivity.this,MainActivity.class);//新建一个显式意图,第一个参数 Context 的解释是用于获得 package name,以便找到第二个参数 Class 的位置
//PendingIntent可以看做是对Intent的包装,通过名称可以看出PendingIntent用于处理即将发生的意图,而Intent用来用来处理马上发生的意图
//本程序用来响应点击通知的打开应用,第二个参数非常重要,点击notification 进入到activity, 使用到pendingIntent类方法,PengdingIntent.getActivity()的第二个参数,即请求参数,实际上是通过该参数来区别不同的Intent的,如果id相同,就会覆盖掉之前的Intent了
PendingIntent contentIntent = PendingIntent.getActivity(MainActivity.this,0,push,0);
//第四步:对Builder进行配置:
builder
.setContentTitle("My notification")//标题
.setContentText("Hello World!")// 详细内容
.setContentIntent(contentIntent)//设置点击意图
.setTicker("New message")//第一次推送,角标旁边显示的内容
.setLargeIcon(BitmapFactory.decodeResource(getResources(),R.drawable.ic_launcher))//设置大图标
.setDefaults(Notification.DEFAULT_ALL);//打开呼吸灯,声音,震动,触发系统默认行为
/*Notification.DEFAULT_VIBRATE //添加默认震动提醒 需要VIBRATE permission
Notification.DEFAULT_SOUND //添加默认声音提醒
Notification.DEFAULT_LIGHTS//添加默认三色灯提醒
Notification.DEFAULT_ALL//添加默认以上3种全部提醒*/
//.setLights(Color.YELLOW, 300, 0)//单独设置呼吸灯,一般三种颜色:红,绿,蓝,经测试,小米支持黄色
//.setSound(url)//单独设置声音
//.setVibrate(new long[] { 100, 250, 100, 250, 100, 250 })//单独设置震动
//比较手机sdk版本与Android 5.0 Lollipop的sdk
if(android.os.Build.VERSION.SDK_INT>= android.os.Build.VERSION_CODES.LOLLIPOP) {
builder
/*android5.0加入了一种新的模式Notification的显示等级,共有三种:
VISIBILITY_PUBLIC只有在没有锁屏时会显示通知
VISIBILITY_PRIVATE任何情况都会显示通知
VISIBILITY_SECRET在安全锁和没有锁屏的情况下显示通知*/
.setVisibility(Notification.VISIBILITY_PUBLIC)
.setPriority(Notification.PRIORITY_DEFAULT)//设置该通知优先级
.setCategory(Notification.CATEGORY_MESSAGE)//设置通知类别
//.setColor(context.getResources().getColor(R.color.small_icon_bg_color))//设置smallIcon的背景色
.setFullScreenIntent(contentIntent, true)//将Notification变为悬挂式Notification
.setSmallIcon(R.drawable.ic_launcher);//设置小图标
}
else{
builder
.setSmallIcon(R.drawable.ic_launcher);//设置小图标
}
//第五步:发送通知请求:
Notification notify = builder.build();//得到一个Notification对象
mNotifyMgr.notify(1,notify);//发送通知请求
}
但上面的做法并不能在android5.0以下的设备上使通知弹出,因此下面的做法是自己重写Notification(网上查找的一些资料,来源忘记了,不好意思)
如果需要使通知自动显示,那么就需要我们在接收到通知后重新定义通知的界面,并使其加载显示在Window界面上,这点需要读者了解Window的加载机制.
其实简单点来说,就是通过windowManager的仅有的三个方法(加载,更新,删除)来实现的.如果有大神熟悉这方面的知识可以分享分享.
自定义Notification的思路:
1.继承重写NotificationCompat,Builder来实现类似的Notification
2.自定义通知界面
3.自定义NotificationManager,发送显示通知
废话不多说,先上主要代码:
1 public class HeadsUp {
2
3 private Context context;
4 /**
5 * 出现时间 单位是 second
6 */
7 private long duration= 3;
8 /**
9 *
10 */
11 private Notification notification;
12
13 private Builder builder;
14
15 private boolean isSticky=false;
16
17
18 private boolean activateStatusBar=true;
19
20 private Notification silencerNotification;
21 /**
22 * 间隔时间
23 */
24 private int code;
25 private CharSequence titleStr;
26 private CharSequence msgStr;
27 private int icon;
28 private View customView;
29 private boolean isExpand;
30 private HeadsUp(Context context) {
31 this.context=context;
32 }
33 public static class Builder extends NotificationCompat.Builder {
34 private HeadsUp headsUp;
35 public Builder(Context context) {
36 super(context);
37 headsUp=new HeadsUp(context);
38 }
39 public Builder setContentTitle(CharSequence title) {
40 headsUp.setTitle(title);
41 super.setContentTitle(title); //状态栏显示内容
42 return this;
43 }
44 public Builder setContentText(CharSequence text) {
45 headsUp.setMessage(text);
46 super.setContentText(text);
47 return this;
48 }
49 public Builder setSmallIcon(int icon) {
50 headsUp.setIcon(icon);
51 super.setSmallIcon(icon);
52 return this;
53 }
54 public HeadsUp buildHeadUp(){
55 headsUp.setNotification(this.build());
56 headsUp.setBuilder(this);
57 return headsUp;
58 }
59 public Builder setSticky(boolean isSticky){
60 headsUp.setSticky(isSticky);
61 return this;
62 }
63 }
64
65 public Context getContext() {
66 return context;
67 }
68
69 public long getDuration() {
70 return duration;
71 }
72
73 public Notification getNotification() {
74 return notification;
75 }
76
77 protected void setNotification(Notification notification) {
78 this.notification = notification;
79 }
80
81 public View getCustomView() {
82 return customView;
83 }
84
85 public void setCustomView(View customView) {
86 this.customView = customView;
87 }
88
89 public int getCode() {
90 return code;
91 }
92
93 protected void setCode(int code) {
94 this.code = code;
95 }
96
97 protected Builder getBuilder() {
98 return builder;
99 }
100
101 private void setBuilder(Builder builder) {
102 this.builder = builder;
103 }
104
105
106 public boolean isSticky() {
107 return isSticky;
108 }
109
110 public void setSticky(boolean isSticky) {
111 this.isSticky = isSticky;
112 }
113
114 }
View Code
1 public class HeadsUpManager {
2
3 private WindowManager wmOne;
4 private FloatView floatView;
5 private Queue<HeadsUp> msgQueue;
6 private static HeadsUpManager manager;
7 private Context context;
8
9 private boolean isPolling = false;
10
11 private Map<Integer, HeadsUp> map;
12 private NotificationManager notificationManager=null;
13
14 public static HeadsUpManager getInstant(Context c) {
15
16 if (manager == null) {
17 manager = new HeadsUpManager(c);
18
19 }
20 return manager;
21
22 }
23
24 private HeadsUpManager(Context context) {
25 this.context = context;
26 map = new HashMap<Integer, HeadsUp>();
27 msgQueue = new LinkedList<HeadsUp>();
28 wmOne = (WindowManager) context
29 .getSystemService(Context.WINDOW_SERVICE);
30
31 notificationManager= (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
32 }
33
34 public void notify(HeadsUp headsUp) {
35
36
37 if (map.containsKey(headsUp.getCode())) {
38 msgQueue.remove(map.get(headsUp.getCode()));
39 }
40 map.put(headsUp.getCode(), headsUp);
41 msgQueue.add(headsUp);
42
43 if (!isPolling) {
44 poll();
45 }
46 }
47 public synchronized void notify(int code,HeadsUp headsUp) {
48 headsUp.setCode(code);
49 notify(headsUp);
50
51 }
52 public synchronized void cancel(HeadsUp headsUp) {
53 cancel(headsUp.getCode());
54 }
55
56
57 private synchronized void poll() {
58 if (!msgQueue.isEmpty()) {
59 HeadsUp headsUp = msgQueue.poll();
60 map.remove(headsUp.getCode());
61
62 // if ( Build.VERSION.SDK_INT < 21 || headsUp.getCustomView() != null ){
63 isPolling = true;
64 show(headsUp);
65 System.out.println("自定义notification");
66 // }else {
67 // //当 系统是 lollipop 以上,并且没有自定义布局以后,调用系统自己的 notification
68 // isPolling = false;
69 // notificationManager.notify(headsUp.getCode(),headsUp.getBuilder().setSmallIcon(headsUp.getIcon()).build());
70 // System.out.println("调用系统notification");
71 // }
72
73 } else {
74 isPolling = false;
75 }
76 }
77 private void show(HeadsUp headsUp) {
78 floatView = new FloatView(context, 20);
79 WindowManager.LayoutParams params = FloatView.winParams;
80 params.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
81 | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
82 |WindowManager.LayoutParams.FLAG_FULLSCREEN
83 | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
84 params.type = WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
85 params.width = WindowManager.LayoutParams.MATCH_PARENT;
86 params.height = WindowManager.LayoutParams.WRAP_CONTENT;
87 params.format = -3;
88 params.gravity = Gravity.CENTER | Gravity.TOP;
89 params.x = floatView.originalLeft;
90 params.y = 10;
91 params.alpha = 1f;
92 wmOne.addView(floatView, params);
93 ObjectAnimator a = ObjectAnimator.ofFloat(floatView.rootView, "translationY", -700, 0);
94 a.setDuration(600);
95 a.start();
96 floatView.setNotification(headsUp);
97 if(headsUp.getNotification()!=null){
98 notificationManager.notify(headsUp.getCode(), headsUp.getNotification());
99 }
100 }
101
102 public void cancel(){
103
104 if(floatView !=null && floatView.getParent()!=null) {
105
106 floatView.cancel();
107 }
108 }
109
110 protected void dismiss() {
111 if (floatView.getParent()!=null) {
112 wmOne.removeView(floatView);
113 floatView.postDelayed(new Runnable() {
114 @Override
115 public void run() {
116 poll();
117 }
118 }, 200);
119 }
120
121 }
122
123 protected void animDismiss(){
124 if(floatView !=null && floatView.getParent()!=null){
125
126 ObjectAnimator a = ObjectAnimator.ofFloat(floatView.rootView, "translationY", 0, -700);
127 a.setDuration(700);
128 a.start();
129
130 a.addListener(new Animator.AnimatorListener() {
131 @Override
132 public void onAnimationStart(Animator animator) {
133
134 }
135 @Override
136 public void onAnimationEnd(Animator animator) {
137
138 dismiss();
139 }
140 @Override
141 public void onAnimationCancel(Animator animator) {
142 }
143 @Override
144 public void onAnimationRepeat(Animator animator) {
145
146 }
147 });
148 }
149
150 }
151
152 protected void animDismiss(HeadsUp headsUp){
153 if(floatView.getHeadsUp().getCode()==headsUp.getCode()){
154 animDismiss();
155 }
156
157 }
158 public void cancel(int code) {
159 if (map.containsKey(code)) {
160 msgQueue.remove(map.get(code));
161 }
162 if(floatView!=null && floatView.getHeadsUp().getCode()==code){
163 animDismiss();
164 }
165
166 }
167 public void close() {
168 cancelAll();
169 manager = null;
170 }
171 public void cancelAll() {
172 msgQueue.clear();
173 if (floatView!=null && floatView.getParent()!=null) {
174 animDismiss();
175 }
176 }
177 }
View Code
1 public class FloatView extends LinearLayout {
2 private float rawX = 0;
3 private float rawY=0;
4 private float touchX = 0;
5 private float startY = 0;
6 public LinearLayout rootView;
7 public int originalLeft;
8 public int viewWidth;
9 private float validWidth;
10 private VelocityTracker velocityTracker;
11 private int maxVelocity;
12 private Distance distance;
13
14 private ScrollOrientationEnum scrollOrientationEnum=ScrollOrientationEnum.NONE;
15
16 public static WindowManager.LayoutParams winParams = new WindowManager.LayoutParams();
17
18 public FloatView(final Context context, int i) {
19 super(context);
20 LinearLayout view = (LinearLayout) LayoutInflater.from(getContext()).inflate(R.layout.notification_bg, null);
21 maxVelocity= ViewConfiguration.get(context).getScaledMaximumFlingVelocity();
22 rootView = (LinearLayout) view.findViewById(R.id.rootView);
23 addView(view);
24 viewWidth = context.getResources().getDisplayMetrics().widthPixels;
25 validWidth=viewWidth/2.0f;
26 originalLeft = 0;
27
28 }
29
30 public void setCustomView(View view) {
31 rootView.addView(view);
32 }
33
34
35 @Override
36 protected void onFinishInflate() {
37 super.onFinishInflate();
38 }
39
40
41 private HeadsUp headsUp;
42 private long cutDown;
43 private Handler mHandle=null;
44 private CutDownTime cutDownTime;
45 private class CutDownTime extends Thread{
46
47 @Override
48 public void run() {
49 super.run();
50
51
52 while (cutDown>0){
53 try {
54 Thread.sleep(1000);
55 cutDown--;
56 } catch (InterruptedException e) {
57 e.printStackTrace();
58 }
59 }
60
61 if(cutDown==0) {
62 mHandle.sendEmptyMessage(0);
63 }
64
65
66 }
67 };
68
69
70
71 public HeadsUp getHeadsUp() {
72 return headsUp;
73 }
74
75 private int pointerId;
76 public boolean onTouchEvent(MotionEvent event) {
77 rawX = event.getRawX();
78 rawY=event.getRawY();
79 acquireVelocityTracker(event);
80 cutDown= headsUp.getDuration();
81 switch (event.getAction()) {
82 case MotionEvent.ACTION_DOWN:
83 touchX = event.getX();
84 startY = event.getRawY();
85 pointerId=event.getPointerId(0);
86 break;
87 case MotionEvent.ACTION_MOVE:
88 switch (scrollOrientationEnum){
89 case NONE:
90 if(Math.abs((rawX - touchX))>20) {
91 scrollOrientationEnum=ScrollOrientationEnum.HORIZONTAL;
92
93 }else if(startY-rawY>20){
94 scrollOrientationEnum=ScrollOrientationEnum.VERTICAL;
95
96 }
97
98 break;
99 case HORIZONTAL:
100 updatePosition((int) (rawX - touchX));
101 break;
102 case VERTICAL:
103 if(startY-rawY>20) {
104 cancel();
105 }
106 break;
107 }
108
109 break;
110 case MotionEvent.ACTION_UP:
111 velocityTracker.computeCurrentVelocity(1000,maxVelocity);
112 int dis= (int) velocityTracker.getYVelocity(pointerId);
113 if(scrollOrientationEnum==ScrollOrientationEnum.NONE){
114 if(headsUp.getNotification().contentIntent!=null){
115
116 try {
117 headsUp.getNotification().contentIntent.send();
118 cancel();
119 } catch (PendingIntent.CanceledException e) {
120 e.printStackTrace();
121 }
122 }
123 break;
124 }
125
126
127 int toX;
128 if(preLeft>0){
129 toX= (int) (preLeft+Math.abs(dis));
130 }else{
131 toX= (int) (preLeft-Math.abs(dis));
132 }
133 if (toX <= -validWidth) {
134 float preAlpha=1-Math.abs(preLeft)/validWidth;
135 preAlpha=preAlpha>=0?preAlpha:0;
136 translationX(preLeft,-(validWidth+10),preAlpha,0);
137 } else if (toX <= validWidth) {
138 float preAlpha=1-Math.abs(preLeft)/validWidth;
139 preAlpha=preAlpha>=0?preAlpha:0;
140 translationX(preLeft,0,preAlpha,1);
141
142 }else{
143 float preAlpha=1-Math.abs(preLeft)/validWidth;
144 preAlpha=preAlpha>=0?preAlpha:0;
145 translationX(preLeft, validWidth + 10, preAlpha, 0);
146 }
147 preLeft = 0;
148 scrollOrientationEnum=ScrollOrientationEnum.NONE;
149 break;
150 }
151
152 return super.onTouchEvent(event);
153
154 }
155 /**
156 *
157 * @param event 向VelocityTracker添加MotionEvent
158 *
159 * @see android.view.VelocityTracker#obtain()
160 * @see android.view.VelocityTracker#addMovement(MotionEvent)
161 */
162 private void acquireVelocityTracker( MotionEvent event) {
163 if(null == velocityTracker) {
164 velocityTracker = VelocityTracker.obtain();
165 }
166 velocityTracker.addMovement(event);
167 }
168 private int preLeft;
169
170 public void updatePosition(int left) {
171
172 float preAlpha=1-Math.abs(preLeft)/validWidth;
173 float leftAlpha=1-Math.abs(left)/validWidth;
174 preAlpha = preAlpha>=0 ? preAlpha : 0;
175 leftAlpha = leftAlpha>=0 ? leftAlpha : 0;
176 translationX(preLeft,left,preAlpha,leftAlpha);
177
178 preLeft = left;
179 }
180
181 public void translationX(float fromX,float toX,float formAlpha, final float toAlpha ){
182 ObjectAnimator a1=ObjectAnimator.ofFloat(rootView,"alpha",formAlpha,toAlpha);
183 ObjectAnimator a2 = ObjectAnimator.ofFloat(rootView, "translationX", fromX, toX);
184 AnimatorSet animatorSet=new AnimatorSet();
185 animatorSet.playTogether(a1,a2);
186 animatorSet.addListener(new Animator.AnimatorListener() {
187 @Override
188 public void onAnimationStart(Animator animation) {
189 }
190
191 @Override
192 public void onAnimationEnd(Animator animation) {
193 if(toAlpha==0){
194 HeadsUpManager.getInstant(getContext()).dismiss();
195
196 cutDown=-1;
197 if(velocityTracker!=null) {
198 velocityTracker.clear();
199 try {
200 velocityTracker.recycle();
201 } catch (IllegalStateException e) {
202
203 }
204 }
205
206 }
207 }
208
209 @Override
210 public void onAnimationCancel(Animator animation) {
211 }
212
213 @Override
214 public void onAnimationRepeat(Animator animation) {
215 }
216 });
217 animatorSet.start();
218 }
219
220 public void setNotification(final HeadsUp headsUp) {
221
222 this.headsUp = headsUp;
223
224 mHandle= new Handler(){
225 @Override
226 public void handleMessage(Message msg) {
227 super.handleMessage(msg);
228 HeadsUpManager.getInstant(getContext()).animDismiss(headsUp);
229 }
230 };
231
232
233
234 cutDownTime= new CutDownTime();
235
236 if(!headsUp.isSticky()){
237 cutDownTime.start();
238 }
239
240
241 cutDown= headsUp.getDuration();
242
243 if (headsUp.getCustomView() == null) {
244
245 View defaultView = LayoutInflater.from(getContext()).inflate(R.layout.notification, rootView, false);
246 rootView.addView(defaultView);
247 ImageView imageView = (ImageView) defaultView.findViewById(R.id.iconIM);
248 TextView titleTV = (TextView) defaultView.findViewById(R.id.titleTV);
249 TextView timeTV = (TextView) defaultView.findViewById(R.id.timeTV);
250 TextView messageTV = (TextView) defaultView.findViewById(R.id.messageTV);
251 imageView.setImageResource(headsUp.getIcon());
252 titleTV.setText(headsUp.getTitleStr());
253 messageTV.setText(headsUp.getMsgStr());
254 SimpleDateFormat simpleDateFormat=new SimpleDateFormat("HH:mm");
255 timeTV.setText( simpleDateFormat.format(new Date()));
256
257
258 } else {
259 setCustomView(headsUp.getCustomView());
260 }
261
262 }
263
264
265 protected void cancel(){
266 HeadsUpManager.getInstant(getContext()).animDismiss();
267 cutDown = -1;
268 cutDownTime.interrupt();
269
270
271 if(velocityTracker!=null) {
272 try {
273 velocityTracker.clear();
274 velocityTracker.recycle();
275 } catch (IllegalStateException e) {
276
277 }
278 }
279 }
280
281
282 enum ScrollOrientationEnum {
283 VERTICAL,HORIZONTAL,NONE
284 }
285 }
View Code
具体用法:
PendingIntent pendingIntent=PendingIntent.getActivity(MainActivity.this,11,new Intent(MainActivity.this,MainActivity.class),PendingIntent.FLAG_UPDATE_CURRENT);
View view=getLayoutInflater().inflate(R.layout.custom_notification, null);
view.findViewById(R.id.openSource).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
}
});
HeadsUpManager manage = HeadsUpManager.getInstant(getApplication());
HeadsUp.Builder builder = new HeadsUp.Builder(MainActivity.this);
builder.setContentTitle("提醒")
//要显示通知栏通知,这个一定要设置
.setSmallIcon(R.drawable.icon)
.setContentText("你有新的消息")
//2.3 一定要设置这个参数,负责会报错
.setContentIntent(pendingIntent)
//.setFullScreenIntent(pendingIntent, false)
HeadsUp headsUp = builder.buildHeadUp();
headsUp.setCustomView(view);
manage.notify(1, headsUp);
}
目前先这样吧,以后继续更新。。。