简体   繁体   English

如何使用USB和/或WPD将文件从Android设备传输到PC

[英]How to transfer files from Android device to PC using USB and/or WPD

I am trying to connect an android device to a (Windows 7 64bit) PC via cable, and then to retrieve some files from android to pc programmatically. 我正在尝试通过电缆将android设备连接到(Windows 7 64bit)PC,然后以编程方式从android到pc检索一些文件。

(Note: I need this for a specific device, Moverio BT-200, and I am having drivers issues with that; so please don't suggest to use adb ;-) I know that's the easy and fast way, but it's not feasible) (注意:我需要特定设备Moverio BT-200来使用它,并且该驱动程序存在问题;所以不要建议使用adb ;-)我知道这是简便快捷的方法,但是不可行)

I have found that my device can be seen as a Windows Portable Device ( WPD ). 我发现我的设备可以看作是Windows便携式设备( WPD )。 I found some really good code examples in C# that enables me to detect WPDs , to enumerate their contents , and to transfer the contents . 我在C#中找到了一些非常好的代码示例,这些示例使我能够检测WPD枚举它们的内容传输内容 I also found some code in C++, which does all of the above and much more . 我还在C ++中找到了一些代码,它可以完成上述所有工作,甚至更多 All of this examples works like a charm as long as I connect a single sdcard, or a usb key (that is: as long as I have a device which gets recognized by Windows and gets a letter as a proper drive), and I get a full list of the present files, with their absolute paths. 只要我连接一个sdcard或一个usb密钥(即:只要我拥有Windows识别的设备并获得一个字母作为正确的驱动器),所有这些示例都可以像一个超级按钮一样工作。当前文件的完整列表及其绝对路径。 However, if I try to connect an android devices, and to list the contents, I get something that I do not understand: 但是,如果我尝试连接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

How can that be? 怎么可能? Browsing the C# code (second link, above), I found that at some points, the code creates several GUID objects, each with some slightly different parameters: 浏览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);

But I couldn't figure out how these exadecimal values work. 但是我不知道这些极值是如何工作的。 The documentation online seems scarce. 在线文档似乎很少。 I found my device guid with the Device Manager ( {eec5ad98-8080-425f-922a-dabf3de3f69a} ), but everytime I tried to replace one of these guid with my own, I got a COMException. 我使用设备管理器( {eec5ad98-8080-425f-922a-dabf3de3f69a} )找到了设备GUID,但是每次我尝试用自己的GUID替换其中一个时,都会出现COMException。

Am I looking in the right place? 我在找对地方了吗? Do I need to set some GUID, or something else? 我需要设置一些GUID还是其他?

I am tagging this question as C# and C++ because I found some code examples in these two languages, but I am willing to solve the problem in any language (java, python, ... ) 我将这个问题标记为C#和C ++,因为我找到了这两种语言的一些代码示例,但是我愿意以任何一种语言(java,python,...)解决该问题。

For the record, I ended up using some horrible hack for solving my problem. 作为记录,我最终使用了一些可怕的技巧来解决我的问题。 Since I know the path where are stored the files I'm looking for, I used the function EnumerateContent from Christophe Geer's blog, and modified to check if current folder has the name I'm looking for: 由于我知道要查找的文件的存储路径,因此我使用了Christophe Geer博客中的EnumerateContent函数,并对其进行了修改以检查当前文件夹是否具有我要查找的名称:

If, for example, the files I'm interested in are in the Sd Card/path/to/directory/ , then I adapted the code like this: instead of calling the method EnumerateContents , I call the method EnumerateContentsInTargetDirectory : 例如,如果我感兴趣的文件位于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);

} }

What's with all the weird filenames? 所有奇怪的文件名是什么? The first list you posted with a lot of entries which begin with o followed by a hexadecimal number are the PTP/MTP Unique Item Identifiers which allow you to refer to file items on the remote device. PTP / MTP唯一项目标识符是您发布的第一个列表,其中有很多条目以o开头,后跟一个十六进制数字,它们使您可以引用远程设备上的文件项目。 Those are normal and a part of the PTP and MTP protocols, they are one of the many pieces of data that go along with the full item enumeration and file transfer systems in the PTP and MTP protocols. 这些是正常的,是PTP和MTP协议的一部分,它们是PTP和MTP协议中与完整的项目枚举和文件传输系统一起使用的众多数据之一。

What's the deal with all the GUIDs and slight variations? 所有GUID和细微变化如何处理? This is basically how the USB HID (Hardware Identification) protocol works under the covers - specifically how Microsoft implements it. 基本上,这就是USB HID(硬件识别)协议在幕后的工作方式-尤其是Microsoft如何实现它。 The GUIDs are Microsoft codes which link to HID paths in the USB drivers, which in-turn make calls to the USB device for information (getting or setting information). GUID是Microsoft代码,链接到USB驱动程序中的HID路径,然后依次调用USB设备获取信息(获取或设置信息)。 Every HID command also uses a PID (Product Identifier) to address a specific location of memory within the HID path or command, so passing different PIDs in the HID commands results in getting/setting different pieces of data on the USB device. 每个HID命令还使用PID(产品标识符)来寻址HID路径或命令中的特定存储器位置,因此在HID命令中传递不同的PID将导致在USB设备上获取/设置不同的数据。

What's a little sad and scary is how Microsoft exposed this very low-level interaction up to high-level engineers and programs. 令人难过和害怕的是,Microsoft如何将这种非常低级的交互作用暴露给高级工程师和程序。 And their documentation really didn't provide much useful background information or explanation for what this stuff is and means. 而且他们的文档确实没有提供很多有用的背景信息或有关这些内容和含义的解释。 If you'd like more solid example code and background, I'd highly recommend checking out Christophe Geer's blogs about using WPD in C#/.Net - they really helped me out a lot. 如果您想要更扎实的示例代码和背景知识,我强烈建议您查看Christophe Geer的有关在C#/。Net中使用WPD 的博客 -它们确实对我有很大帮助。 See his follow-up blog on transferring content for more goodies. 请参阅他的后续博客,了解有关转移内容的更多信息。

One other piece of advice that may be helpful - you can poke around a whole range of PIDs to see what kind of information is there. 另一条可能有用的建议-您可以在整个PID范围内戳一下,以查看其中存在什么样的信息。 Just wrap your peeking and poking in try/catch blocks in case they fail. 只要将它们的窥视和戳入尝试/捕获块中,以防它们失败。 I built an extra little harness around the code from Christophe Geer that peeks into PIDs 0-31 for all of the HID GUIDs in his examples and found a lot of extra and useful information. 我围绕Christophe Geer的代码构建了一个额外的工具,该代码探究了他的示例中所有HID GUID的PID 0-31,并发现了许多额外且有用的信息。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM