博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Programmatically Injecting Events on Android 1
阅读量:6208 次
发布时间:2019-06-21

本文共 5559 字,大约阅读时间需要 18 分钟。

  hot3.png

The successful Android platform has been around for a few years now. End users get lots of bells and whistles in fancy applications, but for developers, this "open-intended" platform seems even more tangled up than ever.

There are various APIs that still do not work, others that get deprecated-and-out in a single release, or some that are locked up for the supreme security purpose, invoked so very often by platform developers, that probably feel they've given the right answer.
All in one, Android also comes with a lot of frustration, because tools that are needed to accomplish various tasks or even more advanced applications, are put behind bars on purpose.

Another example of many is injecting a key press programmatically or the similar counter-part, injecting a touch event (mouse).

Because a malicious programmer might develop a software that would open your Market app and download payed apps without you knowing about it, developers world wide are prohibited from sending a key press programmatically to other applications except their own.

This is just ridiculous narrow thinking.

Of course there will always be a balance between security and functionality, but with paranoia it quickly turns to total failure. In other words why limit something so useful that can create so little damage? Users are warned about risks with normal permissions and it should stay that way for other features as well.

I'll just leave them with their issues and get back to the topic: I am aware of three methods for injecting events programmatically. This refers both to keyboard events (keys) and mouse events (touch events).

Method 1: Using internal APIs

This approach has its risks, like it is always with internal, unpublished APIs.

The idea is to get an instance of WindowManager in order to access the injectKeyEvent / injectPointerEvent methods.

 
  IBinder wmbinder = ServiceManager.getService( "window" ); IWindowManager m_WndManager = IWindowManager..asInterface( wmbinder );  

The ServiceManager and WindowsManager are defined as Stubs. We can then bind to these services and call the methods we need. The interfaces are included in the sample code attached at the end of this article.

To send a key do the following:

 
  // key down m_WndManager.injectKeyEvent( new ( .ACTION_DOWN, .KEYCODE_A ),true ); // key up m_WndManager.injectKeyEvent( new ( .ACTION_UP, .KEYCODE_A ),true );  

To send touch/mouse events use:

 
  //pozx goes from 0 to SCREEN WIDTH , pozy goes from 0 to SCREEN HEIGHT m_WndManager.injectPointerEvent(MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(),MotionEvent.ACTION_DOWN,pozx, pozy, 0), true); m_WndManager.injectPointerEvent(MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(),MotionEvent.ACTION_UP,pozx, pozy, 0), true);  

This works fine, but only inside your application

The moment you're trying to inject keys/touch events to any other window, you'll get a force close because of the following exception:

 
  E/AndroidRuntime(4908): java.lang.: Injecting to another application requires INJECT_EVENTS permission  

Not much joy, as INJECT_EVENTS is a system permission. A possible solution is discussed and .

Method 2: Using an instrumentation object

This is a clean solution based on public API, but unfortunately it still requires that INJECT_EVENTS permission.

 
  Instrumentation m_Instrumentation = new Instrumentation(); m_Instrumentation.sendKeyDownUpSync( .KEYCODE_B );  

For touch events you can use:

 
  //pozx goes from 0 to SCREEN WIDTH , pozy goes from 0 to SCREEN HEIGHT m_Instrumentation.sendPointerSync(MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(),MotionEvent.ACTION_DOWN,pozx, pozy, 0); m_Instrumentation.sendPointerSync(MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(),MotionEvent.ACTION_UP,pozx, pozy, 0);  

All good inside the test application, and will crash instantly when trying to inject keys to outside apps, not because the approach doesn't work, but because Android Developers have chosen so. Thanks guys, you rock! Not.
By looking at sendPointerSync's code, you will quickly see it uses the same approach as presented in method 1). So this is the same thing, but packed nicely in a easy to use API:

 
  public void sendPointerSync(MotionEvent event) {
validateNotAppThread(); try {
(IWindowManager..asInterface(ServiceManager.getService("window"))) .injectPointerEvent(event, true); } catch ( e) {
} }  

Method 3: Direct event injection to /dev/input/eventX

Linux exposes a uniform input event interface for each device as /dev/input/eventX where X is an integer. We can use it directly and skip the above Android Platform permission issues.

For this to work, we will need root access, so this approach only works on a rooted device.
I felt it was easier to deal with linux using native C code, but a pure java implementation is also possible. Therefore I have added a small JNI component to handle the interface with /dev/input/eventX.

The sample code I wrote doesn't detect the X number automatically, so make sure you set that before running the code. By default I set it to event3. You can change that in NativeInput.java, see code below.

As I said, this last method requires root. By default the eventX files have the permission set for 660 (read and write for Owner and Group only). To inject keys from our application, we need to make it writable. So do this first:

 
  adb shell su chmod 666 /dev/input/event3  

You will need root to run the chmod command.

Sample Code

Other great resources:

转载于:https://my.oschina.net/nkm/blog/346119

你可能感兴趣的文章
时下最火搜索引擎:ElasticSearch详解与优化设计
查看>>
RecyclerView Animators
查看>>
微信小程序会让前端开发者失业
查看>>
如何降低应用访问的负载
查看>>
PYTHON之批量文件指定字符串替换
查看>>
修改系统IP(CentOS)
查看>>
【ANDROID游戏开发之五】游戏注册界面DEMO-实现两个ACTIVITY之间的切换与数据交互!...
查看>>
Linux cgroup资源隔离各个击破之 - cpu隔离1
查看>>
**集团RAC 11g 虚拟机生产库环境
查看>>
Java容器——未获支持的操作
查看>>
C# DataTable中返回列中的最大值
查看>>
SVN 中的 truck、branch 和 tag
查看>>
App开发中甲乙方冲突会闹出啥后果?H5 APP 开发可以改变现状吗
查看>>
SVG Gradients之Linear
查看>>
怎么恢复MySQL数据库
查看>>
【转】Shell中脚本变量和函数变量的作用域
查看>>
CSS选择器 < ~ +
查看>>
Java技术_每天掌握一种设计模式(003)_使用场景及简单实例(创建型:工厂方法)...
查看>>
ETL概述(原创)
查看>>
SQLite的使用一
查看>>