1. 程式人生 > >Android實現HID滑鼠的指標自定義

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.
     * <p>
     * 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}.
     * </p>
     * <ul>
     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_ENTER}
     * when the pointer enters the bounds of the view.</li>
     * <li>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.</li>
     * <li>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.</li>
     * </ul>
     * <p>
     * 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.
     * </p><p>
     * 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.
     * </p>
     *
     * @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中間移動的時候,才能捕捉得到。

我們需要的滑鼠在整個螢幕上的位置,於是,用類似與


未完待續