Android 中Notification彈出通知實(shí)現(xiàn)代碼
NotificationManager 是狀態(tài)欄通知的管理類,負(fù)責(zé)發(fā)通知、清除通知等操作。
NotificationManager 是一個(gè)系統(tǒng)Service,可通過getSystemService(NOTIFICATION_SERVICE)方法來獲取
接下來我想說的是android5.0 后的彈出通知,
網(wǎng)上的方法是:
//第一步:實(shí)例化通知欄構(gòu)造器Notification.Builder:
Notification.Builder builder =new Notification.Builder(MainActivity.this);//實(shí)例化通知欄構(gòu)造器Notification.Builder,參數(shù)必填(Context類型),為創(chuàng)建實(shí)例的上下文
//第二步:獲取狀態(tài)通知欄管理:
NotificationManager mNotifyMgr = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);//獲取狀態(tài)欄通知的管理類(負(fù)責(zé)發(fā)通知、清除通知等操作)
//第三步:設(shè)置通知欄PendingIntent(點(diǎn)擊動(dòng)作事件等都包含在這里):
Intent push =new Intent(MainActivity.this,MainActivity.class);//新建一個(gè)顯式意圖,第一個(gè)參數(shù) Context 的解釋是用于獲得 package name,以便找到第二個(gè)參數(shù) Class 的位置
//PendingIntent可以看做是對(duì)Intent的包裝,通過名稱可以看出PendingIntent用于處理即將發(fā)生的意圖,而Intent用來用來處理馬上發(fā)生的意圖
//本程序用來響應(yīng)點(diǎn)擊通知的打開應(yīng)用,第二個(gè)參數(shù)非常重要,點(diǎn)擊notification 進(jìn)入到activity, 使用到pendingIntent類方法,PengdingIntent.getActivity()的第二個(gè)參數(shù),即請(qǐng)求參數(shù),實(shí)際上是通過該參數(shù)來區(qū)別不同的Intent的,如果id相同,就會(huì)覆蓋掉之前的Intent了
PendingIntent contentIntent = PendingIntent.getActivity(MainActivity.this,0,push,0);
//第四步:對(duì)Builder進(jìn)行配置:
builder
.setContentTitle("My notification")//標(biāo)題
.setContentText("Hello World!")// 詳細(xì)內(nèi)容
.setContentIntent(contentIntent)//設(shè)置點(diǎn)擊意圖
.setTicker("New message")//第一次推送,角標(biāo)旁邊顯示的內(nèi)容
.setLargeIcon(BitmapFactory.decodeResource(getResources(),R.drawable.ic_launcher))//設(shè)置大圖標(biāo)
.setDefaults(Notification.DEFAULT_ALL);//打開呼吸燈,聲音,震動(dòng),觸發(fā)系統(tǒng)默認(rèn)行為
/*Notification.DEFAULT_VIBRATE //添加默認(rèn)震動(dòng)提醒 需要VIBRATE permission
Notification.DEFAULT_SOUND //添加默認(rèn)聲音提醒
Notification.DEFAULT_LIGHTS//添加默認(rèn)三色燈提醒
Notification.DEFAULT_ALL//添加默認(rèn)以上3種全部提醒*/
//.setLights(Color.YELLOW, 300, 0)//單獨(dú)設(shè)置呼吸燈,一般三種顏色:紅,綠,藍(lán),經(jīng)測(cè)試,小米支持黃色
//.setSound(url)//單獨(dú)設(shè)置聲音
//.setVibrate(new long[] { 100, 250, 100, 250, 100, 250 })//單獨(dú)設(shè)置震動(dòng)
//比較手機(jī)sdk版本與Android 5.0 Lollipop的sdk
if(android.os.Build.VERSION.SDK_INT>= android.os.Build.VERSION_CODES.LOLLIPOP) {
builder
/*android5.0加入了一種新的模式Notification的顯示等級(jí),共有三種:
VISIBILITY_PUBLIC只有在沒有鎖屏?xí)r會(huì)顯示通知
VISIBILITY_PRIVATE任何情況都會(huì)顯示通知
VISIBILITY_SECRET在安全鎖和沒有鎖屏的情況下顯示通知*/
.setVisibility(Notification.VISIBILITY_PUBLIC)
.setPriority(Notification.PRIORITY_DEFAULT)//設(shè)置該通知優(yōu)先級(jí)
.setCategory(Notification.CATEGORY_MESSAGE)//設(shè)置通知類別
//.setColor(context.getResources().getColor(R.color.small_icon_bg_color))//設(shè)置smallIcon的背景色
.setFullScreenIntent(contentIntent, true)//將Notification變?yōu)閼覓焓絅otification
.setSmallIcon(R.drawable.ic_launcher);//設(shè)置小圖標(biāo)
}
else{
builder
.setSmallIcon(R.drawable.ic_launcher);//設(shè)置小圖標(biāo)
}
//第五步:發(fā)送通知請(qǐng)求:
Notification notify = builder.build();//得到一個(gè)Notification對(duì)象
mNotifyMgr.notify(1,notify);//發(fā)送通知請(qǐng)求
}
但上面的做法并不能在android5.0以下的設(shè)備上使通知彈出,因此下面的做法是自己重寫Notification(網(wǎng)上查找的一些資料,來源忘記了,不好意思)
如果需要使通知自動(dòng)顯示,那么就需要我們?cè)诮邮盏酵ㄖ笾匦露x通知的界面,并使其加載顯示在Window界面上,這點(diǎn)需要讀者了解Window的加載機(jī)制.
其實(shí)簡(jiǎn)單點(diǎn)來說,就是通過windowManager的僅有的三個(gè)方法(加載,更新,刪除)來實(shí)現(xiàn)的.如果有大神熟悉這方面的知識(shí)可以分享分享.
自定義Notification的思路:
1.繼承重寫NotificationCompat,Builder來實(shí)現(xiàn)類似的Notification
2.自定義通知界面
3.自定義NotificationManager,發(fā)送顯示通知
廢話不多說,先上主要代碼:
public class HeadsUp {
private Context context;
/**
* 出現(xiàn)時(shí)間 單位是 second
*/
private long duration= 3;
/**
*
*/
private Notification notification;
private Builder builder;
private boolean isSticky=false;
private boolean activateStatusBar=true;
private Notification silencerNotification;
/**
* 間隔時(shí)間
*/
private int code;
private CharSequence titleStr;
private CharSequence msgStr;
private int icon;
private View customView;
private boolean isExpand;
private HeadsUp(Context context) {
this.context=context;
}
public static class Builder extends NotificationCompat.Builder {
private HeadsUp headsUp;
public Builder(Context context) {
super(context);
headsUp=new HeadsUp(context);
}
public Builder setContentTitle(CharSequence title) {
headsUp.setTitle(title);
super.setContentTitle(title); //狀態(tài)欄顯示內(nèi)容
return this;
}
public Builder setContentText(CharSequence text) {
headsUp.setMessage(text);
super.setContentText(text);
return this;
}
public Builder setSmallIcon(int icon) {
headsUp.setIcon(icon);
super.setSmallIcon(icon);
return this;
}
public HeadsUp buildHeadUp(){
headsUp.setNotification(this.build());
headsUp.setBuilder(this);
return headsUp;
}
public Builder setSticky(boolean isSticky){
headsUp.setSticky(isSticky);
return this;
}
}
public Context getContext() {
return context;
}
public long getDuration() {
return duration;
}
public Notification getNotification() {
return notification;
}
protected void setNotification(Notification notification) {
this.notification = notification;
}
public View getCustomView() {
return customView;
}
public void setCustomView(View customView) {
this.customView = customView;
}
public int getCode() {
return code;
}
protected void setCode(int code) {
this.code = code;
}
protected Builder getBuilder() {
return builder;
}
private void setBuilder(Builder builder) {
this.builder = builder;
}
public boolean isSticky() {
return isSticky;
}
public void setSticky(boolean isSticky) {
this.isSticky = isSticky;
}
}
public class HeadsUpManager {
private WindowManager wmOne;
private FloatView floatView;
private Queue<HeadsUp> msgQueue;
private static HeadsUpManager manager;
private Context context;
private boolean isPolling = false;
private Map<Integer, HeadsUp> map;
private NotificationManager notificationManager=null;
public static HeadsUpManager getInstant(Context c) {
if (manager == null) {
manager = new HeadsUpManager(c);
}
return manager;
}
private HeadsUpManager(Context context) {
this.context = context;
map = new HashMap<Integer, HeadsUp>();
msgQueue = new LinkedList<HeadsUp>();
wmOne = (WindowManager) context
.getSystemService(Context.WINDOW_SERVICE);
notificationManager= (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
}
public void notify(HeadsUp headsUp) {
if (map.containsKey(headsUp.getCode())) {
msgQueue.remove(map.get(headsUp.getCode()));
}
map.put(headsUp.getCode(), headsUp);
msgQueue.add(headsUp);
if (!isPolling) {
poll();
}
}
public synchronized void notify(int code,HeadsUp headsUp) {
headsUp.setCode(code);
notify(headsUp);
}
public synchronized void cancel(HeadsUp headsUp) {
cancel(headsUp.getCode());
}
private synchronized void poll() {
if (!msgQueue.isEmpty()) {
HeadsUp headsUp = msgQueue.poll();
map.remove(headsUp.getCode());
// if ( Build.VERSION.SDK_INT < 21 || headsUp.getCustomView() != null ){
isPolling = true;
show(headsUp);
System.out.println("自定義notification");
// }else {
// //當(dāng) 系統(tǒng)是 lollipop 以上,并且沒有自定義布局以后,調(diào)用系統(tǒng)自己的 notification
// isPolling = false;
// notificationManager.notify(headsUp.getCode(),headsUp.getBuilder().setSmallIcon(headsUp.getIcon()).build());
// System.out.println("調(diào)用系統(tǒng)notification");
// }
} else {
isPolling = false;
}
}
private void show(HeadsUp headsUp) {
floatView = new FloatView(context, 20);
WindowManager.LayoutParams params = FloatView.winParams;
params.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
|WindowManager.LayoutParams.FLAG_FULLSCREEN
| WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
params.type = WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
params.width = WindowManager.LayoutParams.MATCH_PARENT;
params.height = WindowManager.LayoutParams.WRAP_CONTENT;
params.format = -3;
params.gravity = Gravity.CENTER | Gravity.TOP;
params.x = floatView.originalLeft;
params.y = 10;
params.alpha = 1f;
wmOne.addView(floatView, params);
ObjectAnimator a = ObjectAnimator.ofFloat(floatView.rootView, "translationY", -700, 0);
a.setDuration(600);
a.start();
floatView.setNotification(headsUp);
if(headsUp.getNotification()!=null){
notificationManager.notify(headsUp.getCode(), headsUp.getNotification());
}
}
public void cancel(){
if(floatView !=null && floatView.getParent()!=null) {
floatView.cancel();
}
}
protected void dismiss() {
if (floatView.getParent()!=null) {
wmOne.removeView(floatView);
floatView.postDelayed(new Runnable() {
@Override
public void run() {
poll();
}
}, 200);
}
}
protected void animDismiss(){
if(floatView !=null && floatView.getParent()!=null){
ObjectAnimator a = ObjectAnimator.ofFloat(floatView.rootView, "translationY", 0, -700);
a.setDuration(700);
a.start();
a.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animator) {
}
@Override
public void onAnimationEnd(Animator animator) {
dismiss();
}
@Override
public void onAnimationCancel(Animator animator) {
}
@Override
public void onAnimationRepeat(Animator animator) {
}
});
}
}
protected void animDismiss(HeadsUp headsUp){
if(floatView.getHeadsUp().getCode()==headsUp.getCode()){
animDismiss();
}
}
public void cancel(int code) {
if (map.containsKey(code)) {
msgQueue.remove(map.get(code));
}
if(floatView!=null && floatView.getHeadsUp().getCode()==code){
animDismiss();
}
}
public void close() {
cancelAll();
manager = null;
}
public void cancelAll() {
msgQueue.clear();
if (floatView!=null && floatView.getParent()!=null) {
animDismiss();
}
}
}
public class FloatView extends LinearLayout {
private float rawX = 0;
private float rawY=0;
private float touchX = 0;
private float startY = 0;
public LinearLayout rootView;
public int originalLeft;
public int viewWidth;
private float validWidth;
private VelocityTracker velocityTracker;
private int maxVelocity;
private Distance distance;
private ScrollOrientationEnum scrollOrientationEnum=ScrollOrientationEnum.NONE;
public static WindowManager.LayoutParams winParams = new WindowManager.LayoutParams();
public FloatView(final Context context, int i) {
super(context);
LinearLayout view = (LinearLayout) LayoutInflater.from(getContext()).inflate(R.layout.notification_bg, null);
maxVelocity= ViewConfiguration.get(context).getScaledMaximumFlingVelocity();
rootView = (LinearLayout) view.findViewById(R.id.rootView);
addView(view);
viewWidth = context.getResources().getDisplayMetrics().widthPixels;
validWidth=viewWidth/2.0f;
originalLeft = 0;
}
public void setCustomView(View view) {
rootView.addView(view);
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
}
private HeadsUp headsUp;
private long cutDown;
private Handler mHandle=null;
private CutDownTime cutDownTime;
private class CutDownTime extends Thread{
@Override
public void run() {
super.run();
while (cutDown>0){
try {
Thread.sleep(1000);
cutDown--;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if(cutDown==0) {
mHandle.sendEmptyMessage(0);
}
}
};
public HeadsUp getHeadsUp() {
return headsUp;
}
private int pointerId;
public boolean onTouchEvent(MotionEvent event) {
rawX = event.getRawX();
rawY=event.getRawY();
acquireVelocityTracker(event);
cutDown= headsUp.getDuration();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
touchX = event.getX();
startY = event.getRawY();
pointerId=event.getPointerId(0);
break;
case MotionEvent.ACTION_MOVE:
switch (scrollOrientationEnum){
case NONE:
if(Math.abs((rawX - touchX))>20) {
scrollOrientationEnum=ScrollOrientationEnum.HORIZONTAL;
}else if(startY-rawY>20){
scrollOrientationEnum=ScrollOrientationEnum.VERTICAL;
}
break;
case HORIZONTAL:
updatePosition((int) (rawX - touchX));
break;
case VERTICAL:
if(startY-rawY>20) {
cancel();
}
break;
}
break;
case MotionEvent.ACTION_UP:
velocityTracker.computeCurrentVelocity(1000,maxVelocity);
int dis= (int) velocityTracker.getYVelocity(pointerId);
if(scrollOrientationEnum==ScrollOrientationEnum.NONE){
if(headsUp.getNotification().contentIntent!=null){
try {
headsUp.getNotification().contentIntent.send();
cancel();
} catch (PendingIntent.CanceledException e) {
e.printStackTrace();
}
}
break;
}
int toX;
if(preLeft>0){
toX= (int) (preLeft+Math.abs(dis));
}else{
toX= (int) (preLeft-Math.abs(dis));
}
if (toX <= -validWidth) {
float preAlpha=1-Math.abs(preLeft)/validWidth;
preAlpha=preAlpha>=0?preAlpha:0;
translationX(preLeft,-(validWidth+10),preAlpha,0);
} else if (toX <= validWidth) {
float preAlpha=1-Math.abs(preLeft)/validWidth;
preAlpha=preAlpha>=0?preAlpha:0;
translationX(preLeft,0,preAlpha,1);
}else{
float preAlpha=1-Math.abs(preLeft)/validWidth;
preAlpha=preAlpha>=0?preAlpha:0;
translationX(preLeft, validWidth + 10, preAlpha, 0);
}
preLeft = 0;
scrollOrientationEnum=ScrollOrientationEnum.NONE;
break;
}
return super.onTouchEvent(event);
}
/**
*
* @param event 向VelocityTracker添加MotionEvent
*
* @see android.view.VelocityTracker#obtain()
* @see android.view.VelocityTracker#addMovement(MotionEvent)
*/
private void acquireVelocityTracker( MotionEvent event) {
if(null == velocityTracker) {
velocityTracker = VelocityTracker.obtain();
}
velocityTracker.addMovement(event);
}
private int preLeft;
public void updatePosition(int left) {
float preAlpha=1-Math.abs(preLeft)/validWidth;
float leftAlpha=1-Math.abs(left)/validWidth;
preAlpha = preAlpha>=0 ? preAlpha : 0;
leftAlpha = leftAlpha>=0 ? leftAlpha : 0;
translationX(preLeft,left,preAlpha,leftAlpha);
preLeft = left;
}
public void translationX(float fromX,float toX,float formAlpha, final float toAlpha ){
ObjectAnimator a1=ObjectAnimator.ofFloat(rootView,"alpha",formAlpha,toAlpha);
ObjectAnimator a2 = ObjectAnimator.ofFloat(rootView, "translationX", fromX, toX);
AnimatorSet animatorSet=new AnimatorSet();
animatorSet.playTogether(a1,a2);
animatorSet.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
if(toAlpha==0){
HeadsUpManager.getInstant(getContext()).dismiss();
cutDown=-1;
if(velocityTracker!=null) {
velocityTracker.clear();
try {
velocityTracker.recycle();
} catch (IllegalStateException e) {
}
}
}
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
});
animatorSet.start();
}
public void setNotification(final HeadsUp headsUp) {
this.headsUp = headsUp;
mHandle= new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
HeadsUpManager.getInstant(getContext()).animDismiss(headsUp);
}
};
cutDownTime= new CutDownTime();
if(!headsUp.isSticky()){
cutDownTime.start();
}
cutDown= headsUp.getDuration();
if (headsUp.getCustomView() == null) {
View defaultView = LayoutInflater.from(getContext()).inflate(R.layout.notification, rootView, false);
rootView.addView(defaultView);
ImageView imageView = (ImageView) defaultView.findViewById(R.id.iconIM);
TextView titleTV = (TextView) defaultView.findViewById(R.id.titleTV);
TextView timeTV = (TextView) defaultView.findViewById(R.id.timeTV);
TextView messageTV = (TextView) defaultView.findViewById(R.id.messageTV);
imageView.setImageResource(headsUp.getIcon());
titleTV.setText(headsUp.getTitleStr());
messageTV.setText(headsUp.getMsgStr());
SimpleDateFormat simpleDateFormat=new SimpleDateFormat("HH:mm");
timeTV.setText( simpleDateFormat.format(new Date()));
} else {
setCustomView(headsUp.getCustomView());
}
}
protected void cancel(){
HeadsUpManager.getInstant(getContext()).animDismiss();
cutDown = -1;
cutDownTime.interrupt();
if(velocityTracker!=null) {
try {
velocityTracker.clear();
velocityTracker.recycle();
} catch (IllegalStateException e) {
}
}
}
enum ScrollOrientationEnum {
VERTICAL,HORIZONTAL,NONE
}
}
具體用法:
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("提醒")
//要顯示通知欄通知,這個(gè)一定要設(shè)置
.setSmallIcon(R.drawable.icon)
.setContentText("你有新的消息")
//2.3 一定要設(shè)置這個(gè)參數(shù),負(fù)責(zé)會(huì)報(bào)錯(cuò)
.setContentIntent(pendingIntent)
//.setFullScreenIntent(pendingIntent, false)
HeadsUp headsUp = builder.buildHeadUp();
headsUp.setCustomView(view);
manage.notify(1, headsUp);
}
總結(jié)
以上所述是小編給大家介紹的Android 中Notification彈出實(shí)現(xiàn)代碼,希望對(duì)大家有所幫助,如果大家有任何疑問請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
- Android中通過Notification&NotificationManager實(shí)現(xiàn)消息通知
- Android編程實(shí)現(xiàn)google消息通知功能示例
- Android之開發(fā)消息通知欄
- Android消息通知欄的實(shí)現(xiàn)方法介紹
- Android自定義Notification添加點(diǎn)擊事件
- Android中AlarmManager+Notification實(shí)現(xiàn)定時(shí)通知提醒功能
- Android編程使用Service實(shí)現(xiàn)Notification定時(shí)發(fā)送功能示例
- Android 通知使用權(quán)(NotificationListenerService)的使用
- android使用NotificationListenerService監(jiān)聽通知欄消息
- Android消息通知Notification常用方法(發(fā)送消息和接收消息)
相關(guān)文章
Android編程簡(jiǎn)單實(shí)現(xiàn)ImageView點(diǎn)擊時(shí)背景圖修改的方法
這篇文章主要介紹了Android編程簡(jiǎn)單實(shí)現(xiàn)ImageView點(diǎn)擊時(shí)背景圖修改的方法,涉及Android針對(duì)背景圖相關(guān)屬性設(shè)置的操作技巧,需要的朋友可以參考下2015-12-12
Android 自定義View實(shí)現(xiàn)芝麻分曲線圖效果
這篇文章主要介紹了Android 自定義View實(shí)現(xiàn)芝麻分曲線圖效果的相關(guān)資料,非常不錯(cuò)具有參考借鑒價(jià)值,需要的朋友可以參考下2016-11-11
Android實(shí)現(xiàn)左上角(其他邊角)傾斜的標(biāo)簽(環(huán)繞效果)效果
這篇文章主要介紹了Android實(shí)現(xiàn)左上角(其他邊角)傾斜的標(biāo)簽(環(huán)繞效果)效果,本文通過圖文實(shí)例代碼相結(jié)合的形式給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-10-10
Android中手機(jī)錄屏并轉(zhuǎn)換GIF的兩種方式
本文主要介紹了android中手機(jī)錄屏并轉(zhuǎn)換GIF的兩種方式,具有一定的參考價(jià)值,下面跟著小編一起來看下吧2017-01-01
Android編程實(shí)現(xiàn)監(jiān)控各個(gè)程序流量的方法
這篇文章主要介紹了Android編程實(shí)現(xiàn)監(jiān)控各個(gè)程序流量的方法,涉及Android針對(duì)應(yīng)用包的遍歷,權(quán)限控制及相關(guān)屬性操作技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-12-12
android實(shí)現(xiàn)搜索功能并將搜索結(jié)果保存到SQLite中(實(shí)例代碼)
這篇文章主要介紹了android實(shí)現(xiàn)搜索功能并將搜索結(jié)果保存到SQLite中,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-04-04

