Команда ADB из приложения macOS со специальными символами - PullRequest
0 голосов
/ 29 октября 2018

Я хочу получить файл с моего устройства Android с помощью команды adb из моего приложения MacOS.

Все отлично работает с кодом ниже, кроме случаев, когда имя файла, который я хочу вытащить, содержит специальные символы, такие как немецкие умляуты (äöüÄÖÜ).

Я получаю эту ошибку: 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, файл будет перенаправлен на мой компьютер.

Странная вещь здесь в том, что если я скопирую подстроку /storage/emulated/0/Download/Böse из вывода консоли Xcode, команда также не будет работать в Terminal.app, пока я не удалю ö и не заменю ее на ö из мой ввод с клавиатуры.

Я попытался заменить ö представлением в юникоде \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 преобразует и путь, и строки в аргументах в соответствующие строки в стиле C (используя fileSystemRepresentation) перед передачей их задаче через argv []. Строки в аргументах не подвергаются расширению оболочки, поэтому вам не нужно делать специальных кавычек, а переменные оболочки, такие как $ PWD, не разрешаются.

Кажется, я не единственный, кто столкнулся с этой проблемой, и я нашел этот обходной путь: Как обойти вызов NSTask - [NSString fileSystemRepresentation] для аргументов , но я не смог заставить его работать со Swift.

1 Ответ

0 голосов
/ 10 ноября 2018

В качестве обходного пути я сейчас записываю свою команду 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)

Несмотря на то, что это работает на данный момент, это не является удовлетворительным решением, поскольку оно не очень элегантно и неэффективно, поэтому любые улучшения или лучшие ответы приветствуются.

...