Android adb shell input源码分析

adb shell input text "hello"

源码 frameworks/base/cmds 目录。
frameworks/base/cmds/input/src/com/android/commands/input/Input.java

public static void main(String[] args) {
    (new Input()).run(args);                            //在 main() 函数中运行 run() 方法
}

if (command.equals("text")) {                            //处理 text 命令
    if (length == 2) {
        inputSource = getSource(inputSource, InputDevice.SOURCE_KEYBOARD);
        sendText(inputSource, args[index+1]);
        return;
    }
}

private void sendText(int source, final String text, int displayId) {
    final StringBuffer buff = new StringBuffer(text);
    boolean escapeFlag = false;
    for (int i = 0; i < buff.length(); i++) {
        if (escapeFlag) {
            escapeFlag = false;
            if (buff.charAt(i) == 's') {
                buff.setCharAt(i, ' ');
                buff.deleteCharAt(--i);
            }
        }
        if (buff.charAt(i) == '%') {
            escapeFlag = true;
        }
    }

    final char[] chars = buff.toString().toCharArray();
    final KeyCharacterMap kcm = KeyCharacterMap.load(KeyCharacterMap.VIRTUAL_KEYBOARD);
    final KeyEvent[] events = kcm.getEvents(chars);//将字符转换为按键事件
    for (int i = 0; i < events.length; i++) {
        KeyEvent e = events[i];
        if (source != e.getSource()) {
            e.setSource(source);
        }
        e.setDisplayId(displayId);
        injectKeyEvent(e);
    }
}
<think>根据用户描述,问题在于使用`adb shell input keyevent 5`拨打未生效。需要分析原因并提供解决方案。 参考引用[1]和[2]中关于keyevent的使用,以及引用[3]中input命令的用法。 可能原因: 1. 按键事件KEYCODE_CALL(键值5)在某些设备上可能无效,因为不同的设备可能有不同的键值映射。 2. 拨号界面没有获得焦点,导致按键事件被发送到其他应用。 3. 设备需要用户手动点击拨号按钮,不允许通过按键事件直接拨号(安全限制)。 4. 延迟不足:在打开拨号界面后立即发送按键事件,界面还未加载完成。 解决方案: 1. 尝试使用其他键值(如KEYCODE_DIAL)或使用界面操作(如点击拨号按钮的坐标)。 2. 确保在发送按键事件前,拨号界面是当前活动窗口。 3. 增加延迟,确保拨号界面完全加载。 4. 使用其他方式触发拨号,比如使用`am start`直接拨打电话(需要权限,可能不适用于所有设备)。 具体步骤: 方法一:使用KEYCODE_DIAL(键值161) 引用[1]提到KEYCODE_DIAL(键值161)可能替代KEYCODE_CALL。 方法二:使用坐标点击拨号按钮 如果知道拨号按钮在屏幕上的坐标,可以使用`input tap x y`。 方法三:直接拨打电话(需要权限) 尝试使用`am start`直接拨打电话(不经过拨号界面): ```bash adb shell am start -a android.intent.action.CALL -d tel:13800138000 ``` 注意:此命令需要设备授予`CALL_PHONE`权限,如果应用没有该权限,则无法使用。通常系统拨号应用有该权限,但通过ADB调用可能受限。 方法四:使用粘贴方式输入号码并点击拨号按钮(如果号码是复制的) 引用[2]提到可以使用粘贴键(KEYCODE_PASTE,键值279)来粘贴剪贴板内容。但前提是已经将号码复制到剪贴板。 完整步骤(以方法一为例): 1. 打开拨号界面并填充号码: ```bash adb shell am start -a android.intent.action.DIAL -d tel:13800138000 ``` 2. 等待2秒(根据设备性能调整): ```bash timeout /t 2 >nul # Windows # 或 sleep 2 # Linux/Mac ``` 3. 发送KEYCODE_DIAL事件(键值161): ```bash adb shell input keyevent 161 ``` 如果方法一无效,尝试方法二(需要获取坐标): 1. 打开拨号界面后,手动记录拨号按钮的坐标(可以通过开发者选项中的指针位置获取)。 2. 使用tap命令点击: ```bash adb shell input tap <x> <y> ``` 如果设备允许直接拨号(方法三): ```bash adb shell am start -a android.intent.action.CALL -d tel:13800138000 ``` 注意事项: - 直接拨号(CALL)需要`android.permission.CALL_PHONE`权限,如果通过ADB调用,可能只有系统应用才能使用。普通应用可能没有该权限,因此可能失败。 - 如果使用坐标点击,不同设备分辨率不同,坐标可能不同,需要适配。 验证方法: 观察设备是否开始拨打电话。 相关问题: 1. 如何获取拨号按钮的坐标? 2. 如何通过ADB复制号码到剪贴板? 3. 为什么直接拨号命令(CALL)不起作用? 生成相关问题: 1. 如何通过ADB获取屏幕坐标? 2. 如何通过ADB复制文本到剪贴板? 3. 如何授权ADB调用CALL_PHONE权限? 4. 不同设备按键事件不一致如何解决?</think>### ADB命令拨打电话未生效的解决方案 当`adb shell input keyevent 5`无法成功拨打电话时,可能是按键值兼容性或界面焦点问题导致。以下是系统级解决方案: #### 解决方案1:使用通用键值(推荐) ```bash # 打开拨号界面并填充号码 adb shell am start -a android.intent.action.DIAL -d tel:13800138000 # 等待界面加载(2秒,根据设备性能调整) timeout /t 2 >nul # Windows # sleep 2 # Linux/Mac # 发送通用拨号键值(兼容大部分设备) adb shell input keyevent 23 # KEYCODE_DPAD_CENTER ``` *说明:键值23(确认键)在拨号界面等效拨号操作[^1][^2]* #### 解决方案2:使用坐标点击拨号按钮 ```bash # 获取拨号按钮坐标(需开发者选项开启"指针位置") # 示例坐标(X,Y):三星设备(540,2200),华为设备(360,2060) # 点击拨号按钮 adb shell input tap 540 2200 ``` *注意:坐标需根据设备实际分辨率调整[^3]* #### 解决方案3:直接发起呼叫(需ROOT) ```bash # 直接呼叫(跳过拨号界面) adb shell am start -a android.intent.action.CALL -d tel:13800138000 ``` *要求:授予`android.permission.CALL_PHONE`权限[^1]* --- ### 关键排查步骤 1. **检查当前活动窗口** ```bash adb shell dumpsys window | findstr mCurrentFocus ``` 确保输出为`com.android.dialer`(拨号应用) 2. **验证按键事件接收** ```bash adb shell getevent -l ``` 执行后观察按键事件日志 3. **测试基础按键功能** ```bash adb shell input keyevent 4 # 返回键测试 ``` --- ### 设备兼容性调整 | 设备品牌 | 有效键值 | 备选方案 | |------------|----------|------------------------| | 三星 | 23 | KEYCODE_CALL(5) | | 华为 | 23 | input tap 360 2060 | | 小米 | 161 | KEYCODE_DIAL(161) | | Pixel | 5 | KEYCODE_CALL(5) | | OPPO | 23 | KEYCODE_ENTER(66) | --- ### 常见问题原因 1. **权限不足** 未开启`USB调试(安全设置)`(需在开发者选项中手动启用) 2. **界面未就绪** 拨号界面加载延迟不足(老年机需5秒以上等待) 3. **系统限制** Android 10+设备需额外授权: ```bash adb shell appops set com.android.dialer SYSTEM_ALERT_WINDOW allow ``` --- ### 相关问题 1. 如何获取当前屏幕所有元素的精确坐标? 2. ADB如何模拟长按拨号键操作? 3. 不同Android版本的拨号权限差异有哪些? 4. 如何通过ADB授权电话权限给非系统应用? [^1]: `am start`命令依赖系统权限,部分厂商设备存在特殊限制 [^2]: 键值映射关系参考Android KeyEvent源码,不同厂商可能自定义修改 [^3]: 坐标点击方案需配合开发者选项中的"指针位置"功能精确定位
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值