Android获取整个屏幕的Touch事件

在车载开发中,有一个常见的需求就是各种手势控制中控与仪表的交互。
我们需要获取全局的Touch事件,然后解析手势,做对应的动作。这里有个最简单的获取全局Touch事件的方法。

framework

1.frameworks\base\services\core\java\com\android\server\wm\ TaskTapPointerEventListener.java
Android自己就用到了全局触摸的一个事件,所有的触摸事件除了会发送给应用进程窗口,同时也会发送到PointerEventDispatcher中来。

public class TaskTapPointerEventListener implements PointerEventListener {

...省略代码

    public TaskTapPointerEventListener(WindowManagerService service,
            DisplayContent displayContent) {
        mService = service;
        mDisplayContent = displayContent;
    }

    @Override
    public void onPointerEvent(MotionEvent motionEvent, int displayId) {
        if (displayId == getDisplayId()) {
            onPointerEvent(motionEvent);
        }
    }

    @Override
    public void onPointerEvent(MotionEvent motionEvent) {
       ...省略代码
    }

    void setTouchExcludeRegion(Region newRegion) {
        synchronized (this) {
           mTouchExcludeRegion.set(newRegion);
        }
    }

    private int getDisplayId() {
        return mDisplayContent.getDisplayId();
    }
}

2.frameworks/base/core/java/android/view/WindowManagerPolicyConstants.java
这个常量交互类里面定义了PointerEventListener

public interface WindowManagerPolicyConstants {
    // TODO: move this to a more appropriate place.
    interface PointerEventListener {
        /**
         * 1. onPointerEvent will be called on the service.UiThread.
         * 2. motionEvent will be recycled after onPointerEvent returns so if it is needed later a
         * copy() must be made and the copy must be recycled.
         **/
        void onPointerEvent(MotionEvent motionEvent);

        /**
         * @see #onPointerEvent(MotionEvent)
         **/
        default void onPointerEvent(MotionEvent motionEvent, int displayId) {
            if (displayId == DEFAULT_DISPLAY) {
                onPointerEvent(motionEvent);
            }
        }
    }
   } 

3.frameworks\base\core\java\android\view\IWindowManager.aidl
需要在这个aidl接口里面将全局的PointerEventListener接口注册暴露出来。

    /**
     * Notify WindowManager that it should not override the info in DisplayManager for the specified
     * display. This can disable letter- or pillar-boxing applied in DisplayManager when the metrics
     * of the logical display reported from WindowManager do not correspond to the metrics of the
     * physical display it is based on.
     *
     * @param displayId The id of the display.
     */
    void dontOverrideDisplayInfo(int displayId);

    /* add PointerEventListener */
    void registerPointerEventListener(int displayId, IPointerEventListener listener);

    void unregisterPointerEventListener(IPointerEventListener listener);
    /* add PointerEventListener*/

4.frameworks\base\core\java\android\view\WindowManagerImpl.java
客户端处理IWindowManager aidl

public final class WindowManagerImpl implements WindowManager {
 ...省略代码
	 @Override
    public void registerPointerEventListener(int displayId, IPointerEventListener listener) {
        try {
            WindowManagerGlobal.getWindowManagerService().registerPointerEventListener(displayId, listener);
        } catch (RemoteException e) {
        }
    }

    @Override
    public void unregisterPointerEventListener(IPointerEventListener listener) {
        try {
            WindowManagerGlobal.getWindowManagerService().unregisterPointerEventListener(listener);
        } catch (RemoteException e) {
        }
    }
 ...省略代码
}

5.frameworks\base\core\java\android\view\IPointerEventListener.aidl
自己创建对app暴露的接口

package android.view;

import android.view.MotionEvent;

/** @hide */
oneway interface IPointerEventListener {
    void onPointerEvent(in MotionEvent motionEvent);
}

6.frameworks\base\services\core\java\com\android\server\wm\WindowManagerService.java
在服务端我们需要自己注册一个PointerEventListener 把数据通过aidl传到 WindowManagerImpl

public class WindowManagerService extends IWindowManager.Stub
        implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs {
        //添加远程列表
private RemoteCallbackList<IPointerEventListener> mPointerEventListeners = new RemoteCallbackList<>();
	//在构造的方法里面注册
	private WindowManagerService(Context context, InputManagerService inputManager,
            boolean haveInputMethods, boolean showBootMsgs, boolean onlyCore,
            WindowManagerPolicy policy) {
             ...省略代码
        if (mPointerEventDispatcher != null) {
        //因为我们外部的app用这个全局的触摸事件,所以这里注册我们自己的listener
            mPointerEventDispatcher.registerInputEventListener(mListener);
        }
              ...省略代码
     }
	private PointerEventListener mListener = new PointerEventListener() {
        @Override
        public void onPointerEvent(MotionEvent motionEvent) {
            Slog.d(TAG, "onPointerEvent motionEvent: " + motionEvent);
        }

        @Override
        public void onPointerEvent(MotionEvent motionEvent, int displayId) {
            if (DEBUG_INPUT) {
                Slog.d(TAG, "onPointerEvent displayId: " + displayId + " motionEvent: " + motionEvent);
            }
            int i = mPointerEventListeners.beginBroadcast();
            while (i > 0) {
                i--;
                int cookie = (int) mPointerEventListeners.getBroadcastCookie(i);
                if (cookie == displayId) {
                    try {
                        mPointerEventListeners.getBroadcastItem(i).onPointerEvent(motionEvent);
                    } catch (RemoteException e) {
                        e.printStackTrace();
                    }
                }
            }
            mPointerEventListeners.finishBroadcast();
        }
    };

    @Override
    public void registerPointerEventListener(int displayId, IPointerEventListener listener) {
        Slog.d(TAG, "registerPointerEventListener displayId: " + displayId + " listener: " + listener);
        mPointerEventListeners.register(listener, displayId);
    }

    @Override
    public void unregisterPointerEventListener(IPointerEventListener listener) {
        Slog.d(TAG, "unregisterPointerEventListener listener: " + listener);
        mPointerEventListeners.unregister(listener);
    }
}

app

public class TouchManager extends IPointerEventListener.Stub {
WindowManager mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);

 @Override
    public void onPointerEvent(MotionEvent motionEvent) throws RemoteException {
        int action = motionEvent.getAction();
    }

    public void registerListener() {
        try {
            if (mWindowManager != null) {
                Log.e(TAG, "registerPointerEventListener");
                mWindowManager.registerPointerEventListener(Display.DEFAULT_DISPLAY, this);
            }
        } catch (Exception e) {
            Log.e(TAG, "not connected!", e);
        }
    }

    public void unRegisterListener() {
        try {
            if (mWindowManager != null) {
                Log.e(TAG, "unRegisterListener");
                mWindowManager.unregisterPointerEventListener(this);
            }
        } catch (Exception e) {
            Log.e(TAG, "not connected!", e);
        }
    }

}

  • 1
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值