新换的手机,屏幕有点大,操作起来有点费劲,找了一些虚拟按键类的软件,都不是很简洁,最后想写个虚拟返回按钮。
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)。 首先,我们来看一个基本的发送按键事件的代码片段: ```java public static void simulateKeystroke(final int keyCode) { new Thread(new Runnable...
在Android开发中,有时我们需要在程序中模拟按键事件,例如在自动化测试、游戏控制或特殊功能实现时。本文将深入探讨如何在Android代码中模拟按键事件,以按数字键1为例,并扩展到如何响应电源键事件使系统进入待机...
在Android平台上,有...总的来说,Android模拟按键是一个技术性较强的话题,涉及到事件处理、权限控制以及可能的无障碍服务实现。开发者需要理解这些概念,并在合法和安全的前提下,合理地利用它们来增强应用的功能。
总之,Android平台提供了多种方式来模拟按键控制,包括使用`KeyEvent`处理按键事件,通过`MotionEvent`模拟触摸操作,以及利用`Instrumentation`和`UiAutomation`进行自动化测试。理解和熟练掌握这些方法对于Android...
在实际应用中,如果需要在代码中触发返回操作,通常会调用`finish()`方法来关闭当前Activity,而不是模拟按键事件。 关于权限`<uses-permission android:name="android.permission.INJECT_EVENTS" />`,这是注入...
在Android Shell中模拟事件是调试和测试应用程序的一种常见方法,特别是对于那些需要手动触发特定用户输入行为的场景。本文将详细介绍如何使用Android Shell来模拟各种输入事件,包括长按、单击和滑动。 1. **基本...
在Android系统中,"本地注入事件"是一种技术,允许应用程序模拟用户输入,如触摸屏点击、按键等。这种技术在进行自动化测试、调试或者特殊应用需求时非常有用。Android是基于Linux内核构建的,因此它继承了Linux的...
这些框架允许编写测试脚本来模拟按键事件,提高测试效率和覆盖率。 总的来说,"android测试键值apk"是一个实用的工具,它简化了开发者对Android应用按键事件测试的过程,确保应用在各种输入设备上都能提供一致且...
在Android中,可以使用`KeyEvent`类来创建和发送模拟的媒体键事件。以下是一个简单的例子,模拟按下播放/暂停键: ```java Activity activity = ...; // 获取当前活动 activity.runOnUiThread(new Runnable() { @...
在开发过程中,你可能需要模拟外部按键事件来测试你的应用程序。这时,可以使用如`adb`命令行工具,发送按键事件到设备或模拟器。例如,发送按键码为33(`KeyEvent.KEYCODE_X`)的按下和释放事件: ```bash adb ...
ADB Shell Input Keyevent命令用于发送虚拟按键事件到Android设备上,这可以模拟用户的键盘输入行为。下面将详细介绍各种类型的按键代码及其功能: #### 基本功能键 - **KEYCODE_CALL** (5):模拟拨打电话。 - **...
- 模拟按键可能需要`<uses-permission android:name="android.permission.INJECT_EVENTS" />`权限,但这个权限通常只对系统应用开放,普通应用可能无法使用。 4. **注意事项**: - 不恰当的屏幕控制和按键模拟...
在Java中,我们可以通过发送`KeyEvent`对象到系统的输入管道来模拟按键行为。`KeyEvent`主要有两个构造函数,一个用于创建新事件,另一个用于复制已有事件。通常,我们需要指定事件的类型(如ACTION_DOWN或ACTION_UP...
在Android中,键盘事件通常以KeyEvent对象的形式传递。每个KeyEvent包含事件类型(ACTION_DOWN或ACTION_UP)、键码(如KEYCODE_A、KEYCODE_B等)和修饰符(如MetaKeys,如Ctrl、Alt)。通过解析这些信息,我们可以...
`dispatchKeyEvent()`方法用于向系统发送自定义的按键事件。 要注意的是,直接处理key事件可能会影响到系统的正常行为,因此在实际应用中,通常会通过其他方式来实现类似的功能,例如使用意图(Intent)或者自定义...
这份“安卓Android源码——按键的处理.zip”压缩包可能包含了关于Android系统如何管理和响应硬件按键以及软件模拟按键的源代码分析。让我们深入探讨一下这个主题。 首先,Android系统的按键处理主要分为两个层次:...
在Android开发领域, Monkey工具是一种常用的自动化测试工具,它能够模拟用户随机的触摸、按键行为,帮助开发者检测应用的稳定性。本主题将深入探讨“利用monkey注入事件原理实现Android事件注入”的过程,以及如何...
2. **模拟按键**:`input keyevent <event_code>` - 这个命令可以模拟按下或释放指定的按键。按键代码(`event_code`)可以在Android的`KeyEvent`类中找到,例如: ```bash # 模拟按下返回键 adb shell input ...
6. **按键模拟**:利用`adb shell input keyevent`模拟按键事件,如`input keyevent KEYCODE_ENTER`模拟回车键。 7. **日志收集**:通过`adb logcat`命令获取设备的日志信息,用于后期分析和调试。 8. **测试结束**...
在Android系统中,有时我们需要模拟用户输入事件,例如在自动化测试或者特定功能实现时。本文主要探讨了三种在Android中注入事件的方法:使用内部APIs、使用`Instrumentation`对象以及直接向设备的`/dev/input/...