Я пытаюсь подключить устройство Android к (Windows 7 64bit) ПК через кабель, а затем программно получить некоторые файлы с Android на ПК.
(Примечание: это нужно для определенного устройства, Moverio BT-200, и у меня возникают проблемы с драйверами; пожалуйста не предлагайте использовать adb 😉 Я знаю, что это простой и быстрый способ, но это нереально)
Я обнаружил, что мое устройство можно рассматривать как переносное устройство Windows (WPD). Я нашел несколько действительно хороших примеров кода в C #, который позволяет мне обнаружить WPD, в перечислить их содержание, и к перенести содержимое. Я также нашел некоторый код в C ++, который делает все вышеперечисленное и многое другое. Все эти примеры работают как чудо, пока я подключаю одну SD-карту или USB-ключ (то есть: пока у меня есть устройство, которое распознается Windows и получает букву как правильный диск), и я получаю полный список существующих файлов с их абсолютными путями. Тем не менее, если я пытаюсь подключить устройства Android и перечислить содержимое, я получаю нечто, чего я не понимаю:
embt2
SD Card
o15F9A
o15F9B
o15F9C
o15F9D
o15F9E
...etc
Internal Storage
o1
o2
o3
o4
o5
o6
oD1F
oD20
oD24
o7
o8
o1E78
o9
...etc
Как это может быть? Просматривая код C # (вторая ссылка выше), я обнаружил, что в некоторых моментах код создает несколько объектов GUID, каждый из которых имеет несколько отличающиеся параметры:
// Identify the property to retrieve
var property = new _tagpropertykey();
property.fmtid = new Guid(0x26D4979A, 0xE643, 0x4626, 0x9E, 0x2B,
0x73, 0x6D, 0xC0, 0xC9, 0x2F, 0xDC);
property.pid = 12;
[...]
// Get the name of the object
string name;
var property = new _tagpropertykey();
property.fmtid = new Guid(0xEF6B490D, 0x5CD8, 0x437A, 0xAF, 0xFC,
0xDA, 0x8B, 0x60, 0xEE, 0x4A, 0x3C);
property.pid = 4;
[...]
// Get the type of the object
property = new _tagpropertykey();
property.fmtid = new Guid(0xEF6B490D, 0x5CD8, 0x437A, 0xAF, 0xFC,
0xDA, 0x8B, 0x60, 0xEE, 0x4A, 0x3C);
property.pid = 7;
[...]
var folderType = new Guid(0x27E2E392, 0xA111, 0x48E0, 0xAB, 0x0C,
0xE1, 0x77, 0x05, 0xA0, 0x5F, 0x85);
var functionalType = new Guid(0x99ED0160, 0x17FF, 0x4C44, 0x9D, 0x98,
0x1D, 0x7A, 0x6F, 0x94, 0x19, 0x21);
Но я не мог понять, как работают эти десятичные значения. Документация онлайн кажется скудной. Я нашел мой гид устройства с помощью диспетчера устройств ({eec5ad98-8080-425f-922a-dabf3de3f69a}
), но каждый раз, когда я пытался заменить один из этих руководств своим собственным, я получал исключение COMException.
Я смотрю в правильном месте? Нужно ли устанавливать какой-либо GUID или что-то еще?
Я помечаю этот вопрос как C # и C ++, потому что я нашел несколько примеров кода на этих двух языках, но я готов решить проблему на любом языке (Java, Python, …)
Для справки, я решил использовать ужасный хак для решения своей проблемы.
Так как я знаю путь, где хранятся файлы, которые я ищу, я использовал функцию EnumerateContent
из блога Кристофа Гира, и изменил, чтобы проверить, имеет ли текущая папка имя, которое я ищу:
Если, например, интересующие меня файлы находятся в Sd Card/path/to/directory/
Затем я адаптировал код так: вместо вызова метода EnumerateContents
Я называю метод EnumerateContentsInTargetDirectory
:
private static void EnumerateContentsInTargetDirectory(ref IPortableDeviceContent content, PortableDeviceFolder parent)
{
// Get the properties of the object
IPortableDeviceProperties properties;
content.Properties(out properties);
// Enumerate the items contained by the current object
IEnumPortableDeviceObjectIDs objectIds;
content.EnumObjects(0, parent.Id, null, out objectIds);
uint fetched = 0;
do
{
string objectId;
objectIds.Next(1, out objectId, ref fetched);
if (fetched > 0)
{
var currentObject = WrapObject(properties, objectId);
if (currentObject is PortableDeviceFolder)
{
if (currentObject.Name.Equals("SD Card") || currentObject.Name.Equals("path") || currentObject.Name.Equals("to"))
{
parent.Files.Add(currentObject);
EnumerateContentsInTargetDirectory(ref content, (PortableDeviceFolder)currentObject);
}
else if (currentObject.Name.Equals("directory"))
{
parent.Files.Add(currentObject);
// This is the same original method of Christophe Geer.
EnumerateContents(ref content, (PortableDeviceFolder)currentObject);
}
}
}
} while (fetched > 0);
}
Что за странные имена файлов? Первый список вы опубликовали с большим количеством записей, которые начинаются с o
с последующим шестнадцатеричным числом являются PTP / MTP Уникальные идентификаторы предметов которые позволяют ссылаться на элементы файла на удаленном устройстве. Они являются нормальными и являются частью протоколов PTP и MTP, они являются одним из множества фрагментов данных, которые соответствуют системам полного перечисления и передачи файлов в протоколах PTP и MTP.
Как обстоят дела со всеми GUID и небольшими изменениями? По сути, именно так работает протокол USB HID (аппаратная идентификация), особенно Microsoft. GUID — это коды Microsoft, которые ссылаются на пути HID в драйверах USB, которые, в свою очередь, обращаются к устройству USB для получения информации (получения или установки информации). Каждая команда HID также использует PID (идентификатор продукта) для адресации определенного места в памяти в пути или команде HID, поэтому передача разных PID в командах HID приводит к получению / настройке различных фрагментов данных на устройстве USB.
Что немного грустно и страшно, так это то, как Microsoft раскрыла это очень низкое взаимодействие с инженерами и программами высокого уровня. И их документация действительно не предоставила много полезной справочной информации или объяснения того, что это за материал и что он значит. Если вы хотите более твердый пример кода и фона, я настоятельно рекомендую проверить Блоги Кристофа Гира об использовании WPD в C # /. Net — они мне очень помогли. Увидеть его последующий блог о передаче контента для большего количества положительных героев.
Еще один совет, который может быть полезен — вы можете просмотреть целый ряд PID, чтобы увидеть, какая там информация. Просто оберните ваши заглядывающие и пробивающиеся блоки try / catch на случай, если они потерпят неудачу. Я построил дополнительный маленький жгут вокруг кода от Кристофа Гира, который просматривает PID 0-31 для всех идентификаторов HID GUID в его примерах и нашел много дополнительной и полезной информации.