Interface for MTP devices

I am pulling my hairs on that. I want to access a MTP device via dbus interface. I see the service org.gtk.vfs.MTPVolumeMonitor. I can use d-feet to explore the interface org.gtk.Private.RemoteVolumeMonitor. But how on earth am I supposed to understand these excessive signatures of highly complex structures?

I already started to pull the repo of gvfs. I read the code. I still have no clue how to interpret the structures. I mean it’s not a problem of understanding the signature I get with org.freedesktop.DBus.Introspectable. But what is the variable name of each member of the structures. For example this one:

'    <method name="List">\n'
 '      <arg type="a(ssssbbbbbbbbuasa{ss}sa{sv})" name="drives" '
 'direction="out"/>\n'
 '      <arg type="a(ssssssbbssa{ss}sa{sv})" name="volumes" direction="out"/>\n'
 '      <arg type="a(ssssssbsassa{sv})" name="mounts" direction="out"/>\n'
 '    </method>\n'

What is the meaning of all these strings and array? Is it just me too stupid to find that information? Or is it really like someone just dumped that interface without any documentation and you have to somehow know it’s structures?

I would be very grateful if someone could point to into the right direction.

Refer monitor/proxy/gvfsproxyvolumemonitordaemon.c#L517-536.

Great! Thanks!

After reading the documentation of gvfs a bit more I came across the statement that this dbus interface is for internal use only and thus it is not documented. This arises the question if I do the right thing.

Is there another way to access MTP devices? I know that gvfs creates a filesystem for MTP device. This is read-only. Therefore if you need to write files you need some kind of different interface to do a complete file transfer according to the MTP protocol.

Maybe there is a more simple dbus interface? KDE for example defines such an interface in it’s KIOD service. Anything similar for GNOME?

Why do you think that? For example, gvfs creates and mounts a fuse filesystem under /run/user/UID/gvfs and then my Android phone (MTP device) will show up there as something like /run/user/UID/gvfs/mtp:host=PHONEID. You can read/write files below that using normal (OS) operations.

Just tested it.

cp Documents/QMapShack/GPX/test.gpx  /run/user/1000/gvfs/mtp\:host\=Garmin_G_0000d6c54975/Memory\ Card/Garmin/GPX/
cp: cannot create regular file '/run/user/1000/gvfs/mtp:host=Garmin_G_0000d6c54975/Memory Card/Garmin/GPX/test.gpx': Operation not supported

If I use Nemo to copy the file it works. So there must be a difference.

OK, let’s try with gio (a simple CLI for libgio from glib2.0) - if you’re on Debian/Ubuntu it’s in package libgio-2.0-dev-bin. For my Android phone I see

$ gio mount --list
...
Mount(1): mtp -> mtp://PHONEID/
  Type: GDaemonMount

and

gio copy some-file mtp://PHONEID/Samsung\ SD\ card/

will do the trick. Nemo (and Nautilus) probably use the functions from libgio, you can call them from the language of your choice (C, Python, Javascript…).

If that works, but not using the gvfs fuse filesystem: what’s your version of gvfs?

might be the fix (it was merged for gvfs 1.57.1, about some 4 months ago). But I have been copying stuff (just cp or Python shutil.copyfile) to my Android phone for years.

My version is 1.54. So it’s before the patch. Copy via GIO works. But of course only for the Gnome system. For KDE pendant would be kioclient.

So up to now my best bet is to listen on both DBus interfaces (kio and gvfs) and to hide the details from my application behind some abstract API. Bit frustrating that it is that complex, but at least it’s feasible.

That was released in March 2024. Copying to my Android phone via cp (using the gvfs fuse filesystem) has been working for me for much longer.