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
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
比之前的合集更丰富详细的细节;没有最新只有更新! 1、建立GPRS连接 4 2、判断网络状态是否可用 4 3、获得惯性滑动的位置 5 4、横竖屏切换对话框消失 6 5、TextProssBar 显示文字 7 6、TextView的效果 9 1、TextView的Html效果 9 2、TextView实现下划线效果: 10 3、Spanned 实现TextView的各种样式 10 7、通过HttpClient从指定server获取数据 13 8、隐藏小键盘 13 9、响应Touch 15 10、Activity间的通信 15 1、Bundle传值 15 2、利用startActivityForResult与onActivityResult方法 16 11、使程序完全退出 18 12、列出所有音乐文件 18 13、使用Intent ACTION 调用系统程序 19 显示网页: 19 显示地图: 19 路径规划: 19 拨打电话: 19 发送 SMS/MMS 20 发送 Email 20 为程序添加一个“分享” 21 打开多种类型的文件: 21 Uninstall 程序 24 14、将Uri转为绝对路径 24 15、Android支持多种语言 25 16、四种动画的设置属性 25 1、尺寸伸缩动画效果 25 2、translate 位置转移动画效果 27 3、rotate 旋转动画效果 27 4、透明度控制动画效果 alpha 28 17、横竖屏状态获取 28 18、获取手指在屏幕的左右滑动 29 19、解除屏幕锁 30 20、ViewFlippe实现循环的动画 31 21、播放gif动画 31 22、飞行模式转换解析 36 23、实现按home键的效果 38 24、httpget与post 38 Handler+Runnable模式 40 Handler+Thread+Message模式 42 Handler+ExecutorService(线程池)+MessageQueue模式 44 Handler+ExecutorService(线程池)+MessageQueue+缓存模式 45 25、Bitmap操作 49 获得输入流 49 将输入流转化为Bitmap流 49 给ImageView对象赋值 49 获取SD卡上的文件存储路径 50 将图片保存到SD卡上 50 26、TextView垂直滚动 51 27、判断某服务是否开启 56 28、判断SD卡是否已挂载 56 29、文件操作类 57 1、获得文件或目录的大小 57 2、递归删除目录或文件 57 30、手动更新所有Widget 58 31、有关ListView 问题 58 32、在手机上打开文件的方法 59 33、使用系统自带的TabHost的问题 59 34、弹出菜单 61 35、Toast重叠显示时延迟解决 62 36、ADT新特性:ImageView的定义 62 37、MotionEvent获取坐标的问题 63 38、添加多个Widget样式 63 39、为Activity添加快捷方式 67 40、点击widget获取ID 68 41、ViewFlipper小动画 69 42、setTextColor的问题 70 43、获取程序信息并kill 70 44、mediaPlayer 与 soundPool 74 45、标题栏添加图标 76 46、 URI 76 案例分析:SD卡插拔事件的匹配 77 47、BroadcastReceiver旧事重提 77 48、从CalendarProvider得到数据的方法: 78 50、屏幕关闭,不睡眠 79 51、Android与 Linux休眠 79 52、防止系统、屏幕休眠(避免服务停止等问题) 83 53、读取office文件 88 1、读取doc文件: 88 2、 读取xls文件: 90 54、设置ListView滚动条属性 92 55、获取Array.xml文件中的值 93 56、获取系统媒体声音文件 93 57、自定义Adapter 94 58、记住listview滚动位置 94 59、更改系统超时休眠的时间 94 60、更改对话框大小 95 61、json数据格式解析 95 62、两种Toast 97 63、控件抖动的实现 98 64、判断媒体文件类型 99 65、编写使用root权限的应用 102 66、获取所有安装了的App的信息 103 67、帧动画 104 68、scrollview 106 1、横向反弹效果 106 2、整个屏幕横向滚动 108 69、内存泄露分析 111 1、内存检测 111 2、内存分析 112 70、避免内存泄露 113 71、屏蔽Home键 118 72、onTouch 和 onClick 事件 118 73、监听某个数据表 119 74、IP地址 120 1、获得IP 120 2、设置IP 121 75、判断Intent是否可用 122 76、软件更换皮肤 122 77、禁止软件盘自动弹出 124 78、EditText设置最大宽度 124 79、搭建流媒体服务器 125 80、获得 LayoutInflater 实例的三种方式 125 81、获得屏幕像素的两种方法 126 82、ShowDialog(int id); 126 83、透明效果的实现 128 84、根据网络或GPS获得经纬度 128 85、TextView 130 90、获取存储卡和手机内部存储空间 130 91、获得当前应用的UID 131 92、图片压缩类 132 93、一次性退出所有Activity 136 95、Java替换字符串,不区分大小写 138 96、Java获得随机数 139 97、MD5加密 141 98、HTTP数据传输 141 从Internet获取数据 141 向Internet发送数据 143 99、Jason解析 146 100、广播 147 101、SQLite清空数据库 147 102、反射机制 148 103、JS 148 104、TextView多行末尾显示省略号 148 105、竖直显示的textView 153

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值