首页 > 操作系统

Notification弹出实现

2017-08-28 22:00:17

  Notification的几种基本使用方法,大家肯定都已经烂熟于心,我也不必多说.给一个链接:https://zhuanlan.zhihu.com/p/25841482

接下来我想说的是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     @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 }
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添加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 }
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);   }

  目前先这样吧,以后继续更新。。。