How to correctly access existing files in the app data folder created with an Xamarin.Forms app inside a migrated MAUI app? #21438
Replies: 4 comments 7 replies
-
@ewerspej Thanks for bringing this to light. This is a huge migration issue and I'm surprised (or maybe not at this point) that this topic is not getting any attention. Per the guidelines you posted, LocalApplicationData is the appropriate area for an app database. That pathway should not have changed without some sort of HUGE warning that this was happening. |
Beta Was this translation helpful? Give feedback.
-
@ewerspej thanks for raising this issue, I am also facing the same issue as you have mentioned, however what I am observing is when I upgrade the app on a physical device from Xamarin to MAUI.NET, the path /data/user/0/com.myapp.example/files/.local/share/MySQLite.db3 gets wiped off. It does not exists at all. I have added logging and when app starts up post update, the log says path does not exists. I am trying this from VS IDE in development. Moving across git branches first installing the app and adding some data, post that change branch again deploy it on the physical device and on load it logs "Path does not exists". I am on .net-8 and I am stuck what can be done when the whole folder goes away! Others reading this, please advise do you also face this issue where the entire folder simply vanishes. So far I have tried this in Debug mode, I still have to give Release mode a shot, to see if any difference is shown in the process. |
Beta Was this translation helpful? Give feedback.
-
First of all - Thank you @ewerspej so much for the really important information. You increased my lifetime at least for one year ;-) Second (maybe interesting for @gaurav-bagga) - When uploading the release build directly to your device via VS, the old app always gets uninstalled before the new version is installed. When you upload the release build to the play console and let the play store do the update on the android device, the local app data is not removed during the update process. The app gets updated without any data loss (At least in most cases. There can be reasons where the play store decides to remove the old app before installing the new one, but you can test it securely with internal or alpha test tracks). More details now: I had the same problem. My App on play store has not been updated since more than 2 years. In the meanwhile MAUI came up (and kind of stable enough for me) and I decided to migrate everything. After some months of work I came closer to the release date and startet testing. Keeping local app data was not important during development tests but is important for my users because they maintain data over the time and must keep them. Every time when you build a release version and upload it to an Android device with VS, the complete local app data is removed. This is because on Release configuration MAUI/Visual Studio uninstalls the old app before installing the new version (independent from the setting in the Xamarin options dialog). This makes update testing more difficult. I then uploaded the release build to an internal test track on play console and tried it. This was the point where 'my heart slid into my trousers' (like we germans say). I was not aware of that the path to the local app data was changed and I couldn't test it anymore. I implemented the workaround from @ewerspej and run the play console update test again. And now it works. To share my experience. Here is my procedure in the case you already have an app on play store (build with Xamarin) and you want to test (the update) that was build with MAUI:
I implemented a migration code (thanks to ewerspej) that takes over the old local app data (a SQLite database) into the new folder structure and invalidates the old data so that the app can simply work with the new folder strcture. /// <summary>
/// Checks, if a database file is already available
/// </summary>
public static bool HasDatabase
{
get
{
string basePath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
string sDatabaseFolder = Path.Combine(basePath, DATABASE_FOLDER);
string sDatabaseFile = Path.Combine(sDatabaseFolder, DATABASE_FILENMAE);
#if ANDROID
// only used, when the app is updated from Xamarin poject to MAUI
string sXamarinDatabaseFilePath = Path.Combine(basePath, ".local/share", DATABASE_FOLDER, DATABASE_FILENMAE);
try
{
// upgrade scenario for Xamarin.Forms to MAUI (old files are placed in the .local/share sub folder)
if (!basePath.Contains(".local/share") && File.Exists(sXamarinDatabaseFilePath))
{
// Look if the new folder is existant and create in case
if (!Directory.Exists(sDatabaseFolder))
{
Directory.CreateDirectory(sDatabaseFolder);
}
// Copy old database to new folder
File.Copy(sXamarinDatabaseFilePath, sDatabaseFile, false);
if (File.Exists(sDatabaseFile))
{
// Rename the old filename so that the app does not copy it on the next start
File.Move(sXamarinDatabaseFilePath, sXamarinDatabaseFilePath + ".old", true);
}
}
}
catch (Exception ex)
{
Console.WriteLine($"Error when checking and copying old database file (Xamarin) to new directory structure (MAUI). Message is: {ex.Message}");
}
#endif
FileInfo fInfo = new FileInfo(sDatabaseFile);
return fInfo.Exists;
} So the first time the new app version (with MAUI) is started, the data gets migrated and the old data is invalidated with changing the filenames of the old database. But we Keep the files - just in case ;-) The code is a little bit more complex because I used a subfolder for my database. I tested it blind by uploading the new app version to the store and it works really good. Now I'm much more relaxed... |
Beta Was this translation helpful? Give feedback.
-
I've already asked this in a Stack Overflow question, but it seems appropriate to also ask this here:
Is there an official migration path for accessing files in the local application data folder on Android?
Consider the following code in a Xamarin.Forms and a migrated .NET MAUI app:
In Xamarin.Forms, the resulting path on Android is (just like it's documented here):
However, when using the exact same code in MAUI, the resulting path on Android is:
I've resolved this issue by appending ".local/share" to the provided path on Android:
Note: The code above is just exemplary, the actual solution would use preprocessor directives or multi-targeting and constants for the file paths and a const ".local/share" string.
What's the recommended course of action? Is this the way to migrate Xamarin.Forms apps to .NET MAUI when trying to access existing files in an upgraded app?
Beta Was this translation helpful? Give feedback.
All reactions