Android 3.0+的MTP,以及USB debugging

Android到了3.0+有个地方特别弱智,就是USB连上显示出来不是U盘设备,而是个MTP设备……

其他系统的MTP问题

首先这个MTP一开始就是Microsoft自己搞出来的东西,主要是Windows Media Player支持这个东西,日后才被USB那啥论坛搞成一种正式的USB类。应该是因为这个,别的系统下的支持都不怎么样。

别的系统基本上都用了libmtp库,而这个库最弱智的地方,就是刚连上的时候,会扫描所有文件做个索引…… 如果只是个音乐播放器可能还好,文件不多,但是现在是一个Android设备,那里边乱七八糟的可多了…… 于是这个索引要做个4,5分钟。想想你插上一个设备,过个四五分钟才能显示内容,那不是很sx么…… Windows下,MTP文件连上后,过一会就可以看见内容了……

读了代码,发现他是自己递归做索引的,而且好多接口函数都会去确保这个索引存在,不在就建出来……
根据MTP的规范,其实每次请求一个目录也就列出它的子文件和子目录。也就是说,按照规范来说,并没有啥一定要一次性拿到所有文件的必要性。看windows那边的实现也可以说明这一点。或许本来它是考虑搞个缓存提高之后速度,但是这个初次访问速度实在不能忍。而且之后访问慢慢建出来索引也可以,没必要非要一开是就建出全部的索引。

但是USB的传输速度又比较快。理论上wifi也很快,但是我拿scp也好ftp也好adb也好,速度都最多1M多,还不清楚哪儿sx了…… 所以还是要想办法搞定这个事情,难道要重写libmtp么……

Win下的MTP问题

于是我想别的系统MTP支持糟糕,Win总该不错吧?于是打开WinXP虚拟机,嘿,这个MTP还没有驱动……

上网查,说要装WMP10,装完还是不行。再查,说可以装WMP11,装完还是不行。再查,说有个MTP Porting Kit的东西,里面有驱动。下下来装好,里里外外翻了一遍,还是没有驱动…… 后来从WMP11的wmfdist11.exe,也就是Window Media Format 11 Runtime那一部分里,翻出来若干inf以及相关文件,貌似是MTP驱动。但是手动指定到这儿,倒好像装上去了,但还是不行……

到此基本没法,上网继续查。在查了好久之后,终于有个地方说可能和USB debugging有关系。遂关掉USB debugging,立马就好了…… 自动装好驱动,啥都能访问。一开,又不成……

继续观察,发现不开的时候,只有一个设备,VID_22B8&PID_70A8。这个设备的兼容类型里包括了USB\MS_COMP_MTP,所以驱动匹配上了。开了之后,这个设备变成了一个复合设备,VID_22B8&PID_70A9,很神奇的就是PID加了一,估计是为了和原来的区别开来。这个东西下有俩子设备,VID_22B8&PID_70A9&MI_00和VID_22B8&PID_70A9&MI_01。后一个在装了Moto的驱动之后,显示出来是个ADB设备,也就是USB debugging用的…… 前一个名称是MTP,估计就是MTP设备,但是兼容类型里没有USB\MS_COMP_MTP!于是驱动挂不上…… 就弱智了……

解决方法其实很简单,只要改windows\inf下的wpdmtp.inf,在匹配段里面,在

%GenericMTP.DeviceDesc%=MTP, USB\MS_COMP_MTP

之后,加上

%GenericMTP.DeviceDesc%=MTP, USB\VID_22B8&PID_70A9&MI_00

,一切都搞定了……

于是我很难理解,到底是哪里脑残了导致开了USB debugging就不说自己是MTP设备了…… 蛋疼啊……

为啥Google要用MTP……

虽说Google那边说MTP有诸多好处,例如提高了抽象层次,使得一个文件对Android和电脑都可见啦之类(老的方式系统看见了一大块数据,里面有几个分区,所以如果允许两边都看见,那只要有改动,就会导致元数据不一致…… 新的方法等于系统看见了一堆抽象的文件和目录等,所以所有操作都要告诉那边才能做…… Android那边维持着一致性……),但是选MTP这个标准真是蛋疼,你大不了Google自己搞一套+开源实现也不难啊!MTP就不是给你做任意类型文件传输的么!