终端可执行的adb命令在Java Process.exec中报“未闭合引号”错误
为什么Process.exec执行带嵌套引号的adb命令会报“未闭合引号”错误?
这问题我之前踩过坑!核心原因是**Runtime.exec(String)的命令拆分逻辑和终端shell完全不一样**:
当你在终端输入带嵌套引号的命令时,shell(比如bash)会智能解析引号,把su -c 'settings put global airplane_mode_on 1'当成一个完整的参数传给adb shell。但exec(String)只会简单地按空格分割字符串,它完全不识别引号作为参数边界的作用——也就是说,它会把你的命令拆成adb、shell、"su、-c、'settings这些零散的片段,导致shell接收到的命令完全乱套,自然就报“未闭合引号”了。
解决办法有两种,推荐第一种:
1. 用字符串数组传递命令(最可靠)
直接把命令拆分成一个个完整的参数,这样exec就不会乱拆分了:
public static void enableAirplaneMode() { String s = null; try { Runtime rt = Runtime.getRuntime(); Process pr = null; // 按参数边界拆分,每个元素都是完整的参数单元 String[] command = { "adb", "shell", "su -c 'settings put global airplane_mode_on 1'" }; System.out.println(String.join(" ", command)); pr = rt.exec(command); BufferedReader stdInput = new BufferedReader(new InputStreamReader(pr.getInputStream())); while ((s = stdInput.readLine()) != null) { System.out.println(s); } pr.destroy(); } catch (Exception e) { e.printStackTrace(); } }
这种方式不需要处理复杂的转义,参数边界清晰,也是官方推荐的用法。
2. 让shell来解析完整命令
如果坚持要用字符串形式,可以把整个命令包在sh -c里,让shell帮你处理引号,但需要注意转义内层的引号:
public static void enableAirplaneMode() { String s = null; try { Runtime rt = Runtime.getRuntime(); Process pr = null; // 用sh -c触发shell解析逻辑,内层单引号要转义 String command = "sh -c \"adb shell 'su -c \\'settings put global airplane_mode_on 1\\''\""; System.out.println(command); pr = rt.exec(command); BufferedReader stdInput = new BufferedReader(new InputStreamReader(pr.getInputStream())); while ((s = stdInput.readLine()) != null) { System.out.println(s); } pr.destroy(); } catch (Exception e) { e.printStackTrace(); } }
不过这种方式容易因为转义细节出错,不如数组方式省心。
总结一下:终端能正常执行是因为shell帮你处理了引号的解析,而exec(String)只会“傻拆”空格,所以用数组传递参数才是正确的打开方式~
内容的提问来源于stack exchange,提问作者Arya
相关产品推荐
相关产品推荐

