Android|Android getevent拦截输入事件

上篇文章《Android AccessibilityService拦截事件及VR眼镜返回按键捕捉》我们介绍了如何用AccessibilityService来拦截事件。
本篇我们来介绍另一种拦截按键的方式,就是在shell的状态下,使用getevent命令对输入事件进行分析。必须要说明的是getevent命令使用场景有:
1.在PC端shell环境下,不必root
2.在APP端使用必须要root权限

package com.jason.btnmonitor; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.Button; public class MainActivity extends AppCompatActivity {@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initMonitor(); Button get = (Button) findViewById(R.id.get); Button start = (Button) findViewById(R.id.start); Button stop = (Button) findViewById(R.id.stop); get.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { getDevices(); } }); start.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { startMonitor(); } }); stop.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { stopMonitor(); } }); }private void getDevices(){ BtnMonitorController.getInstance().getVRDevice(); }private void initMonitor(){ BtnMonitorController.getInstance().init(); }public void startMonitor(){BtnMonitorController.getInstance().start(); }public void stopMonitor(){BtnMonitorController.getInstance().stop(); }private void releaseMonitor(){ BtnMonitorController.getInstance().release(); }@Override protected void onDestroy() { super.onDestroy(); releaseMonitor(); } }


MainActivity的实现。 【Android|Android getevent拦截输入事件】


layout的实现。
package com.jason.btnmonitor; import android.os.Handler; import android.os.Message; import android.util.Log; import com.stericson.RootTools.RootTools; import com.stericson.RootTools.exceptions.RootDeniedException; import com.stericson.RootTools.execution.Command; import com.stericson.RootTools.execution.Shell; import java.io.IOException; import java.util.concurrent.TimeoutException; public class BtnMonitorController {private static final String COMMAND_GET_DEVICE_VR = "getevent"; private static final String COMMAND_GET_VR_EVENT = "getevent -l -t "; public static final int MSG_EVENT_INPUT = 9000; private String deviceName="/dev/input/event19"; //demo监听的是event19,这里可以改为你所要监听的eventprivate static boolean isMonitorStart = false; private static boolean hasVR = false; private Shell shell; private Command command; private Handler handler; private static BtnMonitorController instance ; private BtnMonitorController(){}public static BtnMonitorController getInstance(){ if (instance == null) { synchronized (BtnMonitorController.class){ if (instance == null) { instance = new BtnMonitorController() ; } } } return instance ; }public void init(){ try { shell = RootTools.getShell(true); //getevent命令必须要root } catch (IOException e) { e.printStackTrace(); LogUtil.e("shell init error"); } catch (TimeoutException e) { e.printStackTrace(); LogUtil.e("shell init error"); } catch (RootDeniedException e) { e.printStackTrace(); LogUtil.e("shell init error"); }handler = new Handler() {public void handleMessage(Message msg) { switch (msg.what) { case MSG_EVENT_INPUT:LogUtil.i(""+msg.obj); break; } super.handleMessage(msg); } }; } //getVRDevice会输出你的inputdevice的列表,选中你想要监听的设备,替换deviceName public void getVRDevice(){ LogUtil.i("BtnMonitor getVRDevice" ); if(isMonitorStart){ LogUtil.e("BtnMonitor is started already!"); return; } startCMD(COMMAND_GET_DEVICE_VR); }public void start(){LogUtil.i("BtnMonitor start" ); if(isMonitorStart){ LogUtil.e("BtnMonitor is started already!"); return; }startCMD(COMMAND_GET_VR_EVENT+deviceName); }public void stop(){ LogUtil.i("BtnMonitor stop" ); if(command.isFinished()){ LogUtil.e("BtnMonitor is stopped already!"); return; }command.terminate("stop"); }public void release(){ LogUtil.i("BtnMonitor release" ); if(handler != null && handler.hasMessages(MSG_EVENT_INPUT)){ handler.removeMessages(MSG_EVENT_INPUT); handler = null; }if(isMonitorStart){ command.terminate("exit"); isMonitorStart = false; }try { if(shell != null) shell.close(); } catch (IOException e) { e.printStackTrace(); LogUtil.e("shell close IOException"); }}private void startCMD(String cmd){isMonitorStart = true; command = new Command(0, 0, cmd) { @Override public void output(int id, String line) { LogUtil.e("MainActivity.java:output, id:" + id + ", output:" + line); Message m = new Message(); m.what = MSG_EVENT_INPUT; m.obj = line + "\n"; handler.sendMessage(m); }@Override public void commandCompleted(int arg0, int arg1) { // TODO Auto-generated method stub LogUtil.e("MainActivity.java:commandCompleted, arg0:" + arg0 + ", arg1:" + arg1); Message m = new Message(); m.what = MSG_EVENT_INPUT; m.obj = "commandCompleted\n" + "================================\n"; handler.sendMessage(m); isMonitorStart = false; }@Override public void commandOutput(int arg0, String arg1) { // TODO Auto-generated method stub LogUtil.e( "MainActivity.java:commandOutput, arg0:" + arg0 + ", arg1:" + arg1); Message m = new Message(); m.what = MSG_EVENT_INPUT; m.obj = "commandOutput, arg0:" + arg0 + ", arg1:" + arg1 + "\n"; handler.sendMessage(m); }@Override public void commandTerminated(int arg0, String arg1) { // TODO Auto-generated method stub LogUtil.e("MainActivity.java:commandTerminated, arg0:" + arg0 + ", arg1:" + arg1); Message m = new Message(); m.what = MSG_EVENT_INPUT; m.obj = "commandTerminated, reason:" + arg1 + "\n" + "================================\n"; handler.sendMessage(m); isMonitorStart = false; } }; try { shell.add(command); } catch (IOException e) { e.printStackTrace(); } }}


BtnMonitorController的实现,使用的是开源项目的RootTools。github工程地址 https://github.com/graygray/getevent.git



Android|Android getevent拦截输入事件
文章图片





$ getevent /dev/input/event19 0004 0004 00090002 0001 0111 00000001 0000 0000 00000000 0004 0004 00090002 0001 0111 00000000 0000 0000 00000000

监听到的VR设备(默认类型为鼠标)单击返回键的内容


$ getevent -l -t /dev/input/event19 [17437.061273] EV_MSCMSC_SCAN00090002 [17437.061273] EV_KEYBTN_RIGHTDOWN [17437.061273] EV_SYNSYN_REPORT00000000 [17437.156346] EV_MSCMSC_SCAN00090002 [17437.156346] EV_KEYBTN_RIGHTUP [17437.156346] EV_SYNSYN_REPORT00000000 [17444.748923] EV_MSCMSC_SCAN00090002 [17444.748923] EV_KEYBTN_RIGHTDOWN [17444.748923] EV_SYNSYN_REPORT00000000 [17446.244327] EV_MSCMSC_SCAN00090002 [17446.244327] EV_KEYBTN_RIGHTUP [17446.244327] EV_SYNSYN_REPORT00000000

监听到的VR设备(默认类型为鼠标)返回键长按的内容,-t加上了时间戳用于判断是否是长按

针对收到的message内容可以判断BACK键的单击和长按。


    推荐阅读