在状态栏上显示会闪烁的图标(类似qq消息提示)

PS:看了9年的小说,自己开始动手写了一本,请各位猿们动动手指,点击下,有起点账号的可以收藏下!!《武意长存》


前两周公司接了个运行在车机上的行车记录仪小项目,在做完提交给对方公司测试后,他们提出了当程序在后台录像时,需要在状态栏上显示个闪烁的图标给用户进行提示。

 

好吧,虽然对方给的需求文档上没这个功能,但既然提了那就做吧。

 

要想完成这个功能,我首先想到的就是利用Notification,我们只需要循环的发送图标不同的Notification就行实现,是不是很简单。当然最后我才发现这个方法在手机实现闪烁图标提示没问题,但在车机上却不管用,这个后面再讲。还是先来先讲讲使用Notification如何实现

 

界面很简单就两个按钮,一个用来开启闪烁提示,一个用来关闭。主要实现代码放置服务中,界面如下

在状态栏上显示会闪烁的图标(类似qq消息提示)_第1张图片

按钮点击执行代码:

 

@Override
	public void onClick(View v) {
		Intent service = new Intent(this, MyService.class);
		switch (v.getId()) {
			case R.id.btn_start:
				startService(service);
				break;

			case R.id.btn_stop:
				stopService(service);
				break;
		}
	}

MyService.java
public class MyService extends Service {
	private static final int MSG_ADD_ICON = 400;
	private static final int NOTIFICATION_ID_ICON = 666;
	private NotificationManager nm;
	private Notification notification;
	private Handler mHandler = new Handler() {
		public void handleMessage(android.os.Message msg) {
			switch (msg.what) {
				case MSG_ADD_ICON:
					boolean flag = (Boolean) msg.obj;
					addIconToStatusbar(flag);
					break;
			}
		};
	};

	@Override
	public IBinder onBind(Intent arg0) {
		return null;
	}

	@Override
	public void onCreate() {
		super.onCreate();
		nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
		addIconToStatusbar(true);
	}

	@Override
	public void onDestroy() {
		mHandler.removeMessages(MSG_ADD_ICON);
		nm.cancel(NOTIFICATION_ID_ICON);
		super.onDestroy();
	}

	@SuppressLint("NewApi")
	private void addIconToStatusbar(boolean isShow) {
		if (notification == null) {
			notification = new Notification();
			notification.icon = R.drawable.notification;
			notification.iconLevel = Integer.MAX_VALUE;

			// 将此通知放到通知栏的"Ongoing"即"正在运行"组中
			notification.flags |= Notification.FLAG_ONGOING_EVENT;
			notification.flags |= Notification.FLAG_INSISTENT;
			notification.flags |= Notification.FLAG_HIGH_PRIORITY;
			// 表明在点击了通知栏中的"清除通知"后,此通知不清除,
			// 经常与FLAG_ONGOING_EVENT一起使用
			notification.flags |= Notification.FLAG_NO_CLEAR;

			Intent intent = new Intent(this, MainActivity.class);
			intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
			PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);
			notification.contentIntent = pendingIntent;
			notification.setLatestEventInfo(this, "DudooDVR", "正在录像", pendingIntent);
		}

		if (isShow) {
			notification.icon = R.drawable.notification;
		} else {
			notification.icon = R.drawable.notification2;
		}

		nm.notify(NOTIFICATION_ID_ICON, notification);
		Message msg = Message.obtain();
		msg.what = MSG_ADD_ICON;
		msg.obj = !isShow;
		mHandler.sendMessageDelayed(msg, 800);
	}
}

代码其实很简单,就是利用handler,循环发送延迟消息,每次只需要根据isShow标记替换图标即可,这里我准备的是一张红色圆点小图标和一张一样大小的透明图标。

效果如下:

在状态栏上显示会闪烁的图标(类似qq消息提示)_第2张图片

如果只是在手机上使用,这样就完成了,但悲催的是在车机上一运行,根本就没效果。

 

原来车机上Notification并不会显示在状态栏上,只有当你下拉状态栏,然后点击通知按钮才能进入查看通知。当然这有可能只是我们要运行的这款车机是这种情况,没办法,都是定制过的系统。(由于写这篇文章是在宿舍,没办法截图车机上的效果,大家自己想象,哈哈...)

 

好吧,本以为轻松搞定,没想到代码白敲了。郁闷归郁闷,功能还是要实现的,那该怎么来实现了呢,我能想到的就是利用WindowManager往屏幕上添加一个全局的view,当然有可能还有其他更好的实现方法。


