Unity-首次运行时未加载Android上的数据库

问题描述 投票:-1回答:1

我正在尝试使用UnityWebRequest从本地数据库获取数据。在Windows上,它可以正常工作。在Android上,它第一次运行时找不到数据库,但是如果返回上一场景并再次加载该场景,则会创建数据库并按预期工作。

我将数据库放置在StreamingAssets文件夹中(我也直接在Assets/中尝试过,但结果相同)。

这是我到目前为止的内容:

private void Start()
{
    //Check platform.
    if (Application.platform == RuntimePlatform.Android)
    {
       platformPath = Application.persistentDataPath;
       databasePath = Path.Combine("URI=file:" + platformPath + dbName);
    }
    else
    {                
       platformPath = Application.dataPath;
       databasePath = Path.Combine("URI=file:" + platformPath + "/StreamingAssets" + dbName);
    }   

  if (!File.Exists(Path.Combine(platformPath + dbName)))
  {
     Debug.Log("File doesn't exists!");           
     StartCoroutine(GetText());
  }

  try
  {
      //Communicate with database.
        IDbConnection dbConnection = new SqliteConnection(databasePath);
        dbConnection.Open();

      //Read and print data in DB table.
         IDbCommand cmnd_read = dbConnection.CreateCommand();
         IDataReader reader;

         string query = "SELECT * FROM BonusWords";
         cmnd_read.CommandText = query;
         reader = cmnd_read.ExecuteReader();

         while (reader.Read())         
            BonusWordsList.Add(reader[0].ToString().ToUpper());


         //Close DB connection.
         dbConnection.Close();
  }
  catch(Exception ex)
  {
      Debug.Log("EXCEPTION: " + ex);
  }
}


private IEnumerator GetText()
{
  string path = Path.Combine("jar:file://" + Application.dataPath + "!/assets" + dbName);

  UnityWebRequest www = UnityWebRequest.Get(path);
  yield return www.SendWebRequest();

  while (!www.isDone) { }
  try
  {
    // Retrieve results as binary data.
    byte[] data = www.downloadHandler.data;

    // Writes the DB in the persistent memory.
    File.WriteAllBytes(Path.Combine(Application.persistentDataPath + dbName), data);
  }
  catch (Exception ex)
  {
    Debug.Log(ex.Message);
  }
}

所以问题是,在Android上,第一次运行时找不到数据库,因此它在加载级别后创建了数据库。在加载其余场景素材之前,我应该如何更改它以始终定位并加载数据库?

android database sqlite unity3d
1个回答
0
投票

通过将此脚本分配给场景中的GameObject解决了该问题,因此它将仅在第一次检查时(在Start()处)并获取适当的平台路径;如果是Android,则在找不到数据库的情况下创建数据库。

public class DBConnection : MonoBehaviour
{
    private IDbConnection dbConnection;
    private IDbCommand dbCommand;
    private IDataReader reader;

    private string platformPath;
    private readonly string databaseFolder = "/StreamingAssets";
    private readonly string dbName = "/BonusWords.db";
    private string connectionString = "";


    private void Start()
    {
        connectionString = GetDatabasePath();
    }

    public string CheckIfWordExistsInDB(string word)
    {    
        try
        {
            OpenDatabaseConnection(connectionString);
        }
        catch(Exception ex)
        {
            Debug.Log("Connection Exception: " + ex);
            return null;
        }

        string sqlQuery = "SELECT * FROM BonusWords WHERE Word='" + word + "' LIMIT 1";

        try
        {
            if (ExecuteQuery(sqlQuery, word) != null)
            {
                /// Close DB connection.
                CloseDatabaseConnection(reader, dbCommand, dbConnection);
                return word;
            }
            else
            {
                /// Close DB connection.
                CloseDatabaseConnection(reader, dbCommand, dbConnection);
                return null;
            }
        }
        catch(Exception ex)
        {
            Debug.Log("Exception: " + ex);
            return null;
        }             
    }

    private void OpenDatabaseConnection(string connectionString)
    {
        dbConnection = new SqliteConnection(connectionString);
        dbConnection.Open();
        Debug.Log("Connected to database: #" + dbConnection.ConnectionString);
    }

    private IDataReader ExecuteQuery(string sqlQuery, string word)
    {
        dbCommand = dbConnection.CreateCommand();
        dbCommand.CommandText = sqlQuery;

        reader = dbCommand.ExecuteReader();

        if (reader[0].ToString() == word)           
            return reader;

        return null;
    }

    /// Close all opened connections.
    private void CloseDatabaseConnection(IDataReader reader, IDbCommand dbCommand, IDbConnection dbConnection)
    {
        reader.Close(); 
        reader = null;
        dbCommand.Dispose();
        dbCommand = null;
        dbConnection.Close();
        dbConnection = null;
        Debug.Log("Closed all opened connections.");
    }

    private string GetDatabasePath()
    {
        string databasePath;

        /// Set path according to platform.
        if (Application.platform == RuntimePlatform.Android)
        {
            platformPath = Application.persistentDataPath;

            /// Looks for the DB in the persistent memory
            /// on Android.
            if (!File.Exists(Path.Combine(platformPath + dbName)))
            {
                Debug.Log("File doesn't exists!");
                StartCoroutine(GetDatabaseForAndroid());
            }

            return databasePath = Path.Combine("URI=file:" + platformPath + dbName);
        }
        else
        {
            platformPath = Application.dataPath;
            return databasePath = Path.Combine("URI=file:" + platformPath + databaseFolder + dbName);
        }
    }

    private IEnumerator GetDatabaseForAndroid()
    {
        string path = Path.Combine("jar:file://" + Application.dataPath + "!/assets" + dbName);

        UnityWebRequest unityWebRequest = UnityWebRequest.Get(path);

        yield return unityWebRequest.SendWebRequest();

        while (!unityWebRequest.isDone) { }

        try
        {
            /// Retrieve results as binary data.
            byte[] data = unityWebRequest.downloadHandler.data;

            /// Writes the DB in the persistent memory.
            File.WriteAllBytes(Path.Combine(Application.persistentDataPath + dbName), data);
        }
        catch (Exception ex)
        {
            Debug.Log(ex.Message);
        }
    }      
}
© www.soinside.com 2019 - 2024. All rights reserved.