android - Unity - 首次运行时未加载 Android 上的数据库
问题描述
我正在尝试使用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 上,第一次运行时找不到数据库,所以它在关卡加载后创建它。在加载其余场景内容之前,我应该如何将其更改为始终定位和加载数据库?
解决方案
通过将此脚本分配给场景中的 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);
}
}
}
推荐阅读
- angular - 模拟 Observable 以在 Jest 中抛出错误
- javascript - 非异步函数中的 Node.js async/await
- security - ATM CVV1 + 服务代码,POS 安全漏洞?
- java - 如果子对象不存在,则 Spring Hibernate 创建
- python - 如何阻止值在字典中覆盖自身:Python
- kubernetes - 为每个虚拟主机应用 envoyfilter ext_authz
- java - 运行 `mvn endpoints-framework:openApiDocs` 时出现 ClassNotFoundException
- sql-server - 部署 SSIS 包需要 Windows 身份验证?
- ruby - 卢卡斯公式用递归求解。然而公式尚未定义
- matlab - 如何(倾斜)旋转 500 x 1000 矩阵?- MATLAB