Reputation: 2327
I would like to create a public file on my android phone which I can find without root access. Somewhere where a user can find it and read it.
My current code doesn't give an error in the Visual Studio error list. Only 36 warnings about not able to read files like mono.android.dll with debugging symbols and about not using the declared exception in my FileSaver class. Currently, I don't think it's related. I don't get exceptions. My code comes successfully to the file created alert.
If someone can push me in the right direction or knows the mistakes I am making, I am all ears.
XAML button part
<Button x:Name="CreateFile" />
XAML.CS constructor and on click part
public MyPage ()
{
InitializeComponent ();
CreateFile.Clicked += OnCreateFileClicked;
}
private async void OnCreateFileClicked(object sender, EventArgs e)
{
IFileSaver FileSaver = DependencyService.Get<IFileSaver>();
if (await FileSaver.CreateFile())
{
await this.DisplayAlert("The file is created","Created file","Okay","Okay");
} else
{
await this.DisplayAlert("The file is NOT CREATED", "The file is NOT CREATED", ":(", ";-;");
}
}
Interface
using System.Threading.Tasks;
namespace PvApp
{
/*
* You can't use C# friends File, Directory, Streamwriter etc. (system.io) in the PCL (public class library).
* So we do it in the platform specific libraries.
*/
public interface IFileSaver
{
Task<bool> CreateFile();
}
}
FileSaver class
using System.Threading.Tasks;
using Xamarin.Forms;
using PvApp.Droid.Assets;
[assembly: Dependency(typeof(FileSaver))]
namespace PvApp.Droid.Assets
{
class FileSaver : IFileSaver
{
public async Task<bool> CreateFile()
{
//TRIED: .MyDocuments,
string folder = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal);
string path = System.IO.Path.Combine(folder, "test.txt");
try
{
System.IO.File.Create(path);
return await Task.FromResult(true);
}
catch (System.Exception exception)
{
return await Task.FromResult(false);
}
}
}
}
1:
I saw this video from Xamarin University which showed me I could use some old friends from the System.IO namespace like File, Directory etc. (https://youtu.be/Xrh6ZJcxtZ8 (4:14)).
The video ALSO showed me that they were only accessible in the platform-specific projects (https://youtu.be/Xrh6ZJcxtZ8 (4:35)).
So I created an interface in the PCL library and added a class that implements the interface in my Android platform specific projects assets folder. I put in the code I already had (see above 1: code block). I called the interface in my page on click event handler. The code runs fine and I get my success alert, but I can't find the file on my device.
2:
Questions like these didn't solve the problem for me:
How to use Internal Storage of Android in Xamarin? How to create a file in Android?
3:
I checked if there were permissions needed. Internal storage doesn't need permissions.
4:
I tried other code from websites or StackOverflow questions that should create a file. Application.Context.FilesDir.Path, for example, it didn't help. I couldn't make it work. For the sake of the length of this post, I keep them out.
Tried Riciprinis code:
{System.UnauthorizedAccessException: Access to the path "/test.txt" is denied.
at System.IO.FileStream..ctor (System.String path, System.IO.FileMode mode, System.IO.FileAccess access, System.IO.FileShare share, System.Int32 bufferSize, System.Boolean anonymous, System.IO.FileOptions options) [0x001b7] in <4d6eb5dfe2ab4eee884ef920069afd5f>:0
at System.IO.FileStream..ctor (System.String path, System.IO.FileMode mode, System.IO.FileAccess access, System.IO.FileShare share, System.Int32 bufferSize) [0x00000] in <4d6eb5dfe2ab4eee884ef920069afd5f>:0
at (wrapper remoting-invoke-with-check) System.IO.FileStream..ctor(string,System.IO.FileMode,System.IO.FileAccess,System.IO.FileShare,int)
at System.IO.File.Create (System.String path, System.Int32 bufferSize) [0x00000] in <4d6eb5dfe2ab4eee884ef920069afd5f>:0
at System.IO.File.Create (System.String path) [0x00000] in <4d6eb5dfe2ab4eee884ef920069afd5f>:0
at PvApp.Droid.Assets.FileSaver+<CreateFile>d__0.MoveNext () [0x00058] in (Filepath to my FileSaver.cs and to function System.IO.File.Create(path);)
Tried Riciprinis internal storage permission:
<uses-permission android:name="android.permission.READ_INTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_INTERNAL_STORAGE" />
Breakpoint suggested by Riciprini
If I use Path.Combine without the suggested by Riciprini /
I went in against Riciprinis advice so I ditched the /
and followed Riciprinis advice to change the folder string.
This code did the trick or maybe finished the job (look at the conversation between me and Rciprini in the comments of his answer for more things I have done):
The code below is placed in the CreateFile function from my FileSaver class where the original folder and path where.
string folder = Android.OS.Environment.ExternalStorageDirectory.AbsolutePath;
string path = System.IO.Path.Combine(folder, "test.txt");
Upvotes: 0
Views: 5390
Reputation: 103
Solution:
string folder = Android.OS.Environment.ExternalStorageDirectory.AbsolutePath;
If you want add request runtime permissions , follow this Request Runtime Permissions
Upvotes: 2