首页 > 解决方案 > 来自 macOS 应用程序的带有特殊字符的 ADB 命令

问题描述

我想通过adb我的 macOS 应用程序中的命令从我的 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 ~/DesktopTerminal.app该文件将被拉到我的计算机上。

这里奇怪的是,如果我/storage/emulated/0/Download/Böse从 Xcode 控制台输出中复制子字符串,则该命令也无法在其中工作,Terminal.app直到我删除并用键盘输入ö中的 an 替换它。ö

我尝试用ö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处理我提供的参数:

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

似乎我不是唯一一个遇到这个问题的人,我发现了这个解决方法: How to work around NSTask calling -[NSString fileSystemRepresentation] for arguments,但我无法让它与 Swift 一起工作。

标签: androidswiftmacosshelladb

解决方案


作为一种解决方法,我现在正在将我的 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)

尽管这目前有效,但它不是一个令人满意的解决方案,因为它不是很优雅且效率也不高,因此欢迎任何改进或更好的答案。


推荐阅读