Android模拟按键

        在源码下写程序可以摆脱SDK的限制,毕竟SDK开放的API有限,比如我们实现模拟按键时,需要用到IWindowManager这个类,但是SDK中是不提供这个类的。

        首先下载编译源码,然后在源码的frameworks/base/cmds下新建一个文件夹作为你新扩展模块的一个目录。比如叫做autotest,在autotest下创建一个java文件,比如AutoTest.java。编写你的程序代码,在此你可以使用IWindowManager类,在此,我模拟了按键key,长按键keypress,点触笔touch,点触笔长按touchpress,以及移动move等,代码如下:

import android.view.MotionEvent;
import android.view.KeyEvent;
import android.view.IWindowManager;
import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.RemoteException;
import android.util.Log;
public class AutoTest 
{
	public static void main(String args[])throws Exception
	{
		String[] mArgs = args;
		try
		{
			String opt = mArgs[0];

			if(opt.equals("touch"))
			{
				float x = Float.valueOf(mArgs[1]);
				float y = Float.valueOf(mArgs[2]);
				MotionEvent e = MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(), MotionEvent.ACTION_DOWN, x, y, 0);
				sendPointerSync(e);
				e = MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(), MotionEvent.ACTION_UP, x, y, 0);
				sendPointerSync(e);
			}
			else if(opt.equals("move"))
			{
				float x = Float.valueOf(mArgs[1]);
				float y = Float.valueOf(mArgs[2]);
				float x2 = Float.valueOf(mArgs[3]);
				float y2 = Float.valueOf(mArgs[4]);
				MotionEvent e = MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(), MotionEvent.ACTION_DOWN, x, y, 0);
				sendPointerSync(e);
				e = MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(), MotionEvent.ACTION_MOVE, x, y, 0);
				sendPointerSync(e);
				e = MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(), MotionEvent.ACTION_MOVE, x, y, 0);
				sendPointerSync(e);
				e = MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(), MotionEvent.ACTION_MOVE, x2, y2, 0);
				sendPointerSync(e);
				e = MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(), MotionEvent.ACTION_MOVE, x2, y2, 0);
				sendPointerSync(e);
				e = MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(), MotionEvent.ACTION_UP, x2, y2, 0);
				sendPointerSync(e);
			}
			else if(opt.equals("key"))
			{
				int keycode = Integer.valueOf(mArgs[1]);
				KeyEvent k = new KeyEvent(KeyEvent.ACTION_DOWN,keycode);
				sendKeySync(k);
				k = new KeyEvent(KeyEvent.ACTION_UP,keycode);
				sendKeySync(k);
			}
			else if(opt.equals("wait"))
			{
				int millsecond = Integer.valueOf(mArgs[1]);
				Thread.sleep(millsecond);
			}
			else if(opt.equals("keypress"))
			{
				int keycode = Integer.valueOf(mArgs[1]);
				int millsecond = Integer.valueOf(mArgs[2]);
				KeyEvent k = new KeyEvent(KeyEvent.ACTION_DOWN,keycode);
				sendKeySync(k);
				Thread.sleep(millsecond);
				k = new KeyEvent(KeyEvent.ACTION_UP,keycode);
				sendKeySync(k);                        
			}
			else if(opt.equals("touchpress"))
			{
				float x = Float.valueOf(mArgs[1]);
				float y = Float.valueOf(mArgs[2]);
				int millsecond = Integer.valueOf(mArgs[3]);
				MotionEvent e = MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(), MotionEvent.ACTION_DOWN, x, y, 0);
				sendPointerSync(e);
				Thread.sleep(millsecond);
				e = MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(), MotionEvent.ACTION_UP, x, y, 0);
				sendPointerSync(e);
			}
			else 
				System.err.println("** Error: Unknown option: " + opt);
		}
		catch (RuntimeException ex){}
		Thread.sleep(2000);        
	}

	private static void sendPointerSync(MotionEvent event) 
	{
		try 
		{
			(IWindowManager.Stub.asInterface(ServiceManager.getService("window"))).injectPointerEvent(event, true);
		} 
		catch (RemoteException e) {}
	}

	private static void sendKeySync(KeyEvent event) 
	{
		try 
		{
			(IWindowManager.Stub.asInterface(ServiceManager.getService("window"))).injectKeyEvent(event, true);
		}
		catch (RemoteException e) {}
	}
}
在与java文件同级创建Android.mk文件,内容如下:

