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 }
1 public class HeadsUpManager { 2 3 private WindowManager wmOne; 4 private FloatView floatView; 5 private QueuemsgQueue; 6 private static HeadsUpManager manager; 7 private Context context; 8 9 private boolean isPolling = false; 10 11 private Map 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 (); 27 msgQueue = new LinkedList (); 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 @Override115 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 @Override132 public void onAnimationStart(Animator animator) {133 134 }135 @Override136 public void onAnimationEnd(Animator animator) {137 138 dismiss();139 }140 @Override141 public void onAnimationCancel(Animator animator) {142 }143 @Override144 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 }
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添加MotionEvent158 *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 @Override188 public void onAnimationStart(Animator animation) {189 }190 191 @Override192 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 @Override210 public void onAnimationCancel(Animator animation) {211 }212 213 @Override214 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 @Override226 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,NONE284 }285 }
具体用法:
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); }
目前先这样吧,以后继续更新。。。