![](/img/trans.png)
[英]How to transfer file to Android Device without drive letter using WPD
[英]How to transfer files from Android device to PC using USB and/or WPD
我正在嘗試通過電纜將android設備連接到(Windows 7 64bit)PC,然后以編程方式從android到pc檢索一些文件。
(注意:我需要特定設備Moverio BT-200來使用它,並且該驅動程序存在問題;所以請不要建議使用adb ;-)我知道這是簡便快捷的方法,但是不可行)
我發現我的設備可以看作是Windows便攜式設備( WPD )。 我在C#中找到了一些非常好的代碼示例,這些示例使我能夠檢測WPD , 枚舉它們的內容並傳輸內容 。 我還在C ++中找到了一些代碼,它可以完成上述所有工作,甚至更多 。 只要我連接一個sdcard或一個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}
)找到了設備GUID,但是每次我嘗試用自己的GUID替換其中一個時,都會出現COMException。
我在找對地方了嗎? 我需要設置一些GUID還是其他?
我將這個問題標記為C#和C ++,因為我找到了這兩種語言的一些代碼示例,但是我願意以任何一種語言(java,python,...)解決該問題。
作為記錄,我最終使用了一些可怕的技巧來解決我的問題。 由於我知道要查找的文件的存儲路徑,因此我使用了Christophe Geer博客中的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);
}
所有奇怪的文件名是什么? PTP / MTP唯一項目標識符是您發布的第一個列表,其中有很多條目以o
開頭,后跟一個十六進制數字,它們使您可以引用遠程設備上的文件項目。 這些是正常的,是PTP和MTP協議的一部分,它們是PTP和MTP協議中與完整的項目枚舉和文件傳輸系統一起使用的眾多數據之一。
所有GUID和細微變化如何處理? 基本上,這就是USB HID(硬件識別)協議在幕后的工作方式-尤其是Microsoft如何實現它。 GUID是Microsoft代碼,鏈接到USB驅動程序中的HID路徑,然后依次調用USB設備獲取信息(獲取或設置信息)。 每個HID命令還使用PID(產品標識符)來尋址HID路徑或命令中的特定存儲器位置,因此在HID命令中傳遞不同的PID將導致在USB設備上獲取/設置不同的數據。
令人難過和害怕的是,Microsoft如何將這種非常低級的交互作用暴露給高級工程師和程序。 而且他們的文檔確實沒有提供很多有用的背景信息或有關這些內容和含義的解釋。 如果您想要更扎實的示例代碼和背景知識,我強烈建議您查看Christophe Geer的有關在C#/。Net中使用WPD 的博客 -它們確實對我有很大幫助。 請參閱他的后續博客,了解有關轉移內容的更多信息。
另一條可能有用的建議-您可以在整個PID范圍內戳一下,以查看其中存在什么樣的信息。 只要將它們的窺視和戳入嘗試/捕獲塊中,以防它們失敗。 我圍繞Christophe Geer的代碼構建了一個額外的工具,該代碼探究了他的示例中所有HID GUID的PID 0-31,並發現了許多額外且有用的信息。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.