中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Android系統全局觸摸事件監聽實例代碼

發布時間:2021-09-08 20:28:30 來源:億速云 閱讀:893 作者:chen 欄目:開發技術

這篇文章主要介紹“Android系統全局觸摸事件監聽實例代碼”,在日常操作中,相信很多人在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系統全局觸摸事件監聽實例代碼”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

新建县| 天等县| 鹤壁市| 恩平市| 遂昌县| 双江| 封丘县| 葵青区| 新乡市| 吉木萨尔县| 大渡口区| 托克托县| 吉隆县| 白水县| 旬阳县| 乌兰察布市| 金乡县| 共和县| 德令哈市| 右玉县| 本溪| 轮台县| 嘉义县| 正宁县| 乐安县| 漠河县| 大埔区| 中山市| 新竹市| 开化县| 新晃| 聊城市| 合作市| 威海市| 栾城县| 九江县| 吴堡县| 宁河县| 安义县| 攀枝花市| 河间市|