通过Unity在android中使用填充的SQLite数据库

时间:2016-08-10 04:36:14

标签: android sqlite unity3d

我将在我使用Unity创建的Android游戏中使用预先填充的SQLite数据库。

由于the simple way无法在Android上运行(它在Windows上完美运行),因此我跟随this tutorial在Android应用中使用我的数据库。< / p>

public void OpenDB(string p) //p is the database name

{
    // check if file exists in Application.persistentDataPath

    string filepath = Application.persistentDataPath + "/" + p;

    if(!File.Exists(filepath))

    {

        // if it doesn't ->

        // open StreamingAssets directory and load the db -> 

        WWW loadDB = new WWW("jar:file://" + Application.dataPath + "!/assets/" + p);  // this is the path to your StreamingAssets in android

        while(!loadDB.isDone) {}  // CAREFUL here, for safety reasons you shouldn't let this while loop unattended, place a timer and error check

        // then save to Application.persistentDataPath

        File.WriteAllBytes(filepath, loadDB.bytes);

    }

    //open db connection

    connection = "URI=file:" + filepath;

    dbcon = new SqliteConnection(connection);

    dbcon.Open();

}

当我运行此代码时,出现以下错误:

  

SqliteSyntaxException:文件已加密或不是数据库

这是完整的错误:

  

SqliteSyntaxException:文件已加密或不是数据库   Mono.Data.SqliteClient.SqliteCommand.GetNextStatement(IntPtr pzStart,   System.IntPtr&安培; pzTail,System.IntPtr&amp;数PreparedStatement pstmt)   Mono.Data.SqliteClient.SqliteCommand.ExecuteReader(CommandBehavior   行为,布尔值want_results,System.Int32&amp; rows_affected)   Mono.Data.SqliteClient.SqliteCommand.ExecuteReader(CommandBehavior   行为)Mono.Data.SqliteClient.SqliteCommand.ExecuteDbDataReader   (CommandBehavior行为)System.Data.Common.DbCommand.ExecuteReader   ()System.Data.Common.DbCommand.System.Data.IDbCommand.ExecuteReader   ()dbAccess.SingleSelectWhere(System.String tableName,System.String   itemToSelect,System.String wCol,System.String wPar,System.String   wValue)(在Assets / dbAccess.cs:152)

我已从该帖子下载了该示例,并得到了同样的错误。

我对这一行感到怀疑:

File.WriteAllBytes(filepath, loadDB.bytes); 

我的想法是出于某种原因,它无法将数据库数据写入文件。

有谁知道如何解决这个问题?

1 个答案:

答案 0 :(得分:3)

由于this blog,我解决了这个问题。

由于 if 语句将根据应用程序运行的平台执行不同的行为,因此此代码在每个平台上都运行良好。

这是执行重要部分的DataService.cs或者我更好地说整个部分

using SQLite4Unity3d;
using UnityEngine;
#if !UNITY_EDITOR
using System.Collections;
using System.IO;
#endif
using System.Collections.Generic;

public class DataService  {

    private SQLiteConnection _connection;

    public DataService(string DatabaseName){

#if UNITY_EDITOR
            var dbPath = string.Format(@"Assets/StreamingAssets/{0}", DatabaseName);
#else
        // check if file exists in Application.persistentDataPath
        var filepath = string.Format("{0}/{1}", Application.persistentDataPath, DatabaseName);

        if (!File.Exists(filepath))
        {
            Debug.Log("Database not in Persistent path");
            // if it doesn't ->
            // open StreamingAssets directory and load the db ->

#if UNITY_ANDROID 
            var loadDb = new WWW("jar:file://" + Application.dataPath + "!/assets/" + DatabaseName);  // this is the path to your StreamingAssets in android
            while (!loadDb.isDone) { }  // CAREFUL here, for safety reasons you shouldn't let this while loop unattended, place a timer and error check
            // then save to Application.persistentDataPath
            File.WriteAllBytes(filepath, loadDb.bytes);
#elif UNITY_IOS
                 var loadDb = Application.dataPath + "/Raw/" + DatabaseName;  // this is the path to your StreamingAssets in iOS
                // then save to Application.persistentDataPath
                File.Copy(loadDb, filepath);
#elif UNITY_WP8
                var loadDb = Application.dataPath + "/StreamingAssets/" + DatabaseName;  // this is the path to your StreamingAssets in iOS
                // then save to Application.persistentDataPath
                File.Copy(loadDb, filepath);

#elif UNITY_WINRT
        var loadDb = Application.dataPath + "/StreamingAssets/" + DatabaseName;  // this is the path to your StreamingAssets in iOS
        // then save to Application.persistentDataPath
        File.Copy(loadDb, filepath);
#else
    var loadDb = Application.dataPath + "/StreamingAssets/" + DatabaseName;  // this is the path to your StreamingAssets in iOS
    // then save to Application.persistentDataPath
    File.Copy(loadDb, filepath);

#endif

            Debug.Log("Database written");
        }

        var dbPath = filepath;
#endif
            _connection = new SQLiteConnection(dbPath, SQLiteOpenFlags.ReadWrite | SQLiteOpenFlags.Create);
        Debug.Log("Final PATH: " + dbPath);     

    }

