1. 程式人生 > >Android模擬按鍵——原始碼環境下開發應用程式

Android模擬按鍵——原始碼環境下開發應用程式

   在http://blog.csdn.net/ericahdu 的幫助下,實現了模擬按鍵,在此,首先表示感謝:)
在原始碼下寫程式可以擺脫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 := $(call all-subdir-java-files)
LOCAL_MODULE := autotest
include $(BUILD_JAVA_LIBRARY)

在終端命令列下進入autotest資料夾,輸入mm命令,如果報錯,則返回Android原始碼主目錄,輸入如下命令:
. build/envsetup.sh

此時再返回你的工程目錄輸入mm就可以了,如果報如下錯誤:
build/core/base_rules.mk:98: *** user tag detected on new module - user tags are only supported on legacy modules. Stop.
在Android.mk檔案中加入LOCAL_MODULE_TAGS := optional 即可。
user: 指該模組只在user版本下才編譯
eng: 指該模組只在eng版本下才編譯
tests: 指該模組只在tests版本下才編譯
optional:指該模組在所有版本下都編譯

編譯生成一個.jar文 件,位於原始碼的/out/target/product/generic/system/framework下
將編譯好的.jar檔案放在裝置的/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,向系統注入了調節音量的按鍵事件。