# Copyright 2008 The Android Open Source Project
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := \
	AutoTest.java
LOCAL_MODULE := autotest
LOCAL_MODULE_TAGS := eng
include $(BUILD_JAVA_LIBRARY)

//**********************************Android.mk 文件详解

1、LOCAL_PATH:一个Android.mk 首先必须定义好LOCAL_PATH变量。它用于在开发树中查找源文件。在这个例子中,宏函数’my-dir’, 由编译系统提供,用于返回当前路径(即包含Android.mk文件的目录)。

2、CLEAR_VARS 由编译系统提供,指定让GNU MAKEFILE为你清除许多LOCAL_XXX变量(例如 LOCAL_MODULE, LOCAL_SRC_FILES, LOCAL_STATIC_LIBRARIES, 等等...),LOCAL_PATH 。这是必要的,因为所有的编译控制文件都在同一个GNU MAKE执行环境中,所有的变量都是全局的。

3、LOCAL_MODULE变量必须定义,以标识你在Android.mk文件中描述的模块。名称必须是唯一的,而且不包含任何空格。注意编译系统会自动产生合适的前缀和后缀,换句话说,一个被命名为'HcSyncml'的共享库模块,将会生成'libHcSyncml.so'文件。

4、LOCAL_C_INCLUDES := $(LOCAL_PATH)/extra_inc$(LOCAL_PATH)/main_inc4、

LOCAL_C_INCLUDES 中加入所需要包含的头文件路径【针对C文件来说的】

5、 LOCAL_SRC_FILES: LOCAL_SRC_FILES中加入源文件路径(需要编译的文件),多个文件用 ‘\’ 隔开

//**************************************

在终端命令行下进入autotest文件夹,输入mm命令,如果报错,则返回Android源码主目录,输入如下命令:

. build/envsetup.sh
此时再返回你的工程目录输入mm就可以了,编译生成一个.jar文件,位于源码的/out/target/product/generic/system/framework下
将编译好的.jar文件及.odex文件 放在设备的/system/framework下,新建一个文件,名称为autotest,内容如下:
# Script to start "monkey" on the device, which has a very rudimentary
# shell.
#
base=/system
export CLASSPATH=$base/framework/autotest.jar
exec app_process $base/bin AutoTest $*
将autotest文件放在/system/bin下,用chmod修改文件属性(777)
这样你可以在shell下调用你的.jar文件了
比如在shell中输入: autotest key 24,向系统注入了调节音量的按键事件。

===========================================================

以上过程中出现的问题解析:

一、/system没有空间:

1、启动模拟器时,用命令 android sdk tools目录下  emulator -avd my_avd -partition-size 512 启动后 system目录的空间就变为了512M

2、获得root权限 adb root

3、设置/system为可读写 adb remount //解决可读写的问题

二、启动emulator时 ,有如下 错误提示

ERROR: You did not specify a virtual device name, and the system
directory could not be found.
If you are an Android SDK user, please use '@<name>' or '-avd <name>'
to start a given virtual device (see -help-avd for details).
Otherwise, follow the instructions in -help-disk-images to start the emulator

原因是你没有建立avd,建立方法如下:

1、终端中输入 ./android 执行该脚本,启动 Android SDK Manager -> Tools -> Manage AVDs -> 打开 Android Virtual Device Manager 后,新建一个avd,然后再执行emulator -avd my_avd -partition-size 512 便可正常。

三、在tools目录下,用adb push 把相应的文件push到指定目录下,便可在emulator下的shell中执行autotest key 24命令,把指定的键值推送给android系统了。

adb push /home/yinjk/Android/Android-source-code/djasdjaskdj/autotest /system/bin/


你可能感兴趣的:(android,manager,Module,Path,float,tools)