新换的手机,屏幕有点大,操作起来有点费劲,找了一些虚拟按键类的软件,都不是很简洁,最后想写个虚拟返回按钮。
Instrumentation inst=new Instrumentation(); inst.sendKeyDownUpSync(KeyCode);
这段代码在非UI线程调用可以达到返回键的效果,但是不能跨进程(怒!不能跨进程要你何用)。严格来讲不是不能,而是比较麻烦。
http://www.cnblogs.com/TerryBlog/archive/2012/06/07/2539866.html 这篇帖子看似给出方案。用ndk封装的方式忽略。第二种修改为系统进程的方式需要源码环,拿到公钥等,除了自己编译的rom,其他的rom不可能拿到这些。
还有一种方式是:
private void sendKeyEvent(int keyCode) { int eventCode = keyCode; long now = SystemClock.uptimeMillis(); try { KeyEvent down = new KeyEvent(now, now, KeyEvent.ACTION_DOWN, eventCode, 0); KeyEvent up = new KeyEvent(now, now, KeyEvent.ACTION_UP, eventCode, 0); (IWindowManager.Stub .asInterface(ServiceManager.getService("window"))) .injectInputEventNoWait(down); (IWindowManager.Stub .asInterface(ServiceManager.getService("window"))) .injectInputEventNoWait(up); } catch (RemoteException e) { Log.i(TAG, "DeadOjbectException"); } }
这种方式在1.6版本以后就被放弃了删掉了,新版系统源码中根本就没有这个类
最终的解决办法:
上述帖子三楼给出了模拟系统协议的方式。这种方式可以跨进程,但是需要root
大部分虚拟按键类软件都是这么做的。
这个开源项目就是一个很好的例子:国人开发的
https://code.google.com/p/assistivetouch/
提取其中关键类和代码 如下:
RootContext.java
package com.leon.assistivetouch.main.util; import java.io.DataOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.OutputStreamWriter; import android.content.Context; /** * 类名 RootContext.java * 说明 获取root权限 * 创建日期 2012-8-21 * 作者 LiWenLong * Email lendylongli@gmail.com * 更新时间 $Date$ * 最后更新者 $Author$ */ public class RootContext { private static RootContext instance = null; private static Object mLock = new Object(); String mShell; OutputStream o; Process p; private RootContext(String cmd) throws Exception { this.mShell = cmd; init(); } public static RootContext getInstance() { if (instance != null) { return instance; } synchronized (mLock) { try { instance = new RootContext("su"); } catch (Exception e) { while (true) try { instance = new RootContext("/system/xbin/su"); } catch (Exception e2) { try { instance = new RootContext("/system/bin/su"); } catch (Exception e3) { e3.printStackTrace(); } } } return instance; } } private void init() throws Exception { if ((this.p != null) && (this.o != null)) { this.o.flush(); this.o.close(); this.p.destroy(); } this.p = Runtime.getRuntime().exec(this.mShell); this.o = this.p.getOutputStream(); system("LD_LIBRARY_PATH=/vendor/lib:/system/lib "); } private void system(String cmd) { try { this.o.write((cmd + "\n").getBytes("ASCII")); return; } catch (Exception e) { while (true) try { init(); } catch (Exception e1) { e1.printStackTrace(); } } } public void runCommand(String cmd) { system(cmd); } /** * 判断是否已经root了 * */ public static boolean hasRootAccess(Context ctx) { final StringBuilder res = new StringBuilder(); try { if (runCommandAsRoot(ctx, "exit 0", res) == 0) return true; } catch (Exception e) { } return false; } /** * 以root的权限运行命令 * */ public static int runCommandAsRoot(Context ctx, String script, StringBuilder res) { final File file = new File(ctx.getCacheDir(), "secopt.sh"); final ScriptRunner runner = new ScriptRunner(file, script, res); runner.start(); try { runner.join(40000); if (runner.isAlive()) { runner.interrupt(); runner.join(150); runner.destroy(); runner.join(50); } } catch (InterruptedException ex) { } return runner.exitcode; } private static final class ScriptRunner extends Thread { private final File file; private final String script; private final StringBuilder res; public int exitcode = -1; private Process exec; public ScriptRunner(File file, String script, StringBuilder res) { this.file = file; this.script = script; this.res = res; } @Override public void run() { try { file.createNewFile(); final String abspath = file.getAbsolutePath(); Runtime.getRuntime().exec("chmod 777 " + abspath).waitFor(); final OutputStreamWriter out = new OutputStreamWriter( new FileOutputStream(file)); if (new File("/system/bin/sh").exists()) { out.write("#!/system/bin/sh\n"); } out.write(script); if (!script.endsWith("\n")) out.write("\n"); out.write("exit\n"); out.flush(); out.close(); exec = Runtime.getRuntime().exec("su"); DataOutputStream os = new DataOutputStream(exec.getOutputStream()); os.writeBytes(abspath); os.flush(); os.close(); InputStreamReader r = new InputStreamReader( exec.getInputStream()); final char buf[] = new char[1024]; int read = 0; while ((read = r.read(buf)) != -1) { if (res != null) res.append(buf, 0, read); } r = new InputStreamReader(exec.getErrorStream()); read = 0; while ((read = r.read(buf)) != -1) { if (res != null) res.append(buf, 0, read); } if (exec != null) this.exitcode = exec.waitFor(); } catch (InterruptedException ex) { if (res != null) res.append("\nOperation timed-out"); } catch (Exception ex) { if (res != null) res.append("\n" + ex); } finally { destroy(); } } public synchronized void destroy() { if (exec != null) exec.destroy(); exec = null; } } }
模拟按键指令:
RootContext.getInstance().runCommand("input keyevent " + KeyEvent.KEYCODE_BACK);
ps:缺点,反应慢。想想这也是市面上找不到像样的虚拟按键类软件的原因吧,体验太差。
最后的最后,放弃了。凑合着用吧。
相关推荐
主要介绍了Android 跨进程模拟按键(KeyEvent )实例详解的相关资料,类似手机遥控器的需求就可以这么做,需要的朋友可以参考下
9.0 10.0 在framework层添加KeyEvent按键事件的流程
该文档包含了Android中常用的210个按键及对应的值数据。
android keyevent事件分析
Robot键盘常量java.awt.event.KeyEvent。KeyEvent全部键盘按键映射整理KeyEvent枚举类
在android 平台上,通过三种方式实现模拟按键控制的功能
该组件用于React-Native中获取Android原生层面的键盘响应事件,目前开发者本人的主要使用场景是Android-TV端获取遥控器的按键事件。
安卓 adb shell input keyevent 按键大全.txt
模拟键模拟 Android KeyEvent
按键事件和返回键有关的常量和方法有。 KeyEvent.KEYCODE_BACK: 表示key类型为返回键 KeyEvent.ACTION_DOWN:表示事件为按下key,如果一直按住不放,则会不停产生此事件。 KeyEvent.ACTION_UP:表示事件为为...
前言 Android模拟用户点击。在自动化测试中可使用的工具。 可以利用adb命令,也可以使用Android SDK中的monkeyrunner工具。 win7-64 ...keyevent指的是android对应的keycode,比如home键的keycode=3
捕获外部键盘按键或远程控制按钮事件 。 安装 通过npm 运行npm install react-native-keyevent --save 通过纱线 运行yarn add react-native-keyevent 连结中 Android: react-native link react-native-keyevent ...
该库模拟键盘上的按键。 它可以在Linux,Windows和Mac上运行。 重要事项: 键会在目标计算机的不同键盘布局中更改。 我已经在系统上测试了此代码,但没有发现任何错误。 如果有错误,请创建一个问题。 范例: ...
在一个activity 重载父类 的下面这三个方法来处理按键事件 public boolean onKeyDown(int keyCode, KeyEvent event): public boolean onKeyUp(int keyCode, KeyEvent event): public boolean onKeyLongPress...
而今天我们准备学习的是如何通过实现KeyEvent.Callback这个接口从而能重新定义Android设备上的功能按键,为我们开发的应用服务。功能按键的常量定义和方法KeyEvent类有多个定义好的key常量,表示一个标准的Andro
遥控器按键捕获js封装,适用于做联通iptv和广电DVB平台遥控器按键识别,引入该JS识别遥控器按键
介绍了androind开发中对于键盘监听类KeyEvent的成员变量定义以及API描述,并给出示例代码。
代码如下:public boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK) { Intent intent = new Intent(Intent.ACTION_MAIN); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_...
JAVA.SWT/JFace: 按键与其对应的常量表、KeyEvent事件比较、VerifyEvent事件比较