您好,登錄后才能下訂單哦!
這篇文章主要介紹“Android系統全局觸摸事件監聽實例代碼”,在日常操作中,相信很多人在Android系統全局觸摸事件監聽實例代碼問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”Android系統全局觸摸事件監聽實例代碼”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!
Android觸摸全局監聽指的是調用監聽后在任何界面都能獲取到觸摸事件。
要實現這個功能必須要修改源碼添加新的接口,因為系統默認是不暴露這個方法的。
監聽系統全局觸摸事件的類和相關代碼:
frameworks\base\services\core\java\com\android\server\wm\WindowManagerService.java @Override public void registerPointerEventListener(PointerEventListener listener, int displayId) { Slog.i(TAG, "registerPointerEventListener PointerEventListener = " + listener); synchronized (mGlobalLock) { final DisplayContent displayContent = mRoot.getDisplayContent(displayId); if (displayContent != null) { displayContent.registerPointerEventListener(listener); } } } @Override public void unregisterPointerEventListener(PointerEventListener listener, int displayId) { synchronized (mGlobalLock) { final DisplayContent displayContent = mRoot.getDisplayContent(displayId); if (displayContent != null) { displayContent.unregisterPointerEventListener(listener); } } }
第一個參數:是中PointerEventListener接口,
里面有MotionEvent
對象含有點擊事件,比如DOWN、UP、MOVING
等其他信息。
package android.view; public interface WindowManagerPolicyConstants { interface PointerEventListener { void onPointerEvent(MotionEvent motionEvent); } }
第二個參數,屏幕id,正常用0 ,表示主屏幕id。有些設備有投屏或者第二屏才需要關注這個。
下面介紹如何注冊這個服務
1、綁定這個系統服務,這個方法行不通
因為這個服務的aidl接口IWindowManager,并沒有暴露這個方法
registerPointerEventListener方法定義在另一個內部接口 WindowManagerFuncs 中
public interface WindowManagerPolicy extends WindowManagerPolicyConstants { public interface WindowManagerFuncs { /** Register a system listener for touch events */ void registerPointerEventListener(PointerEventListener listener, int displayId); /** Unregister a system listener for touch events */ void unregisterPointerEventListener(PointerEventListener listener, int displayId); } }
2、獲取WindowManagerFuncs對象,該對象獲取的方式在源碼中有多種
參考:
frameworks\base\services\core\java\com\android\server\policy\PhoneWindowManager.java public PhoneWindowManager extends AbsPhoneWindowManager implements WindowManagerPolicy, IHwPhoneWindowManagerInner{ public WindowManagerFuncs getWindowManagerFuncs(){ return mWindowManagerFuncs; } }
WindowManagerFuncs在源碼中是可以直接new的,使用如下:
PhoneWindowManager phoneWindowManager = new PhoneWindowManager(); WindowManagerFuncs windowManagerFuncs = phoneWindowManager.getWindowManagerFuncs(); windowManagerFuncsEx.registerPointerEventListener(listener, Display.DEFAULT_DISPLAY);
3、在華為Emui源碼添加aidl回調
WindowManagerEx有通道直接發送數據到WindowManagerService并可以進行數據監聽
(1)添加aidl接口
vendor\huawei\Emui\frameworks\hwCommInterface\base\core\java\com\huawei\android\app\IHwPointEventCallback.aidl package com.huawei.android.app; import android.view.MotionEvent; oneway interface IHwPointEventCallback { void onPointerEvent(in MotionEvent motionEvent); }
(2)WindowManagerEx的修改
vendor\huawei\Emui\frameworks\hwext\hwext\framework\src\com\huawei\android\app\WindowManagerEx.java private final int TRANSACTION_SET_POINTER_EVENT_LISTENER = android.os.IBinder.FIRST_CALL_TRANSACTION + 2100; //給WindowManagerService傳遞監聽對象 public static void setPointerEventListener(IHwPointEventCallback listener) { Log.i(LOG_TAG, "setPointerEventListener listener = " + listener); IBinder windowManagerBinder = WindowManagerGlobal.getWindowManagerService().asBinder(); if (windowManagerBinder != null) { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); try { data.writeInterfaceToken("android.view.IWindowManager"); //傳遞aidl監聽對象 data.writeStrongBinder(listener != null ? listener.asBinder() : null); //發送 windowManagerBinder.transact(TRANSACTION_SET_POINTER_EVENT_LISTENER, data, reply, 0); } catch (RemoteException e){ Log.e(LOG_TAG, "setPointerEventListener exception is " + e.getMessage()); } finally { data.recycle(); reply.recycle(); } } else { Log.w(LOG_TAG, "setPointerEventListener windowManagerBinder is null"); } }
(3)在WindowManagerService中接收數據并做實際監聽
基于盡量不修改源碼的理念,Emui中有WindowManagerService的子類HwWindowManagerService,在子類中修改代碼即可。
vendor\huawei\Emui\frameworks\base\services\java\huawei\com\android\server\wm\HwWindowManagerService.java HwWindowManagerService extends WindowManagerService private final int TRANSACTION_SET_POINTER_EVENT_LISTENER = android.os.IBinder.FIRST_CALL_TRANSACTION + 2100; private IHwPointEventCallback mIHwPointEventCallback = null; //接收WindowManagerEx傳遞過來的數據 public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException { switch (code) { case TRANSACTION_SET_POINTER_EVENT_LISTENER: data.enforceInterface("android.view.IWindowManager"); IHwPointEventCallback observer = IHwPointEventCallback.Stub.asInterface(data.readStrongBinder()); setPointerEventListener(observer); reply.writeNoException(); return true; } } //在Service中創建唯一的監聽對象 private PointerEventListener mPointerEventListener = new PointerEventListener() { @Override public void onPointerEvent(MotionEvent motionEvent) { if(mIHwPointEventCallback != null) { try { mIHwPointEventCallback.onPointerEvent(motionEvent); } catch (RemoteException e) { Slog.e(TAG, "mIHwPointEventCallback error = " + e.getMessage()); } } } }; //添加設置觸摸監聽方法 private void setPointerEventListener(IHwPointEventCallback listener) { Slog.i(TAG, "setPointerEventListener PointerEventListener = " + listener); int uid = Binder.getCallingUid(); if(uid != Process.SYSTEM_UID){ Slog.e(TAG, "setPointerEventListener uid must be "+ Process.SYSTEM_UID +",but now uid = " + uid); return; } mIHwPointEventCallback = listener; if(listener != null) { //實際調到父類的注冊觸摸事件的方法 registerPointerEventListener(mPointerEventListener, Display.DEFAULT_DISPLAY); } else { //實際調到父類的反注冊觸摸事件的方法 unregisterPointerEventListener(mPointerEventListener, Display.DEFAULT_DISPLAY); } }
方法3可以實現在普通app中監聽到系統的全局觸摸事件,
因為app可以依賴Emui的emui_addons.jar,
調用到里面的部分類,比如WindowManagerEx,就可以監聽全局觸摸事件。
其他系統環境可以根據實際情況參考上面的實現。
到此,關于“Android系統全局觸摸事件監聽實例代碼”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。