Get a known folder in Xamarin Android - c#

I'm developing an Android application for my thesis with Xamarin. I need to export a file in a folder I can access via my PC, doesn't matter what (Documents, Pictures, Music).
I'm using this code to get the folders' path:
Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
In the manifest, I've included these permissions:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
Substituting MyDocuments with the others enum, I get these paths:
Folder MyDocuments: /data/data/MagMapTimeDroid.MagMapTimeDroid/files
Folder MyMusic: /data/data/MagMapTimeDroid.MagMapTimeDroid/files/Music
Folder MyPictures: /data/data/MagMapTimeDroid.MagMapTimeDroid/files/Pictures
Folder CommonDocuments: /* EMPTY STRING */
Folder CommonPictures: /* EMPTY STRING */
Folder ApplicationData: /data/data/MagMapTimeDroid.MagMapTimeDroid/files/.config
Folder Desktop: /data/data/MagMapTimeDroid.MagMapTimeDroid/files/Desktop
No one of these paths is accessible via pc. I'm using a Galaxy Tab 2 (7") with CyanogenMod and Android 5.1.1.
So, the question is: how can I access a public folder in order to write the file and get it from pc?
Thank you,
Luca

So, the question is: how can I access a public folder in order to write the file and get it from pc?
You can use the DDMS tool to get the file from your android device and then pull the file from the android device to your PC, after you complete to write this file from PC, you can then push this file again to the device.
To use DDMS tool with VS2015, you can open your android project with VS2015 and click the icon to Open Android Device Monitor(DDMS):
Then if your android device is already connected to PC, you can find it in the Devices List on the left side of DDMS, select this device, then on the right side, go to the table File Explorer, and find your app which should be installed in this android device:
In the files folder, you should be able to find your file.
To pull and push the files, you can click the buttons here:

To get one of the known or 'public' folders you have to use the external storage directory environment strings.
The example below saves to the public "My Documents" folder of a samsung s6.
public void Save(string filename, string data)
{
var docPath = Android.OS.Environment.ExternalStorageDirectory.AbsolutePath;
docPath = Path.Combine(docPath, "My Documents");
var filepath = Path.Combine(docPath, filename);
System.IO.File.WriteAllText(filepath, data);
}
When you look at the string returned by the Android.OS.Environment.ExternalStorageDirectory.AbsolutePath it may look funny but it is actually getting the root public folder of the device, I then add the my documents folder to it and then append the filename to the end.
Let me know if this does not work for you.

Related

C# shell.NameSpace does not find the folder on an external device

I have the following problem:
I am using the Shell32 library to be able to access files even on external devices such as my android phone. Getting a local folder and the Phone itself works, but not the folder on the phone. My current code to get a folder (found the solution here):
Shell shell = new Shell();
Folder folder = shell.BrowseForFolder((int)Hwnd, "Choose Folder", 0, 0);
if (folder != null) {
FolderItem fi = (folder as Folder3).Self;
string path = fi.Path;
//...
}
And later I am trying to get the Folder again by using:
Folder folder = shell.NameSpace(path);
which works fine for all local files and the phone itself, but not for the directories on the phone.
The path for a local directory looks like a normal path: "D:\\Bilder\\Bretagne 2016",
the one for the phone:
"::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\\\\\?\\usb#vid_04e8&pid_6860&ms_comp_mtp&samsung_android#6&2a1f2d33&0&0000#{6ac27878-a6fa-4155-ba85-f98f491d4f33}",
which is some identifier, but works and then for a specific directory on my phone:
"::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\\\\\?\\usb#vid_04e8&pid_6860&ms_comp_mtp&samsung_android#6&2a1f2d33&0&0000#{6ac27878-a6fa-4155-ba85-f98f491d4f33}\\SID-{10001,SECZ9519043CHOHB,114301988864}\\{E398106A-CD20-9A9C-490B-5079C2D70B84}"
with this path I just get a null object when calling shell.NameSpace(path);
Has anyone an idea what I am doing wrong? Have absolutely no idea how to fix this.
Thanks in advance,
Finn
So, found an interesting workaround.
To get a folder on my phone, I can just join the id/path I get from selecting the phone in the BrowseForFolder dialog and the human readable path like this:
::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\\\\\?\\usb#vid_04e8&pid_6860&ms_comp_mtp&samsung_android#6&2a1f2d33&0&0000#{6ac27878-a6fa-4155-ba85-f98f491d4f33}\\Phone\DCIM\Camera and everything works fine.
Not really an idea why the path you get from Folder.path does not work, but this does. As long as there is no other solution this works at least.

C# ClickOnce Deployment Mapping Back to My Desktop Drive

