I am trying to implement a very simple function in NET MAUI, however I am not able to do it. I have an excel file that I want to deploy as a resource on the target device and read later in the application.
In Windows App I can do this very easily by setting the Excel file as content and activating copy.
How does this work on Android? In some posts I have read that one should proceed as follows, yet it does not work:
you open .csproj and define there.
<ItemGroup>
<MauiAsset Include="Resources\Assets\*" />
</ItemGroup>
then create a new folder Assets in the project under Platforms -> Android -> Resources and place the Excel file Info.xlsx there.
set the build process for excel file as MauiAsset. I have also activated the copy here.
Now I read the Excel file in the program via the OpenXml library:
using (SpreadsheetDocument spreadSheetDocument = SpreadsheetDocument.Open(fileName, false))
I set the location of the file using:
string mainDir = FileSystem.Current.AppDataDirectory;
var fullpath = Path.Combine(mainDir, #"Info.xlsx");
When running, the debug reports that the file does not exist. If you check the data -> com.company... folder on the Android device, you will see only cash and no other folder!
By the way I tried something before and found out that you can't create folders on an Android device via MAUI, so I wasn't very surprised here when I only saw cash folders.
Am I doing something fundamentally wrong or is it MAUI bug? You read in some places already that MAUI is not redy for use and even worse that even basic things do not work.
I hope someone has an idea what is going on here.
Thanks
pcsasa
EDIT:
So, I've been working on the problem of reading a simple text file for a couple of hours now, and it's been without result.
In summary:
I noticed that Visual Studio also has a Resources folder in the project and a Raw folder under it. I now also have the same structure under Platforms -> Android then Resources -> Raw because I don't know where the app is looking.
in the folder I then placed an usual text file and set build to MauiAsset
then I used from MAUI doc the code to read "Bundled files":
public async Task<string> ReadTextFile(string filePath)
{
using Stream fileStream = await FileSystem.Current.OpenAppPackageFileAsync(filePath);
using StreamReader reader = new StreamReader(fileStream);
return await reader.ReadToEndAsync();
}
once I specified plain text file as filePath and when that didn't work, I also supplied the path:
var fullpath = Path.Combine(#"Resources/Raw", #"AboutAssets.txt");
...but that doesn't work either!
The thing that surprises me the most is that there is no error message, but the string set is equal to "" (so not even null).
I really can't imagine that no one has included a file in the project until now to read it out in the application (e.g. image, settings, texts, Excel, etc.)? I wonder because there is really nothing in the MAUI documentation that describes how to read a file on an Android device except this "File system helpers" post. You can not find even in forums this question that I asked?
Is the mistake somewhere with me and I ask stupid questions, or do I try here something what does not go at all, because MAUI has a fundamental error in itself?
If my intention cannot be implemented in MAUI (i.e. simply include the file in the project and read it out on the target device), then that is a criterion for exclusion from using MAUI.
Thanks
pcsasa
To read a plain text file in Andriod, you could drag a TextFile.txt to Project/Resources/Raw folder and set its Build Action to MauiAsset.
You could check in the *.csproj file, please remove the following code if it exists
<ItemGroup>
<None Remove="Resources\Raw\TextFile.txt" />
</ItemGroup>
<ItemGroup>
<BundleResource Include="Resources\Raw\TextFile.txt" />
</ItemGroup>
Then you could try reading the string in text file like this:
using var stream = await FileSystem.OpenAppPackageFileAsync("FileText.txt");
using var reader = new StreamReader(stream);
var contents = reader.ReadToEnd();
Console.WriteLine(contents);
Hope it works for you.
Thanks Liqun Shen-MSFT
Since I have lost a lot of time and there are probably still people who have or will have the same problem, here again resumed how to include a resource (text or Excel) via NET MAUI and read out on the target device (eg an Android Phone) and use in the program:
if one, like me, has entered an entry to the resource in cproj, delete it !
in the project under Project/Resources/Raw insert the required resource (I tried it only with text and Excel) and set Build Action to MauiAsset.
the readout is done with the code :
using var stream = await FileSystem.OpenAppPackageFileAsync("FileText.txt");
using var reader = new StreamReader(stream);
var contents = reader.ReadToEnd();
Console.WriteLine(contents);
...or if you want to read an Excel file via OpenXml, then you pass the stream to the function:
using (SpreadsheetDocument spreadSheetDocument =
SpreadsheetDocument.Open(stream, false))
So this worked very well in the Android emulator as well as on a physical device (Android Phone). If it works on the iPhone I couldn't try it, but I would be very happy if someone could check it and write something here.
Thanks for the help.
Related
I have a form that will accept and save a MP4 video file. I need to be able to get the dimensions of the video as well. This will be running on a server running ASP.NET 2.0 so any external libs must be able to be placed in the Bin folder as they can not be installed on the server.
Any ideas how to get the information? If the same lib would let me transcode the video to flv that would be a huge bonus.
Update: The server is XP Service Pack 2 with .NET Framework (2,0,50727,0)
There are a few ways to do this, but no library per-se that will work with C# for any/all .mp4 video files. That is nothing that is 100% reliable.
Both are command line options (in a sense). Basically, what you'd be doing is running a process from your ASP.NET application using System.Diagnostics.Process.
On of them is to use ffmpeg. With ffmpeg if you just give it a file (as a command line argument if will return various metadata about the file. This information can be parsed to extract the dimensions.
The other is to use MediaInfo. It's a great tool for this. But again, you'll have to use the Command line version (CLI version) and pretty much give it the file name as a command line argument. It has an otion to produce and xml response so you can easily parse this and other information if can provide.
ffmpeg can transcode your video as well. Though I don't see the point of transcoding from mp4. flv?
Alturos.VideoInfo is a wrapper for ffprobe that makes it rather easy to integrate into a C# project.
It can be installed from NuGet like this:
PM> Install-Package Alturos.VideoInfo
To use it, you need ffprobe.exe. If it's not in your project already, you can run this code to download it:
var ffmpegDownloader = new FileDownloader();
var ffmpegUrl = ffmpegDownloader.GetFfmpegPackageUrl();
var ffmpegDownloadResult = await ffmpegDownloader.DownloadAsync(ffmpegUrl, #"ffprobe\ffprobe.exe");
var ffprobePath = ffmpegDownloadResult.FfprobePath;
The dimensions of the video can then easily be retrieved by getting the video stream:
var videoAnalyzer = new VideoAnalyzer(ffprobePath);
var analyzeResult = videoAnalyzer.GetVideoInfo(/* your video file path here */);
if (analyzeResult.Successful)
{
var videoStream = analyzeResult.VideoInfo.Streams.Single(o => o.CodecType == "video");
var width = videoStream.Width;
var height = videoStream.Height;
}
I've a text file and I want to reach it from a shared code project. I want it to work for Android, iOS and Windows Phone. What would be the best approach and where should I put the text file?
You can use the following plugin to reach it: https://github.com/dsplaisted/PCLStorage
For more information about where to put it and build settings take a look at this: https://developer.xamarin.com/guides/xamarin-forms/working-with/files/
Since a shared project gets compiled into the native project you will need to place it there (copy the file to the Android, iOS & Windows Phone project). Now you have to access it from your shared project by using reflection like this:
var assembly = GetType().GetTypeInfo().Assembly;
using (var stream = assembly.GetManifestResourceStream("YourNativeAssembly.FolderYouPutTheFileIn.filename.txt"))
using (var reader = new StreamReader(stream))
{
string contents = reader.ReadToEnd();
}
Do note that the file you just added should be a EmbeddedResource!
If you want to target multiple platforms you would probably have to change the 'YourNativeAssembly' based on the platform (or name every native assembly the same). To do that see this documentation.
I have a windows form application that in a certain moment (on a click event), save data to a xml file. This xml file will be used when application start again (I check if the file exists). In debug/release mode works perfectly but when I use the exe version (the version that gonna be used in others computers), the app can't start.
I can see the file that was created in my computer (AppData/Local...).
In my code, the file is save it into the Debug/Release folder.
if (System.IO.File.Exists("recover.xml"))
{
LoadXML();
}
And I save it
XmlSerializer xmlSerializer = new XmlSerializer(typeof(ConsoleData));
StreamWriter myWriter = new StreamWriter( "recover.xml" );
xmlSerializer.Serialize(myWriter, data);
myWriter.Close();
Where the problem could come?
Thanks.
Well, I 've analyzed the situation and searching any problem in my source but I realized that the way that I was using the xml file (load and save) was correct. So, I started to search line by line after load data from the xml and I saw that the problem was in other site. The result from the xml was correctly.
I apologize, this question was wrong.
I'll check things better next time.
I am working on a simple landing page for a project that is sheduled to release in a couple of months. People can use a form to sign up to be notified on release. Currently the form simply generates an email saying "email adresse foo#bar.com wants to be notified on release" and sends it to me.
Now I want to save the data from the form into a simple text file so I can more easily feed it to my email programm later. In Visual Studio I created a new folder in my project named "subscriptions" and in that folder created an emptry text file release_notification_emails.txt". I tried using the StreamWriter to write to the file, but it failed. Here is my code:
using (StreamWriter writer = new StreamWriter("/subscriptions/release_notification_emails.txt", true))
{
writer.WriteLine(eMail);
}
It results in the following exception/error
Could not find a part of the path 'C:\subscriptions\release_notification_emails.txt'.
So it looks like it treats the path parameter of the StreamWriter as relative to the file system root instead of the project root, which is problematic. I use paths relative to the project root all the time to include images, scripts, views, etc. It seemed to me that this was the standard way asp.net does this (I AM very new to asp.net though, you can probably tell).
So my question ow is: How can I write to a text file that is within my project/solution file tree? It doesn't have to use the StreamWriter I just want it to work. It needs to be within the project file tree so that it will be tracked by out version management system and colleagues working on the project have the same file.
You need to add Server.MapPath to get the physical path.
new StreamWriter(Server.MapPath("/subscriptions/release_notification_emails.txt"), true)
I have a Silverlight 4 / C# project I'm working on in Visual Studio. I made an XML data file by right clicking on the project >> Add New Item >> Xml File. I then try to open the file:
StreamReader streamReader = new StreamReader("data.xml");
However, this gives a security exception. How can I get around this, or grant the necessary permissions?
Silverlight doesn't allow local file system access by default. Your options are:
Using IsolatedStorage.
Run with elevated permissions.
Embedding the file in the assembly, if you only need to read it, as suggested by Jon Skeet.
If you need to store data in general, use IsolatedStorage if you can.
You would need to mark the item as a resource, NOT an embedded resource.
From MSDN...
The Properties window in Visual Studio
provides several other values in the
Build Action drop-down list. However,
you can use only the previous three
values with Silverlight projects. In
particular, Silverlight embedded
resources must always use the Resource
build action, and not the Embedded
Resource build action, which uses a
format that Silverlight cannot
recognize.
A great walk through can be seen here entailing what you are trying to accomplish. Since you are not trying to access files on disk but as resources this is not a problem. IsolatedStorage nor elevated permissions are pertinent here.
Do you just need to be able to read the file at execution time? If so, I would suggest you set it to have a Resource build action in Visual Studio, and then use Assembly.GetManifestResourceStream to open it. That's the simplest way of bundling read-only data with an application, IMO.
That constructor of StreamReader is expecting a file path into the local file system, which is only available out of browser with elevated trust.
Instead you should be using Application.GetResourceStream:-
Stream stream = Application.GetResourceStream(new Uri("data.xml", UriKind.Relative));
StreamReader reader = new StreamReader(stream);
However I expect you really just want this in an XDocument, you bypass this StreamReader stage:-
XDocument doc = XDocument.Load(stream);
BTW, I personally would leave the XML as Content in the Xap rather than embedding it in the assembly.