I have been searching for almost a day now and this matter is driving me crazy.
I am trying to open a connection to a SQLite DB I push to the device from windows.
The database now is inside this path:
Phone/Android/data/MyApp.Droid/files/MyDB.db3
which can be read without 'Phone/Android' I think.
When I try to make a connection to the DB I can't seem to find the path.
Here's my code for retrieving the path and creating the connection.
public SQLite.SQLiteConnection GetConnection()
{
var sqliteFile = "MyDB.db3";
var dataPath = global::Android.OS.Environment.DataDirectory.AbsolutePath;
var dataPathExtension = #"MyApp.Droid/files";
var destination = Path.Combine(dataPath, dataPathExtension, sqliteFile);
//this outputs the following: /data/MyApp.Droid/files/MyDB.db3
//When I check my phone this is exactly when I can find the file.
return new SQLite.SQliteConnection(destination);
//It can't find the path/file.
}
The DB needs to be in a location I can access from windows without rooting the device.
Can anyone explain to me why it can not find the path/file and if possible tell me how I can read the location?
Note: I cannot access any 'Environment.SpecialFolder' from windows it seems as this gives me a path like: data/user/0/MyApp.Droid/files/
Yours,
I use this implementation:
public SQLiteAsyncConnection GetConnection()
{
var fileName = "DatabaseName.db3";
var documentsPath = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
var path = Path.Combine(documentsPath, fileName);
var connection = new SQLiteAsyncConnection(path);
return connection;
}
Then I'll grab the .db3 file using Android Device Monitor and the File Explorer inside. You can then open that .db3 file with http://sqlitebrowser.org/ or another browser that supports SQLite. Please note: It's easiest on an Emulator as pulling the files from a physical device can be quite cumbersome without root.
Open Tools -> Android -> Android Device Monitor:
Run your Application in Debug mode
Select your Device in the Devices section:
Pull your .db3 file from data/data/com.mypackage.name/files via the Save Icon:
Open the .db3 file in a SQLite browser
Related
The code I have now is:
Intent intent = new Intent();
intent.SetType("text/plain");
intent.SetAction(Intent.ActionGetContent);
StartActivityForResult(Intent.CreateChooser(intent, "Select file"), 1);
string str = System.Environment.GetFolderPath(?????);
That last line of course doesn't work. I'd like the user to be able to browse folders on the device and open one of them. This is simple in Windows but Android is proving difficult.
1/3/2023:
This issue is still unsolved. Coming from Windows and C# this is all trivial. But Android, not.
I have tried these:
var documents = System.Environment.GetFolderPath(System.Environment.SpecialFolder.MyDocuments);
var documents = Path.Combine(Xamarin.Essentials.FileSystem.AppDataDirectory);
var documents = System.Environment.CurrentDirectorygetExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS);
WIth some I can save the file from my app on Android but I cannot find them (non-programmatically).
When I save files in FXTextEdit (on Android), I save them to folders I can easily access. Why not progammatically?
I am coding in C#.
Thanks.
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'm currently developing a Xamarin.iOS App that gets a document from a web service that should then be edited offline on the tablet after being downloaded to the internal storage.
The most common answer was to use the UIDocumentInteractionController. However if I use the UIDocumentInteractionController then I can only create a copy of my original file and open this copy. To get it back into my app I have to make the user select the document from the 'UIDocumentPickerViewController'.
Is there a better way to make the `UIDocumentInteractionController' not create and open a copy of the original, or to at least get the url from the new documentcopy?
Code to open the file:
public void OpenFile()
{
var url = NSUrl.FromFilename(FilePath);
var controller = new UIDocumentInteractionController();
controller.Url = url;
controller.PresentOpenInMenu(table.Frame, table, true);
}
If that is not Possible: Are there different tools or controlls i could use to open and edit a MS-Office file directly?
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 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