来自macOS应用程序的带有特殊字符的ADB命令

时间:2018-10-29 16:19:26

标签: android swift macos shell adb

我想通过我的macOS应用程序中的adb命令从Android设备中提取文件。

所有内容都可以与下面的代码完美配合,除非当我要提取的文件名包含特殊字符(如德国变音符(äöüÄÖÜ))时,其他代码均如此。

我收到此错误: adb: error: failed to stat remote object '/storage/emulated/0/Download/Böse': No such file or directory

但是当我从adb pull /storage/emulated/0/Download/Böse ~/Desktop中使用命令Terminal.app时,文件将被拉到我的计算机上。

这里的奇怪之处在于,如果我从Xcode控制台输出中复制子字符串/storage/emulated/0/Download/Böse,则在删除Terminal.app并将其替换之前,该命令在ö中也不起作用从我的键盘输入中输入ö

我尝试用Unicode表示形式ö替换\u{00f6},但这没有任何效果(但是控制台输出仍然显示ö,但编码错误。

// Configure task.
let task = Process()
task.launchPath = "~/Library/Android/sdk/platform-tools/adb"
task.arguments = ["pull", "/storage/emulated/0/Download/Böse", "~/Desktop"]

// Configure pipe.
let pipe = Pipe()
task.standardOutput = pipe
task.standardError = pipe
task.launch()

// Run task.
let data = pipe.fileHandleForReading.readDataToEndOfFile()
let output = String(data: data, encoding: .utf8)
task.waitUntilExit()

// adb: error: failed to stat remote object '/storage/emulated/0/Download/Böse': No such file or directory
print(output)

我在文档中发现了Process如何处理我提供的参数的以下内容:

  

在通过argv []将它们传递给任务之前,NSTask对象将参数中的路径和字符串都转换为适当的C样式字符串(使用fileSystemRepresentation)。参数中的字符串不会进行shell扩展,因此您无需执行特殊的引号,并且不会解析shell变量(例如$ PWD)。

似乎我不是唯一遇到此问题的人,并且我找到了解决方法: How to work around NSTask calling -[NSString fileSystemRepresentation] for arguments,但我无法使其与Swift一起使用。

1 个答案:

答案 0 :(得分:0)

作为一种解决方法,我现在将adb命令写入文件并从应用程序中的bash命令执行它。

let source = "/storage/emulated/0/Download/Böse"
let destination = "~/Desktop"
guard let uniqueURL = URL(string: destination + "/" + ProcessInfo.processInfo.globallyUniqueString) else { return }

// Write command to file
let scriptContent = "#!/bin/bash\n~/Library/Android/sdk/platform-tools/adb pull -a \"" + source + "\" \"" + destination + "\""
try? scriptContent.write(to: uniqueURL, atomically: false, encoding: .utf8)

// Configure task.
let task = Process()
task.environment = ["LC_ALL": "de_DE.UTF-8", "LANG": "de_DE.UTF-8"]
task.launchPath = "/bin/bash"
task.arguments = [uniqueURL.path]

// Configure pipe.
let pipe = Pipe()
task.standardOutput = pipe
task.standardError = pipe
try? task.run()

// Run task.
let data = pipe.fileHandleForReading.readDataToEndOfFile()
let output = String(data: data, encoding: .utf8)
task.waitUntilExit()

print(output)

即使此操作目前仍有效,但它也不是一种令人满意的解决方案,因为它也不是很优雅,效率也不高,因此欢迎进行任何改进或更好的答案。