I created a WinForms application that includes code to find the user's desktop and perform 3 tasks:
1. Create a folder
2. Read a .csv file
3. Output some data to a .csv file on the desktop.
I'm using the code below to find the user's desktop
string desktop = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
I used the ClickOnce deployment to install the program to our network drive. The program installs successfully, but Whenever I have someone attempt to run the program from their terminal, they get an error message that states "The directory name is invalid" and it references my desktop and not the user's.
How should I change my code or the deployment method so it references the user's desktop?
If directory invalid try creating it
Try with this code
string filePath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
string extension = ".log"; filePath += #"\Error Log\" + extension;
if (!Directory.Exists(filePath)) {
Directory.CreateDirectory(filePath);
}
I made the following change to my code and it worked as needed:
string desktop = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory);

Setting image source to application folder

I'm trying to get an image from a certain path, but the path must only be referenced from the application's current folder and not from the Local C: drive.
My reason for this is because the application is going to get published soon and I can't reference the image to the same local location on my current PC, because the application is going to be used on a lot of other PC's and the path would not work on other someone else's computer.
This is the current path that works:
SetDefaultImage(new Binary(File.ReadAllBytes("C:\\Users\\mclaasse\\Desktop\\Haze Update\\Haze\\Haze\\Icons\\user6.jpg")));
And this is how I need it to be:
SetDefaultImage(new Binary(File.ReadAllBytes("Haze\\Icons\\user6.jpg")));
But i'm getting the error:
Could not find a part of the path 'C:\Haze\Icons\user6.jpg'.
Is there a simple work around for getting my path to work?
Not sure if this is exactly what you need, but provided that you have an image file user6.jpg in your Visual Studio project in a project folder named Images, and the Build Action of the image file is set to Resource, you could simply load it from a Resource File Pack URI:
var image = new BitmapImage(new Uri("pack://application:,,,/Images/user6.jpg"));
None of the references worked for me(I don't know why), but this worked:
string directory = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
string filePath = Path.Combine(directory, "Icons\\user6.jpg");
Then check if the file that you are looking for exists:
if (!File.Exists(filePath))
{
MessageBox.Show("The default image does not exist", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
}
else
{
...
}

Cannot create files on Android with Xamarin

I have a Xamarin-Studio App for Android and I simply want to download files and save them locally. But when I try to create a file in the files folder I get an exception:
File.Create("data/data/com.company.app/files/newFile.png");
gives me:
System.UnauthorizedAccessException
Access to the path 'data/data/com.company.app/files/newFile.png' is denied.
What am I doing wrong?
You should use Environment or IsolatedStorage. For example:
var path = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
var filename = Path.Combine(path, "newFile.png");
I am coding Xamarin with VS2013. I had the access denied error for a directory created with the application I am writing. My application creates a directory called /storage/emulated/0/POIApp by concatenating via:
System.IO.Path.Combine(Android.OS.Environment.ExternalStorageDirectory.Path, "POIApp");
I found that I had to use VS2013 to edit the "properties" of my application (POIApp), i.e., right-click the project icon in the solution explorer; choose properties from the pop-up menu. A new tab appears in the main VS2013 window. On the left there are a few choices, e.g., Application, Android Manifest, Android Options, Build, etc. Choose "Android Manifest". At the bottom of the main panel is a section "required permissions". My problem was solved when I checked "READ_EXTERNAL_STORAGE" and "WRITE_EXTERNAL_STORAGE".
Add the following permission to Android.Manifest file
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
I finally realized that File.create() was not the problem. I had code like this:
string tmpFilePath = FilesDir.AbsolutePath.stringByAppendingPath (f.Path);
Java.IO.File tmpFile = new Java.IO.File( tmpFilePath);
tmpFile.Mkdirs ();
Yet, Mkdirs() does not only create all intermediate directories – as I had assumed – but also creates a directory at the file path itself. So the file could not be created because there already was a directory with the same name.
The correct way is:
string tmpFile = FilesDir.AbsolutePath.stringByAppendingPath (f.Path);
Java.IO.File tmpParentFolder = new Java.IO.File(tmpFile).getParentFile();
tmpParentFolder.Mkdirs ();
In my defense, an FileExistsAndIsDirectory exception would have been much more helpful than the UnauthorizedAccessException
Using Mono, I think must be the same as in Xamarin Studio.
var path = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
File.Create(path + "newFile.png");

UnauthorizedAccessException when downloading a file using the TFS SDK

When I try to download a file from TFS version control SDK to my computer I receive an 'UnauthorizedAccessException' saying Access to the local path I'm trying to download to is denied. I included a stripped down version of the code I am using below.
var projectCollection = GetProjectCollection();
var versionControl = (VersionControlServer)projectCollection.GetService(typeof(VersionControlServer));
versionControl.DownloadFile('$/path to file', 'local path to download to');
Does anyone know how to resolve this issue?
I found the issue.
The second argument in DownloadFile() needs to be the file name it will be downloaded as and not the parent directory it will be placed in. I thought it just needed the directory name.
So instead of what I originally had
versionControl.DownloadFile("$/Readme.txt", "C:\\Temp");
it needs to be
versionControl.DownloadFile("$/Readme.txt", "C:\\Temp\\Readme.txt");
This is because the process does not have rights to the local path. Make sure the local path has the appropriate right set to the user that is running the process.

Categories