I am using the media plugin for xamarin forms (by james montemagno) and the actual taking of the picture and storing it works fine, I have debugged the creation of the image on the emulator and it is stored in
/storage/emulated/0/Android/data/{APPNAME}.Android/files/Pictures/{DIRECTORYNAME}/{IMAGENAME}
however in my app it will get a list of file names from an API I want to check if the image exists in that folder.
The following works fine on IOS
var documentsDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
string jpgFilename = System.IO.Path.Combine(documentsDirectory, App.IMAGE_FOLDER_NAME);
jpgFilename = System.IO.Path.Combine(jpgFilename, name);
I have tried the 2 following methods for getting it on android but both are incorrect
var documentsDirectory = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal);
string jpgFilename = System.IO.Path.Combine(documentsDirectory, App.IMAGE_FOLDER_NAME);
jpgFilename = System.IO.Path.Combine(jpgFilename, name);
Java.IO.File dir = Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DataDirectory + "/" + App.IMAGE_FOLDER_NAME + "/" + name);
dir ends up as
/storage/emulated/0/data/{DIRECTORY}/{IMAGENAME}
jpgFileName ends up as /data/data/{APPNAME}.Android/files/{DIRECTORYNAME}/{IMAGENAME}
I dont want to hardcode anything in the paths but neither of these are right. I could not find anything in the GIT documentation for getting the file path except by looking at the path of the file created when taking a picture
The problem
I had the same kind of issue with Xamarin Media Plugin. For me, the problem is:
we don't really know where the plugin save the picture on android.
After reading all documentation I found, I just noted this:
... When your user takes a photo it will still store temporary data, but also if needed make a copy to the public gallery (based on platform). In the MediaFile you will now see a AlbumPath that you can query as well.
(from: Github plugin page)
so you can save your photo to your phone gallery (it will be public) but the path is known.
and we don't know what means "store the temporary data".
Solution
After investigating on how/where an app can store data, I found where the plugin stores photos on Android >> so I can generate back the full file names
In your Android app, the base path you are looking for is:
var basePath = Android.App.Application.Context.GetExternalFilesDir(null).AbsolutePath
It references your app's external private folder. It looks like that:
/storage/emulated/0/Android/data/com.mycompany.myapp/files
So finally to get your full file's path:
var fullPath = basePath + {DIRECTORYNAME} + {FILENAME};
I suggest you to make a dependency service, for instance 'ILocalFileService', that will expose this 'base path' property.
Please let me know if it works for you !
I resolved a similar problem. I wanted to collect all files for my app in a folder visible to all users.
var documentsDirectory = Android.OS.Environment.GetExternalStoragePublicDirectory(
Android.OS.Environment.DirectoryDocuments);
If you want to create Directory, add to your class using System.IO; and you have the same functions in a normal .NET application.
if (!Directory.Exists(path))
Directory.CreateDirectory(path);
If you want to create files or directory, you can use PCLStorage.
public async Task<bool> CreateFileAsync(string name, string context)
{
// get hold of the file system
IFolder folder = FileSystem.Current.LocalStorage;
// create a file, overwriting any existing file
IFile file = await folder.CreateFileAsync(name,
CreationCollisionOption.ReplaceExisting);
// populate the file with some text
await file.WriteAllTextAsync(context);
return true;
}
to get the private path
var privatePath = file.Path;
to get the public Album path
var publicAlbumPath = file.AlbumPath;
se the documentation here https://github.com/jamesmontemagno/MediaPlugin
Related
public void Save_Token(string _Token)
{
var Token_Location = #".\token.txt";
using (StreamWriter sw = new StreamWriter(Token_Location))
{
sw.WriteLine(_Token);
}
}
I tried to get the token from the api (json) and I deserialized and saved it. I would like to write to the file to save for later. But I want this application to be ran on anyone's PC. So I don't want to use the full path.
I also tried
Path.Combine(Environment.CurrentDirectory,Token_Location);
still nothing is written, unless I use the full path.
You can't guarantee that the current user has write access to the folder from where the file is executed. There is a special folder (APP_DATA) that applications are supposed to use when storing user data on a computer:
public void Save_Token(string _Token)
{
var tokenDirectory = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "YourCompanyOrOrganizationName");
var tokenFile = Path.Combine(tokenDirectory, "token.txt");
Directory.CreateDirectory(tokenDirectory);
File.WriteAllText(tokenFile, _Token);
}
Your file will then be stored in a path like "C:\Users\yourusername\AppData\Roaming\YourCompanyOrOrganizationName\token.txt"
It is generally a bad idea to use a relative path in software source code because the "current working directory" of the process that the relative path is relative to can change over the runtime of the application.
Activities like showing a file open dialog or using a third-party component can unexpectedly change the current working directory so that it is dangerous to assume a certain current working directory.
I need to play video from sdcard on VideoView and always getting "Can't play this video message". I am testing on physical device. File is on external storage, and can be played by build in phone apps with no problem.
I have read some topics before and tried changing file format and resolution with no effect.
Second guess was path to the file so tried to change it multiple times in many variants using Android.OS.Environment.ExternalStorageDirectory.AbsolutePath, creating File variable and getting path from File.Path.
Got the TextView where I put path every time and it is always correct.
I have no idea why it does not work.
Code:
Java.IO.File file = new Java.IO.File (Android.OS.Environment.ExternalStorageDirectory.AbsolutePath + "/myimage/", "video.mp4");
tView.Text = file.Path;
MediaController mediaController = new MediaController(context: this);
vView.SetMediaController(mediaController);
mediaController.SetAnchorView(vView);
vView.SetVideoPath(file.Path);
vView.Start();
File.Path value:
"/storage/emulated/0/myimage/video.mp4"
EDIT: I have created "raw" folder in resource putted file there and then used following path:
vView.SetVideoPath("android.resource://" + PackageName + "/" + Resource.Raw.video);
It works, but if anyone know how to get the proper path to folder on sdCard?
Finally I figured it out. The problem was that my phone mounted card at path /storage/xxxx-xxxx/ my research revealed that the dir's name come from volume serial number(where android automatically mount card) and ExternalStorageDirectory refers to other locations in each android device. Sometimes it's internal sometimes usb mass storage.
Anyway didn't manage to find any method that returns the path so created following method:
string GetCardMountPoint()
{
string[] listOfDirs = Directory.GetDirectories("/storage/");
string path = null;
foreach ( string dir in listOfDirs)
{
if(dir.Contains('-'))
{
path = dir;
}
}
return path;
It's not much of sophisticated solution but it works for now.
I am trying to read a text file named thedata.txt that has a list of words that I want to use in a hangman game. I have tried different ways, but I can't figure out where the file gets placed, if at all when the app runs. I added the file to my project, and I have tried setting the build properties to content, and then embedded resource, but can't find the file. I have made a Windows 10 universal app project. The code I tried looks like this:
Stream stream = this.GetType().GetTypeInfo().Assembly.GetManifestResourceStream("thedata.txt");
using (StreamReader inputStream = new StreamReader(stream))
{
while (inputStream.Peek() >= 0)
{
Debug.WriteLine("the line is ", inputStream.ReadLine());
}
}
I get exceptions.
I also tried to list the files in another directory:
string path = Windows.Storage.ApplicationData.Current.LocalFolder.Path;
Debug.WriteLine("The path is " + path);
IReadOnlyCollection<StorageFile> files = await Windows.Storage.ApplicationData.Current.LocalFolder.GetFilesAsync();
foreach (StorageFile file2 in files)
{
Debug.WriteLine("Name 2 is " + file2.Name + ", " + file2.DateCreated);
}
I don't see the file there either...I want to avoid hard coding the list of names in my program. I'm not sure what the path that the file is placed.
the code is very simple, you just have to use a valid scheme URI (ms-appx in your case) and transform your WinRT InputStream as a classic .NET stream :
var file = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///thedata.txt"));
using (var inputStream = await file.OpenReadAsync())
using (var classicStream = inputStream.AsStreamForRead())
using (var streamReader = new StreamReader(classicStream))
{
while (streamReader.Peek() >= 0)
{
Debug.WriteLine(string.Format("the line is {0}", streamReader.ReadLine()));
}
}
For the properties of the embedded file, "Build Action" must be set to "Content" and "Copy to Ouput Directory" should be set to "Do not Copy".
You can't use classic .NET IO methods in Windows Runtime apps, the proper way to read a text file in UWP is:
var file = await ApplicationData.Current.LocalFolder.GetFileAsync("data.txt");
var lines = await FileIO.ReadLinesAsync(file);
Also, you don't need a physical path of a folder - from msdn :
Don't rely on this property to access a folder, because a file system
path is not available for some folders. For example, in the following
cases, the folder may not have a file system path, or the file system
path may not be available. •The folder represents a container for a
group of files (for example, the return value from some overloads of
the GetFoldersAsync method) instead of an actual folder in the file
system. •The folder is backed by a URI. •The folder was picked by
using a file picker.
Please refer File access permissions for more details.
And Create, write, and read a file provides examples related with File IO for UWP apps on Windows 10.
You can retrieve a file directly from your app's local folder by using an app URI, like this:
using Windows.Storage;
StorageFile file = await StorageFile.GetFileFromApplicationUriAsync("ms-appdata:///local/file.txt");
The situation is like this:
I am modifying someone's code to download an image file from a shared path. So the person hardcoded the piece of code to be #"\\" + local_path
Since the call is expected to go and download from the shared path \\network\bla\bla\bla, it is fine to get hardcode in this way.
Now my problem come in, I actually need to modify some other parts and test it out in playback mode before I deliver this for actual use. However, my work guideline is not to delete away the #"\\" appended. Because, without the #"\\" the path would not link to the share directory and this changed .dll could not be used for actual activity.
Yet with this, if I were to use playback, the file path will now be \\C:\temp\Images, which will be wrong. My problem now is, how to maintain the ability of the code to link to share path and at the same time create a path local so that the code can reference to.
The UNC path \\localhost\C$\ will access the drive C: on your local computer.
The easiest solution is to simply provide a flag which indicates the type of path you want to create e.g.
public string BuildPath(bool isUnc, params string[] pathParts)
{
var path = Path.Combine(pathParts);
return isUnc ? #"\\" + path : path;
}
...
var uncPath = BuildPath(isUnc: true, "network", "bla", "bla", "bla");
var localPath = BuildPath(isUnc: false, #"C:\", "temp", "images");
In my app I have a WebBrowser element.
I would like to load a local file in it.
I have some questions:
Where to place the HTML file (so that it will also be installed if a user executes the setup)
how to reference the file? (e.g. my guess is the user's installation folder would not always be the same)
EDIT
I've added the HTML file to my project.
And I have set it up so that it gets copied to output folder.
When I check it it is present when run: \bin\Debug\Documentation\index.html
However when I do the following I get a 'Page cannot be displayed' error in the webbrowser element.
I use the following code to try to display the HTML file in the Webbrowser.
webBrowser1.Navigate(#".\Documentation\index.html");
Do a right click->properties on the file in Visual Studio.
Set the Copy to Output Directory to Copy always.
Then you will be able to reference your files by using a path such as #".\my_html.html"
Copy to Output Directory will put the file in the same folder as your binary dlls when the project is built. This works with any content file, even if its in a sub folder.
If you use a sub folder, that too will be copied in to the bin folder so your path would then be #".\my_subfolder\my_html.html"
In order to create a URI you can use locally (instead of served via the web), you'll need to use the file protocol, using the base directory of your binary - note: this will only work if you set the Copy to Ouptut Directory as above or the path will not be correct.
This is what you need:
string curDir = Directory.GetCurrentDirectory();
this.webBrowser1.Url = new Uri(String.Format("file:///{0}/my_html.html", curDir));
You'll have to change the variables and names of course.
quite late but it's the first hit i found from google
Instead of using the current directory or getting the assembly, just use the Application.ExecutablePath property:
//using System.IO;
string applicationDirectory = Path.GetDirectoryName(Application.ExecutablePath);
string myFile = Path.Combine(applicationDirectory, "Sample.html");
webMain.Url = new Uri("file:///" + myFile);
Note that the file:/// scheme does not work on the compact framework, at least it doesn't with 5.0.
You will need to use the following:
string appDir = Path.GetDirectoryName(
Assembly.GetExecutingAssembly().GetName().CodeBase);
webBrowser1.Url = new Uri(Path.Combine(appDir, #"Documentation\index.html"));
Place it in the Applications setup folder or in a separte folder beneath
Reference it relative to the current directory when your app runs.
Somewhere, nearby the assembly you're going to run.
Use reflection to get path to your executing assembly, then do some magic to locate your HTML file.
Like this:
var myAssembly = System.Reflection.Assembly.GetEntryAssembly();
var myAssemblyLocation = System.IO.Path.GetDirectoryName(a.Location);
var myHtmlPath = Path.Combine(myAssemblyLocation, "my.html");
What worked for me was
<WebBrowser Source="pack://siteoforigin:,,,/StartPage.html" />
from here. I copied StartPage.html to the same output directory as the xaml-file and it loaded it from that relative path.
Windows 10 uwp application.
Try this:
webview.Navigate(new Uri("ms-appx-web:///index.html"));
Update on #ghostJago answer above
for me it worked as the following lines in VS2017
string curDir = Directory.GetCurrentDirectory();
this.webBrowser1.Navigate(new Uri(String.Format("file:///{0}/my_html.html", curDir)));
I have been trying different answers from here, but managed to derive something working, here it is:
1- Added the page in a folder i created at project level named WebPagesHelper
2- To have the page printed by webBrowser Control,
string curDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().GetName().CodeBase);
var uri = new Uri(curDirectory);
string myFile = Path.Combine(uri.AbsolutePath, #"WebPagesHelper\index.html");
Uri new_uri = new Uri(myFile);
i had to get the assembly path, create a first uri to get an absolute path without the 'file://' attached, next i combined this absolute path with a relative path to the page in its folder, then made another URI from the result.
Then pass this to webBrowser URL property webBrowser.URL = new_uri;