13

When I connect my Android phone to my Windows 7 with USB cable, Windows pop-up a window and show me the phone's internal storage at Computer\HTC VLE_U\Internal storage from Windows Explorer. But there is no drive letter linked with this phone storage! Inside Windows Explorer, I can manipulate the file system.

How can I manipulate the same files or folders from C# program?

As I tested,

DirectoryInfo di = new DirectoryInfo(@"C:\"); 

works, but

DirectoryInfo di = new DirectoryInfo(@"Computer\HTC VLE_U\Internal storage");

failed.

But in Windows Explorer, IT IS Computer\HTC VLE_U\Internal storage! No drive letter!

Yes, this is MTP device.

I see this answer in Stack Overflow, but the return results are empty for me after running this code

var drives = DriveInfo.GetDrives();
var removableFatDrives = drives.Where(
    c=>c.DriveType == DriveType.Removable &&
    c.DriveFormat == "FAT" && 
    c.IsReady);
var androids = from c in removableFatDrives
    from d in c.RootDirectory.EnumerateDirectories()
    where d.Name.Contains("android")
    select c;

I get correct drives. But android phone's internal storage is not here. Both removableFatDrives and androids are empty for me.

Community
  • 1
  • 1
Herbert Yu
  • 578
  • 6
  • 16
  • MTP is not mounted as a file system and cannot be accessed using those APIs. – SLaks Jul 30 '14 at 00:01
  • @SLaks Is there a way to assign a drive letter to MTP device? Or alternatively: How can I access this MTP device, Any API here? Thanks in advance – Herbert Yu Aug 01 '14 at 06:18
  • Found this URL: https://bitbucket.org/derekwilson/podcastutilities/src/b18a9926c1dcbfb884b34b9865ebaec96abfdb82/PodcastUtilities.PortableDevices/?at=default . And I'll try to use these source codes, to see if I can connect to this phone. – Herbert Yu Aug 01 '14 at 06:23
  • @Herbert did you find a solution to your problem? I am looking for a solution too, if you have, please post it here and mark it as a solution. – IdontCareAboutReputationPoints Jul 29 '15 at 17:03
  • @MusuNaji No, unfortunately. But I found, I can use Windows Explorer to access it even there is no drive letter assigned to my phone. Strange, but worked. – Herbert Yu Aug 11 '15 at 18:37
  • @HerbertYu what is windows explorer? you included a com object that is a browser? – Yogurtu May 31 '18 at 20:26

2 Answers2

9

I used nugetpackage "Media Devices by Ralf Beckers v1.8.0" This made it easy for me to copy my photos from my device to my computer and vice versa.

 public class Program
{
    static void Main(string[] args)
    {
        var devices = MediaDevice.GetDevices();
        using (var device = devices.First(d => d.FriendlyName == "Galaxy Note8"))
        {
            device.Connect();
            var photoDir = device.GetDirectoryInfo(@"\Phone\DCIM\Camera");

            var files = photoDir.EnumerateFiles("*.*", SearchOption.AllDirectories);

            foreach (var file in files)
            {
                MemoryStream memoryStream = new System.IO.MemoryStream();
                device.DownloadFile(file.FullName, memoryStream);
                memoryStream.Position = 0;
                WriteSreamToDisk($@"D:\PHOTOS\{file.Name}", memoryStream);
            }
            device.Disconnect();
        }

    }

    static void WriteSreamToDisk(string filePath, MemoryStream memoryStream)
    {
        using (FileStream file = new FileStream(filePath, FileMode.Create, System.IO.FileAccess.Write))
        {
            byte[] bytes = new byte[memoryStream.Length];
            memoryStream.Read(bytes, 0, (int)memoryStream.Length);
            file.Write(bytes, 0, bytes.Length);
            memoryStream.Close();
        }
    }
}
ZackOfAllTrades
  • 567
  • 5
  • 12
  • MediaDevice.GetDevices() doesnt work anymore it seems this method is not there anymore..... – eMi Sep 23 '22 at 18:08
3

Using ZackOfAllTrades' code, I ran into OutOfMemoryException when invoking MediaDevice.DownloadFile(string, Stream).

[1] Go to project properties, set project to build for x64, that seems to get rid of OutOfMemoryException; I am able to start copying files between 1GB to 2GB without any problems.

[2] However, as soon as I start copying files of 2.5GB the WriteStreamToDisk() util function by ZackOfAllTrades started to complain about Stream too long.

DownloadFile takes a Stream object, it doesn't need to be a MemoryStream so I switched it to a FileStream object :

static void Main(string[] args)
{
    string DeviceNameAsSeenInMyComputer = "Mi Note 10 Pro";

    var devices = MediaDevice.GetDevices();

    using (var device = devices.Where(d => d.FriendlyName == DeviceNameAsSeenInMyComputer || d.Description == DeviceNameAsSeenInMyComputer).First())
    {
        device.Connect();
        var photoDir = device.GetDirectoryInfo(@"\Internal shared storage\DCIM\Camera");
        var files = photoDir.EnumerateFiles("*.*", SearchOption.TopDirectoryOnly);

        foreach (var file in files)
        {
            string destinationFileName = $@"F:\Photo\{file.Name}";
            if (!File.Exists(destinationFileName))
            {
                using (FileStream fs = new FileStream(destinationFileName, FileMode.Create, System.IO.FileAccess.Write))
                {
                    device.DownloadFile(file.FullName, fs);
                }
            }

            
        }
        device.Disconnect();
    }

    Console.WriteLine("Done...");
    Console.ReadLine();
}

Worked beautifully. When I am using ZackOfAllTrades' code, VS profiler shows memory consumption at about 2.5 times the size of file. Eg: if the file is 1.5GB large, the memory consumption is roughly 4GB. But if one is to copy to file system directly, the memory consumption is negligible (<50mb).

The other issue is with MediaDevice.FriendlyName. I know for sure my Xiaomi Note 10 Pro did not support FriendlyName. What worked for me is MediaDevice.Description.

user4157124
  • 2,809
  • 13
  • 27
  • 42
Ji_in_coding
  • 1,691
  • 1
  • 14
  • 17