ADBKeyBoard:通过ADB实现Android虚拟键盘输入
项目描述
ADBKeyBoard 是一个创新的Android虚拟键盘输入法。它通过接收系统广播意图(Broadcast Intents)来执行输入命令,使得用户能够使用ADB(Android Debug Bridge)直接向Android设备发送文本输入。该项目主要解决了标准ADB input 命令无法输入Unicode字符(如中文、表情符号等)的问题,是自动化测试、设备批量操作和特殊字符输入场景的理想工具。
功能特性
- ADB驱动的文本输入:通过ADB命令直接发送任意文本到当前激活的输入框。
- 完整的Unicode字符支持 :突破了原生
adb shell input text命令的限制,可以输入包括中文、日文、韩文及Emoji在内的所有Unicode字符。 - 多种输入模式 :
- 直接文本输入 (
ADB_INPUT_TEXT)。 - Base64编码文本输入 (
ADB_INPUT_B64),用于解决高版本Android系统的兼容性问题。 - 发送键位事件码 (
ADB_INPUT_CODE),模拟物理按键(如删除、回车)。 - 发送编辑器动作 (
ADB_EDITOR_CODE),如执行搜索、前往等动作。 - 发送Unicode字符码点 (
ADB_INPUT_CHARS)。 - 发送组合键(Meta键) (
ADB_INPUT_MCODE),如Ctrl+A。 - 清空文本 (
ADB_CLEAR_TEXT)。
- 直接文本输入 (
- 便捷的ADB控制:提供完整的ADB命令来启用、切换和重置输入法。
- 轻量级与易集成:APK体积小,通过广播机制与系统交互,无需复杂的权限或后台服务。
安装指南
方法一:直接安装APK(推荐)
-
从项目的Release页面下载最新的
ADBKeyboard.apk文件。 -
连接Android设备并开启USB调试模式。
-
执行以下命令进行安装:
bashadb install ADBKeyboard.apk
方法二:从源码构建
-
克隆仓库 :
bashgit clone https://github.com/senzhk/ADBKeyBoard.git cd ADBKeyBoard -
配置环境 :
-
设置
ANDROID_HOME环境变量指向你的Android SDK路径,例如:bashexport ANDROID_HOME=$HOME/Android/Sdk -
或者直接编辑项目根目录下的
local.properties文件,添加sdk.dir=/path/to/your/Android/Sdk。
-
-
构建并安装 :
bash./gradlew installDebug
启用键盘
安装后,需要通过ADB或系统设置启用并切换到此输入法。
通过ADB启用和切换:
bash
# 启用ADBKeyBoard输入法
adb shell ime enable com.android.adbkeyboard/.AdbIME
# 将ADBKeyBoard设置为当前默认输入法
adb shell ime set com.android.adbkeyboard/.AdbIME
通过系统设置启用 : 进入设备的 设置 -> 系统 -> 语言和输入法 -> 虚拟键盘,找到并启用"ADBKeyBoard"。
使用说明
启用ADBKeyBoard后,即可通过发送广播意图(Broadcast Intents)来控制输入。
基础使用示例
-
发送普通文本 (可能在高版本Android上失效):
bashadb shell am broadcast -a ADB_INPUT_TEXT --es msg '你好嗎? Hello?' -
发送Base64编码的文本 (推荐,兼容性更好):
bash# Mac/Linux adb shell am broadcast -a ADB_INPUT_B64 --es msg `echo -n '你好嗎? Hello?' | base64` # Windows (需借助PowerShell或Python脚本处理Base64) -
发送按键事件 (如删除键,码值67):
bashadb shell am broadcast -a ADB_INPUT_CODE --ei code 67 -
发送编辑器动作 (如"前往"动作,码值2):
bashadb shell am broadcast -a ADB_EDITOR_CODE --ei code 2 -
发送Unicode字符码点 (发送"😸 Cat"):
bashadb shell am broadcast -a ADB_INPUT_CHARS --eia chars '128568,32,67,97,116' -
发送组合键 (如Ctrl + A):
bashadb shell am broadcast -a ADB_INPUT_MCODE --es mcode '4096,29' -
清空当前输入框的所有文本:
bashadb shell am broadcast -a ADB_CLEAR_TEXT
ADB输入法管理命令
-
列出所有可用输入法 :
bashadb shell ime list -a -
切换回其他输入法 (例如Swype):
bashadb shell ime set com.nuance.swype.dtc/com.nuance.swype.input.IME -
重置为系统默认输入法 :
bashadb shell ime reset
核心代码
以下是项目核心类 AdbIME.java 的关键代码片段,展示了广播接收器的注册和消息处理逻辑。
java
package com.android.adbkeyboard;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.inputmethodservice.InputMethodService;
import android.util.Base64;
import android.util.Log;
import android.view.InputDevice;
import android.view.KeyEvent;
import android.view.View;
import android.view.inputmethod.ExtractedTextRequest;
import android.view.inputmethod.InputConnection;
public class AdbIME extends InputMethodService {
// 定义广播Action常量,用于识别不同类型的输入指令
private String IME_MESSAGE = "ADB_INPUT_TEXT";
private String IME_CHARS = "ADB_INPUT_CHARS";
private String IME_KEYCODE = "ADB_INPUT_CODE";
private String IME_META_KEYCODE = "ADB_INPUT_MCODE";
private String IME_EDITORCODE = "ADB_EDITOR_CODE";
private String IME_MESSAGE_B64 = "ADB_INPUT_B64";
private String IME_CLEAR_TEXT = "ADB_CLEAR_TEXT";
private BroadcastReceiver mReceiver = null;
@Override
public View onCreateInputView() {
// 加载一个简单的空视图作为输入法界面
View mInputView = getLayoutInflater().inflate(R.layout.view, null);
// 注册广播接收器,用于监听来自ADB的命令
if (mReceiver == null) {
IntentFilter filter = new IntentFilter(IME_MESSAGE);
filter.addAction(IME_CHARS);
filter.addAction(IME_KEYCODE);
filter.addAction(IME_EDITORCODE);
filter.addAction(IME_MESSAGE_B64);
filter.addAction(IME_CLEAR_TEXT);
mReceiver = new AdbReceiver();
registerReceiver(mReceiver, filter);
}
return mInputView;
}
public void onDestroy() {
// 服务销毁时,注销广播接收器以防止内存泄漏
if (mReceiver != null)
unregisterReceiver(mReceiver);
super.onDestroy();
}
// 内部广播接收器类,负责处理接收到的各种输入命令
class AdbReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
// 处理普通文本输入命令
if (intent.getAction().equals(IME_MESSAGE)) {
String msg = intent.getStringExtra("msg");
if (msg != null) {
InputConnection ic = getCurrentInputConnection();
if (ic != null)
ic.commitText(msg, 1); // 将文本提交到当前输入连接
}
// 此处代码省略了处理元键(Meta Key)的部分逻辑
}
// 其他Action(如IME_CHARS, IME_KEYCODE等)的处理逻辑在此类中继续实现...
}
}
}
代码关键点解析:
-
继承
InputMethodService:AdbIME类是Android输入法服务的基础,使其成为一个合法的系统输入法。 -
onCreateInputView方法 :在创建输入法视图时,初始化并注册一个BroadcastReceiver(AdbReceiver)。它监听所有预定义的广播动作。 -
AdbReceiver内部类 :核心逻辑所在。其onReceive方法根据Intent的 Action 类型,提取附加数据(如文本、键值码),并通过getCurrentInputConnection()获取当前焦点输入框的连接,最终将输入内容提交 (commitText) 或执行相应动作。 -
生命周期管理 :在
onDestroy中注销广播接收器,这是Android开发中防止上下文泄漏的良好实践。
这段代码清晰地展示了ADBKeyBoard的工作原理:作为一个"无界面"的输入法,它主要依靠后台接收广播指令来工作,从而实现高度的自动化控制能力。