不过这里得做个提醒,这个方法用在手机不好,会和其他通知重叠,只能用在我上面提到的状态不显示Notification的情况下。好吧,废话不好多说,上代码吧

public class RedPoint {
	private static final int FLASH_DELAY_TIME = 1000;
	private static final int MSG_FLASH = 1;
	public static final int REDPOINT_HEIGHT = 15;
	public static final int REDPOINT_POSITION_X = 15;
	public static final int REDPOINT_POSITION_Y = 7;
	public static final int REDPOINT_WIDTH = 15;
	private static boolean hasRedpoint = false;
	private static RedPoint mRedPoint;
	private static WindowManager redPointWm;
	boolean isShouldFlash;
	private Context mContext;
	private WindowManager.LayoutParams redPointParams;
	private View redpointFramelayout;
	private Handler mHandler = new Handler() {
		public void dispatchMessage(Message msg) {
			super.dispatchMessage(msg);
			switch (msg.what) {
				case MSG_FLASH: {
					if (hasRedpoint) {
						redpointFramelayout.setVisibility(isShouldFlash ? View.VISIBLE : View.INVISIBLE);
						isShouldFlash = (!isShouldFlash);
						mHandler.sendEmptyMessageDelayed(MSG_FLASH, FLASH_DELAY_TIME);
						break;
					}
				}
			}
		}
	};

	public RedPoint(Context paramContext) {
		this.mContext = paramContext;
		init();
	}

	public static RedPoint getInstance(Context context) {
		synchronized (RedPoint.class) {
			if (mRedPoint == null) {
				mRedPoint = new RedPoint(context);
			}
		}
		return mRedPoint;
	}

	private void init() {
		redPointWm = (WindowManager) this.mContext.getSystemService("window");
		initRedPointWm();
	}

	private void initRedPointWm() {
		this.redPointParams = new WindowManager.LayoutParams();
		// 期望的位图格式。默认为不透明。参考android.graphics.PixelFormat。
		// 1 表示 RGBA_8888
		this.redPointParams.format = 1;
		this.redPointParams.width = 30;
		this.redPointParams.height = 30;
		this.redPointParams.x = 15;
		this.redPointParams.y = 7;
		// Gravity.AXIS_PULL_BEFORE | Gravity.AXIS_SPECIFIED | Gravity.TOP 这个值等于51
		this.redPointParams.gravity = Gravity.AXIS_PULL_BEFORE | Gravity.AXIS_SPECIFIED | Gravity.TOP;
		this.redPointParams.type = LayoutParams.TYPE_SYSTEM_OVERLAY; // 设置窗口的级别
		// 312 相当于
		// LayoutParams.FLAG_LAYOUT_IN_SCREEN | LayoutParams.FLAG_NOT_FOCUSABLE 
		// | LayoutParams.FLAG_NOT_TOUCHABLE | LayoutParams.FLAG_NOT_TOUCH_MODAL;
		this.redPointParams.flags = 312;
		this.redpointFramelayout = View.inflate(this.mContext, R.layout.redpoint, null);
	}

	private void startFlash(boolean isFlash) {
		if (isFlash) {
			isShouldFlash = true;
			mHandler.sendEmptyMessage(MSG_FLASH);
			return;
		}

		mHandler.removeMessages(MSG_FLASH);
	}

	public void addRedPointWm() {
		if (!hasRedpoint) {
			try {
				redPointWm.addView(redpointFramelayout, redPointParams);
				hasRedpoint = true;
				startFlash(true);
				return;
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	public void removeRedPointWm() {
		if (hasRedpoint) {
			startFlash(false);
			try {
				redPointWm.removeView(redpointFramelayout);
			} catch (Exception e) {
				e.printStackTrace();
			}
			hasRedpoint = false;
		}
		mHandler.removeCallbacksAndMessages(MSG_FLASH);
	}
}

RedPoint 类用于闪烁图标的管理,其实还是利用handler发送延迟消息,循环的显示和隐藏添加到屏幕上的view

 

我们只需要在服务开启的时候调用addRedPointWm方法,把view添加到屏幕中,然后在关闭服务时调用removeRedPointWm方法就可以了。至于添加时设置的一些参数注释也写得挺清楚了,不清楚的请自行百度或者谷歌

 

对了,由于我们设置成的是系统级别的window,所以别忘了添加上权限



由于在宿舍没车机,就用大概看下手机实现后的效果吧

在状态栏上显示会闪烁的图标(类似qq消息提示)_第3张图片


demo下载:FlickerIconDemo


你可能感兴趣的:(Android)