Unity - база данных на Android не загружается при первом запуске - PullRequest
0 голосов
/ 25 октября 2019

Я пытаюсь получить данные из локальной базы данных, используя 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 при первом запуске база данных не может быть найдена, поэтому она создает ее после загрузки уровня. Как мне изменить его, чтобы всегда находить и загружать базу данных перед загрузкой остальной части сцены?

1 Ответ

0 голосов
/ 29 октября 2019

Решил проблему, назначив этот сценарий 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);
        }
    }      
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...