1

I have some Config files as part of my solution on Windows Mobile. I am porting the code to MonoForAndroid and MonoTouch, so I want to keep my code unchanged as much as possible.

When loading these xml files, on Windows Mobile works fine, in my last prototype it also worked on iOS, but the code does not work on MonForAndroid

I have these files

/solution folder
    /My Documents/
        /Business
            App.Config
            Settings.Config

I have these files build action set to Content and I can see that they are being copied to the /bin/Debug/ but When I try to read these files, I get the following exception:

System.IO.DirectoryNotFoundException

I see that there is a similar question in here, but they advised to use AndroidResources, which I do not want to do, there are many placed where these files are needed, so I do not want to change it in many places.

AndrodiResources, is out of the question, and if possible I would like to avoid using EmbededResources

ah and the way I am reading it, very straightforward xmDoc.Load(filePath) I also tried File.ReadAllText() I made sure that the filePath is correct, and I got the path generated using Path.Combine() to avoid any issues with the filePath/slashes Here is how I construct my file path

var filePath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().GetName().CodeBase).Replace(FileURIPrefix, ""), "My Documents", "Business");
filePath = Path.Combine(filePath, "App.Config");

And I can see in the debugger that the filePath is correct Thanks for the help in advance

Community
  • 1
  • 1
Has AlTaiar
  • 4,052
  • 2
  • 36
  • 37

1 Answers1

0

After searching all around, I could not get the MonoDroid to load (or include) my files when their build action is set to Content.

I had to create an entity called FileHelper which is implemented differently on Android, I then use that FileHelper.ReadAllText(string filename);

I will put my implementation here, hoping that it would benefit somebody else.

Windows Mobile and iOS

    public class FileHelper 
    {
        public static string ReadAllText(string filePath)
        {
            var path = filePath.GetFullPath();
            if (!File.Exists(path))
            {
                Logging.LogHandler.LogError("File " + path + " does not exists");
                return string.Empty;
            }
            using (var reader = new StreamReader(filePath))
            {
                return reader.ReadToEnd();
            }
        }
   }

Android version

public class FileHelper : BaseFileHelper 
{
    public static string ReadAllText(string filePath)
    {
        var entryAssemblyPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().GetName().CodeBase).Replace("file:", ""), "MyExecutableAssemblyName.dll");
        // This is because Assembly.GetEntryAssembly() returns null on Android... Booohhh
        var assembly = Assembly.LoadFrom(entryAssemblyPath);
        using (var stream = assembly.GetManifestResourceStream(filePath.GetFullPath()))
        {
            using (var reader = new StreamReader(stream))
            {
                return reader.ReadToEnd();
            }
        }
    }
}

I had a shared code for Constants and an extention method for paths as below

Constants.cs

public static Class Constants
     {
        private static string _RootPath;
                private static string _iOSRootPath;
        private static string _AndroidResourcePath;

        public static string RootPath
        {
            get
            {
                if (string.IsNullOrEmpty(_RootPath))
                {
                    _RootPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().GetName().CodeBase).Replace(FileURIPrefix, "") + "\\My Documents\\Business";
                }
                return _RootPath;
            }
        }

        public static string iOSRootPath
        {
            get
            {
                          if (!string.IsNullOrEmpty(_iOSRootPath)) 
                          {
                       _iOSRootPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().GetName().CodeBase).Replace(FileURIPrefix, "").Replace("file:", ""), Path.Combine("My_Documents", "Business"));
                  }
                          return _iOSRootPath;
                     }
        }

        public static string AndroidResourcePath
        {
            get
            {
                if (string.IsNullOrEmpty(_AndroidResourcePath))
                {
                    _AndroidResourcePath = "Leopard.Delivery.My_Documents.Business.";
                }
                return _AndroidResourcePath;
            }
        }
  }

PathExtentions.cs

public static class PathExtensions
    {
        public static string GetFullPath(this string filePath)
        {
            if (Platform.IsAndroid) // platform is a class that I have to tell me which platfrom I am at :)
            {
                return Constants.AndroidResourcePath + filePath;
            }
            if (Platform.IsIOS)
            {
                return Path.Combine(Constants.iOSRootPath, filePath);
            }
            return Path.Combine(Constants.RootPath, filePath);
        }
    }

After setting this up, I am using my FileHelper just as easy as below

string configuratinContents = FileHelper.ReadAllText(configruationPath); 

To whoever using this code, remember to set the build action to EmbededResources on Android, and to Content on iOS and Windows Mobile.

Has AlTaiar
  • 4,052
  • 2
  • 36
  • 37