How to deploy a database file with a Xamarin.from app?

狂风中的少年 提交于 2020-01-15 05:33:54

问题


I created a sqlite file in my project with some data in it, but I don't know how to link it to my app. I expect the data could be loaded on a Android simulator.

I found a tutorial which was published in 2015, it works no longer, such as GetLocalFilePath function cannot be found after new a FileAccessHelper Class. And the tutorial project seemed using an olde version of SQLite.net-PCL package, because SQLite.Net.Platform.XamarinAndroid was used in the tutorial project, while this package is no longer exist. Any ideas?

http://arteksoftware.com/deploying-a-database-file-with-a-xamarin-forms-app/

This is the code from the tutorial:

[Activity (Label = "People", Icon = "@drawable/icon", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsApplicationActivity  
{
    protected override void OnCreate (Bundle bundle)
    {
        base.OnCreate (bundle);
        global::Xamarin.Forms.Forms.Init (this, bundle);

        string dbPath = FileAccessHelper.GetLocalFilePath ("people.db3");

        LoadApplication (new People.App (dbPath, new SQLitePlatformAndroid ()));
    }
}

FileAccessHelper.cs

public class FileAccessHelper  
{
    public static string GetLocalFilePath (string filename)
    {
        string path = Environment.GetFolderPath (Environment.SpecialFolder.Personal);
        string dbPath = Path.Combine (path, filename);

        CopyDatabaseIfNotExists (dbPath);

        return dbPath;
    }

    private static void CopyDatabaseIfNotExists (string dbPath)
    {
        if (!File.Exists (dbPath)) {
            using (var br = new BinaryReader (Application.Context.Assets.Open ("people.db3"))) {
                using (var bw = new BinaryWriter (new FileStream (dbPath, FileMode.Create))) {
                    byte[] buffer = new byte[2048];
                    int length = 0;
                    while ((length = br.Read (buffer, 0, buffer.Length)) > 0) {
                        bw.Write (buffer, 0, length);
                    }
                }
            }
        }
    }
}

回答1:


You will need to implement an Interface for each platform if you are wanting to call the method from Xamarin.Forms but I will not go into detail on how all that works in this example. Here are the Xamarin docs on the topic of the DependencyService used below.

For Android you will need to place the DB file in the Assets folder. This is the code you will need in your Android project for the interface that copies the DB and return its path:

[assembly: Xamarin.Forms.Dependency(typeof(FileAccessHelper))]
namespace MyNamespace.Droid
{
    class FileAccessHelper : MyXamarinFormsPage.IFileAccessHelper
    {
        public async Task<String> GetDBPathAndCreateIfNotExists()
        {
            String databaseName = "MyLite.db";
            var docFolder = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal);
            var dbFile = Path.Combine(docFolder, databaseName); // FILE NAME TO USE WHEN COPIED
            if (!File.Exists(dbFile))
            {
                FileStream writeStream = new FileStream(dbFile, FileMode.OpenOrCreate, FileAccess.Write);
                await Forms.Context.Assets.Open(databaseName).CopyToAsync(writeStream);
            }
            return dbFile;
        }
    }
}

For UWP you will want to place the DB file in the root folder. The interface in your UWP project that copies the file and returns the path should look like this:

[assembly: Xamarin.Forms.Dependency(typeof(FileAccessHelper))]
namespace MyNamespace.UWP
{
    public class FileAccessHelper : MyXamarinFormsPage.IFileAccessHelper
    {
        public async Task<String> GetDBPathAndCreateIfNotExists()
        {
            String filename = "MyLite.db";
            bool isExisting = false;
            try
            {
                StorageFile storage = await ApplicationData.Current.LocalFolder.GetFileAsync(filename);
                isExisting = true;
            }
            catch (Exception)
            {
                isExisting = false;
            }
            if (!isExisting)
            {
                StorageFile databaseFile = await Package.Current.InstalledLocation.GetFileAsync(filename);
                await databaseFile.CopyAsync(ApplicationData.Current.LocalFolder, filename, NameCollisionOption.ReplaceExisting);
            }
            return Path.Combine(ApplicationData.Current.LocalFolder.Path, filename);
        }
    }
}

For iOS you will want to place the DB file in your Resources folder. Then this is the code in your iOS project for the interface:

[assembly: Xamarin.Forms.Dependency(typeof(FileAccessHelper))]
namespace MyNamespace.iOS
{
    public class FileAccessHelper : MyXamarinFormsPage.IFileAccessHelper
    {
        public async Task<String> GetDBPathAndCreateIfNotExists()
        {
            String databaseName = "MyLite.db";
            var documentsPath = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal);
            var path = Path.Combine(documentsPath, databaseName);
            if (!File.Exists(path))
            {
                var existingDb = NSBundle.MainBundle.PathForResource("MyLite", "db");
                File.Copy(existingDb, path);
            }
            return path;
        }
    }
}

It can then be called from your Xamrin.Forms project by doing this:

public class MyXamarinFormsPage
{
    public MyXamarinFormsPage()
    {
        String DBPath = await DependencyService.Get<IFileAccessHelper>().GetDBPathAndCreateIfNotExists()
        //Store string for path
    }

    public interface IFileAccessHelper
    {
        Task<String> GetDBPathAndCreateIfNotExists();
    }
}



回答2:


Try assigning your dbpath variable in your Android project with the following (and forget about the FileAccessHelper class):

[Activity (Label = "People", Icon = "@drawable/icon", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsApplicationActivity  
{
    protected override void OnCreate (Bundle bundle)
    {
        base.OnCreate (bundle);
        global::Xamarin.Forms.Forms.Init (this, bundle);

        // Retrieves the "AppHome"/files folder which is the root of your app sandbox on Android 
        var appDir = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal);
        // Locates your dbPath.
        string dbPath = Path.Combine(appDir , "people.db3");

        LoadApplication (new People.App (dbPath, new SQLitePlatformAndroid()));
    }
}

Hope this helps!



来源:https://stackoverflow.com/questions/43129861/how-to-deploy-a-database-file-with-a-xamarin-from-app

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!