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.
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();
}
}
}
This question definitely help me! I was trying to write a simple program to auto sync my photos/videos from an android device to my computer. Hence I ended up asking the same question as Herbert Yu, how do I access the device path when there are no drive letters?
ZackOfAllTrades' answer helped me. Thumbs up!
I copied ZackOfAllTrades' code, tweaked it to my needs and Bang! it worked, but not for long. I have a 108MP camera on my Xiaomi Note 10 Pro, 4 minutes videos can easily go past 1GB; some of my videos are 4GBs large. using ZackOfAllTrades' code, I quickly ran into OutOfMemoryException when invoking MediaDevice.DownloadFile(string, Stream).
[1] My initial attempt at fixing this is to go to project properties, set my 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 large, the WriteStreamToDisk() util function written by ZackOfAllTrades started to complain about Stream too long.
Then I realized that DownloadFile takes a Stream object, it doesn't need to be a MemoryStream as Zack has used. So I switched it to a FileStream object as follow
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 issues is with MediaDevice.FriendlyName. In ZackOfAllTrades' example, he is using a Samsung, and I am guessing Samsung phones supported this property. I did not bother digging out my old Samsung to try this out. I know for sure my Xiaomi Note 10 Pro did not support FriendlyName, instead what worked for me is MediaDevice.Description
Hope this helps others who are asking the same question.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With