新换的手机,屏幕有点大,操作起来有点费劲,找了一些虚拟按键类的软件,都不是很简洁,最后想写个虚拟返回按钮。

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;}@Overridepublic 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:缺点,反应慢。想想这也是市面上找不到像样的虚拟按键类软件的原因吧,体验太差。

最后的最后,放弃了。凑合着用吧。

更多相关文章

  1. android中开启子线程
  2. Android(安卓)Service 两种启动方式的区别
  3. Android顶部banner轮播图的两种实现(ViewPager+ViewPagerIndicato
  4. Android(安卓)四大存储方式
  5. 二种方法实现 Android(安卓)TabWidget
  6. android项目中bindService失败的原因
  7. Android(安卓)资源文件屏幕适配
  8. Android(安卓)实现倒计时的简单方式
  9. Android面试题目

随机推荐

  1. Google Android手机操作系统发展历程[信
  2. android 控件使用集锦
  3. android layout布局属性
  4. 从0到1实现一个Android路由(4)——多模块
  5. android中的布局文件
  6. Ubuntu android NDK 配置
  7. android高仿小视频、应用锁、3种存储库、
  8. 动态添加TableRow
  9. android sdk 离线下载地址及对应映射关系
  10. Android(安卓)SDK 2.0安装、配置图文教程