How to prepopulate database in an iOS/Android App?

bdpbdp USMember

Hey, guys. I'm working on an Xamarin.Forms app for iOS and Android that needs to read a prepopulated database file (about 350KB of info) that has multiple tables. I'm using the Nuget Package sqlite-net-pcl, and right now I'm going through two problems:
1. Is it possible to read a file with multiple tables? What I've done is create a model for each one and instantiating all the tables, for example:
public ObservableCollection<MapCoord> coords { get; set; }
And in the constructor:
mapdatabase.CreateTable();
this.coords = new ObservableCollection<MapCoord>(mapdatabase.Table<MapCoord>());
And then to search the table:
var query = from coord in mapdatabase.Table()
where coord.map_coord_type_id == -1
select *;
Is this correct?

  1. How can I save the file in the Resources folder, either in the iOS or the Android project, and read it correctly? Right now what I am doing is (for Android):

    public class SQLiteMapAndroid : ISQLiteMap
    {
    public SQLiteConnection GetMapConnection ()
    {
    var sqliteFileName = "map_old.db3";
    string documentsPath = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
    var path = Path.Combine(documentsPath, sqliteFileName);

            Console.WriteLine(path);
            if (!File.Exists(path))
            {
                var s = Android.App.Application.Context.Resources.OpenRawResource(Resource.Raw.map_old);
    
                // create a write stream
                FileStream writeStream = new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write);
                // write to the stream
                ReadWriteStream(s, writeStream);
            }
    
            return new SQLiteConnection(path);
    
        }
    
        void ReadWriteStream(Stream readStream, Stream writeStream)
        {
            int Length = 1024;
            Byte[] buffer = new Byte[Length];
            int bytesRead = readStream.Read(buffer, 0, Length);
            // write the required bytes
            while (bytesRead > 0)
            {
                writeStream.Write(buffer, 0, bytesRead);
                bytesRead = readStream.Read(buffer, 0, Length);
            }
            readStream.Close();
            writeStream.Close();
        }
    }
    

I got this code from a Todo example, and adapted bits of it. The file is in Resources/raw with "AndroidResource" Build Action.

And for iOS:

public class SQLiteMapiOS : ISQLiteMap
{
    var sqliteFileName = "map_old.db3";
    string documentsPath = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
    string libFolder = Path.Combine(documentsPath, "..", "Library");
    var path = Path.Combine(libFolder, sqliteFileName);

    if (!File.Exists(path))
    {
        var appdir = NSBundle.MainBundle.ResourcePath;
        var source = Path.Combine(appdir, "map_old.db3");

        File.Copy(source, path);
    }

    return new SQLiteConnection(path);
}

The file in the iOS project is in Resources with BundleResource Build Action.

When I run the app the file isn't copied, either on iOS or on Android. I've read many tutorials and can't find a solution. Can anyone shine some light over this subject? Thanks in advance.

BDP

Sign In or Register to comment.