Android实现HID鼠标的指针自定义

写在前面:本文所提供方法仅供研究学习,不可用于商业用途,转载请注明出处。

好,正文开始...


首先介绍下蓝牙HID设备,指市面上出售的可用于连接PC、Android的可输入设备,这类设备遵循了hid通信协议,可以用于输入操作(如按键、鼠标移动等),作为一个交互设备存在。

由于hid设备遵循的是其封装好的通信协议,数据流经过系统封装好的hid通道来进行传输的,因此我们无法直接获取到其原始输入数据。但在这次的研究过程中我发现了一种能够直接获取到其输入数据的方法,由于与本文关系不大,这里不再赘述。想了解hid设备原始数据获取的同学,可以移步我的另一篇博客 。

目的:蓝牙hid鼠标在连接到android手机上后会显示一个系统自带的鼠标,我们的需求是将该光标进行自定义(调整大小,形状,图片资源)。

这里有两种思路可以选择:

1.通过替换系统的鼠标图片资源来实现

2.完全隐藏系统鼠标,由自己的服务来绘制,这时候的自定义操作就相当简单了

工程最后采用的是第二种方法,不采用第一种思路的原因有很多,android4.0.3源码之鼠标光标绘制简略版 这篇博客里详细描述了android绘制鼠标的过程,简而言之,系统的鼠标图片是在资源文件打包了,并且在框架层framework中写死,android sdk没有提供任何开放的API来修改系统鼠标(谁会没事做这个呢?)。当然想替换也不是没办法,可以编译源码,简单点的做法是解包framework-res.apk后替换其中的cursor.png图片后再打包,重启手机生效。这些方法都显得非常繁琐,而且修改一次就得编译一次或是重启一次,不能进行动态的实时修改,所以第一种思路pass了。

说了这么多,下面是具体的解决方案:

我们需要自定义鼠标,但又不影响其原有的操作,比如说我们移动鼠标进行点击,这个不能没有把,也就是说除了替换鼠标之外,其他功能都必须进行保留。比如点击,拖动,因此自己画的鼠标位置需要跟原生鼠标位置保持一致。

第一步: 用透明图片替换framework-res.apk中的鼠标图片资源,这里不同手机的位置可能不一样,但名称都类似于cursor_arrow.png,全部替换后打包,重启手机。此时连接hid设备后屏幕不再显示鼠标(因为是透明的嘛)。

第二步:现在我们隐藏了系统自带的鼠标,我们需要自己绘制鼠标,并且位置和原来的一致(实现点击、拖动),绘制鼠标需要我们知道这个原生鼠标(现在已透明了)的位置,怎么获取呢?各种翻阅sdk文档后,终于让我找到了这样一个方法:

/**
     * Implement this method to handle hover events.
     * 

* This method is called whenever a pointer is hovering into, over, or out of the * bounds of a view and the view is not currently being touched. * Hover events are represented as pointer events with action * {@link MotionEvent#ACTION_HOVER_ENTER}, {@link MotionEvent#ACTION_HOVER_MOVE}, * or {@link MotionEvent#ACTION_HOVER_EXIT}. *

*
    *
  • The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_ENTER} * when the pointer enters the bounds of the view.
  • *
  • The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_MOVE} * when the pointer has already entered the bounds of the view and has moved.
  • *
  • The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_EXIT} * when the pointer has exited the bounds of the view or when the pointer is * about to go down due to a button click, tap, or similar user action that * causes the view to be touched.
  • *
*

* The view should implement this method to return true to indicate that it is * handling the hover event, such as by changing its drawable state. *

* The default implementation calls {@link #setHovered} to update the hovered state * of the view when a hover enter or hover exit event is received, if the view * is enabled and is clickable. The default implementation also sends hover * accessibility events. *

* * @param event The motion event that describes the hover. * @return True if the view handled the hover event. * * @see #isHovered * @see #setHovered * @see #onHoverChanged */ public boolean onHoverEvent(MotionEvent event);

onHoverEvent可以检测鼠标或者轨迹球在view上移动时,相对于view的坐标位置,问题是只有鼠标在这个view中间移动的时候,才能捕捉得到。

我们需要的鼠标在整个屏幕上的位置,于是,用类似与



未完待续

你可能感兴趣的:(HID,Android)