    public void CreateDB(){
        _connection.DropTable<Person> ();
        _connection.CreateTable<Person> ();

        _connection.InsertAll (new[]{
            new Person{
                Id = 1,
                Name = "Tom",
                Surname = "Perez",
                Age = 56
            },
            new Person{
                Id = 2,
                Name = "Fred",
                Surname = "Arthurson",
                Age = 16
            },
            new Person{
                Id = 3,
                Name = "John",
                Surname = "Doe",
                Age = 25
            },
            new Person{
                Id = 4,
                Name = "Roberto",
                Surname = "Huertas",
                Age = 37
            }
        });
    }

    public IEnumerable<Person> GetPersons(){
        return _connection.Table<Person>();
    }

    public IEnumerable<Person> GetPersonsNamedRoberto(){
        return _connection.Table<Person>().Where(x => x.Name == "Roberto");
    }

    public Person GetJohnny(){
        return _connection.Table<Person>().Where(x => x.Name == "Johnny").FirstOrDefault();
    }

    public Person CreatePerson(){
        var p = new Person{
                Name = "Johnny",
                Surname = "Mnemonic",
                Age = 21
        };
        _connection.Insert (p);
        return p;
    }
}

它由另外两个脚本来创建或使用现有数据库。

<强> ExistingDBScript.cs

using UnityEngine;
using System.Collections.Generic;
using UnityEngine.UI;

public class ExistingDBScript : MonoBehaviour {

    public Text DebugText;

    // Use this for initialization
    void Start () {
        var ds = new DataService ("existing.db");
        //ds.CreateDB ();
        var people = ds.GetPersons ();
        ToConsole (people);

        people = ds.GetPersonsNamedRoberto ();
        ToConsole("Searching for Roberto ...");
        ToConsole (people);

        ds.CreatePerson ();
        ToConsole("New person has been created");
        var p = ds.GetJohnny ();
        ToConsole(p.ToString());

    }

    private void ToConsole(IEnumerable<Person> people){
        foreach (var person in people) {
            ToConsole(person.ToString());
        }
    }

    private void ToConsole(string msg){
        DebugText.text += System.Environment.NewLine + msg;
        Debug.Log (msg);
    }

}

<强> CreateDBScript.cs

using UnityEngine;
using System.Collections.Generic;
using UnityEngine.UI;

public class CreateDBScript : MonoBehaviour {

    public Text DebugText;

    // Use this for initialization
    void Start () {
        StartSync();
    }

    private void StartSync()
    {
        var ds = new DataService("tempDatabase.db");
        ds.CreateDB();

        var people = ds.GetPersons ();
        ToConsole (people);
        people = ds.GetPersonsNamedRoberto ();
        ToConsole("Searching for Roberto ...");
        ToConsole (people); 
    }

    private void ToConsole(IEnumerable<Person> people){
        foreach (var person in people) {
            ToConsole(person.ToString());
        }
    }

    private void ToConsole(string msg){
        DebugText.text += System.Environment.NewLine + msg;
        Debug.Log (msg);
    }
}

person脚本演示了数据库中的人员表

using SQLite4Unity3d;

public class Person  {

    [PrimaryKey, AutoIncrement]
    public int Id { get; set; }
    public string Name { get; set; }
    public string Surname { get; set; }
    public int Age { get; set; }

    public override string ToString ()
    {
        return string.Format ("[Person: Id={0}, Name={1},  Surname={2}, Age={3}]", Id, Name, Surname, Age);
    }
}

您还需要在项目中添加插件和Sqlite.cs,您可以在git repository

中找到

它帮助我克服了这个问题,希望它能帮助其他人。